我认为扩展 parameter pack有以下行为:
// for Args ... p
f(p)...;
// was equivalent to
f(p1); f(p2); ...; f(pn);
但我刚刚发现 gcc(4.6、4.7 和 4.8)是相反的:
f(pn); ...; f(p2); f(p1);
而 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);
}
编译和执行:
$> 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
回答
Martinho Fernandes 很快就发现了这里的错误。问题是参数的评估顺序,标准(1.9.3)没有定义:
Certain other aspects and operations of the abstract machine are described in this International Standard as unspecified (for example, order of evaluation of arguments to a function).
最佳答案
Is the order for variadic template pack expansion defined in the standard?
是的。扩展元素的顺序与包的原始顺序相对应。
在测试中,扩展[](...){}(print(i++, args)...);
等同于:[](... ){}(打印(i++, a), 打印(i++, b), 打印(i++, c));
。
该测试的缺陷在于它测试了函数参数的求值顺序,这是完全不同的事情。如果您尝试执行上面显示的扩展表单,您将观察到相同的行为。或者,如果代码没有未定义的行为,您会这样做,因为变量 i
递增了几次,但没有对递增进行排序。
关于c++ - 标准中是否定义了可变参数模板包扩展的顺序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22248587/