【问题标题】:How does overload resolution work with variadic functions?重载解析如何与可变参数函数一起使用?
【发布时间】:2014-09-12 15:13:33
【问题描述】:

假设我有这个程序:

#include <iostream>

int fun(...) {return 0;}

template <typename... Args>
int fun(const Args&...) {return 1;}

int fun(const double val) {return 2;}

int main()
{
  std::cout << fun(1,2,3) << fun(1) << fun(1.0);
  return 0;
}

此程序返回以下内容:

112

我明白为什么fun(1.0) 会返回2,因为这是最接近匹配的候选函数,但为什么前两个示例返回1

此页面 (http://en.cppreference.com/w/cpp/language/overload_resolution) 提供了函数重载规则的参考,但似乎没有涵盖可变参数。在哪里可以找到可变参数/模板可变参数函数的重载规则?

【问题讨论】:

  • 一般来说,它是特定类型(double),后跟模板类型。 1 不是double,所以它与Args 中的int 匹配。
  • 从 [over.match] 开始的 20 页有趣的内容涵盖了这一点

标签: c++


【解决方案1】:

为什么前 2 个示例返回 1

C 风格的可变参数函数总是最差匹配(从技术上讲,它涉及“省略号转换序列”,比任何标准或用户定义的转换序列都差)。对于fun(1, 2, 3),使用可变参数函数模板,像往常一样执行推导,得到Args = intintint。这是完全匹配的。

对于fun(1),可变参数函数模板再次获胜,因为Args 被推导出为int,并且我们再次得到完全匹配,这比调用fun(double) 所需的浮点整数转换要好。

在哪里可以找到可变参数/模板可变参数函数的重载规则?

您链接的页面已经涵盖了您需要了解的有关 C 样式可变参数函数的内容:

1) 标准转换序列总是优于用户定义的转换序列或省略号转换序列。

2) 用户定义的转换序列总是优于省略号的转换序列

对于可变参数模板,实际上并没有任何特殊规则;模板参数推导照常执行,然后应用通常的重载解析规则。

在这样的情况下规则变得更加复杂:

template <class... Args> int f(Args...) { return 1; }
template <class T> int f(T) { return 2; }
f(1); // returns 2

在这种情况下,通常的规则无法解决重载问题,但选择了第二个函数,因为它“更专业”。确定一个函数模板何时比另一个更专业的规则(在我看来)很难理解。您可以在 C++11 标准的 §14.5.6.2 [temp.func.order] 中找到它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-07
    • 2013-05-23
    • 2015-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多