使用constexpr表达式中的公共初始序列检查并集的不活动成员

问题描述

第12.3.1点中的C ++标准说:

如果标准布局联合包含多个共享公共初始序列的标准布局结构,并且此标准布局联合类型的对象的非静态数据成员处于活动状态并且是标准布局之一结构,则可以检查任何标准布局结构成员的公共初始序列;

但是以下代码无法在任何主要的编译器(https://godbolt.org/z/3jM1co)上进行编译:

struct type {
    union {
        int a;
        int b;
    };

    constexpr type(int n) : a(n) {}
};

constexpr int fun(int n) {
    type t(n);

    return t.b;
}

constexpr int res = fun(5);

为什么代码无法编译(我相信所有编译器在这里都没有错)?该代码应满足访问联盟中技术上不活跃的成员的条件(标准布局,通用初始序列)。删除constexpr关键字后,此代码将毫无问题地编译。

解决方法

您引用的文本是正确的,但是在constexpr上下文中访问联合的非活动成员还有其他限制。特别是,您违反了此rule

表达式E是一个核心常量表达式,除非按照抽象机([intro.execution])的规则对E的求值将对以下之一进行求值:

应用于左值的左值到右值转换,该值引用联合的非活动成员或其子对象;


请注意,您可以在constexpr上下文中更改联合的活动成员,因此您可以执行以下操作:

constexpr int fun(int n) 
{
    type t(n);
    t.b = t.a;    // t.b is now the active member
    return t.b;   // ok,reading from active member is fine
}

我相信只有c ++ 20:demo允许这样做。

相关的rule是这样的:

表达式E是一个核心常量表达式,除非按照抽象机([intro.execution])的规则对E的求值将对以下之一进行求值:

为其活动成员(如果有)可变的联合调用隐式定义的复制/移动构造函数或复制/移动赋值运算符,除非联合对象的生存期在E的评估内开始,;

(重点是我的)。由于t的生存期始于fun的评估之内,因此可以这样做。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...