可变参数模板和省略号有啥区别?
Posted
技术标签:
【中文标题】可变参数模板和省略号有啥区别?【英文标题】:What is the difference between variadic template and ellipsis?可变参数模板和省略号有什么区别? 【发布时间】:2020-09-09 05:56: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);
在阅读续篇之前尝试猜测这个程序的输出:
所以输出是AB
谁能解释为什么 1 个参数函数优先考虑省略号,而 2 个参数优先考虑可变参数模板?
【问题讨论】:
你确定第一个函数模板编译了吗? @IgorR。 gcc.godbolt.org/z/67Dgk8 @Ayxan 我会说这是一个奇怪的 gcc 错误,但 clang 也可以编译它......令人兴奋。template<typename... Ts> void foo(Ts......)
更“有趣”,请阅读 foo(Ts..., ...)
。
@Jarod42 现在只需要解释为什么第一次调用选择了这个重载。
【参考方案1】:
什么是第一个重载?
每[dcl.fct]
语法正确且“...”不属于 抽象声明符,“, ...”与“...”同义。
因此,这使得第一个重载成为可变参数函数(也恰好是模板化的),相当于:
template<typename T>
void foo(T, ...) std::cout << 'A';
(注意,cppreference 页面包含一个示例,其中第一个参数和可变参数之间的逗号省略了类似的省略号。)
为什么我们会看到特定的输出?
当您传递两个参数时,编译器更喜欢其他重载,因为在重载解析期间,在对可行重载进行排序时,省略号转换序列总是排在最后。 ([over.ics.rank])
当传递单个参数时,编译器更喜欢第一个重载,因为简单来说,省略号不匹配(因为没有什么可以匹配)。这可以防止该函数被视为省略号转换序列。然后进行正常函数模板排名,并确定此函数比可变参数更专业([temp.deduct.partial])
【讨论】:
请注意,您可以引用一个特定的句子,这里可能更方便:dcl.fct/4/8。 @DanielLangr:谢谢我不知道 是的,它是一个可变参数函数,但 OP 已经知道这一点。他在问为什么第二个调用使用可变参数函数模板而不是 C 风格的可变参数函数。 @Sebastian Redl 可变参数函数总是最差的匹配。所以问题可能是为什么第一个调用使用它。 它确实在没有第一个函数gcc.godbolt.org/z/bhsmzb的情况下编译【参考方案2】:关注overload_resolution#Best_viable_function
对于f(1)
,
我们通过 5)
或者,如果不是这样,F1 和 F2 都是模板特化,根据模板特化的偏序规则,F1 更加特化
来自Function_template_overloading
在两个方向上考虑每个 P 和 A 之后,如果对于所考虑的每种类型, [..]
在平局的情况下,如果一个函数模板有一个尾随参数包而另一个没有,则认为带有省略参数的模板比带有空参数包的模板更专业。
因此省略号函数template<typename T> void foo(T,...)
被认为比可变参数template<typename ...Ts> void foo(Ts...)
更专业。
为f(1, 2)
阅读Ranking_of_implicit_conversion_sequences
在可变参数版本中我们有完全匹配,而省略号有省略号转换序列
所以可变参数更好匹配。
【讨论】:
虽然这确实解释了重载解决方案 (+1
),但我认为为了完整起见,您还应该提及为什么第一个函数是 C 风格的可变参数函数。 OP 似乎没有意识到这一点。
@Ayxan:我没有看到任何来自 OP 的混淆。有一些评论员虽然
@Ayxan:我会说混淆而不是混淆。
什么样的人会以其他方式混淆他们需要帮助的代码,然后不提?关键是让别人更难帮助你?或者我需要更多的咖啡。
OP 可能用于以这种方式使用省略号。与运算符优先级一样,一些被认为是已知的,然后添加括号可能被认为是多余的,只是增加冗长(3 + (4 * 5)
,(a + b) < c
),因为其他省略“额外”括号是不安全和混淆的(a || b1 && b2
)。并不总是很容易知道什么让其他人感到困惑(尤其是当我们已经在上下文中时)。以上是关于可变参数模板和省略号有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章