3

我想std::vector<std::unique_ptr<MyClass>>在 lambda 表达式中捕获类型变量(换句话说,“通过移动捕获”)。我找到了一个使用 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>          ]
4

3 回答 3

4

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

如果您将 lambda 的签名更改为std::unique_ptr通过引用/常量引用,它应该编译(未经测试)

于 2013-06-24T14:59:11.503 回答
2

unique_ptr通过引用传递 lambda 的版本的问题std::bind是您转换为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>());
于 2013-06-24T16:57:30.390 回答
0

我对的内部结构的理解std::bind是,它总是会复制绑定到函数对象的第一个参数对象而不是移动它(即使该参数是右值),所以你总是会得到为您尝试绑定到函数对象的任何对象调用复制构造函数,而不是移动构造函数,即使使用std::move.

于 2013-06-24T16:43:26.913 回答