c++ - 在 constexpr 表达式中检查具有公共(public)初始序列的 union 的非事件成员

标签 c++ language-lawyer constexpr unions

C++ 标准第 12.3.1 点说:

If a standard-layout union contains several standard-layout structs that share a common initial sequence, and if a non-static data member of an object of this standard-layout union type is active and is one of the standard-layout structs, it is permitted to inspect the common initial sequence of any of the standard-layout struct members;

然而,以下代码无法在任何主要编译器 (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);

为什么代码无法编译(我相信所有的编译器都没有错)?此代码应满足访问技术上不活跃的 union 成员的条件(标准布局,公共(public)初始序列)。当 constexpr 关键字被删除时,这段代码编译没有问题。

最佳答案

您引用的文本是正确的,但是在 constexpr 上下文中访问 union 体的非事件成员还有其他限制。特别是,您违反了此 rule :

An expression E is a core constant expression unless the evaluation of E, following the rules of the abstract machine ([intro.execution]), would evaluate one of the following:

an lvalue-to-rvalue conversion that is applied to a glvalue that refers to a non-active member of a union or a subobject thereof;


请注意,您可以在 constexpr 上下文中更改 union 的事件成员,因此您可以这样做:

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这是:

An expression E is a core constant expression unless the evaluation of E, following the rules of the abstract machine ([intro.execution]), would evaluate one of the following:

an invocation of an implicitly-defined copy/move constructor or copy/move assignment operator for a union whose active member (if any) is mutable, unless the lifetime of the union object began within the evaluation of E;

(重点是我的)。由于 t 的生命周期从 fun 的计算开始,这是允许的。

关于c++ - 在 constexpr 表达式中检查具有公共(public)初始序列的 union 的非事件成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64098077/

相关文章:

c++ - clam-NetworkEditor 编译失败

c++ - 我可以避免 RTTI 吗?

c++ - 可以使用 std::launder 将对象指针转换为其封闭数组指针吗?

c++ - 覆盖虚函数时的奇怪语法

c++ - 编译时类型转换检查(constexpr 和用户定义的文字)

c++ - decltype(constexpr 变量)

Java访问桥损坏的dll

c++ - 模板类可以在不指定其模板参数两次的情况下为自己起别名吗?

c++ - 类型特征检查类特殊函数的琐碎性的基本原理

c++ - 使用函数外部的 const 变量计算时,Constexpr 不会被求值