Home > Enterprise >  Is it OK to use lambda function parameter as a constant expression?
Is it OK to use lambda function parameter as a constant expression?

Time:09-18

Why in this example the first call doesn't compile and the second one compiles?

consteval auto foo(auto x) {
    static_assert(x);
}

int main(){
    foo(42);   // error: non-constant condition for static assertion
    foo([]{}); // OK
}

If I understand correctly, the first one is wrong due to lvalue-to-rvalue conversion not being a constant expression. Why then the second one is OK?

CodePudding user response:

static_assert(x); while passing []{} works, because a capture-less lambda has a conversion operator to function pointer and a function pointer can be converted to a bool (which is going to be true for everything but a null pointer which the conversion can't return).

An expression is a core constant expression as long as it doesn't fall in any of a number of exceptions listed in [expr.const]/5. In relation to the potentially relevant exceptions, neither is x a reference, which would disqualify the expression x from being a constant expression immediately, nor is a lvalue-to-rvalue conversion on x or one of its subobjects required in the call to the conversion function or the conversion to bool. The returned function pointer is in no way dependent on the value of the lambda. The call to the conversion function is also allowed in a constant expression, since it is specified to be constexpr ([expr.prim.lambda.closure]/11), so that the exception of calling a non-constexpr function also doesn't apply.

None of the exceptions apply and x (including the conversions to bool) is a constant expression. The same is not true if 42 is passed, because the conversion to bool includes an lvalue-to-rvalue conversion on x itself.

  • Related