2

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

遗留代码大量使用嵌套在联合中的匿名结构和具有指定初始化的聚合初始化,例如:

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

这个例子用 编译clang -std=gnu++2a -Wall -Wextra,但它不能用 编译g++ -std=gnu++2a -Wall -Wextra

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

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

4

2 回答 2

2

通过将嵌套结构移动到联合中的第一个位置并像非匿名结构一样初始化结构,编译g++ -std=gnu++2a -Wall -Wextra

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

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

于 2020-07-02T12:56:32.983 回答
0

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

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

因此,如果您输入:{ .b=1, .c=2 }它会看到您正在初始化两个成员。

然后您可以初始化其中一个,.b.c两者都初始化。

而且:

如果元素是匿名联合对象并且初始化器列表是指定初始化器列表,则匿名联合对象由指定初始化器列表初始化​​{​​D​​}​,其中​D​是​designated-initializer-clause​命名匿名联合对象的成员。应该只有一个这样的指定初始化子句。

关键是:其中​D​是​designated-initializer-clause​命名匿名联合对象的成员

您可能会在此处获得更多信息。

为了能够给成员一个值,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 编译和工作?当不涉及构造函数和/或析构函数时,它可能是一个扩展。

于 2020-07-02T15:07:02.703 回答