c++ - 标准中是否定义了可变参数模板包扩展的顺序?

标签 c++ c++11 variadic-templates

我认为扩展 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/

相关文章:

c++11 - 未定义对天鹰座的引用::WaveFile

c++ - 派生类中的 GMOCK 基类方法

c++ - 使用默认参数从 lambda 调用最少数量的参数

c++ - 创建一个类模板,该模板可以将由其自身创建的类作为参数

c++ - 是否可以调用具有不同数量参数的函数,传递相同的参数包

c++ - 从 WindowsAPI 调用 NetLocalGroupAddMembers 时,安全 ID 结构无效错误

c++ - 为什么不显示我的窗口? (诅咒)

c++ - 将 'std::initializer_list<int>' 转换为 'int'

c++ - 在 opengl 中显示 16 位无符号整数

c++ - "type-switch"在 C++11 中构造