This compiles fine, however, when I try to add a specialization below it:
1 2 3 4
template <> //just for practice really
std::string to_string(std::string thing) {
return thing;
}
I receive a bunch of linker errors stating that the specialized version of the function is already defined in the other object files. What exactly is the problem? Do I need to put the specialization somewhere else?
You cannot make a specialization of a template function.
EDIT: Apparently I was wrong. The code you posted compiles and links fine on mingw.
EDIT 2: One thing that comes to my mind is that this specialization is not "visible" everywhere where the base template is. In this situation one compilation unit could use std::string to_string(std::string thing) generated based on the base template, and another compilation unit could use std::string to_string(std::string thing) generated from the specialization, what would lead to link errors.
EDIT 3: Tested again with two compilation units, and mingw generates errors even if visibility of the base tamplate and its specialization is the same. It looks that the compiler treats the specialization just like a regular function, i.e. its symbol name is global. Adding static to the function's declaration helped.
There are no specializations of function templates. But you can have several function templates with the same function name. The only difference between instantiated templates and normal overloads is that 1) templates have lower priority when it comes to overload resolution and do not contend with non-template functions (therefore not causing ambiguity errors with them) 2) template functions are instantiated on a per-need basis.
So, I would understand ambiguity error from the compiler, but linker error? May be the problem is that you instantiate in one translation unit the parametrized template with string and in another the non-parametrized template and the mangled names of the resulting compiled functions are the same and the linker dies. That would explain why adding static modifier fixes the problem. But I still can not understand why you don't get ambiguity error for overload resolution during compilation. May be I don't understand overload resolution that well.
True, this works. I was confused because partial template specialization is not available. But I didn't know that full template specialization works ok with functions. I need to look into that stuff more seriously :)
All template specializations need to be inline? You mean, like, always?
And is there a difference between template <> std::string to_string(std::string thing) and template <> std::string to_string<std::string>(std::string thing)?
Are they both template specializations of the to_string template, or only the latter one and the former one is separate template?
Yes, that was my guess also - the second one is specialization like in your example. But the one from the snippet in the original post is not specialization, but separate template, or am I wrong?
Putting the implementation of a concrete (non-template) function in a header file is the same thing as putting a global variable in a header file, only the duplicate symbol definition linker error complains about the name of the function instead of the name of the variable.
Putting the implementation of a concrete (non-template) function in a header file is the same thing as putting a global variable in a header file, only the duplicate symbol definition linker error complains about the name of the function instead of the name of the variable.
To confirm what JSmith said - the following is from the book C++ Templates - The Complete Guide concerning function templates.
A full specialization is in many ways similar to a normal declaration (or rather, a normal redeclaration). In particular, it does not declare a template, and therefore only one definition of a noninline full function template specialization should appear in a program.
That's very useful info. But does this mean that full template specialization participates in overload resolution with the same priority as non-template function overloads?
And I still don't understand what is the difference between the syntaxes template <> std::string to_string(std::string thing) and template <> std::string to_string<std::string>(std::string thing)?
Are they the same thing? You certainly can not use the former syntax in circumstances like these:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
#include <iostream>
template <int N> int f()
{
return N;
}
template <> int f<5>()
{
return 6;
}
int main(void)
{
std::cout << f<5>() << std::endl;
}
They are the almost the same. The first allows the compiler to infer the template type from the arguments (as normal) and the second type lets you tell the compiler explicitly. In your example, the compiler can't guess the template arguments from the function, so you need to specify.
Oh, ok. So it is the same mechanism as in template instantiation. You either specify the template arguments explicitly or rely on their deduction. Boy, was I confused on the subject.
To answer my last question. Fully specialized function templates are apparently assigned lower priority to non-template functions in overload resolution:
Here's a link that might help you out with your question: http://www.gotw.ca/publications/mill17.htm
Be careful about what compiler you are using for your test. For me, different versions of gcc give
different results for the code examples given in the link.