Considere el siguiente ejemplo ( fragmento (0) ):
struct X
{
constexpr int get() const { return 0; }
};
void foo(const X& x)
{
constexpr int i = x.get();
}
int main()
{
foo(X{});
}
El ejemplo anterior se compila con todas las versiones g++anteriores g++ 10.xy nunca compiladas bajo clang++. El mensaje de error es:
error: 'x' is not a constant expression 8 | constexpr int i = x.get(); |
ejemplo en vivo en godbolt.org
Sin embargo, el tipo de error tiene sentido, ya xque nunca es una expresión constante en el cuerpo de foo:
X::get()está marcadoconstexpry no depende del estado dex;Cambiar
const X&aconst Xhace que el código se compile con cada fragmento del compilador (en godbolt.org) (1) .
Se vuelve aún más interesante cuando marco X::get()como static( (en godbolt.org) fragmento (2) ). Con ese cambio, todas las versiones probadas de g++compilación (incluida la troncal), aunque clang++siempre fallan al compilar.
Entonces, mis preguntas:
¿Es
g++ 9.xcorrecto aceptar el fragmento (0) ?¿Todos los compiladores son correctos al aceptar el fragmento (1) ? Si es así, ¿por qué es importante la referencia?
Son
g++ 9.xyg++ trunkcorrecta al aceptar fragmento (2) ?
xen foono es una expresión constante. Incluso hay un informe de error antiguo (rechazado informalmente) en el sonido metálico por su comportamiento correcto (mientras que GCC tenía un error real).