【问题标题】:Return brace-enclosed initializer list as struct将大括号括起来的初始化列表作为结构返回
【发布时间】:2020-06-02 00:59:03
【问题描述】:

下面给出使用g++ -c test.cppg++ -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,结果是一样的。

标签: c++ gcc clang


【解决方案1】:

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

因此,您依赖于支持此即将推出的功能的编译器作为扩展。

在已发布的 C++ 标准中,除了第一个之外,没有办法为联合成员提供这样的初始化程序。 (你可以在类定义中有一个默认的成员初始化器)。

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

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

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

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

【讨论】:

  • 那么返回这样的结构的首选语法是什么?
  • @Mine 添加了一个示例
  • C++20 草案已于上周定稿。我认为现在只需要通过投票/批准程序,据我所知,这似乎是一种形式。
  • @walnut 在 N4849 之后还有一个吗?
  • @M.M 我想会有另一个,包括上周的更改,一旦它们被编辑。The draft repository 仍然有未决问题的动议。
猜你喜欢
  • 2013-08-23
  • 2012-11-21
  • 2016-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-14
相关资源
最近更新 更多