11

Почему выход этого code:Специализируется шаблон функции для ссылочных типов

#include <iostream> 
template<typename T> void f(T param) 
{ 
    std::cout << "General" << std::endl ; 
} 
template<> void f(int& param) 
{ 
    std::cout << "int&" << std::endl ; 
} 

int main() 
{ 
    float x ; f (x) ; 
    int y ; f (y) ; 
    int& z = y ; f (z) ; 
} 

является

Общие
Общие
Общие

Третий один surprizing потому функция была специализированной точно f или int&

Редактировать: Я знаю, что перегрузка может быть правильным решением. Я просто хочу изучить логику этого.

+0

Может быть, потому что сопзЬ ИНТ является предпочтительным и для Int &? – Septagram

+0

@ Сепараграмма: const int &? –

+0

Я не знаю, помогает ли это, но если вы измените шаблон, чтобы принять 'T &', то оба 'f (y)' и 'f (z)' вызывают 'int &' версию. –

ответ

8

Тип выражения y и выражение z: int. Ссылка, отображаемая в выражении, не будет содержать ссылочный тип. Вместо этого тип выражения будет ссылочным типом, при этом выражение будет lvalue.

В обоих случаях T выведено на int, и поэтому явная специализация не используется вообще.

Важно отметить (кроме того, что вы действительно должны использовать перегрузку, как сказал другой парень), заключается в том, что у вас есть параметр без ссылки в вашем шаблоне. Прежде чем вычесть T против типа аргумента, тип аргумента будет преобразован из массивов в указатель на их первый элемент (для функций аргументы будут преобразованы в указатели функций). Таким образом, шаблон функции с необязательным параметром функции не позволяет точно вычитать.

+1

+1 (и спасибо за обнаружение ошибки в моем собственном ответе, пока я нахожусь) –

1

Ссылка - это просто псевдоним, а не тип. Поэтому, когда вы вызываете f (z), он соответствует первой версии с T = int, что является лучшим вариантом, который T = int &. Если вы измените T на T &, то аргументы int и int & вызовут вторую версию.

+0

Если я изменяю T на T &, у меня есть ошибка компилятора, когда 'f (2)' или 'f (" text ")' –

+0

Измените его на const. –

0

Я знаю, что это не ответ, но, ИМХО, вы можете попробовать это с чертой, как подход в структуры:

template<typename T> 
struct value_traits 
{ 
    static void print(){std::cout << "General" << std::endl ;} 
}; 

template<> 
struct value_traits<const long> 
{ 
    static void print(){std::cout << "const long" << std::endl ;} 
}; 

template<> 
struct value_traits<std::vector<unsigned char> > 
{ 
    static void print(){std::cout << "std::vector<unsigned char>" << std::endl ; } 
}; 

template<> 
struct value_traits<const int> 
{ 
     static void print(){std::cout << "const int" << std::endl ;} 
};