gpt4 book ai didi

c++ - 在 lambda 中捕获完美转发的变量

转载 作者:行者123 更新时间:2023-12-01 14:07:34 25 4
gpt4 key购买 nike

我对 C++ 很陌生,目前正在为我的第一个项目编写一个控制反转容器,扩展到 this blog post通过在基类上添加注册并将其他参数转发给构造函数。
它现在工作得很好,但是当我多次实例化一个 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 被实例化为 5 而不是 3。
我试过 this作为解决方案,但它没有解决问题。
那么在实例化 lambda 时如何正确捕获变量?
我需要以一种使我能够在 lambda 中使用完美转发的方式进行捕获

最佳答案

当你真正需要一个拷贝时,不要试图避免拷贝。在您的情况下,您尝试通过 std::forward 保留参数的值类别。他们。但是当你返回一个工厂函数时 std::function<T*()> ,这个闭包必须拥有它用来执行延迟构造的数据。否则,您最终会得到悬空引用,因为参数传递给 AsMinimalAsItGets只比函数调用的范围长。
修复很简单:

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
};
}
请注意,正如@HolyBlackCat 指出的那样,这并不能完美地将参数转发到 lambda 捕获中。如 this answer所示, 在 C++20 中,你可以
return [...args = std::forward<TArgs>(args)]() mutable -> T* 
{
return new T(args...);
};
在 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));
};

关于c++ - 在 lambda 中捕获完美转发的变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63414770/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com