"template"关键字限定符是否会导致代码成功编译,但不同?



我正在阅读有关模板关键字限定符的信息(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。这应该具有从考虑中消除非模板重载的效果。

最新更新