Why can't a stateful but `constexpr` lambda not be used as a non-type template parameter?

Somehow I still think of lambdas as "syntactic sugar" for regular function objects, so it surprises me that under C++-20 a stateful but otherwise constexpr lambda instance cannot be used as a non-type template parameter, unlike an equivalent function object instance.

Can anyone explain this behavior or decision?

Example on godbolt:

struct always_fn {
    const int x;

    int operator()() const
        return x;
inline constexpr always_fn always_f{5};

// lambda equivalent to `always_f`
inline constexpr auto always_2_f = [x = 5]() {
    return x;

template<typename F>
struct wrapped {
    F f_;
inline constexpr auto wrapped_f = wrapped{always_f};
inline constexpr auto wrapped_2_f = wrapped{always_2_f};

template<auto f>
void pass() {}

int main() {
    // error: no matching function for call to 'pass'
 // ^~~~~~~~~~~~~~~~
    // error: no matching function for call to 'pass'
 // ^~~~~~~~~~~~~~~~~

    return 0;


  • Lambdas (whether stateful or not) are never structural types and therefore can never be used as non-type template argument.

    This was clarified by CWG 2542 which compilers might not implement yet.

    Without making such a decision, whether or not the lambda has a structural type would depend on implementation details such as whether the members of the closure type are private/public or the implementation of the closure type would have to be specified in much more detail.

    In particular, there is nothing requiring that x in your equivalent function object should be public and if it isn't, then it wouldn't be usable as non-type template argument either.