Search code examples
c++c++-concepts

Can a consteval lambda be used in concept requirements?


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


Solution

  • 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;
    };