I defined the following concept:
template <class T>
concept Config = requires {
{
[]() consteval { return T::len; }()
} -> std::same_as<int>;
};
The requirement is satisfied even if the len
isn't usable in constant expressions:
struct S {
static int len;
};
int main() {
[](Config auto) {}(S{}); // This compiles OK, but I expect it shouldn't
}
Is the concept valid C++?
Your call of an immediate function is in an unevaluated context. This means that it isn't an immediate invocation (and doesn't have to be a constant expression / isn't evaluated).
This essentially means that making it consteval
doesn't actually add anything, so it's as if it wasn't an immediate function ([]() { return T::len; }
). Which is satisfied since the deduced return type is int
.
If you want to use an immediate function, it has to be in a potentially-evaluated position (see also: In a nested requirement, why use `requires bool_constant<X>::value;` instead of `requires X;`?):
template <class T>
concept Config = requires {
{ auto(T::len) } -> std::same_as<int>;
requires std::bool_constant<([] consteval {
return T::len;
}(), true)>::value;
};
Which can be written without the consteval
lambda:
template <class T>
concept Config = requires {
{ auto(T::len) } -> std::same_as<int>;
requires std::bool_constant<(auto(T::len), true)>::value;
};