Проблема "неоднозначной специализации шаблона"
В настоящее время я портирую кучу кода, который ранее был скомпилирован только с Visual Studio 2008. В этом коде есть такая схема:
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 );
}
Как правило, существует множество специализаций шаблонной функции с различными типами возврата, которые вызываются следующим образом:
int i = convert<int>( szInt );
Проблема состоит в том, что эти шаблонные специализации приводят к "неоднозначной шаблонной специализации". Если бы это было что-то помимо возвращаемого типа, которое отличало бы эти специализации функции, я бы, очевидно, мог просто использовать перегрузки, но это не вариант.
Как я могу решить эту проблему, не меняя все места, где вызываются функции преобразования?
Обновление Я добавил эти две универсальные шаблонные специализации, которые я пропустил в первый раз. Мне стыдно сказать, я не уверен насчет мотивации для второго, но первый из-за того, что функция convert используется во многих местах, где строковые данные передаются как пустота *. Я не могу проверить это с GCC прямо сейчас, но я подозреваю, что это может быть проблемой.
Обновление 2 Вот полный файл cpp, который будет воспроизводить это. Если вы удалите обе функции общего назначения, он скомпилируется. Если вы позволите одному из них остаться, возникнет неоднозначная ошибка специализации шаблона.
#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;
}
1 ответ
По-видимому return convert<T>( static_cast<const char*>( s ));
(или что-то еще, чего я не вижу) побуждает компилятор создавать экземпляр шаблона T convert( const char * s )
для T=float. Затем, когда вы пытаетесь специализировать его позже, он терпит неудачу, потому что версия шаблона уже существует.
Когда я переместил inline float convert<float>( const char * s )
до преобразователей общего назначения (сразу после const char*
функция шаблона), я смог успешно скомпилировать с g++ 4.2.