简体   繁体   中英

Invoking `constexpr` member function through reference - clang vs gcc

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(); |

live example on godbolt.org

The error kind of makes sense, as x is never a constant expression in the body of foo , however:

  • X::get() is marked constexpr and it does not depend on the state of x ;

  • Changing const X& to const 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 and g++ trunk correct in accepting snippet (2) ?

Is g++ 9.x correct in accepting snippet (0)?

No.

Are all compilers correct in accepting snippet (1)? If so, why is the reference significant?

Yes, they are.

A constant expression cannot use an id-expression naming a reference that doesn't have a previous constant expression initialization or began its lifetime during the constant expression evaluation. [expr.const]/2.11 ( same in C++20 )

The same is not true if you are naming a non-reference variable without involving any lvalue-to-rvalue conversion. x.get() only refers to x as lvalue and only calls a constexpr function that doesn't actually access any member of x , so there is no issue.

Are g++ 9.x and g++ trunk correct in accepting snippet (2)?

No, because the expression still contains the subexpression x which violates the rule mentioned above.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM