I’ve come across a strange problem with method specialisation.
Given this code…
#include <string>
class X
{
public:
template< typename T >
void set( T v );
};
template<>
void X::set( const std::string & v )
{
}
template<>
void X::set( int v )
{
}
int main( int, char *[] )
{
X x;
std::string y;
x.set( y );
x.set( 1 );
}
When I link it with g++ 4.3.3 I get an undefined reference to
void X::set<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >).
Which is basically an undefined reference to void X::set( std::string ).
So my question is, why doesn’t the compiler use the specialisation with const std::string & ?
If I explicitly call x.set< const std::string & >( y ) then this compiles and links fine.
Probably this article
will explain the situation.
You might expect the specialization
void X::set( const std::string& )will participate in overloadresolution.
However, surprisingly,
specializations don’t participate in overload resolution.
In the call
x.set( y ), the compiler deduces the type ofTin the primarytemplate from the argument
ywith a typestd::string.So, the compiler deduces that
Tisstd::string, then searches matchingspecialization.
However, since
std::stringandconst std::string&are different types,the compiler selects primary template in the end.
After proper primary template is selected, the matching specialization is
selected in the same manner as the case for class template.
The reason that the specialization
set( const std::string& )isn’t selectedis similar to that the specialization
A< std::string >isn’t selectedin the following code: