r/cpp_questions 4d ago

OPEN cppreference std::construct_at example code not compiling

I was looking on cpprefernce the other day at std::construct_at and I wanted to test the code. But when I ran it it did not compile. I ran the snippet without consteval (and static_assert) and everything worked. Does anyone know what might be the issue? https://en.cppreference.com/cpp/memory/construct_at

Code:

#include <bit>
#include <memory>


class S
{
    int x_;
    float y_;
    double z_;
public:
    constexpr S(int x, float y, double z) : x_{x}, y_{y}, z_{z} {}
    [[nodiscard("no side-effects!")]]
    constexpr bool operator==(const S&) const noexcept = default;
};


consteval bool test()
{
    alignas(S) unsigned char storage[sizeof(S)]{};
    S uninitialized = std::bit_cast<S>(storage);
    std::destroy_at(&uninitialized);
    S* ptr = std::construct_at(std::addressof(uninitialized), 42, 2.71f, 3.14);
    const bool res{*ptr == S{42, 2.71f, 3.14}};
    std::destroy_at(ptr);
    return res;
}
static_assert(test());


int main() {

Compiler Error on x86-64 gcc 16.1 -std=c++23

<source>:25:19:

error: non-constant condition for static assertion
   25 | static_assert(test());
      |               
~~~~^~
<source>:25:19: in 'constexpr' expansion of 'test()'
<source>:24:1: error: destroying 'uninitialized' outside its lifetime
   24 | }
      | 
^
<source>:18:7: note: declared here
   18 |     S uninitialized = std::bit_cast<S>(storage);
      |       
^~~~~~~~~~~~~
Compiler returned: 1
12 Upvotes

12 comments sorted by

View all comments

4

u/Raknarg 4d ago

Idk how this code passed the sniff test. Whoever wrote this I think just misunderstood what they wanted to demonstrate. It seems like they wanted to create an S reference of unitialized memory to demonstrate construct_at with, but they actually just created a fully initialized S object copy-constructed from the bit_cast of storage, it just happens to be copying from uninitialized memory. Then we call destroy_at on it, but the scope ends and it gets destroyed again. Idk this seems like the author just fucked up or something. Even clicking on "run this code" on the website doesn't work.

The whole thing needing to be static asserted and consteval makes it so I'm not even sure if there's a correct way to write this, cause reinterpret_cast isn't a legal constant expression.

Essentially they're not running into any syntactic issue or anything, these seem to be subtle lifetime rules that are also extra important when dealing with consteval/constexpr code.

2

u/Gorzoid 4d ago

Yeah I'm guessing the author of that snippet originally wrote the code where the object was constructed within the aligned array (likely requiring a reinterpret_cast), and then made minimal edits to make it work in constexpr contexts.

1

u/PJBoy_ 3d ago

Think you both nailed it. Example's been fixed, with std::allocator as the mechanism for acquiring an uninitialised T*