在与一个我无法让std::initializer_list
逻辑按预期工作的程序进行了长时间的斗争之后,我最终得到了一个小案例,我发现clang++
6.0.1 和g++
8.2.0 都在编译,但语义不同。
哪一个是正确执行该标准的?我试图通过阅读相关部分来自己理解规则,但我的大脑在尝试中爆炸了......
#include <vector>
#include <stdio.h>
struct Value {
int i;
std::vector<Value> *v;
Value() : i(0), v(nullptr) {}
Value(int x) : i(x), v(nullptr) {}
template<typename T>
Value(const std::vector<T>& x)
: v(new std::vector<Value>(x.begin(), x.end())) { }
Value(std::initializer_list<Value> L)
: Value(std::vector<Value>(L)) { }
void dump(int indent = 0) {
if (v) {
printf("%*s[\n", indent, "");
for (int i=0,n=v->size(); i<n; i++) {
(*v)[i].dump(indent + 4);
}
printf("%*s]\n", indent, "");
} else {
printf("%*s%i\n", indent, "", i);
}
}
};
int main(int argc, const char *argv[]) {
Value x; printf("x:\n"); x.dump(); printf("---\n\n");
Value y1 = x; printf("y1:\n"); y1.dump(); printf("---\n\n");
Value y2 = {x}; printf("y2:\n"); y2.dump(); printf("---\n\n");
Value y3; y3 = {x}; printf("y3:\n"); y3.dump(); printf("---\n\n");
Value y4; y4 = {{x}}; printf("y4:\n"); y4.dump(); printf("---\n\n");
return 0;
}
在特定的g++
初始化y2
为值列表(v
指针被初始化),而clang++
只是调用复制构造函数x
。
活生生的例子: