首页 > 解决方案 > 可变参数模板和省略号有什么区别?

问题描述

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

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);
}

在继续阅读之前尝试猜测该程序的输出:

所以输出是AB

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

标签: c++c++11templatesoverloadinglanguage-lawyer

解决方案


第一次重载是什么?

[dcl.fct]

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

因此,这使得第一个重载成为可变参数函数(也恰好是模板化的),它等效于:

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

(注意,cppreference页面包含一个示例,在第一个参数和可变参数之间省略了逗号。)

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

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

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


推荐阅读