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


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. 
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.
 
> | }
> |
> | // #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
>   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.
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. But where
can it find __definition__ of assign()? There is no general one. Does
the compiler expect to find it in another compilation 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
}

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.

Nathan writes: 
>you need to _declare_ the specialization, before you use it. I.e
>        A<int> &A<int>::assign (int const &obj);
>before the body of dummy_func.

It would do the job, but I don't know in general case, what classes I
will use as parameters of A, because dummy_func is also a template
function in that library. The example, I've posted to the newsgroup is a
simplification of general case. And this approach is a little bit
"indirect".

I'd like to understand, why can't I use explicit template
specialization, if it's the ONLY definition of function of function's
body in the current compilation unit and hence it shoudn't conflict with
anything else.

Roman Levenstein

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