Can I define one of class-specific deallocation functions and use it in a constant expression?
For example a destroying delete:
#include <new>
struct A {
constexpr void operator delete(A *, std::destroying_delete_t);
};
struct B : A {};
constexpr void A::operator delete(A *p, std::destroying_delete_t) {
::delete static_cast<B*>(p);
}
constexpr bool foo() {
A *p = new B;
delete p;
return true;
}
static_assert( foo() );
GCC and MSVC do accept it, however Clang complains:
error: constexpr function never produces a constant expression [-Winvalid-constexpr]
note: call to class-specific 'operator delete'
Online demo: https://godbolt.org/z/47h1Y4sr3
Which behavior is correct?
[expr.const]/5, bullet points 18-19 state that constant evaluation may not encounter:
This does not specify that the selected deallocation function must be a replaceable global deallocation function; as long as it ends up calling such a deallocation function if necessary to satisfy the preceding bullet point, your code is valid.
A further possibly-motivating example:
An interesting question is raised by the following:
That is, does it matter which region of storage the delete-expression deallocates, or is it expected to be the region of storage corresponding to the object to which the operand of the delete-expression points? Perhaps the current language should be replaced by its inversion: