Error C3074: an array can only be initialized using a list of initializers

I am working on a small (beautiful) printer for POD, STL, and composite types such as arrays. In doing so, I also played with initialization lists and came across the following declaration

std::vector<double[3]> arr{ { 10, 11, 12 }, { 20, 21, 22 } }; 

It seems that both VC2013 and g ++ 4.8 are not completely satisfied and give an error message, which in any case is not very useful for me.

For VC ++: error C3074: an array can only be initialized with an initialize-list

For g ++ 4.8: error: array must be initialized with a brace-enclosed initialize

So none of the initialization lists can be used here, or is my syntax completely wrong?

On a similar front, the following syntax seems valid

 std::vector<std::array<int, 3>> arr{ { 10, 11, 12 }, { 20, 21, 22 } }; 

What is the possible problem with my initialization list?

  • Note I understand that instead of arrays of type C I have to use std::array , but I'm just experimenting.
  • Note If you do not want to play with this, here is the IDEONE version
  • Note In addition, it would be very helpful if you would return me to the standard.
+5
source share
2 answers

Reading the current C ++ 1y draft standard .

From table 99:

T is EmplaceConstructible in X from arg, for zero or more arguments arg, means that the following expression is well-formed: allocator_traits :: construct (m, p, args)

Table 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. 

So std::vector<double[3]> v{ {1,2,3}, {4,5,6} }; valid if if double[3] is an EmplaceConstructible of {1,2,3} as an element of the initializer list passed to std::vector<double[3]> .

There is also a proposal for forward iterators, but that is not a problem (since std::initialzier_list iterators are forward iterators).

std::vector<T> takes the std::initializer_list<T> parameter.

So, std::initializer_list<double[3]> is a list of candidates.

Firstly, std::initializer_list<double[3]> x = {{1.0, 2.0, 3.0}}; not compiled in gcc. But suppose this is a bug in gcc.

Secondly, ::new (nullptr) double[3](std::initializer_list<double>{1.0, 2.0, 3.0}); the new placement, which EmplaceConstructable boils down to lacking a suitable construct override, will not compile.

So, double[3] not EmplaceConstruble from std::initalizer_list<double> or from double[3] and nothing else (since the error occurs because I used a bracket, and not because it was in brackets , in the placement new), if the dispenser does not do magic, I do not know to avoid placing a new one.

Thus, your code violates the current draft standard and, possibly, C ++ 11 and, of course, C ++ 03 (which presented more stringent requirements for containers).

+5
source

This is a bug in gcc and MSVC; clang compiles your code correctly.

Recent versions of gcc actually crash ("ice") the compiler:

compiler internal error: tree check: expected class type, has an exception (error_mark) in useless_type_conversion_p, on tree-ssa.c: 1189

The standard is clear enough; from [dcl.init.list] :

5 - An object of type std::initializer_list<E> is created from the list of initializers, as if the implementation allocated an array of elements N type E , where N is the number of elements in the list of initializers. Each element of this array is initialized with a copy with the corresponding element in the list of initializers, and the std::initializer_list<E> object is created to access this array. [...]

Adapting the example from this paragraph:

 using E = double[3]; using X = std::vector<E>; E __a[2] = {{10, 11, 12}, {20, 21, 22}}; X x(__a, __a+2); 

This is a little trickster; a closer translation will write E __a[2] = {E{10, 11, 12}, E{20, 21, 22}}; that is unacceptable. But, of course, you can copy-initialize the double[3] array from the list with binding-init: E __a0 = {10, 11, 12};

+3
source

Source: https://habr.com/ru/post/1200433/


All Articles