将花括号包含的初始化列表作为结构体返回

3

以下是使用 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中得到修复?

实际上,我确实使用了-std=c++17,结果是一样的。 - Mine
1个回答

3

指定初始化语法在标准的C++中还未被支持。然而,它已被计划包括在C++20中,但尚未最终确定或发布。

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

在已发布的C++标准中,除了第一个成员,没有其他方式可以为联合成员提供这样的初始化程序。(您可以在类定义中有一个默认的成员初始化程序)。

与此同时,以下代码可以工作:

sd_bus_vtable get()
{
    sd_bus_vtable r{};
    r.x.signal = {"", ""};
    return r;    
}
注意:使用赋值运算符来切换联合体的活动成员只适用于所有联合体成员都具有平凡构造函数和析构函数的情况。否则,您需要手动销毁和创建。
此外,还可以省略名称x(这称为匿名联合体),然后联合成员的名称可访问,就好像它们是封闭结构体的成员一样。

那么返回这样的结构体的首选语法是什么? - Mine
@Mine 添加了一个例子。 - M.M
C++20 草案上周已经定稿。我认为现在它只需要经过投票/批准程序,这似乎是一种形式程序,从我所知道的情况来看。 - walnut
@walnut,N4849之后还有其他的吗?还是就这一个? - M.M
@M.M 我认为一旦上周的更改被编辑进去,就会有另一个版本。草案存储库仍然将这些动议作为未解决的问题。 - walnut

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接