Constexpr размещение нового?

Стандарт С++ специально запрещает вызов new в постоянном выражении (раздел N4296 5.20 [expr.const]):

Условное выражение e является выражением основной константы, если оценка e, следуя правилам абстрактной машины (1.9), не будет оценивать одно из следующих выражений:

...

- новое выражение (5.3.4);

Этот запрет (насколько я вижу) распространяется на все формы new, включая размещение new. Однако, поскольку размещение new фактически не выделяет какую-либо память и просто запускает конструкторы в заданном месте, и поскольку это право принимать адрес переменной в контексте constexpr (действительно, std::addressof будет constexpr в C + +17), мне кажется, что этот запрет можно (в принципе, по крайней мере) облегчить, чтобы позволить размещение новых в функциях constexpr.

Итак, мой вопрос: я что-то упускаю? Есть ли веская причина, почему размещение новых запрещено в constexpr функциях?

(Для контекста: текущие правила в значительной степени требуют, чтобы типы сумм с поддержкой constexpr, такие как std::variant, были реализованы как рекурсивный союз. Было бы лучше использовать что-то вроде std::aligned_storage и размещения new, но в настоящее время это невозможно.)

Ответ 1

#include <cstdint>
#include <iostream>

class A {
public:
    constexpr A() = default;
    int a = 5;
};

constexpr int foo() {
    uint8_t space[sizeof(A)];
    new(space) A();
    A& a = *reinterpret_cast<A*>(space);
    return a.a;
}

int main() {
  std::cout << foo() << std::endl;
}

Конечно, возможно, что компилятор может понять вышеупомянутую программу. Как правило, я не думаю, что это возможно из-за сложности, необходимой для обеспечения того, чтобы параметр места размещения всегда указывал на локальную память.

Я не думаю, что понятие "память" даже применяется к функциям constexpr, потому что они обычно оцениваются во время компиляции.