"template"关键字限定符是否会导致代码成功编译,但不同?
Can `template` keyword qualifier cause code to compile successfully, but differently?
我正在阅读有关模板关键字限定符的信息(https://www.ibm.com/support/knowledgecenter/SSPSQF_9.0.0/com.ibm.xlcpp111.aix.doc/language_ref/keyword_template_qualifier.html,以及我必须在哪里以及为什么必须放置"模板"和"类型名称"关键字?),但仍然有一些东西让我感到困惑。
是否有可能拥有这样的代码,成功编译,但导致两个不同的操作?
SomeObjectInstance.template some_function();
SomeObjectInstance.some_function();
是的,你可以写这样的东西,让它格式正确,并给出不同的结果。基本上是你自己的例子:
#include <iostream>
struct foo {
template <int = 0>
void some_function() { std::cout << "templaten"; }
void some_function() { std::cout << "non-templaten"; }
};
int main(void) {
foo f{};
f.some_function();
f.template some_function();
return 0;
}
将打印您期望的内容。当编译器看到第一次调用some_function
时,它必须检查它是否可以合成模板重载。它可以,因为我们为模板参数提供了一个默认参数。然后它对两个候选者进行重载解析,并且 [over.match.best]/1 告诉我们
根据这些定义,可行的函数 F1 被定义为 如果对于所有参数,则比另一个可行的函数 F2 更好的函数 i, ICSi(F1) 不是比 ICSi(F2) 更糟糕的转换序列,然后
F1 不是函数模板专用化,
- F2 是函数模板专用化,或者,如果不是,
我们有两个同样好的隐式转换序列(空),并且该项目符号明确表示非模板版本是更好的候选者,因为其他一切都相同。
但是当使用template
关键字时,我们遵循 [temp.names]/5:
以关键字模板为前缀的名称应为模板 ID 或 名称应指类模板或别名模板。
模板 id 在第 1 段中有以下语法生成:
simple-template-id: template-name < template-argument-list > template-id: simple-template-id operator-function-id < template-argument-list > literal-operator-id < template-argument-list >
模板参数列表在上述所有内容中都是可选的。但精明的读者会注意到尖括号没有被指定为可选。似乎我们必须将模板成员函数命名为some_function<>
.但幸运的是,我们正在做一个函数调用。模板参数推导正在发生,正是由于这个原因,可以应用 [temp.arg.explicit]/3:
。如果可以推导出所有模板参数,则可以全部省略;在这种情况下,也可以省略空模板参数列表
<>
本身。...
所以我们确实可以写f.template some_function();
,它必须引用一个模板,根据[temp.names]/5。这应该具有从考虑中消除非模板重载的效果。