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

wye*_*r33 7 c++ lambda c++14

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

// 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();
}
Run Code Online (Sandbox Code Playgroud)

在使用GCC 4.9.2和C++ 14打开时,一切正常.具体来说,它表明广义lambda捕获工作.但是,当我们更改代码时#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
Run Code Online (Sandbox Code Playgroud)

现在,假设我们返回的函数包含a std::unique_ptr,那么我们无法复制结果是有意义的std::function.但是,由于我们正在返回一个动态创建的lambda函数,这不应该是一个r值而且定义有效吗?基本上,有没有办法解决make_foo我们仍然有一个广义lambda捕获std::unique_ptr?

Pra*_*ian 7

正如@TC在评论中所说,std::function 要求它包装的可调用者是CopyConstructible,而你的lambda不是因为unique_ptr数据成员.

您可以使用C++ 14的返回类型推导函数来返回lambda make_foo并避免将其包装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
Run Code Online (Sandbox Code Playgroud)

现场演示