麻烦使用std :: bind在lambda中捕获std :: unique_ptr

时间:2013-06-24 14:55:03

标签: c++ c++11 lambda unique-ptr

我想在lambda表达式中捕获类型std::vector<std::unique_ptr<MyClass>>的变量(换句话说,“通过移动捕获”)。我找到了一个使用std :: bind捕获unique_ptr(https://stackoverflow.com/a/12744730/2478832)的解决方案,并决定将其用作起点。但是,我可以得到的最简化版本的代码不能编译(很多模板错误,似乎试图调用unique_ptr的复制构造函数)。

#include <functional>
#include <memory>

std::function<void ()> a(std::unique_ptr<int>&& param)
{
    return std::bind( [] (int* p) {},
        std::move(param));
}

int main()
{
    a(std::unique_ptr<int>(new int()));
}

有人能指出这段代码有什么问题吗?

编辑:尝试更改lambda以引用unique_ptr,它仍然无法编译。

#include <functional>
#include <memory>

std::function<void ()> a(std::unique_ptr<int>&& param)
{
    return std::bind( [] (std::unique_ptr<int>& p) {}, // also as a const reference
        std::move(param));
}

int main()
{
    a(std::unique_ptr<int>(new int()));
}

这是Visual Studio 2012输出:

1>C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\tuple(151): error C2248: 'std::unique_ptr<int,std::default_delete<_Ty>>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<int,std::default_delete<_Ty>>'
1>          with
1>          [
1>              _Ty=int
1>          ]
1>          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\memory(1447) : see declaration of 'std::unique_ptr<int,std::default_delete<_Ty>>::unique_ptr'
1>          with
1>          [
1>              _Ty=int
1>          ]
1>          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\tuple(521) : see reference to function template instantiation 'std::_Tuple_val<_This>::_Tuple_val<const _Ty&>(_Other)' being compiled
1>          with
1>          [
1>              _This=std::unique_ptr<int,std::default_delete<int>>
1>  ,            _Ty=std::unique_ptr<int,std::default_delete<int>>
1>  ,            _Other=const std::unique_ptr<int,std::default_delete<int>> &
1>          ]
1>          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\tuple(521) : see reference to function template instantiation 'std::_Tuple_val<_This>::_Tuple_val<const _Ty&>(_Other)' being compiled
1>          with
1>          [
1>              _This=std::unique_ptr<int,std::default_delete<int>>
1>  ,            _Ty=std::unique_ptr<int,std::default_delete<int>>
1>  ,            _Other=const std::unique_ptr<int,std::default_delete<int>> &
1>          ]
1>          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\tuple(521) : while compiling class template member function 'std::tuple<std::unique_ptr<int,std::default_delete<_Ty>>,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>::tuple(const std::tuple<std::unique_ptr<_Ty,std::default_delete<_Ty>>,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil> &)'
1>          with
1>          [
1>              _Ty=int
1>          ]
1>          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\functional(1152) : see reference to function template instantiation 'std::tuple<std::unique_ptr<int,std::default_delete<_Ty>>,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>::tuple(const std::tuple<std::unique_ptr<_Ty,std::default_delete<_Ty>>,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil> &)' being compiled
1>          with
1>          [
1>              _Ty=int
1>          ]
1>          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\functional(1152) : see reference to class template instantiation 'std::tuple<std::unique_ptr<int,std::default_delete<_Ty>>,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>' being compiled
1>          with
1>          [
1>              _Ty=int
1>          ]
1>          main.cpp(15) : see reference to class template instantiation 'std::_Bind<false,void,a::<lambda_2ad08ede4c4ce9c02d5497417b633d1d>,std::unique_ptr<int,std::default_delete<_Ty>>,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil,std::_Nil>' being compiled
1>          with
1>          [
1>              _Ty=int
1>          ]

3 个答案:

答案 0 :(得分:4)

bind的第二个参数将在调用时传递给绑定对象。问题是lambda采用int*,但参数是std::unique_ptr<int>,后者没有转换为前者。

如果你改变lambda的签名以通过引用/ const-reference

获取std::unique_ptr,它应该编译(未经测试)

答案 1 :(得分:2)

通过unique_ptr引用std::bind传递lambda的版本的问题是您转换为std::function - std::function要求函数为CopyConstructible([func。 wrap.func.con] p7)。不使用std::functionLive at ideone):

进行试用
auto f = std::bind([](std::unique_ptr<int>&){},
                   std::make_unique<int>());

答案 2 :(得分:0)

我对std::bind内部的理解是,它总是复制第一个参数对象,它被绑定到函数对象而不是移动它(即使该参数是一个右值),因此,即使使用std::move,您最终也会调用复制构造函数来查找试图绑定到函数对象的任何对象,而不是move-constructor。