0

I am importing/porting existing C code to C++. I am hoping to make as few changes to the existing body of code as possible to minimize preterbing the existing code. This code makes use of static named initialization of nested structures. For quick made up example:

Car car =
{
  .color = RED,
  .tire.tread = OLD,
  .tire.diameter = 27.106,
  .tire.material.type = RUBBER,
  .tire.material.density = 700,
};

I figured out that these are called designated initializers.

I learned about GNU initializers but I haven't figured out how to implement hierarchy with it.

I read that designated initializers are supported in g++ with c++11 enabled, but that didn't seem to work for me.

The code I am porting has pages of initialization with at least four layers deep of hierarchy. So I am trying to look for a straightforward transformation which doesn't get too involved.

I am looking for one of these possible solutions:

  • How to enable C99 designated initializers
  • How to formulate hierarchical GNU style initialization
  • What is a C++ equivalent way to do this which wouldn't be error prone transcribing war and peace.
  • An obvious solution I haven't thought of

I am using g++ version

g++.exe (i686-posix-dwarf-rev0, Built by MinGW-W64 project) 8.1.0
Joshua
  • 1,185
  • 14
  • 23
  • I have also tried -std=c++2a which also results in the error: expected primary-expression before '.' token – Joshua Jan 31 '20 at 15:32

1 Answers1

0

The use of such nested designated initializers seems to be something of an edge case. The following works in both clang-cl (in Visual Studio 2019) and the native MSVC compiler (but the latter only with the /std:c++latest option, which uses the draft C++20 standard):

struct inner {
    int x, y;
    double z;
};
struct outer {
    char a;
    double b;
    inner c;
};

outer my_outer = { .a = 'a', .b = 1.2, .c = { .x = 3, .y = 4, .z = 5.6 } };

With clang-cl, the initializer can be abbreviated to the following form:

outer my_outer = { .a = 'a', .b = 1.2, .c.x = 3, .c.y = 4, .c.z = 5.6 };

but MSVC complains in this case, with:

error C7558: nested member access is not allowed in standard C++ designated initializers; use a nested initializer list

So, for your example, you could try this:

Car car =
{
  .color = RED,
  .tire = {
     .tread = OLD,
     .diameter = 27.106,
     .material.type = RUBBER,
     .material.density = 700,
   }
};

There's a helpful 'discussion' of the topic on cppreference, with this part being notable:

...each designator must name a direct non-static data member of T, and all designators used in the expression must appear in the same order as the data members of T.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83