函数模板显式特化声明中尾随模板参数的推导(无函数参数推导)

Deduction of trailing template-argument in declaration of explicit specializations of function templates (no function arg. deduction)

(这个问题是 评论中讨论的分支。)


[temp.expl.spec]/10 表示 [强调 我的]:

A trailing template-argument can be left unspecified in the template-id naming an explicit function template specialization provided it can be deduced from the function argument type. [ Example:

template<class T> class Array { /* ... */ };
template<class T> void sort(Array<T>& v);

// explicit specialization for sort(Array<int>&)
// with deduced template-argument of type int
template<> void sort(Array<int>&);

 — end example ]

这显然适用于下面示例中 foo(T) 的(完全)显式特化:

#include <iostream>

template <typename T>
void foo(T) { std::cout << "primary\n"; }

template <>
void foo(int) { std::cout << "int\n"; }
// OK   ^<int> deduced from template argument deduction
//             in this _declaration_, as of [temp.expl.spec]/10

int main()
{
    const int a = 42;
    foo(a);  // int
    // OK, <int> deduced from template argument deduction.
}

但是,对于 clang 和 GCC,对于我测试过的所有各种 ISO C++ 版本,这也适用于函数模板中没有函数参数的示例,以及它的类型模板参数仅作为函数模板的 return 类型存在:

#include <iostream>

template <typename T>
T bar() { std::cout << "primary\n"; return 0; }

template <>
int bar() { std::cout << "int\n"; return 42; }
//     ^<int> deduced?

int main()
{
    (void)bar<int>();  // int
    //        ^^^ OK, no template argument deduction.
}

我对上面引述中的术语 “演绎” 有点困惑,因为它,afaics,并不是指典型意义上的演绎(称为 site/instantiation) 模板参数推导,而是在专业化声明的上下文中推导。

问题:

我认为 [temp.expl.spec]/10 在说 "function argument type" 而不是 "function type" 时用词不当一个函数模板。 (当然,函数参数类型可能不止一种。)

不同的上下文指定不同的依赖类型集 (P) 和指定的(通常是非依赖的)类型集 (A) 用于模板参数推导,如小节 [temp.deduct.call], [temp.deduct.funcaddr], [temp.deduct.conv], [temp.deduct.partial], and [temp.deduct.decl].

最熟悉的可能是第一个,[temp.deduct.call]:调用函数模板时,函数参数类型为P,参数表达式的类型为A,但return类型的函数模板不参与

最后一个,[temp.deduct.decl],涵盖了函数模板显式特化的匹配(如您的示例)、函数模板的显式实例化以及函数特定特化的友元声明模板。对于这些情况,整个函数类型为 PA。由于函数类型算作由 return 类型和参数类型形成的 "compound type",类似于指针类型 T* 由类型 T 形成的方式,这允许推导在参数类型中 return 类型 and/or 中出现的模板参数的数量。