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

dfr*_*fri 5 c++ templates template-specialization language-lawyer

(这个问题是从Template specialization of variable template and type deduction的评论中的讨论的一个分支。)


[temp.expl.spec]/10指出 [强调我的]:

尾随 模板参数 可以模板 id 中未指定, 命名显式函数模板特化,前提是它可以从函数参数类型中推导出来。[?例子:

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>&);
Run Code Online (Sandbox Code Playgroud)

?—?结束示例?]

这显然适用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.
}
Run Code Online (Sandbox Code Playgroud)

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

#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.
}
Run Code Online (Sandbox Code Playgroud)

我对上面引用中的术语“推导”有点困惑,因为它,afaics,不是指典型(调用站点/实例化)模板参数推导意义上的推导,而是在上下文中的推导专业化声明。

题:

  • ISO C++ 标准在哪里涵盖了在显式函数模板特化声明中的尾随模板参数,其中模板参数仅作为返回类型出现,实际上可以省略(推导)?

asc*_*ler 4

我认为 [temp.expl.spec]/10 在说“函数参数类型”而不仅仅是“函数类型”时有不好的措辞,这实际上是在模板参数推导中用于函数模板的显式特化的。(当然,函数参数类型可能不止一种。)

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

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

最后一个[temp.deduct.decl]涵盖了函数模板的显式专业化的匹配(如您的示例中所示)、函数模板的显式实例化以及与函数模板的特定专业化友好的友元声明。对于这些情况,整个函数类型是PA。由于函数类型被视为由返回类型和参数类型形成的“复合类型”,类似于从T*type 形成指针类型的方式T,这允许推导出现在返回类型和/或参数类型中的模板参数。