专门针对哪个函数重载的规则

Rule for which function overload to specialize

考虑代码:

#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 的前两个版本(第三个版本是特化,不参与重载),并决定第二个版本是更好的版本。一旦做出决定,我们就会查看第二个版本是否存在任何专业化。有,我们用。

那么我的问题是:编译器如何知道我的显式特化是对第二个重载的特化而不是对第一个重载的特化?我没有为它提供模板参数来做出选择。决定专门化哪个函数遵循与决定调用哪个重载(如果它正在调用函数)相同的规则 similar/the 只是这种情况吗?这有点道理...

template_argument_deduction#Explicit_instantiation

中有那个例子

Template argument deduction is used in explicit instantiations, explicit specializations, and those friend declarations where the declarator-id happens to refer to a specialization of a function template (for example, friend ostream& operator<< <> (...)), if not all template arguments are explicitly specified or defaulted, template argument deduction is used to determine which template's specialization is referred to.

P is the type of the function template that is being considered as a potential match, and A is the function type from the declaration. If there are no matches or more than one match (after partial ordering), the function declaration is ill-formed:

template<class X> void f(X a);  // 1st template f
template<class X> void f(X* a); // 2nd template f
template<> void f<>(int* a) { } // explicit specialization of f
// P1 = void(X), A1 = void(int*): deduced X = int*, f<int*>(int*)
// P2 = void(X*), A2 = void(int*): deduced X = int, f<int>(int*)
// f<int*>(int*) and f<int>(int*) are then submitted to partial ordering
// which selects f<int>(int*) as the more specialized template