Igor R.
Igor R.

Reputation: 15075

When does reference evaluation make something not a constant expression?

Consider the following snippet:

struct test1 {
    static constexpr int get()  {
        return 1;
    }
};

struct test2 {
    constexpr int get() const {
        return 1;
    }
};

template <class T>
int get(T&& t) {
    if constexpr (t.get() == 1) {
        return 1;
    }
    return 2;
}

int main() {
    return get(test1{}) + get(test2{});
}

When trying to compile with GCC-11.1 (-std=c++2a), get template successfully compiles with test1, but not with test2. The only difference between them is fact that test2::get is static.

Obviously, it does not compile with test2, because t parameter is not a "core constant expression", as per 7.7 expr.const(5.13):

An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine, would evaluate one of the following expressions:

  • an id-expression that refers to a variable or data member of reference type unless the reference has a preceding initialization...

The question is why it does compile, when the function being accessed via the very same reference is static. Isn't the refence "evaluated" in this case? Is it a GCC bug or there's some wording in the Standard that allows it?

Upvotes: 5

Views: 211

Answers (1)

dfrib
dfrib

Reputation: 73186

Pointers and references to unknowns in constant expressions being directly ill-formed will possibly be addressed in C++23 and, if so, as a Defect Report for earlier language versions.


[...] when the function being accessed via the very same reference is static. Isn't the refence "evaluated" in this case? Is it a GCC bug or there's some wording in the Standard that allows it?

Your program is ill-formed also for the static case, as is answered in detail in the follow Q&A:

However, EWG considered this a defect in the specification of constexpr, and recommending CWG to consider resolving it by P2280R3 (Using unknown pointers and references in constant expressions), targeted for C++23, and as a DR (defect report) for C++11 through C++20.

jfbastien commented on Feb 3, 2021

EWG saw this paper in today's telecon.

P2280 Using unknown references in constant expressions

The use cases presented in P2280 are problems in C++’s specification of constexpr, and we would like to fix these problems, ideally in C++23.

This should be a Defect Report against C++20, C++17, C++14, and C++11.

CWG agreed and P2280 has now been accepted into C++23 and as a defect report.

Upvotes: 4

Related Questions