4

Context

We develop a templated settings system class, that will be part of an API we expose to users of different architectures (fewer words : we should not rely on compiler-specific behaviors)

The generalized code would look like :

In the header

namespace Firm
{

// Class definition
class A
{
  template<class T>
  void foo(T* aParam);
};

// Non specialized template definition
template<class T>
void A::foo(T* aParam)
{
  //...
}

// Declaration of a specialization
template<>
void A::foo<int>(int* aParam); 

} // namespace

In the CPP file

namespace Firm
{

// Definition of the specialized member function
template<>
void A::foo<int>(int* aParam)
{
  //...
}

} // namespace


Questions

Everything runs fine with gcc 4.x. (i.e. Different compilation units use the specialized methods when appropriate.) But I feel uncomfortable since I read the following entry :

Visibility of template specialization of C++ function

Accepted answer states, if I correctly understand it, that it is an error if the definition of the specialization of a template method is not visible from call site. (Which is the case in all compilation units that are not the CPP file listed above but include the header)

  1. I cannot understand why a declaration would not be enough at this point (declaration provided by the header) ?

  2. If it really is an error, is there a correct way to define the specialization for it to be :

    • non-inline
    • usable in any compilation unit that includes the header (and links with the corresponding .obj) ?
Community
  • 1
  • 1
Ad N
  • 7,930
  • 6
  • 36
  • 80

1 Answers1

0

Put the declaration in the header file.

The compiler either needs to instantiate the template (needs the definition) or you need to use c++0x extern templates

look here:https://stackoverflow.com/a/8131212/258418

edit @ Single definition rule: YOu should be fine since I expirienced the following behaviour for templates: Create them in the different o files (multiple time, time consuming due to several compilations), when the linker comes in it removes the duplicates and uses one instantiation.

also look at this answer/wiki link: https://stackoverflow.com/a/8133000/258418

edit2

for classes it works like this:

extern template class yourTemplate<int>; //tell the compiler to just use this like a funciton stub and do no instantiation. put this in the header

template class yourTemplate<int>; //instantiation, put this in a c file/object that you link with the project

for your function it should work like this: // Declaration of a specialization in your header extern template<> void A::foo(int* aParam);

//in your cpp file
template<>
void A::foo<int>(int* aParam) {
    code...
}

template class A::foo<int>(int* aParam);
Community
  • 1
  • 1
ted
  • 4,791
  • 5
  • 38
  • 84
  • 1
    This one violates the single definition rule if the method is not inline. (Posted when the answer was only the first line) – Ad N Jan 10 '12 at 13:04
  • Why would it **need** to instantiate the template for the specialized case, since the header says "I declare that a complete specialization of the template exists for int". This specialization ***could*** imho behave like any regular method, and the linker would be in charge to check that one and only one definition of this method exists. – Ad N Jan 10 '12 at 13:08
  • I think you are making a confusion between a fully specified template (what the link you provide refers to : http://stackoverflow.com/a/8133000/258418) and a full specialization of a template (what my question is primarily about). There is I think no need to instantiate the template when you fall down to a case where the fully specified usage of your template matches a defined complete specialization of this template. – Ad N Jan 10 '12 at 13:14
  • just try this: `extern template<> SomeFunc();` to let the compiler know that you have the specialization, so it does not instantiate the unspecialized version and instantiate it explicitly in the source file(.cpp). Or put the definition of the specialization in the header as i said. The con of the later is that you will recompile the code for your specialization every time you use it in a different compilation unit (the linker will sort this out later), the pro part is, that if your specialization is never used it is never instantiated (this would be the case with explicit instantiation). – ted Jan 10 '12 at 13:21
  • Another con of the second is that it will violate the "single definition rule". (Just tested with VS 2010 and gcc) Linker sort out the template instantiations that are for the same full specification if the compiler had to make several. But once again, when it comes down to the fully specialized version of the template method, **no instantiation occurs** (since, the specific code already exist, you wrote it) – Ad N Jan 10 '12 at 13:36
  • unfortunately i dont have access to gcc at the moment, I will try what you said as soon as i come home, one issue might be that it is only a template function not a templated class, but i never run in the issue of the single definition rule. Till then you will have to hope for others. I would be unsure about the last part, since this means that the compiler has to differentiate between the full specialization and partial specialization. But if what you say is right, the explicit instantiation might cause the double instantiation part. – ted Jan 10 '12 at 13:41