asc*_*ler 5 c++ templates language-lawyer
是什么决定两个函数模板声明是声明相同的模板,还是相同名称的重载?
答案的开头是在3.5p9中找到的:
如果两个名称相同(第3条)并且在不同范围中声明,则它们应表示相同的变量,函数,类型,枚举器,模板或名称空间(如果
两个名称都具有外部链接,或者两个名称都具有内部链接,并且在同一翻译单元中声明;和
这两个名称都引用相同名称空间的成员,或者引用同一类的成员,而不是通过继承。和
当两个名称都表示函数时,这些函数的参数类型列表(8.3.5)相同;和
当两个名称都表示功能模板时,签名(14.5.6.1)相同。
非模板非成员函数的签名为(1.3.17):
签名
<功能>名称,参数类型列表(8.3.5)和封闭的名称空间(如果有)
[ 注意:签名用作名称处理和链接的基础。- 尾注 ]
在8.3.5p5节中已经定义了两次提到的parameter-type-list。本段描述了如何从声明的类型调整函数参数的实际类型,如何用指针替换数组和函数,以及如何舍弃顶级cv-qualifiers。然后,
转换后的参数类型以及省略号或功能参数包的存在或不存在的结果列表就是函数的parameter-type-list。
因此,在非模板的情况下,parameter-type-list显然是类型的概念性语义列表(可能还有一个奇特的结尾),而不是标记序列或语法构造。正如我们所期望的,以下内容违反了ODR,因为这两个定义定义了相同的功能:
void f(int, int*) {}
void f(int p, decltype(p)*) {}
Run Code Online (Sandbox Code Playgroud)
在模板的情况下,我们有(1.3.18):
签名
<功能模板>名称,参数类型列表(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
Run Code Online (Sandbox Code Playgroud)
g ++ -std = c ++ 0x版本4.6.3抱怨定义#1和#2定义了相同的函数,但是毫无疑问接受#1和#3作为重载。(它也认为#3比#1更专业,并且没有办法调用#1,但这是一个切线的问题。)#2和#3之间的主要区别在于q类型相关,而与类型p无关。因此,我猜想在decltype(q)模板实例化之前无法确定的含义?标准是否保证了这种行为?
对于功能模板,必须允许parameter-type-list的含义包括尚未被实例化替代的模板参数,并因此包括从属名称及所有其他内容。但是,如果可能的话,要知道两个声明是否等效就很棘手。
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
Run Code Online (Sandbox Code Playgroud)
而第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>);
Run Code Online (Sandbox Code Playgroud)
但这不适用于g上面的示例函数。 T*并且decltype(q)*在类型的等效性的某种类似定义下可以被认为在功能上是等效的,但是14.5.6.1节仅说明替换表达式,而不是类型。
该标准对类型有一个安静的、未明确定义的等价规则,该规则主要基于限定名称的语法,但对于模板参数来说,是参数列表中的位置以及该列表的嵌套深度(即,它是否是成员模板之一)或封闭类模板的)。
typedef 会记住特定的依赖类型。然而 14.4p2 的 decltype 类型是一种不同的类型,并不与 T 等效。