简体   繁体   中英

Aggregate initialization of anonymous struct with designated initializers

I am porting legacy C++ code to work with GCC 9.2. Using C++20 and GNU extensions are valid options.

The legacy code makes heavy use of anonymous structs nested in unions and aggregate initialization with designated initializes for example:

union u 
{ 
    int a; 
    struct
    {
        int b;
        int c;
    }; 
};
u f = { .b = 1, .c = 2 };

This example does compile with clang -std=gnu++2a -Wall -Wextra , but it does not compile with g++ -std=gnu++2a -Wall -Wextra :

error: too many initializers for 'u'

As there are many cases where such constructs are applied in the code, it would be necessary to apply potential changes to the code in an automated way (for example with the help of regular expressions). How can I compile "this code" with GCC 9.2 by changing the code in an automated way and as little as possible?

By moving the nested structure to the first position within the union and initializing the structure like an non-anonymous structure compiles with g++ -std=gnu++2a -Wall -Wextra :

union u { 
    struct
    {
        int b;
        int c;
    }; 
    int a; 
};
u f = { {.b = 1, .c = 2 } };

It should be possible to detect all anonymous struct s within union s with regular expressions in the union 's definitions. But I do not see how regular expressions can be used to modify the list initialization appropriately.

You can initialize only one member of the union:

because of 15.6.2 [class.base.init] paragraph 8: An attempt to initialize more than one non-static data member of a union renders the program ill-formed.

so if you put: {.b=1, .c=2 } it sees you are initializing two members.

Then you can initialize either, .b or .c but not both.

Moreover:

If the element is an anonymous union object and the initializer list is a designated-initializer-list, the anonymous union object is initialized by the designated-initializer-list{D}, where D is the designated-initializer-clause naming a member of the anonymous union object. There shall be only one such designated-initializer-clause.

The key is: where D is the designated-initializer-clause naming a member of the anonymous union object

You may get more info here .

To be able to give a value to the members of the struct you should give an element :

union u 
{ 
    int a; 
    struct
    {
        int b;
        int c;
    } v; // <-- this
};

u f = { .v = { .b = 1, .c = 2 } };

But this would break the accesses to every u : ie fvb = 0 .

So I think your construct is not compatible with C++20. Why clang compiles and works? May be it is an extension when there are no constructors and/or destructors involved.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM