#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([] {});
}
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