7

以下程序

#include <iostream>
#include <tuple>

struct A {
    A() { std::cout << "A constructor\n"; }
};

struct B {
    B() { std::cout << "B constructor\n"; }
};

int main() {
    std::tuple<A, B> t;
}

在不同的编译器上给出不同的输出:

# libstdc++
B constructor
A constructor
# libc++
A constructor
B constructor

这看起来很奇怪......我认为标准会保证元组元素按顺序构造,例如,A、B、...、Y、Z?

4

2 回答 2

6

std::tuple施工顺序目前不详

已向委员会提交了对其命令做出具体决定的提案,但在此之前不应依赖该命令。

于 2015-08-26T12:01:35.047 回答
2

如您所见,该标准未在此处定义排序。我只看到它以相反的顺序发生,但原则上编译器可以做它想做的任何事情。更糟糕的是,您对“标准化构造函数”的请求不会成功,因为这个问题并非特定于构造函数:所有函数参数都以这种方式工作!

考虑这个例子:

bool putOnTheSpaceSuits() { /* ... */ }
bool openTheAirlock() { /* ... */ }
void tryGoIntoSpace(bool spaceSuitsOn, bool airlockOpen) {
  if(spaceSuitsOn && airlockOpen) {
    spacewalk();
  }
}

当我们跑步时会发生什么tryGoIntoSpace(putOnTheSpaceSuits(), openTheAirlock())?在我的机器上,openTheAirlock()首先进行评估,将我们未受保护的宇航员抛入太空。哎呀!

您的原始问题使用两个隐式转换;它相当于std::tuple<X,Y> t(X(1),Y(2));. X您可以使用任何带有a 和 a 的随机自由函数看到相同的效果Y

void frob(X x, Y y) { /* ... */ }

frob(X(1), Y(2)); // It's unspecified, but I bet Y(2) will happen first here.

自己看看:http ://coliru.stacked-crooked.com/a/e4142f3c8342ebf2

您使用递归模板元组构造函数的事实与此处无关;所有 C++ 函数都是相似的。理想情况下,您的函数参数不应具有有趣的、相互交互的副作用,但如果这是不可能的,您必须自己进行排序:

X x(1);
Y y(2);
std::tuple<X,Y> t(x, y);
于 2015-08-25T08:42:21.873 回答