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?
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.