This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Possible bug in explicit template specialization


Roman Levenstein <romix@geocities.com> writes:

| Thanks for your answer, but I still have several questions.
|  
| Gabriel Dos Reis wrote:
| > 
| > | Here is the source code(it's a part of an library):
| > |
| > | template <class E>
| > | class A
| > | {
| > | public:
| > |    A(){}
| > |
| > |    A& assign(E const & obj); // do I need to add "export" here?
| > 
| > Maybe. But g++ doesn't understand `export', right now; and that isn't
| > the source of the problem.
| > 
| > |
| > |    A& operator=(E const & obj)
| > |    {
| > |       assign(obj);
| > |    }
| > | };
| > |
| > | void dummy_func()
| > | {
| > |    A< int > obj;
| > |    obj=4;
| >         ^
| > First instantiation here.
| > 
| > |    obj.assign(5); // first instantiation?
| > 
| > No, second instantiation.
| 
|  If I comment this line: obj.assign(5); 
|  then gcc-2.96.20000605 compiles it without any problems and calls the
| correct version of assign,i.e. A<int>::assign(). According to your
| explanation , it's a bug ( or a feature :-) in gcc-2.96.20000605. 

Well, as per 14.7.3/6, your code is invalid and the compiler isn't
required to emit any diagnostic.  

GCC implements an extension that tries to catch violation of 14.7.3/6.
The fact it fails to catch *all* cases isn't something I would call a
bug; it's neither a feature.

| gcc-2.92.2 can't compile it even in this case.
| 
|  So, this line seems to be a place of first instantiation , at least for
| gcc-2.96.20000605.

No, think of it again.  A<T>::operator=(const T&) requires
instantiation of A<T>::assign(const T&). 

| > | }
| > |
| > | // #1 <- error message
| > | A<int>& A<int>::assign(int const & obj)
| > | {
| > |   // code of assign
| > | }
| > 
| > This is invalid.  You're declaring a specialization after an implicit
| > instantiation.
| > 
| 
| > 17.7.3/6

I meant 14.7.3/6

| >   If a template, a member template or the member of a class template
| >   is explicitly specialized then that specialization shall be declared
| >   before the first use of the specialization that would cause an
| >   implicit instantiation to take place, in every translation unit in
| >   which such a use occurs; no diagnostic is required.
| 
|  
| > | Even if it's not an error, but a correct behavior of gcc, I'd like to
| > | know, what is being instantiated at obj.assign(5) as a body of assign()?
| > 
| > A declaration was instantiated from the general declaration.
|   
|   If there was a general definition of assign implementation, then this
| explicit specialization would be a redefinition and produce an error.

No. The problem isn't a lack of definition, but that of declaration.
If you intend to use an explicit specialization, then you have to
declare it before the first use that would cause, otherwise, an
implicit instantiation.  That is non negociable.

| It's OK. But there is no general definition of A<E>::assign(). That is
| the body of assign is not defined for the general case. There are just
| explicit specializations for concerte cases. I understand, that compiler
| can take __declaration__ of assign() from class A definition.

Not only it can but that is how it is expected to behave.

| ... But where
| can it find __definition__ of assign()? There is no general one.

As I said in my earlier message, it instantiated a declaration, not a
definition.  The general definition is still to be provided somewhere.

| ... Does
| the compiler expect to find it in another compilation unit?

In the current translation unit.

| ... Why can't I
| define it in the same compilation unit, if there is a previous
| declaration, but there's no other __definition__ of it? For normal
| functions I can do it without problems:
| 
| // declaration of function.
| return_type func_name(param_types);
| 
| void f()
| {
|    func_name(...); // use of function func_name
| }
| 
| // definition of function.
| return_type func_name(param_types)
| {
|   // code of func_name
| }

You can define an explicit specialization, provided you declare it
before its first use that would cause an implicit instantiation.

| As I understand, when gcc does implicit instantiation of class A, but
| sees no __definition__ of assign() it simply produces call
| instruction(i.e. doesn't inline) of A<int>::assign() at the appropriate
| places. Later, at the link-time it tries to find the __definition__ of
| the A<int>::assign()(i.e. compiled body) in one of the object files. But
| why can't I define this body in the same file? This behaviour is a
| liitle bit strange for me.

Well, this is a C++ specific question and is best handled in a
dedicated newsgroup.  
An explicit specialization is different form an implicit instantiation.
An explicit specialization shall be declared before its first use that
would cause an implicit instantiation. Having done so you are free to
define its body somewhere at your discretion.
An implicit instantiation is generated from the primary template;
which, if non exported, shall be defined in every translation unit
that requires its instantiation.
Please, feel free to consult a dedicated C++ newsgroup for further
information. 

-- Gaby
CodeSourcery, LLC                             http://www.codesourcery.com

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]