У меня есть следующий набор шаблонов:
//1
template< typename T > void funcT( T arg )
{
std::cout<<"1: template< typename T > void funcT( T arg )";
}
//2
template< typename T > void funcT( T * arg )
{
std::cout<<"2: template< typename T > void funcT( T * arg )";
}
//3
template<> void funcT< int >( int arg )
{
std::cout<<"3: template<> void funcT< int >( int arg )";
}
//4
template<> void funcT< int * >( int * arg )
{
std::cout<<"4: template<> void funcT< int *>( int * arg )";
}
//...
int x1 = 10;
funcT( x1 );
funcT( &x1 );
Может кто-то объяснять почему funcT( x1 );
вызовы функционируют № 3 и funcT( &x1 );
вызовы функционируют № 2, но не № 4 как ожидалось?
Я уже прочитал эту статью http://www.gotw.ca/publications/mill17.htm, в которой говорится, что "разрешение перегрузки игнорирует специализации и воздействует на основные шаблоны функций только". Но согласно этой логике funcT( x1 );
должен назвать функциональный № 1, не № 3. Я смущен.
Функции №3 и №4 являются специализациями №1, а не №1 и №2 соответственно.
Это означает, что ваш компилятор сначала выберет между №1 и №2. Когда он выбрал # 1 как наиболее подходящий для funcT (x1), он затем выбирает специализацию # 3. Для funcT (& x1) он выбирает № 2 как наиболее подходящий и не находит специализаций.
Написав # 4 как
template<> void funcT<>( int * arg )
, он станет специализацией # 2, и вы получите ожидаемый результат, что # 4 вызывается для funcT (& x1).
Другой вариант - просто написать
void funcT(int *arg)
, поскольку вместо шаблонных версий всегда будут выбираться обычные функции, если они совпадают.