使用指定的初始化程序聚合匿名结构的初始化

时间:2020-07-02 10:14:13

标签: c++ g++ unions aggregate-initialization anonymous-struct

我正在移植旧版C ++代码以与GCC 9.2一起使用。使用C ++ 20和GNU扩展是有效的选择。

旧版代码大量使用嵌套在并集中的匿名结构,并使用指定的初始化来聚合初始化,例如:

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

此示例可以compile with clang -std=gnu++2a -Wall -Wextra,但不能compile with g++ -std=gnu++2a -Wall -Wextra

错误:“ u”的初始化程序太多

由于在许多情况下在代码中应用了此类构造,因此有必要以自动化方式(例如在正则表达式的帮助下)对代码进行潜在更改。 如何通过自动且尽可能少地更改代码来在GCC 9.2中编译“此代码”?

2 个答案:

答案 0 :(得分:1)

通过将嵌套结构移动到并集内的第一个位置,并像非匿名结构compiles with g++ -std=gnu++2a -Wall -Wextra一样初始化结构:

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

应该有可能使用struct定义中的正则表达式检测union内的所有匿名union。但是我看不到如何使用正则表达式来适当地修改列表的初始化。

答案 1 :(得分:0)

您只能初始化联合的一个成员:

由于15.6.2 [class.base.init]第8段: 尝试初始化一个并集的多个非静态数据成员会导致程序格式错误。

因此,如果您输入:{ .b=1, .c=2 },则表明您正在初始化两个成员。

然后,您可以初始化.b.c,但不能同时初始化两者。

此外:

如果元素是一个匿名联合对象,而初始化程序列表是一个指定的初始化程序列表,则匿名联合对象由指定的初始化程序列表{D}}初始化,其中D是指定匿名联合对象成员的指定初始化器子句。这样的指定初始化程序子句应该只有一个。

关键是:其中D是命名匿名联合对象的成员的指定初始化子句

您可能会获得更多信息here

要能够为struct的成员赋予价值,您应该给一个元素

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

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

但这会中断对每个u的访问,即f.v.b = 0

所以我认为您的构造与C ++ 20不兼容。为什么clang可以编译和工作?当不涉及构造函数和/或析构函数时,它可能是扩展。

相关问题