Why does C++11 not support designated initializer lists as C99? [closed]

On July 15 ’17 P0329R4 was accepted into the standard: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0329r4.pdf
This brings limited support for ‘s Designated Initializers. This limitation is described as follows by C.1.7[diff.decl].4, given:

struct A { int x, y; };
struct B { struct A a; };

The following Designated Initializations, which are valid in C, are restricted in C++:

  • struct A a = { .y = 1, .x = 2 } is invalid in C++ because designators must appear in the declaration order of the data members
  • int arr[3] = { [1] = 5 } is invalid in C++ because array designated initialization is not supported
  • struct B b = {.a.x = 0} is invalid in C++ because designators cannot be nested
  • struct A c = {.x = 1, 2} is invalid in C++ because either all or none of the data members must be initialized by designators

For and earlier Boost actually has support for Designated Intializers and there have been numerous proposals to add support to the standard, for example: n4172 and Daryle Walker’s Proposal to Add Designation to Initializers. The proposals cite implementation of ‘s Designated Initializers in Visual C++, gcc, and Clang claiming:

We believe the changes will be relatively straightforward to implement

But the standard committee repeatedly rejects such proposals, stating:

EWG found various problems with the proposed approach, and didn’t think it’s feasible to try solving the problem, as it has been tried many times and every time it has failed

Ben Voigt’s comments have helped me to see the insurmountable problems with this approach; given:

struct X {
    int c;
    char a;
    float b;
};

What order would these functions be called in in : struct X foo = {.a = (char)f(), .b = g(), .c = h()}? Surprisingly, in :

The order of evaluation of the subexpressions in any initializer is indeterminately sequenced [1]

(Visual C++, gcc, and Clang seem to have an agreed upon behavior as they will all make the calls in this order:)

  1. h()
  2. f()
  3. g()

But the indeterminate nature of the standard means that if these functions had any interaction the resulting program state would also be indeterminate, and the compiler wouldn’t warn you: Is there a Way to Get Warned about Misbehaving Designated Initializers?

does have stringent initializer-list requirements 11.6.4[dcl.init.list]4:

Within the initializer-list of a braced-init-list, the initializer-clauses, including any that result from pack expansions (17.5.3), are evaluated in the order in which they appear. That is, every value computation and side effect associated with a given initializer-clause is sequenced before every value computation and side effect associated with any initializer-clause that follows it in the comma-separated list of the initializer-list.

So support would have required this to be executed in the order:

  1. f()
  2. g()
  3. h()

Breaking compatibility with previous implementations.
As discussed above, this issue has been circumvented by the limitations on Designated Initializers accepted into . They provide a standardized behavior, guaranteeing the execution order of Designated Initializers.

Leave a Comment