So I started a twitter thread on this a while ago here in response to the question:
Current implementations don't allow placement new()
in constexpr context.
and I replied:
If we look at p0784r0: https://wg21.link/p0784r0
The paper mentioned two approaches:
- in terms placement new
- in terms of the standard allocator
by the time we get to p0784r3: https://wg21.link/p0784r3
placement new is dropped, IIUC there are implementation issues here.
The reply from Richard Smith was:
Full placement new support is hard for some implementations, so a restricted form is exposed through std::construct_at and allocator_traits::construct. For now in clang, we actually implement a quite general form of placement new, but only allow it inside namespace std.
to which I asked:
I am curious why this is difficult for some implementations or maybe easier why it is not difficult for clang.
and the reply to this was:
I am told that getting from the void*
parameter to placement new back to a typed pointer is infeasible for some constexpr
evaluators, presumably due to how they represent pointers. construct_at
avoids this because it takes a T*
not a void*
.
Basically it comes down to some implementation don't have the machinery in place to do this in a general way using placement new. This document has some discussions on this but really raises more questions then answers but hints at some details:
Unfortunately this allows placement new to foul analyses which use address value propagation to refine aliasing based on knowing where the pointer points. In the example above, such an optimization may find that the address of bp->buf[0] to be associated with the object a. From that finding, the optimizer may then decide that accesses to the memory ought to be done through a glvalue which may access the stored value of a without invoking undefined behavior (§3.10 [basic.lval]). The initialization done via the new-expression is not such an access.