为什么 std::forward 在 lambda 主体中不起作用?

xml*_*lmx 3 c++ lambda mutable perfect-forwarding c++20

#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([] {});
}
Run Code Online (Sandbox Code Playgroud)

神电演示

为什么 std::forward 在 lambda 体内不起作用?


更新信息:

g++ 可以,但 clang++ 拒绝它。谁是正确的?

Cal*_*eth 5

lambda 的捕获是闭包类的成员,主体是operator() const

您正在尝试在成员函数中移动类的数据成员const,这就是编译器错误告诉您的内容

note: candidate function template not viable: 1st argument ('const (lambda at <source>:20:7)') would lose const qualifier
Run Code Online (Sandbox Code Playgroud)


son*_*yao 5

Clang 拒绝它是正确的。

decltype(fn2)给出 的类型fn2,假设 lambda 闭包类型是T,那么它就是T。lambda 的函数调用运算符是 const 限定的,因此std::forward<decltype(fn2)>(fn2)无法调用。模板参数 forstd::forwardT显式指定, thenstd::forward<decltype(fn2)>应该接受T&(and T&&) 作为其参数类型,但 aconst fn2不能绑定到对非 const 的引用。

作为解决方法,您可以将 lambda 标记为mutable

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

  • 但“fn2”是左值。它是如何绑定到“T&amp;&amp;”的? (2认同)
  • 谢谢您的编辑完美地回答了我的疑问。 (2认同)