2017-01-09 95 views
1

我使用的是函数的引用(不是我的,从库,我不控制),用类似这样的签名:获取对拉姆达的捕捉值

template<typename T, typename F> 
void do_async(T const&, F); // the second parameter is a callable 

,通常像这样使用

do_async(obj, [this](){ ... }); 

我写了一个类似的功能总是使用相同的回调拉姆达:

template<typename T> 
void do_async_wrapper(T obj) { 
    do_async(obj, [this](){ ... }); 
} 

我的问题造成的FR om因为obj作为参考传递,所以必须保持活动状态,直到调用回调。我的功能应该考虑到这一点,所以调用者不必担心对象的生命周期。这就是为什么它按价值接受。
我愿做这样的事情,以保持它活着:

template<typename T> 
void do_async_wrapper(T obj) { 
    do_async(obj, [this, obj{std::move(obj)}](){ ... }); 
} 

显然,这不会(总是)工作的,是因为参考指向函数本地一个不存在了,而保持活力的是它的(移动)副本。

有什么建议吗?

+0

什么'do_async'与参数做什么?你确定它不在内部复制吗? – TartanLlama

+0

@TartanLlama是的。库文档指定确保对象保持活动状态是调用者的责任。 – baruch

+0

你能链接到文档吗?一个选项是'std :: shared_ptr'。 – TartanLlama

回答

2

由于函子是按值取值的,因此不能直接在函数中存储对象并传递它的引用。 您可以变通,通过使用智能指针为shared_ptr

template<typename T> 
void do_async_wrapper(T obj) { 
    auto ptr = std::make_shared<T>(std::move(obj)); 
    do_async(*ptr, [this, ptr](){ /*...*/ }); 
} 
+0

我被'make_unique'而不是'make_shared'诱惑,因为'do_async'不应该*拷贝* lambda。但是这需要额外的一行才能使其工作('auto&obj_ref = * ptr;')。 – Yakk

+0

@Yakk我使用make_unique进行类似的解决方案。我不需要你展示的那一行。它的目的是什么? – baruch

+0

@baruch:在'* ptr'和'[ptr = std :: move(ptr)]'之间存在2个问题,未指定的顺序,'do_async'中的'F'的副本(这使得2个实例'T'不同)。 – Jarod42