Considere o seguinte exemplo ( snippet (0) ):
struct X
{
constexpr int get() const { return 0; }
};
void foo(const X& x)
{
constexpr int i = x.get();
}
int main()
{
foo(X{});
}
O exemplo acima é compilado com todas as versões g++
anteriores g++ 10.x
e nunca compiladas abaixo clang++
. A mensagem de erro é:
error: 'x' is not a constant expression 8 | constexpr int i = x.get(); |
exemplo ao vivo em godbolt.org
O erro meio que faz sentido, pois x
nunca é uma expressão constante no corpo de foo
:
X::get()
está marcadoconstexpr
e não depende do estado dex
;Mudar
const X&
paraconst X
faz com que o código seja compilado com todos os trechos do compilador (em godbolt.org) (1) .
Fica ainda mais interessante quando eu marcar X::get()
como static
( (no godbolt.org) trecho (2) ). Com essa alteração, todas as versões testadas g++
(incluindo o tronco) são compiladas, embora clang++
sempre falhem na compilação.
Então, minhas perguntas:
Está
g++ 9.x
correto ao aceitar o snippet (0) ?Todos os compiladores estão corretos ao aceitar o snippet (1) ? Se sim, por que a referência é significativa?
São
g++ 9.x
eg++ trunk
corretos ao aceitar o trecho (2) ?
x
in foo
não é uma expressão constante. Existe até um relatório de bug antigo (rejeitado informalmente) no clang por seu comportamento correto (enquanto o GCC tinha um bug real).