错误C3074:只能使用初始化列表初始化数组

时间:2014-08-15 16:42:09

标签: c++ arrays visual-c++ c++11 initialization-list

我正在为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类数组,但我只是在试验。
  • 注意如果你不想玩这个,这里有一个IDEONE版本
  • 注意此外,如果您可以将我推荐回标准,那将是非常有益的。

2 个答案:

答案 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};