I forgot to say that "behaves right" requires operator new to correspond to operator delete.

If it corresponds, then the behavior is completely correct, because the delete expression is equivalent to call destructor + operator delete.

Of course the code could be better:

auto* p = operator new(sizeof(T));
auto* pc = new(p) T;
::delete pc;

This way for any T, the code is correct.

If T definitely does not overload operator new and operator delete, then :: may not be used. If it's wrong, the behavior is undefined.

The same applies to the original issue.

On Sun, Oct 2, 2022 at 9:29 AM Jason McKesson via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
On Sat, Oct 1, 2022 at 8:51 PM blacktea hamburger via Std-Proposals
<std-proposals@lists.isocpp.org> wrote:
>
> I'm using "forbid" wrong. It should be "undefined behavior," because obviously it can't be checked at compile time. It's better to make it well-formed, because unintended but correct behavior is better than undefined behavior.

That changes nothing about my question: why not? Equally importantly,
how is it "correct behavior"? It's code that is *incoherent.* You
initialized the object in a way that says something about the
relationship between the object and its storage, and you destroyed the
object in a way that says something *different* about the relationship
between the object and its storage.

Why is this "correct behavior"? Who is to say what "correct behavior"
even is if you're not consistent on what you're doing?

Not to mention the fact that, as Thiago pointed out, it is not even
"correct behavior" if `T` has an `operator delete` overload. And
again, IOC can work just fine on such types.
--
Std-Proposals mailing list
Std-Proposals@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals