问题
Consider the following code:
#include <iostream>
constexpr int fun(int const&) { return 5; }
struct T { int x; };
int main() {
std::cout << fun(T::x) << std::endl; // Line A
std::cout << requires { fun(T::x); } << std::endl; // Line B
}
If I only comment Line B, then the code cannot be compiled (as expected, since x
is not static in T
). But when I only comment Line A, the code compiles just fine with both Clang 11.0.0 and GCC 10.2.0 (both output 1
). What it is that I am missing about requires
? shouldn't it return false
?
回答1:
A requires expression is one big list of unevaluated operands.
[expr.prim.req]
2 A requires-expression is a prvalue of type bool whose value is described below. Expressions appearing within a requirement-body are unevaluated operands.
And a qualified-id naming a non-static data member always could appear in an unevaluated operand.
[expr.prim.id]
2 An id-expression that denotes a non-static data member or non-static member function of a class can only be used:
as part of a class member access in which the object expression refers to the member's class or a class derived from that class, or
to form a pointer to member ([expr.unary.op]), or
if that id-expression denotes a non-static data member and it appears in an unevaluated operand. [ Example:
struct S { int m; }; int i = sizeof(S::m); // OK int j = sizeof(S::m + 42); // OK
— end example ]
The unevaluated operand where T::x
may appear can be any expression. So even pre-C++20 you could for example write
decltype(fun(T::x)) i{};
来源:https://stackoverflow.com/questions/64798455/requires-ignores-a-field-is-not-static