c++ - 为什么在具有相同签名的模板和非模板函数之间进行选择时没有歧义?

标签 c++ templates language-lawyer

以下代码传递断言:

int foo() { return 1; }

template<typename T>
int foo() { return 2; }

int main() {
  assert( 1 == foo() );
  assert( 2 == foo<int>() );
  return 0;
}

但据我了解,根据 C++11 标准的第 13.3.3/1 段:

[...] Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then [...] F1 is a non-template function and F2 is a function template specialization [...]

不应该,因为签名最终是相同的。那么为什么foo<int>()时没有歧义呢?叫做?我错过了什么?

最佳答案

你引用的文字比较密集;你必须仔细阅读它。 “如果对于所有参数 i,ICSi(F1) 不是比 ICSi(F2) 更差的转换序列,则 F1 优于 F2”——这里是正确的,因为两个转换序列是相同,因此,两者都不另一个差。所以现在你转到最后一部分:“然后 F1 是一个非模板函数,F2 是一个函数模板特化”。没错,所以 F1 比 F2 更匹配。替换 foo()foo<int>()对于 F1 和 F2,规则分别表示 foo()是比 foo<int>() 更好的匹配.

糟糕,我回答错了问题。正如评论所指出的,问题是,为什么显式调用 foo<int>()不解决 foo() ?答案是foo<int>()是对显式模板实例化的调用,而不是对重载函数的调用。考虑:

template <class Ty>
void f(Ty) { }

void f(int);
void g(int);

f(3.14);      // calls f<double> (overloaded function call)
f(1);         // calls f(int) (overloaded function call)
f<int>(3.14); // calls f<int> (explicit call of template instantiation)
g(3.14);      // calls g(int)

在这个例子中,f<int>是模板特化的名称。它不是名为f 的通用函数,因此无需考虑重载,就像对 g(3.14) 的调用一样.

关于c++ - 为什么在具有相同签名的模板和非模板函数之间进行选择时没有歧义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54671044/

相关文章:

c++ - 非原始盒装类型的运算符

c# - C# 规范 7.16.2.5 中的不一致

c++ - 从未使用过的无效默认成员初始值设定项

c++ - 在线程之间共享一个文件描述符

c++ - 创建顺序文件

c++ - Qt自定义QPushButton不在布局上显示

c++ - 将数组参数传递给主函数索引始于1 c++

excel - 在 Excel VBA 中获取使用 "Save As"时使用的路径(从模板创建的文档!)

c++ - 试图更好地理解 std::forward、std::move

c++ - 是否未指定在未评估的上下文中实例化模板/lambda?