"специализации не участвуют в перегрузке" - PullRequest
4 голосов
/ 04 февраля 2020

Что на самом деле означает "Специализация шаблонов функций Не принимайте участия в разрешении перегрузки. Учитываются только базовые шаблоны"

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

// Base template
template <typename T>
T max(T a, T b) {
    std::cout << "Base Template" << std::endl;
    return (a>b) ? a : b;
}

// Specialization for int
template<>
int max<int>(int a, int b) {
    std::cout << "int specialization" << std::endl;
    return (a>b) ? a : b;
}
max(2,3);// prints "int specialization"

Глядя на другой StackOverflow, связанный с этой концепцией, я нашла еще один пост, в котором можно доказать, что специализации не участвуют в перегрузке он показал следующий пример, в котором специализированная версия не была вызвана, и я все еще не уверен, почему она не была вызвана. Но кроме этого, в этом примере аргумент не имеет имени переменной, все еще нет ошибки компиляции или времени выполнения для части (char const* const&)

template<typename T>
void f(T const&)
{
        std::cout<<std::endl<<"Base Template for f() called\n";
}

template<>
void f<char const * const &>(char const* const&)
{
        std::cout<<std::endl<<"Specialized f() for char const* called\n";
}
f("Hello") //prints "Base Template for f() called"

В целом, я все еще пытаюсь понять Выясните значение «Специализация шаблонов функций. Не принимайте участия в разрешении перегрузки. Рассматриваются только базовые шаблоны», если кто-то может объяснить с помощью примера (и почему базовый шаблон был вызван во втором примере). А во-вторых, почему во втором примере программа скомпилирована и работает без имени переменной.

1 Ответ

5 голосов
/ 04 февраля 2020

Если вы попробуете max(5, 7.0), вы получите ошибку, даже если double конвертируется в int. Таким образом, специализация int max не участвует в разрешении перегрузки.

template <typename T>
T max(T a, T b);

template <>
int max(int a, int b);

max(5, 7.0); // compiler error (no matching function)

Однако, если бы вы использовали обычную функцию вместо специализации шаблона, вы бы получили ожидаемое поведение.

template <typename T>
T max(T a, T b);

int max(int a, int b);

max(5, 7.0); // this is fine

Когда компилятор рассматривает типы аргументов (int, double), он ищет функции в следующем порядке (это немного сложнее, чем в ADL и других деталях):

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

Обратите внимание, что я не упомянул специализации шаблонов функций. Если найден соответствующий шаблон функции, будет использоваться точно соответствующая специализация (поэтому, если вы специализировались на double s, но вы вызываете int s, специализация не будет использоваться), в противном случае будет использоваться базовый шаблон.

Для лучшего объяснения см. cppreference .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...