std::construct_at 位于现有对象之上,跳过某些字段的重新初始化

Fed*_*dor 5 c++ language-lawyer constexpr

A在以下程序中,在常量表达式中,创建了一个临时对象,并初始化了所有字段,然后函数在同一地址f创建了另一个对象A,跳过(重新)初始化字段x,随后读取该对象:

#include <memory>

struct A {
    int x;
    constexpr A() {}
    constexpr A(int xx) : x(xx) {}
};

constexpr int f(A && a) { 
    std::construct_at<A>(&a);
    return a.x; 
}

static_assert( f(A{5}) == 5 ); //ok in GCC only
Run Code Online (Sandbox Code Playgroud)

GCC 接受得很好。但其他编译器会抱怨,例如 Clang:

note: read of uninitialized object is not allowed in a constant expression
    return a.x; 
           ^
Run Code Online (Sandbox Code Playgroud)

演示: https: //gcc.godbolt.org/z/87zrEb7q7

确实x没有在 中初始化std::construct_at<A>(&a),但它是在 中初始化的A{5}

这里是哪个编译器?

Hol*_*Cat 4

我确信这是 UB,而 GCC 是错误的。

std::construct_at<A>(&a)创建一个新A对象,从而int x在其中创建一个新成员。该新对象未初始化。

为了使其合法,必须有一个特殊的规则,即未初始化的对象可以根据它们占用的内存内容获取值,但我认为这样的规则不存在。[basic.indet] 没有提到它。

  • 不过,当产生不确定值时,[basic.indet] 的措辞有点奇怪,请参见 [CWG 1997](http://www.open-std.org/JTC1/SC22/WG21/docs/cwg_active)。 html#1997)。 (2认同)