Специализация шаблона со ссылкой на const

Я пытаюсь понять, как работают специализации шаблонов. У меня есть следующий шаблон функции:

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 *&.

Разве константа в списке параметров шаблона функции не всегда является константой низкого уровня?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
0
403
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Шаблоны — это не простой механизм замены токенов, как макросы. 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 Перегрузка функций или эта статья (старый, но по-прежнему верный), чтобы узнать больше об этом…

Другие вопросы по теме