函数模板签名
Function template signatures
是什么决定两个函数模板声明是声明同一个模板,还是同名的重载?
答案的开头见3.5p9:
非模板非成员函数的签名为(1.3.17):在不同作用域声明的相同的两个名称(第3条)应表示相同的变量、函数、类型、枚举数、模板或命名空间,如果
两个名字都有外部链接,否则两个名字都有内部链接,并在同一个翻译单元中声明;和
两个名字都指向同一个命名空间的成员,或者指向同一个类的成员(不通过继承);和
当两个名字都表示函数时,函数的参数类型列表(8.3.5)是相同的;和
当两个名字都表示函数模板时,签名(14.5.6.1)是相同的。
已经提到两次的形参type-list在第8.3.5p5节中定义。这段描述了如何从声明的类型调整函数参数的实际类型,用指针替换数组和函数,以及丢弃顶级cv-限定符。然后,& lt; function>名称、参数类型列表(8.3.5)和封闭命名空间(如果有的话)
[注意:签名被用作名称修改和链接的基础。——结束说明]
因此,在非模板的情况下,形参-type-list显然是类型的概念语义列表(可能加上一个花哨的结尾),而不是标记序列或语法结构。正如我们所料,下面的代码违反了ODR,因为这两个定义定义了同一个函数:转换后的形参类型和省略号或函数形参包的存在与否的结果列表是函数的形参类型列表。
void f(int, int*) {}
void f(int p, decltype(p)*) {}
在模板的例子中,有(1.3.18):
& lt; template>函数;名称、形参类型列表(8.3.5)、封闭命名空间(如果有的话)、返回类型和模板形参列表
现在考虑:
template<typename T> void g(int, int*, T, T*) {} // #1
// template<typename T> void g(int p, decltype(p)*, T, T*) {} // #2
template<typename T> void g(int, int*, T q, decltype(q)*) {} // #3
c++ -std=c++0x版本4.6.3抱怨定义#1和#2定义了相同的函数,但是接受#1和#3作为重载没有问题。(它还认为#3比#1更专业,而且没有办法调用#1,但这是一个切题的问题。)#2和#3的主要区别在于,q
是类型依赖的,而p
不是。所以我猜decltype(q)
的含义不能确定,直到模板实例化?这种行为是否受到标准的保证?
对于函数模板,必须允许形参类型列表的含义包含尚未被实例化取代的模板形参,因此包含依赖名称等。但是,如果可能的话,要知道两个声明是否等价就变得很棘手了。
14.5.6.1第5-6段解决了类似的问题,其中定义了等效表达式和等效函数模板声明(相同的令牌序列,除了不同的声明可以为模板参数使用不同的标识符),函数等效表达式和函数等效函数模板声明(实例化后相同),要求:如果一个程序包含函数模板的声明,这些声明在功能上等价但不等价,则该程序是病态的;不需要诊断。
第5段中的一个例子演示了安全等效的函数模板:
template <int I, int J> void f(A<I+J>); // #1
template <int K, int L> void f(A<K+L>); // same as #1
和第7段中的一个例子演示了对该规则的违反:
// Ill-formed, no diagnostic required
template <int I> void f(A<I>, A<I+10>);
template <int I> void f(A<I>, A<I+1+2+3+4>);
但这不适用于上面的g
函数示例。在类似的类型等价的定义下,T*
和decltype(q)*
可能被认为在功能上是等价的,但是第14.5.6.1节只说明了表达式的替换,而不是类型的替换。
标准对类型有一个没有明确定义的等价规则,该规则主要基于限定名的语法,但对于模板形参是形参列表中的位置和该列表的嵌套深度(即它是成员模板中的一个还是封闭类模板中的一个)。
特定的依赖类型由typedef记住。然而,14.4p2中的decltype类型是一个不同的类型,不等同于t。
- 当函数模板参数是具有默认参数的类模板时,函数模板参数的推导如何执行
- 将重载的成员函数传递给函数模板
- C++17中函数模板中的静态数组初始化(MSVC 2019)
- 为什么 gcc 和 clang 为函数模板的实例化生成不同的符号名称?
- 具有常量引用参数的函数模板专用化
- std::span<const T> 作为函数模板中的参数
- 如何编写一个完美的缩写函数模板?
- 仅在函数模板中为那些定义了函数的类型执行函数
- 如何在C++中伪造虚拟可变参数函数模板?
- 以下代码中的函数模板有什么问题?
- 在 C++20 中是否不再允许在 std 中对程序定义类型的函数模板进行专用化?
- 将显式实例化的函数模板与转换匹配
- 使用定义函数模板别名
- 函数模板返回类型
- C++有什么方法可以在既不调用函数模板也不提供其模板参数的情况下引用函数模板?
- C++ std::functional 中的可变参数函数模板
- 单行函数模板 c++ 的内联性保证
- C++函数模板需要 &for 数组参数
- 概念解析为使用 std::make_signed_t 时意外的函数模板
- 两个函数模板候选项.将一个参数作为引用后,选择不太专业的模板