https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91369
--- Comment #15 from Jonathan Wakely <redi at gcc dot gnu.org> ---
That's not valid, because operator new is not a constexpr function.
You have to use a new-expression (that resolves to one of the standard operator
new allocation functions), or std::allocator<T>::allocate, or
std::allocator_traits<std::allocator<T>>::allocate.
The result of std::allocator<T>::allocate can't be dereferenced until you've
constructed an object there (and attempting to do so in a constexpr function
should be ill-formed).
This should work:
constexpr int
bar ()
{
auto a = new int; // obtain storage for an int and begin its lifetime
*a = 1;
*a = *a + 2;
int r = *a;
delete a; // end lifetime and release storage
return r;
}
constexpr auto p = bar ();
And this:
constexpr int
baz ()
{
auto a = std::allocator<int>::allocate(1); // obtain storage for an int
std::construct_at(a); // begin lifetime of an int
*a = 1;
*a = *a + 2;
int r = *a;
std::destroy_at(a); // end lifetime
std::allocator<int>::deallocate(a, 1); // release storage
return r;
}
constexpr auto q = baz ();
And the equivalent using std::allocator_traits:
constexpr int
baz2 ()
{
std::allocator<int> alloc;
using A = std::allocator_traits<std::allocator<int>>;
auto a = A::allocate(alloc, 1); // obtain storage for an int
A::construct(a); // calls std::construct_at
*a = 1;
*a = *a + 2;
int r = *a;
A::destroy(alloc, a); // calls std::destroy_at
A::deallocate(alloc, a, 1); // release storage
return r;
}
constexpr auto q = baz2 ();