2016-07-06 3 views
1

맵 값에 unique_ptr을 사용하고 있습니다. 그 값을 원시 포인터의 목록/벡터로 가져와야합니다. 지금까지 나는 다음과 같이했다.맵 값에서 unique_ptr의 원시 포인터를 반복합니다.

#include <iostream> 
#include <string> 
#include <vector> 
#include <memory> 
#include <map> 

class Foo { 
    public: 
    std::string val; 

    Foo(std::string v) : val(v) { 
    } 
}; 

class Unique { 
    public: 
    std::map<int, std::unique_ptr<Foo>> unique_map; 

    std::vector<Foo*> getFoos() { 
     std::vector<Foo*> foos; 
     for (auto& it : unique_map) { 
     foos.push_back(it.second.get()); 
     } 

     return foos; 
    } 
}; 

int main() { 
    Unique unique; 
    Foo* f1 = new Foo("1"); 
    Foo* f2 = new Foo("2"); 

    unique.unique_map.emplace(1, f1); 
    unique.unique_map.emplace(2, f2); 

    std::vector<Foo*> foos = unique.getFoos(); 

    for (Foo* foo : foos) { 
    std::cout << foo->val; 
    } 

    std::cout<<"\n"; 

    return 0; 
} 

그러나 컴파일이 실패합니다. 주의 : 관련된 가장 중요한 오류 메시지가

는 "/usr/include/c++/4.8/bits/stl_tree.h:140:49 것으로 보인다 을 변환 할 수 없습니다 '표준 앞으로 :: ((* & __args 번호 1)) '(유형'푸 * const를 표준 : & unique_ptr ' "

')을 입력합니다 '하지만 내 이해가 it.second 반환이기 때문에 나는 그것이 무슨 뜻인지 확실하지 않다 unique_ptr에 대한 참조는 Foo 인스턴스가 아니라 문제가있는 것으로 가정합니다. 이 예제를 수정하기 위해 수행해야 할 작업은 무엇입니까?

편집 다소 나이가 많은 g ++ 버전을 사용하고 있습니다.

그램 ++ (~ 14.04.3 우분투 4.8.4-2ubuntu1) 명령 라인 4.8.4

. 이 코드를 실행하면

그램 ++ -std = C++ (11) -o 독특한 unique.cpp는

+0

나를 위해 컴파일하십시오. 'g ++ (GCC) 6.1.1 20160602', 추가 플래그 없음. – Thomas

+0

흥미 롭습니다. 그래서 컴파일러 버그일까요? 그냥 내 컴파일러 세부 정보를 추가했습니다. – chamibuddhika

+0

Clang ++도 그것을 받아들입니다 ('-std = C++ 11'이 주어 졌을 때). 'clang version 3.8.0 (tags/RELEASE_380/final'. – Thomas

답변

1

Foo*에서 std::unique_ptr<Foo>으로의 암시 적 변환이 허용되지 않기 때문에 오류가 발생합니다. 왜냐하면, 원시 포인터를 취하는 unique_ptr의 생성자는 explicit으로 표시되어 있기 때문입니다. emplace

참고하는 동안

explicit 
     unique_ptr(pointer __p) noexcept 
     : _M_t(__p, deleter_type()) 
     { static_assert(!is_pointer<deleter_type>::value, 
        "constructed with null function pointer deleter"); } 

그래서, 당신은 unique_ptrmove를 작성해야한다 : 나는 확실하지 않다 왜 또는 어떻게 g ++> 6.0 라이브러리에서의 작업. 하지만 개인적으로 원시 포인터를 암시 적으로 스마트 포인터로 변환하는 것이 안전하다고 생각하지 않습니다. 이유를 알아 보려면 https://stackoverflow.com/a/11367997/434233

+0

설명과 링크를 제공해 주셔서 감사합니다. 지금 더 의미가 있습니다. 나는 당신이이 행동에 대한 이유를 설명했기 때문에 그것을 더 좋은 대답으로 받아 들일 것입니다. – chamibuddhika

+0

@Arunmu이 암시 적 전환이 위험하다는 것에 전적으로 동의하지만 Sutter의 기사에서는 링크를 사용하여 다른 방향 (원시에서 영리하지 않음)에 대해 이야기합니다. – Thomas

+0

@ 토마스 그래, 고마워. 관련 답변을 가리 키도록 링크를 업데이트했습니다. – Arunmu

1

, 불만은 std::pair 클래스의 생성과 관련이있을 것으로 보인다.

unique.unique_map.emplace(1, std::unique_ptr<Foo>(f1)); 
unique.unique_map.emplace(2, std::unique_ptr<Foo>(f2)); 

나를 위해,이 빌드 및 작동, 내가 말할 수있는 것은 그것이 실제로 당신이 원하는대로 할 수있는 것은 아닙니다. 그것은 컴파일되고 실행됩니다.

나는 QT 라이브러리와 클래스를 사용하여 대부분의 C++ 시간을 소비하지만 FOO*unique_ptr<FOO>으로 쌍을 변환하는 방법을 찾지 못한 것 같습니다.

+0

실제로! 명시 적 std :: pair 기반 삽입을 사용했을 때 효과가있었습니다. emplace가 내가 생각하고있는 방식으로 작동하지 않는 것처럼 보입니다 (적어도 현재 컴파일러 인 것처럼 보입니다). – chamibuddhika

관련 문제