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

2024-04-12

(这个问题是评论中讨论的分支变量模板的模板特化和类型推导 https://stackoverflow.com/questions/61384251/template-specialization-of-variable-template-and-type-deduction.)


[温度解释规格]/10 https://timsong-cpp.github.io/cppwp/n4659/temp.expl.spec#10指出[emphasis mine]:

尾随一个模板参数 https://timsong-cpp.github.io/cppwp/n4659/temp.names#nt:template-argument 可以不指定 in the 模板 ID https://timsong-cpp.github.io/cppwp/n4659/temp.names#nt:template-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>&);

—《示例结束》]

这显然适用于(完全)显式专业化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++ 版本,这也适用于函数模板中没有函数参数的示例,并且其类型模板参数仅作为函数模板的返回类型:

#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 并不是指典型(调用站点/实例化)模板参数推导意义上的推导,而是指专门化声明上下文中的推导。

问题:

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

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

不同的上下文指定不同的依赖类型集(P)和指定的(通常是非依赖的)类型(A) 用于模板参数推导,如小节中列出的[临时扣费电话] https://timsong-cpp.github.io/cppwp/n4659/temp.deduct#call, [temp.deduct.funcaddr] https://timsong-cpp.github.io/cppwp/n4659/temp.deduct#funcaddr, [温度扣除转换] https://timsong-cpp.github.io/cppwp/n4659/temp.deduct#conv, [温度扣除部分] https://timsong-cpp.github.io/cppwp/n4659/temp.deduct#partial, and [温度扣除.decl] https://timsong-cpp.github.io/cppwp/n4659/temp.deduct#decl.

最熟悉的案例可能是第一个,[临时扣费电话] https://timsong-cpp.github.io/cppwp/n4659/temp.deduct#call:调用函数模板时,函数参数类型为P参数表达式的类型是A,但函数模板的返回类型不参与。

其中最后一个,[温度扣除.decl] https://timsong-cpp.github.io/cppwp/n4659/temp.deduct#decl,涵盖了函数模板的显式特化的匹配(如您的示例中所示)、函数模板的显式实例化以及支持函数模板的特定特化的友元声明。对于这些情况,整个函数类型是P and A。由于函数类型被视为由返回类型和参数类型形成的“复合类型”,类似于指针类型T*由类型形成T,这允许推断出现在返回类型和/或参数类型中的模板参数。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐