我正在为POD,STL和像阵列这样的复合类型打造小型(漂亮)打印机。在这样做的同时,我也在摆弄初始化列表,并且遇到了以下声明
std::vector<double[3]> arr{ { 10, 11, 12 }, { 20, 21, 22 } };
似乎VC2013和G ++ 4.8都不太满意并发出一致的错误信息,无论哪种情况对我都没有帮助
对于VC ++: error C3074: an array can only be initialized with an initialize-list
对于G ++ 4.8: error: array must be initialized with a brace-enclosed initialize
所以这里不能使用初始化列表,或者我的语法不正确吗?
在类似的方面,以下语法似乎有效
std::vector<std::array<int, 3>> arr{ { 10, 11, 12 }, { 20, 21, 22 } };
初始化列表可能出现什么问题?
std::array
而不是C类数组,但我只是在试验。 答案 0 :(得分:5)
阅读current C++1y draft standard。
从表99之前:
Ť 是 EmplaceConstructible 成 X 从 ARGS ,零个或多个参数 ARGS ,意思是 以下表达式格式正确: allocator_traits :: construct(m,p,args)
表100:
X(il); | Equivalent to | X(il.begin(), il.end());
--------------------+---------------------+--------------------------------
X(i, j); | | Requires:
X a(i, j); | | T shall be EmplaceConstructible
| into X from *i.
因为std::vector<double[3]> v{ {1,2,3}, {4,5,6} };
double[3]
EmplaceConstructible
来自{1,2,3}
,std::vector<double[3]>
作为初始化程序列表的元素传递给std::initialzier_list
,所以std::vector<T>
有效。
还有一个关于前向迭代器的子句,但这没有问题(因为std::initializer_list<T>
迭代器是前向迭代器)。
std::initializer_list<double[3]>
需要std::initializer_list<double[3]> x = {{1.0, 2.0, 3.0}};
参数。
所以::new (nullptr) double[3](std::initializer_list<double>{1.0, 2.0, 3.0});
是候选名单。
首先,EmplaceConstructable
无法在gcc中编译。但是假设这是gcc中的一个错误。
其次,construct
展示位置new double[3]
在缺少合适的EmplaceConstruble
覆盖时缩小,无法编译。
所以std::initalizer_list<double>
不是来自double[3]
的{{1}},也不是来自{{1}}的{{1}},也不是因为我使用括号,而不是因为什么是在括号中,在新的位置),除非分配器具有魔力,否则我不知道要避免放置新的。
因此,您的代码违反了当前的标准草案,可能是C ++ 11,当然还有C ++ 03(对容器有更严格的要求)。
答案 1 :(得分:3)
这是gcc和MSVC中的错误; clang正确编译你的代码。
gcc的最新版本实际上崩溃了(&#34; ice&#34;)编译器:
内部编译器错误:树检查:期望的类'type',在useless_type_conversion_p中有'exception'(error_mark),在tree-ssa.c:1189
标准相当清楚;来自 [dcl.init.list] :
5 - 类型
std::initializer_list<E>
的对象是从初始化列表构造的,就好像实现分配了N
类型为E
的元素数组,其中N
是初始化列表中的元素数量。使用初始化列表的相应元素对该数组的每个元素进行复制初始化,并构造std::initializer_list<E>
对象以引用该数组。 [...]
调整该段落中的示例:
using E = double[3];
using X = std::vector<E>;
E __a[2] = {{10, 11, 12}, {20, 21, 22}};
X x(__a, __a+2);
但这有点像作弊;更接近的翻译会写E __a[2] = {E{10, 11, 12}, E{20, 21, 22}};
,这是无效的。但肯定 可以从braced-init-list复制初始化数组double[3]
:E __a0 = {10, 11, 12};