【问题标题】:Variadic function and variadic template overloading lookup可变参数函数和可变参数模板重载查找
【发布时间】:2020-09-18 09:09:22
【问题描述】:

我有一个带有 2 个重载参数的函数

template<typename... Args>
void f(Args&&...) {
    cout << "Args..." << endl;
}
 
void f(...) {
    cout << "..." << endl;
}

有人能解释一下查找是如何工作的吗?在我看来,每个函数的目的都是一样的(除了第一个是 c++ 风格,第二个是 c 风格)。当我调用带有参数的函数时,尽管它们的类型为f(5, "hello")f(5, 10),它始终是可变参数模板(第一次重载),但是当我调用不带参数的函数f() 时,它始终是可变参数函数(第二次重载)。编译器是否有严格的规则来选择正确的函数,其背后的逻辑是什么?

【问题讨论】:

  • 我似乎记得有一个固定的规则,始终将可变参数放在堆的底部。

标签: c++


【解决方案1】:

是的,在 C++ 中有很多关于此的规则。

当编译器遇到像f(5, 10) 这样的调用时,首先会合成一个可行的候选列表,这涉及函数模板的实例化(其中涉及模板参数的deduction)。

然后,如果列表中有多个候选者,则执行overload resolution

一些关键的超载排名规则是:

  • 总是首选更好的匹配(隐式转换最少的那个)。

    • 标准转换优于用户定义的转换,后者优于省略号。
  • 当没有更好的匹配时,首选非模板版本。

所以在f(5, 10)的情况下我们得到

  • f&lt;int,int&gt;(int,int) - 需要 0 次转化,
  • f(...) - 需要 2 个省略号“转换”。

第一个需要较少的转换,所以它赢了。

如果是f(),我们会得到

  • f&lt;&gt;() - 需要 0 次转化,
  • f(...) - 需要 0 次转化。

有歧义,但第一个是模板,所以选择了非模板f(...)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-01
    • 1970-01-01
    • 2017-12-23
    • 2015-05-08
    • 2019-01-03
    • 1970-01-01
    相关资源
    最近更新 更多