c++;-在lambda中捕获完全转发的vars 我是C++的新手,目前正在为我的第一个项目编写一个控制容器的反转,通过在基类上添加注册并向构造函数转发附加的参数来扩展。

c++;-在lambda中捕获完全转发的vars 我是C++的新手,目前正在为我的第一个项目编写一个控制容器的反转,通过在基类上添加注册并向构造函数转发附加的参数来扩展。,c++,lambda,c++17,variadic-templates,C++,Lambda,C++17,Variadic Templates,目前它运行得很好,但当我多次实例化lambda时,捕获的值似乎被覆盖 例如: struct A{ short a; explicit A(short a_) : a(a_) {} }; struct IC{ virtual unsigned C() = 0; }; struct CImpl : public IC{ explicit CImpl(unsigned c_) : IC(), c(c_) {} unsigned C() override{retu

目前它运行得很好,但当我多次实例化lambda时,捕获的值似乎被覆盖

例如:

struct A{
    short a;
    explicit A(short a_) : a(a_) {}
};
struct IC{
    virtual unsigned C() = 0;
};
struct CImpl : public IC{
    explicit CImpl(unsigned c_) : IC(), c(c_) {}
    unsigned C() override{return c;}
private:
    unsigned c;
};
template<class T, typename...TArgs> 
std::function<T*()> AsMinimalAsItGets(TArgs&&...args)
{ 
    return [&args...]() mutable -> T* 
    { 
        return new T(std::forward<TArgs>(args)...); 
    }; 
} 
auto aFactory = AsMinimalAsItGets<A>(3);
auto cFactory = AsMinimalAsItGets<CImpl>(5);
auto aInst = aFactory();//aInst->a should be 3 but is 5
auto cInst = cFactory();//cInst->C() is 5
结构A{ 短a; 显式A(短A):A(A){ }; 结构IC{ 虚拟无符号C()=0; }; 结构CImpl:公共IC{ 显式CImpl(无符号c_u1;):IC(),c(c_1;){ 无符号C()重写{return C;} 私人: 无符号c; }; 模板 std::函数AsMinimalAsItGets(targets&&…args) { 返回[&args…]()可变->T* { 返回新的T(标准::转发(参数)…); }; } auto aFactory=AsMinimalAsItGets作为解决方案,但它没有解决问题

那么,在实例化lambda时,如何正确捕获变量呢?
我需要以一种能够让我在lambda中使用完美转发的方式进行捕获

当您实际需要拷贝时,不要试图避免拷贝。在本例中,您尝试通过
std::forward
保存参数的值类别。但是,当您返回工厂函数
std::function
时,此闭包必须拥有用于执行延迟构造的数据。否则,您将以悬空引用结束,因为传递给
asminimalsitgets
的参数仅在函数调用的范围之外

解决方法很简单:

template<class T, typename...TArgs> 
std::function<T*()> AsMinimalAsItGets(TArgs&&...args)
{ 
    return [args...]() mutable -> T* 
    //      ^^^^^^^ (1) Copy the arguments into the closure
    { 
        return new T(args...); 
        //           ^^^^^^^ (2) Pass them as is to the ctor
    }; 
} 
模板
std::函数AsMinimalAsItGets(targets&&…args)
{ 
返回[args…]()可变->T*
//^(1)将参数复制到闭包中
{ 
返回新的T(参数…);
//^^^^^(2)按原样将其传递给ctor
}; 
} 
请注意,@HolyBlackCat指出,这并没有将参数完美地转发到lambda捕获中。如中所示,在C++20中,您可以

return [...args = std::forward<TArgs>(args)]() mutable -> T* 
{ 
    return new T(args...); 
}; 
return[…args=std::forward(args)]()可变->T*
{ 
返回新的T(参数…);
}; 
在C++17中,您需要以下解决方法:

return [args = std::make_tuple(std::forward<TArgs>(args)...)]() mutable -> T* 
{ 
    return std::apply([](auto&&... args){ return new T(args...); },
        std::move(args));
}; 
return[args=std::make_tuple(std::forward(args)…])()可变->T*
{ 
return std::apply([](自动&&…参数){返回新的T(参数…;},
std::move(args));
}; 

&args
成为临时../的参考,该临时../同时被更改为新的值这不就是完美的正向
args
?捕获必须是
…args=std::forward(args)
,并且在lambda内部使用
args
也需要
forward
@HolyBlackCat感谢您的帮助,现在应该修复。我想注意std::make\ tuple不适用于左值引用,它们将被值捕获。我改用std::tuple(std::forward(args)…),现在它适用于所有值