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 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;
}