2013-06-24 1 views
2

std::vector<std::unique_ptr<MyClass>> 유형의 변수를 람다 식으로 캡처하고 싶습니다 (바꿔 말하면 "이동으로 캡처"). unique_ptr (https://stackoverflow.com/a/12744730/2478832)을 캡처하기 위해 std :: bind를 사용하는 솔루션을 발견하고 그것을 시작점으로 사용하기로 결정했습니다. 그러나 내가 얻을 수있는 제안 된 코드의 가장 단순화 된 버전은 컴파일되지 않습니다 (많은 템플릿 실수, unique_ptr의 복사본 생성자를 호출하려고 시도하는 것 같습니다).std :: bind를 사용하여 람다에서 std :: 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())); 
} 

아무도이 코드의 문제점을 지적 할 수 있습니까?

EDIT : 람다를 변경하여 unique_ptr에 대한 참조를 시도했지만 여전히 컴파일되지 않습니다.

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>   ] 
+0

을 당신이 작성했습니다'[] (표준 :: unique_ptr & & P) {}'대신'[] (INT의 * p를) {}' – Nawaz

+0

의 @ Nawaz : 아니, 정말로. 실제로 람다도'a'도 rvalue-reference를 통해'std :: unique_ptr'을 가져 가야합니다. –

+0

@ DavidRodríguez-dribeas : 왜? – Nawaz

답변

2

std::bind 참조하여 unique_ptr 복용 람다 통과 버전의 문제점 std::function로 전환된다. std::function (Live at ideone)없이 시도 :

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

bind에 두 번째 인수는 호출시 바인딩 된 객체에 전달됩니다 :

#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())); 
} 

여기에 비주얼 스튜디오를 2012 출력을합니다. 문제는 람다가 int*을 사용하지만 인수가 std::unique_ptr<int>이고 후자에서 전으로 변환되지 않는다는 것입니다.

당신이 참조/const를 참조하여 std::unique_ptr을 위해 람다의 서명을 변경하는 경우 그것은 (안된) 컴파일해야

+0

시도해 보았지만 컴파일되지 않습니다. 나는 ideone.com을 통해 테스트하고있다 (그들은 gcc 4.7.2를 가지고있다). 나는 또한 Visual Studio 2012 (11 월 CTP)와 동일한 결과를 시도했습니다. – user2478832

+0

@ user2478832 : IDEONE 링크를 게시 할 수 있습니까? –

+0

예, 여기 있습니다 : http://ideone.com/fYt9Zs – user2478832

0

std::bind의 내부의 나의 이해는 항상 1의 복사본을 만들 것입니다 (그 인수가 rvalue 인 경우 라하더라도) 함수 객체를 움직이는 것이 아니라 함수 객체에 바인드되는 인자 객체를 가져 오게됩니다. 그래서 당신은 객체에 바인딩하려는 객체에 대한 복사 생성자를 항상 호출하게 될 것입니다 심지어는 std::move을 사용하는 경우에도 이동 생성자가 아닌 함수 객체를 반환합니다. std::function CopyConstructible (복사 가능 생성자) ([func.wrap.func.con] P7)로 기능 요구 -

관련 문제