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.xe 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 xnunca é uma expressão constante no corpo de foo:
X::get()está marcadoconstexpre não depende do estado dex;Mudar
const X¶const Xfaz 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.xcorreto 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.xeg++ trunkcorretos ao aceitar o trecho (2) ?
xin foonã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).