代码之家  ›  专栏  ›  技术社区  ›  Mine

将括号内的初始值设定项列表作为结构返回

  •  3
  • Mine  · 技术社区  · 6 年前

    下面给出用 g++ -c test.cpp g++ -std=c++17 -c test.cpp

    #include <cstddef>
    
    struct sd_bus_vtable {
            union {
                    struct {
                            size_t element_size;
                    } start;
                    struct {
                            const char *member;
                            const char *signature;
                    } signal;
            } x;
    };
    
    sd_bus_vtable get()
    {
        return {
            .x = {
                .signal = {
                    .member = "",
                    .signature= "",
                }
            }
        };
    }
    

    它在GCC 9.2.0和clang 5/6上编译良好,但在8.3.0或7.4.0上编译失败,错误消息如下:

    test.cpp:25:5: error: could not convert ‘{{{"", ""}}}’ from ‘<brace-enclosed initializer list>’ to ‘sd_bus_vtable’
         };
    
    

    为了解决这个问题,函数 get() 可以按以下方式更改,但看起来不太干净。。。

    sd_bus_vtable get()
    {
        struct sd_bus_vtable t = {
            .x = {
                .signal = {
                    .member = "",
                    .signature= "",
                }
            }
        };
        return t;
    }
    

    问题是,上述代码是否有效?如果是,它是否会触发GCC中修复的GCC9中的某些错误?

    1 回复  |  直到 6 年前
        1
  •  3
  •   M.M    6 年前

    指定的初始化器语法不是标准C++。它计划包含在C++20中,但尚未最终确定或发布。

    因此,您依赖于支持这个即将到来的特性的编译器作为扩展。

    在发布的C++标准中,除了第一个成员之外,没有办法为联盟成员提供这样的初始化器。(可以在类定义中使用默认的成员初始值设定项)。

    同时,以下代码将起作用:

    sd_bus_vtable get()
    {
        sd_bus_vtable r{};
        r.x.signal = {"", ""};
        return r;    
    }
    

    注: 此方法(使用赋值运算符切换联合的活动成员)仅在所有联合成员都具有普通构造函数和析构函数时有效。否则,您需要手动销毁和创建。

    也可以省略名称 x (这叫做 匿名联合 ),则可以访问联合成员的名称,就像它们是封闭结构的成员一样。