The problem with template specializations is that they’re treated like normal functions because there is no template parameter used anywhere anymore.
Therefor if the following code is put in a header file it works at first.
template <typename foo>
void f(foo p)
{
std::cout << "f one" << std::endl;
}
template <>
void f<int>(int p)
{
std::cout << "f two" << std::endl;
}
But this stops working if the header is included in two files.
In this case the error I get (with VS2010) is:
templateordering.obj : error LNK2005: "void __cdecl f<int>(int)" (??$f@H@@YAXH@Z) already defined in othertu.obj
And this is fixable by using the inline keyword as mentioned in many other questions.
template <>
inline void f<int>(int p)
{
std::cout << "f two" << std::endl;
}
Now this raises two questions for me:
- Is there any other way to do this? Putting the specialized function in the source file doesn’t seem to work. Probably because I would need some sort of declaration in the header.
- What does inline actually do? It seems to be a common rule of thumb all over the internet that inline shouldn’t be used because the compiler “will probably inline the function the way he likes in any case”. So if the compiler may not inline a function that I declare as “inline”, why does this work?
You need to declare the specialisation in the header, just like any other function. It’s up to you whether to define it inline in the header, or in (exactly one) source file; again, just like any other function. As you say, it must be declared
inlineif you do define it in the header.Normally, the one-definition rule requires functions to be defined in exactly one translation unit in the program. In practice this means that you can’t define a function in a header, since a header is intended to be included in more than one translation unit.
However, sometimes you want, or need, to define functions in headers – for example, some compilers are only able to inline a function call if they can see the definition. The
inlinekeyword relaxes the rule, so that you can define the function in multiple translation units, as long as all the definitions are identical.