Topic: Explicit template specialization


Author: Roman Levenstein <romix@geocities.com>
Date: 2000/06/07
Raw View
I have a question about explicit template instantiation.

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?

   A& operator=(E const & obj)
   {
      assign(obj);
   }
};


void AnotherClass<int>::dummy_func()
{
   // ... some code goes here

   A< int > obj;
   obj=4; //first instantiation?
   obj.assign(5);
}

// #1 <- error message
A<int>& A<int>::assign(int const & obj)
{
  // code of assign
}



GCC compiler gives the following error messages:

templ.cpp:24: specialization of A<int>::assign(const int &) after
instantiation
templ.cpp:24: explicit specialization of A<int>::assign(const int
&)after first use

(BTW, Sun C++ compiler can compile it without problems, according to the
author of the library)

The problem is that I can't place the code of assign() before
dummy_func,because they are placed in different source files in the
library and the code above was produced by preprocessor. It would be
rather difficult to correct all such declarations in all library files.

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()?
As I understand it's not defined at that place. But then it's not clear
, why can't
I define assign later?

Can "export" specifier help in this situation?

I've sent this questions to the GCC newsgroups and GCC people've told
me, that this behaviour is according to standard:

------------------
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.
------------------

  If there was a general definition of assign()'s implementation, then
this explicit specialization if A<int>::assign would be a redefinition
after first use 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 takes __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 and probaly usage,
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 after first use
return_type func_name(param_types)
{
  // code of func_name
}

As I understand, when gcc does implicit instantiation of class A ( at
the place of first use ), but sees no __definition__ of assign() it
simply produces assembler CALL instruction 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 later in the same file?
This behaviour is a liitle bit strange for me, though it seems to be
standard conforming. Does standard really disallows explicit
specialzation of the function after the first use, even if at the place
of the first use any implementation of this function was not known? How
does it differs from the situation, where I do explicit specialization
in the other compilation unit, but I do it before the first use there,
and then link both units together? I think it contradicts to the
situation with normal functions. And I see no technical reasons or
implementation difficuties, why standard  doesn't permit it.



>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.

This approach 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. So I can't declare specialization.

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

Roman Levenstein

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]