Home > Back-end >  Why does std::forward not work in the lambda body?
Why does std::forward not work in the lambda body?

Time:12-04

#include <utility>

void f(auto const& fn1)
{
    {
        auto fn2 = std::forward<decltype(fn1)>(fn1);
        auto fn3 = std::forward<decltype(fn2)>(fn2); // ok
        fn3();
    }

    [fn2 = std::forward<decltype(fn1)>(fn1)]
    {
        auto const fn3 = fn2;
        auto fn4 = std::forward<decltype(fn3)>(fn3); // ok
        fn4();
    
        auto fn5 = std::forward<decltype(fn2)>(fn2); // error
        fn5();
    }();
}

int main()
{
    f([] {});
}

godbolt demo

Why does std::forward not work in the lambda body?


Updated Information:

g is ok, but clang rejects it. Who is correct?

CodePudding user response:

Clang is correct to reject it.

decltype(fn2) gives the type of fn2, suppose the lambda closure type is T, then it'll be T. Function-call operator of the lambda is const-qualified, then std::forward<decltype(fn2)>(fn2) fails to be called. The template argument for std::forward is specified as T explicitly, then std::forward<decltype(fn2)> is supposed to accept T& (and T&&) as its parameter type, but a const fn2 can't be bound to reference to non-const.

As the workaround you might mark the lambda as mutable.

[fn2 = std::forward<decltype(fn1)>(fn1)] mutable
{
    auto fn3 = std::forward<decltype(fn2)>(fn2); // fine
    fn3();
}();

CodePudding user response:

The captures of a lambda are members of the closure class, and the body is operator() const.

You are trying to move a data member of a class in a const member function, which is what the compiler error is telling you

note: candidate function template not viable: 1st argument ('const (lambda at <source>:20:7)') would lose const qualifier
  • Related