c++ language-lawyer constexpr placement-new

c++ - Constexpr colocación nueva?



language-lawyer placement-new (2)

No hay ninguna razón conceptual por la que la colocación nueva no pueda funcionar. Supongo que esto fue un descuido, la nueva ubicación es básicamente una llamada al constructor en una ubicación de memoria predefinida.

Asegurar que la ubicación del nuevo parámetro tenga un argumento válido, la ubicación no es más difícil que garantizar que la escritura en un puntero aleatorio sea válida.

El estándar de C ++ prohíbe específicamente las llamadas a new en una expresión constante (N4296 sección 5.20 [expr.const]):

Una expresión condicional e es una expresión constante central a menos que la evaluación de e, siguiendo las reglas de la máquina abstracta (1.9), evalúe una de las siguientes expresiones:

...

- una nueva expresión (5.3.4);

Esta prohibición (por lo que puedo ver) se extiende a todas las formas de new , incluida la colocación nueva. Sin embargo, dado que la nueva ubicación no asigna realmente memoria y simplemente ejecuta constructores en la ubicación dada, y dado que es legal tomar la dirección de una variable en un contexto constexpr (de hecho, std::addressof será constexpr en C ++ 17), me parece que esta prohibición podría (en principio al menos) ser facilitada para permitir la colocación de nuevas funciones constexpr.

Así que mi pregunta es, ¿me estoy perdiendo algo? ¿Hay una buena razón por la cual la colocación nueva está prohibida en constexpr funciones constexpr ?

(Para el contexto: las reglas actuales requieren bastante que los tipos de suma habilitados para constexpr como std::variant se implementen como una unión recursiva. Sería mejor poder usar algo como std::aligned_storage y la ubicación nueva, pero actualmente eso es imposible.)


#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; }

Es ciertamente imaginable que un compilador pueda entender el programa anterior. En general, no creo que sea factible debido a la complejidad necesaria para garantizar que el parámetro de ubicación siempre apunte a la memoria local.

No creo que el concepto de "memoria" se aplique a las funciones constexpr porque generalmente se evalúan en tiempo de compilación.