Рассмотрим код:
#include <iostream>
template <typename T>
void f(T)
{
std::cout << "Version 1" << std::endl;
}
template <typename T>
void f(T *)
{
std::cout << "Version 2" << std::endl;
}
template <>
void f<>(int *)
{
std::cout << "Version 3" << std::endl;
}
int main()
{
int *p = nullptr;
f(p);
return 0;
}
Этот код выведет Version 3
. Происходит то, что правила перегрузки функций рассматривают первые две версии void f
(третья версия является специализацией и не участвует в перегрузке) и решают, что вторая версия является лучшей версией. Как только это решение будет принято, мы увидим, существуют ли какие-либо специализации для второй версии. Существует, и мы используем его.
Тогда мой вопрос: как компилятор узнал, что моя явная специализация была специализацией второй перегрузки, а не первой? Я не предоставил ему параметр шаблона, чтобы он мог сделать этот выбор. Это просто тот случай, когда решение о том, какая функция должна специализироваться, следует тому же / тому же правилу, что и решение о том, какую перегрузку вызывать (если она вызывала функцию)? Это имело бы какой-то смысл ...