Linux C++: How to properly use template specializa

2019-04-08 12:19发布

问题:

I have a strange problem. On Windows, with Visual Studio 2010 and also with the Intel Compiler everything is linked as expected. But when I try to compile my code with CLang 3.0 on Linux, it does compile (and if I only use a single CPP file it does also link and run) but does not link.

The message is that there are multiple symbol definitions, referring to template instanciations. For example consider the following two lines in a header file shared across multiple compilation units:

 template<class T> void myFunc(T in) { }
 template<> void myFunc<int>(int in) { }

Now from the Linux linker I would get something along the lines of:

"file xyz": Multiple definition of "myFunc(int in)", first defined in "some file".

But how would I prevent that? Since it works on Windows I suppose it should work on Linux too somehow?

The same goes for static template data members, which are more or less the same as above just that you declare a variable instead of a function. I would prefer if it worked for static template data members.

If everything else fails I suppose I could still create a "MakeAll.cpp" file which just includes all CPP there are, but that doesn't sound like a desirable solution to me...

Thanks for your help!

回答1:

In my understanding, you are in fact defining your template specializations multiple times, and this should also give you an error for Windows compilers.

In your header file you are defining a function by providing a body:

template<> void myFunc<int>(int in) { }

This definition will exist in multiple compilation units and the linker should complain.

The same rules apply for your template specialization as for ordinary non-template functions: Either use inline or use a separate declaration and definition, by putting

template<> void myFunc<int>(int in);

in a header and

template<> void myFunc<int>(int in)
{
    // ...
}

in a .cpp file.



回答2:

Templates are instantiated by the compiler, and it is the compilers responsibility to make sure that they are only defined once.

When you fully specialize a function, it is not a template anymore (but an ordinary function), and it is your responsibility to make sure it is not multiply defined.

There is very little difference between these functions

template<>
void f<int>(int x)
{ }

void f(int x)
{ }

when it comes to the one definition rule.

Adding inline helps in both cases.



回答3:

I don't have the standard at hand now, but I think that the specialization has to be declared inline.