可变参数模板和省略号有什么区别?

Edu*_*yan 18 c++ templates overloading language-lawyer c++11

我知道标题没有多大意义,但代码将解释我的问题。

template<typename T>
void foo(T...) {std::cout << 'A';}

template<typename... Ts>
void foo(Ts...) {std::cout << 'B';}

int main(){  
   foo(1); 
   foo(1,2);
}
Run Code Online (Sandbox Code Playgroud)

在阅读续篇之前尝试猜测这个程序的输出:

所以输出是 AB

谁能解释为什么 1 个参数函数优先考虑省略号,而 2 个参数优先考虑可变参数模板?

And*_*dyG 14

甚至第一个过载是什么?

根据[dcl.fct]

在语法正确且“...”不属于抽象声明符的情况下,“, ...”与“...”同义。

所以这使得第一个重载成为一个可变参数函数(也恰好是模板化的),相当于:

template<typename T>
void foo(T, ...) {std::cout << 'A';}
Run Code Online (Sandbox Code Playgroud)

(注意cppreference页面包含一个示例,其中第一个参数和可变参数之间的逗号类似省略。)

为什么我们会看到那个特定的输出?

当您传递两个参数时,编译器更喜欢另一个重载,因为在重载解析期间,省略号转换序列在对可行重载进行排序时总是排在最后。( [over.ics.rank] )

当传递单个参数时,编译器更喜欢第一个重载,因为很简单,省略号不匹配(因为没有匹配项)。这可以防止将函数视为省略号转换序列。然后发生正常函数模板排名,并确定此函数比可变参数([temp.deduct.partial])更专业


Jar*_*d42 5

遵循overload_resolution#Best_viable_function

  • 对于f(1)

    我们虽然去了 5)

    或者,如果不是这样,F1 和 F2 都是模板特化,根据模板特化的偏序规则,F1 更特化

    Function_template_overloading

    在两个方向上考虑每个 P 和 A 之后,如果对于所考虑的每种类型,[..]

    在平局的情况下,如果一个函数模板有一个尾随参数包而另一个没有,则认为省略参数的函数模板比​​空参数包的函数模板更专业。

    所以省略号函数template<typename T> void foo(T,...)被认为比 variadic 更专业template<typename ...Ts> void foo(Ts...)

  • 为了 f(1, 2)

    阅读Ranking_of_implicit_conversion_sequences

    在可变参数版本中,我们有精确匹配,而省略号有省略号转换序列

    所以可变参数是更好的匹配。

  • @Ayxan:我会说混淆而不是混淆。 (3认同)
  • OP 可能用于以这种方式使用省略号。与运算符优先级一样,有些被认为是已知的,然后添加括号可能被认为是多余的,只需添加详细信息(`3 + (4 * 5)`、`(a + b) &lt; c`),对于其他省略“额外”括号的情况是不安全和混淆的(`a || b1 &amp;&amp; b2`)。知道什么让别人感到困惑并不总是那么容易(特别是当我们已经处于上下文中时)。 (2认同)