"Ambiguous template specialization" problem
I'm currently porting a heap of code that has previously only been compiled with Visual Studio 2008. In this code, there's an arrangement like this:
template <typename T>
T convert( const char * s )
{
// slow catch-all
std::istringstream is( s );
T ret;
is >> ret;
return ret;
}
template <typename T, typename T2>
T convert( T2 * s )
{
return convert<T>( static_cast<const char*>( s ));
}
template <typename T, typename T2>
T convert( T2 s )
{
return T( s );
}
template <>
inline int convert<int>( const char * s )
{
return (int)atoi( s );
}
Generally, there are a lot of specializations of the templated function with different return types that are invoked like this:
int i = convert<int>( szInt );
The problem is, that these template specializations result in "Ambiguous template specialization". If it was something besides the return type that differentiated these function specializations, I could obviously just use overloads, but that's not an option.
How do I solve this without having to change all the places the convert functions are called?
Update I added these two catch-all template specializations that I omitted the first time around. I am embarassed to say, I am unsure about the motivation for the second one, but the first one is due to the convert function being used a lot of places where string data is passed as a void *. I am unable to check it with GCC right now, but I suspect that these might be the problem.
Update 2 Here's the complete cpp file that will reproduce this. If you remove both of the "general purpose" functions, it will compile. If 开发者_JS百科you let either of them stay, the ambiguous template specialization error will result.
#include <iostream>
#include <sstream>
template <typename T>
T convert( const char * s )
{
// this is a slow slow general purpose catch all, if no specialization is provided
std::istringstream is( s );
T ret;
is >> ret;
return ret;
}
// general purpose 1
template <typename T, typename T2>
T convert( T2 * s )
{
return convert<T>( static_cast<const char*>( s ));
}
// general purpose 2
template <typename T, typename T2>
T convert( T2 s )
{
return T( s );
}
// Type specialized
template <>
inline float convert<float>( const char * s )
{
return (float)atof( s );
}
int main( int argc, const char * sz[] )
{
return 0;
}
Apparently return convert<T>( static_cast<const char*>( s ));
(or something else I can't see) is inducing the compiler to create a template instantiation of T convert( const char * s )
for T=float. Then when you try to specialize it later, it fails because the template version already exists.
When I moved the inline float convert<float>( const char * s )
before the general purpose converters (immediately after the const char*
template function), I was able to compile successfully with g++ 4.2.
精彩评论