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.
It's altogether incorrect syntax. When specializing templates, you have to include the angle brackets with the types you are specializing for. E.g.:
template<typename T>
struct X { ... };
template<>
struct X<int> { ... };
// ^^^^^ see, there have to be angle brackets after the identifier
So
template<>
void X::set(std::string &) { ... }
is not specializing anything, it is implementing
class X {
template<>
void set(std::string &) { ... }
};
which is altogether different function. What I don't understand is why gcc didn't produce an error because the class does not have that member.
Now even if you used the supposedly-correct syntax, it wouldn't be correct, because, as already answered by Tom, you can't specialize functions (just overload with non-template version). In C++03, that is; it is allowed in C++0x.
Reverting back to original proposition after compilation:
Your method signature for string should not be a reference. Should be:
template<>
void X::set( const std::string v )
{
}
This is because in your template definition you have specified T paramater
and not T& paramater
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With