Consider the following example (snippet (0)):
struct X
{
constexpr int get() const { return 0; }
};
void foo(const X& x)
{
constexpr int i = x.get();
}
int main()
{
foo(X{});
}
The above example compiles with all versions of g++
prior to g++ 10.x
, and never compiled under clang++
. The error message is:
error: 'x' is not a constant expression 8 | constexpr int i = x.get(); |
The error kind of makes sense, as x
is never a constant expression in the body of foo
, however:
X::get()
is markedconstexpr
and it does not depend on the state ofx
;Changing
const X&
toconst X
makes the code compile with every compiler (on godbolt.org) snippet (1).
It gets even more interesting when I mark X::get()
as static
((on godbolt.org) snippet (2)). With that change, all tested versions of g++
(including trunk) compile, while clang++
still always fail to compile.
So, my questions:
Is
g++ 9.x
correct in accepting snippet (0)?Are all compilers correct in accepting snippet (1)? If so, why is the reference significant?
Are
g++ 9.x
andg++ trunk
correct in accepting snippet (2)?