如何从C ++ 14中的广义lambda捕获返回包含std :: unique_ptr的std :: function?

时间:2015-07-29 04:37:02

标签: c++ lambda c++14

我们如何从C ++ 14中的广义lambda捕获返回包含std::function的{​​{1}}?具体来说,在以下代码中

std::unique_ptr

使用GCC 4.9.2和C ++ 14打开时,一切正常。具体来说,它表明广义lambda捕获工作。但是,当我们将代码更改为// For std::function #include <functional> // For std::iostream #include <iostream> // For std::unique_ptr #include <memory> #if 0 std::function <void()> make_foo() { auto x = std::make_unique <int> (3); return [x=std::move(x)]() { std::cout << *x << std::endl; }; } #endif int main() { auto x = std::make_unique <int> (3); auto foo = [x=std::move(x)]() { std::cout << *x << std::endl; }; foo(); } 时,我们会收到编译错误:

#if 1

现在,鉴于我们返回的功能包含g++ -g -std=c++14 test01.cpp -o test01 In file included from test01.cpp:4:0: /usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/include/g++-v4/functional: In instantiation of 'static void std::_Function_base::_Base_manager<_Functor>::_M_clone(std::_Any_data&, const std::_Any_data&, std::false_type) [with _Functor = make_foo()::<lambda()>; std::false_type = std::integral_constant<bool, false>]': /usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/include/g++-v4/functional:1914:51: required from 'static bool std::_Function_base::_Base_manager<_Functor>::_M_manager(std::_Any_data&, const std::_Any_data&, std::_Manager_operation) [with _Functor = make_foo()::<lambda()>]' /usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/include/g++-v4/functional:2428:19: required from 'std::function<_Res(_ArgTypes ...)>::function(_Functor) [with _Functor = make_foo()::<lambda()>; <template-parameter-2-2> = void; _Res = void; _ArgTypes = {}]' test01.cpp:17:5: required from here /usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/include/g++-v4/functional:1878:34: error: use of deleted function 'make_foo()::<lambda()>::<lambda>(const make_foo()::<lambda()>&)' __dest._M_access<_Functor*>() = ^ test01.cpp:15:27: note: 'make_foo()::<lambda()>::<lambda>(const make_foo()::<lambda()>&)' is implicitly deleted because the default definition would be ill-formed: return [x=std::move(x)]() { ^ test01.cpp:15:27: error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]' In file included from /usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/include/g++-v4/memory:81:0, from test01.cpp:10: /usr/lib/gcc/x86_64-pc-linux-gnu/4.9.2/include/g++-v4/bits/unique_ptr.h:356:7: note: declared here unique_ptr(const unique_ptr&) = delete; ^ Makefile:2: recipe for target 'all' failed make: *** [all] Error 1 ,我们无法复制生成的std::unique_ptr。但是,由于我们正在返回一个动态创建的lambda函数,这不应该是一个r值而且定义有效吗?基本上,有没有办法解决std::function我们仍然有一个make_foo的广义lambda捕获?

2 个答案:

答案 0 :(得分:5)

As @ T.C。在评论中std::function requires说它包装的可调用者是CopyConstructible,而你的lambda不是因为unique_ptr数据成员。

您可以使用C ++ 14的函数返回类型推导来从make_foo返回lambda,并避免将其包装在std::function中。

auto make_foo() {
    auto x = std::make_unique <int> (3);
    return [x=std::move(x)]() {
        std::cout << *x << std::endl;
    };
}

make_foo()();  // prints 3

Live demo

答案 1 :(得分:3)

std::function是不必要的可复制的(你多久经常想要复制std::function?)。由于类型擦除,您可以复制std::function的事实意味着您存储在std::function中的内容必须是可复制的,即使您从未这样做过!

您可以非常轻松地实现仅限移动std::function。获得良好的QOI更难 - 类似于SSO(小字符串优化)的SFO(小函数优化)是避免无用堆分配的好主意。

http://sandbox.onlinephpfunctions.com/code/fa5b2e7e6602e60cdeb054b705a69e4a226bd52c是仅限移动std::function的草图task。它没有SFO。

只有当您需要存储在代码中生成的lambda&#34; type-unconnected&#34;时才需要它。生成lambda的代码。如果您不必这样做,您可以返回auto并公开您的实现,让C ++ 14返回类型演绎为您完成工作。