Thi*_*aut 4 c++ variadic-templates c++11
我认为扩展参数包具有以下行为:
// for Args ... p
f(p)...;
// was equivalent to
f(p1); f(p2); ...; f(pn);
Run Code Online (Sandbox Code Playgroud)
但我刚刚发现gcc(4.6,4.7和4.8)反过来说:
f(pn); ...; f(p2); f(p1);
Run Code Online (Sandbox Code Playgroud)
而clang按照我的预期做到了.
这是GCC中的错误还是根据标准有效?
最小的例子
#include <iostream>
#include <string>
template<typename T>
bool print(const unsigned index, const T& value){
std::cerr << "Parameter " << index << " is " << value << std::endl;
return true;
}
template<typename ... Args>
void printAll(Args ... args){
unsigned i = 0;
[](...){}(print(i++, args)...);
}
int main(){
int a = 1; float b = 3.14; std::string c("hello");
printAll(a, b, c);
}
Run Code Online (Sandbox Code Playgroud)
编译和执行:
$> clang++ -std=c++11 -o test test.cpp
$> ./test
Parameter 0 is 1
Parameter 1 is 3.14
Parameter 2 is hello
$> g++ -std=c++11 -o test test.cpp
$> ./test
Parameter 0 is hello
Parameter 1 is 3.14
Parameter 2 is 1
Run Code Online (Sandbox Code Playgroud)
回答
不久,Martinho Fernandes就发现了错误.问题是参数的评估顺序,这是标准(1.9.3)没有定义的:
抽象机器的某些其他方面和操作在本国际标准中被描述为未指定的(例如,对函数的参数的评估顺序).
R. *_*des 12
是否在标准中定义了可变参数模板包扩展的顺序?
是.扩展元素的顺序与包的原始顺序相对应.
在测试中,扩展[](...){}(print(i++, args)...);相当于:[](...){}(print(i++, a), print(i++, b), print(i++, c));.
测试存在缺陷,因为它测试了函数参数的评估顺序,这是一个完全不同的问题.如果您尝试执行上面提到的扩展表单,您将观察到相同的行为.或者,如果代码没有未定义的行为,您将会这样做,因为变量i会增加几次,而不会对增量进行排序.