This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
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