Я пытаюсь понять, как работают специализации шаблонов. У меня есть следующий шаблон функции:
template <typename T>
void function(const T &t1, const T &t2)
{
std::cout << "in function template: " << t1 << ", " << t2 << std::endl;
}
теперь я хочу специализировать этот шаблон функции на случай, если он вызывается с указателем на const:
// template specialization
template <>
void function(const char *&t1, const char *&t2)
{
std::cout << "in compare template specialization: " << t1 << ", " << t2 << std::endl;
}
но компилятор жалуется, что не может найти шаблон функции для специализации:
In file included from main.cpp:1:0:
template.h:23:5: error: template-id 'compare<>' for 'int compare(const char*&, const char*&)' does not match any template declaration
int compare(const char *&t1, const char *&t2)
^~~~~~~
template.h:10:5: note: candidate is: template<class T> int compare(const T&, const T&)
int compare(const T &t1, const T &t2)
если я специализирую шаблон так (ссылка на указатель CONST на const), он работает:
// template specialization
template <>
int compare(const char * const &t1, const char * const &t2) // now the pointer itself is const
{
std::cout << "in compare template specialization: " << t1 << ", " << t2 << std::endl;
}
Я хочу вызвать функцию с помощью const char *Ptr = "hello world", поэтому я подумал, что выводимый параметр T — это char*, а параметр — const char *&.
Разве константа в списке параметров шаблона функции не всегда является константой низкого уровня?





Шаблоны — это не простой механизм замены токенов, как макросы. const T здесь не означает «вставьте мне что-нибудь T в место сразу после const». Это означает, что тип вещи есть «const что бы ни было T». В случае вашего шаблона функции, если вы установите T как const char*, то тип const T& будет ссылкой на const независимо от того, чем является T, т. е. ссылкой на const char*, который сам является const, то есть const char * const &. На самом деле это ничем не отличается от того, если бы T было именем с заданным типом, а не параметром шаблона, например:
using T = int*;
const T blub = 42; // type of blub is int* const, not const int*
Следовательно,
template <>
void function(const char*& t1, const char*& t2);
не является допустимой специализацией шаблона функции function. Нет T, которые вы могли бы подставить в свой шаблон function, чтобы получить эту подпись. Если заменить параметр const char* на T, то есть форму function<const char*>, то его подпись получится
void function<const char*>(const char * const& t1, const char * const& t2);
Обратите внимание, что вместо того, чтобы полагаться на явную специализацию, если вы хотите, чтобы отдельная функция обрабатывала
void function(const char*& t1, const char*& t2);
случае просто добавьте такую функцию и полагайтесь на перегрузку, чтобы творить чудеса. В общем, когда вы обнаружите, что пишете явные специализации шаблонов функций, есть вероятность, что на самом деле вы хотели просто использовать перегрузку. См. также Специализация шаблона VS Перегрузка функций или эта статья (старый, но по-прежнему верный), чтобы узнать больше об этом…