2016-07-06 21 views
1

Ich verwende unique_ptr in Kartenwerten. Ich muss diese Werte als eine Liste/einen Vektor von rohen Zeigern erhalten. Bisher habe ich Folgendes getan.Iterate rohe Zeiger von unique_ptr in Kartenwerte

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

Aber das kompiliert nicht. Die relevent Fehlermeldung scheint

„/usr/include/c++/4.8/bits/stl_tree.h:140:49 zu sein: Hinweis: nicht ‚std :: Vorwärts umwandeln kann ((* & __args # 1)) '(Typ 'Foo * const std') eingeben' :: unique_ptr & ‚“

Aber ich bin nicht sicher, ob ich verstehe, was es bedeutet, da mein Verständnis ist, dass it.second zurückkehren ein Verweis auf die unique_ptr nicht die Foo-Instanz selbst nimmt an, dass, wo das Problem ist. Was muss getan werden, um dieses Beispiel zu beheben?

Bearbeiten Ich verwende eine etwas ältere Version g ++.

g ++ (Ubuntu 4.8.4-2ubuntu1 ~ 14.04.3) 4.8.4

mit Befehlszeile.

g ++ -std = C++ 11 -o einzigartig unique.cpp

+0

Kompiliert für mich. 'g ++ (GCC) 6.1.1 20160602', keine zusätzlichen Flags. – Thomas

+0

Interessant. Also könnte es ein Compiler Bug sein? Habe gerade meine Compilerdetails hinzugefügt. – chamibuddhika

+0

Clang ++ akzeptiert es auch (wenn "-std = C++ 11" angegeben). 'clang Version 3.8.0 (tags/RELEASE_380/final'. – Thomas

Antwort

1

Der Fehler, den Sie erhalten, ist, weil die implizite Konvertierung von Foo* zu nicht zulässig ist. Das liegt daran, dass der Konstruktor unique_ptr, der einen rohen Zeiger verwendet, mit explicit gekennzeichnet ist. Ich bin nicht sicher, warum oder wie ihre Arbeits in g ++> 6.0 Bibliothek:

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

Also, sollten Sie es eine unique_ptr und move während Sie ein emplace

HINWEIS erschaffen. Aber persönlich denke ich nicht, dass es unbedenklich ist, rohe Zeiger implizit in intelligente Zeiger umzuwandeln. Um zu wissen, warum, siehe: https://stackoverflow.com/a/11367997/434233

+0

Danke für die Erklärung und den Link. Macht jetzt mehr Sinn. Ich werde es als die bessere Antwort akzeptieren, da Sie den Grund für dieses Verhalten erklärt haben. – chamibuddhika

+0

@Arunmu Stimmen völlig zu, dass diese implizite Umwandlung gefährlich ist, aber der Sutter Artikel, den Sie verlinken, spricht über die andere Richtung (intelligent zu roh, nicht roh zu intelligent). – Thomas

+0

@Thomas Ja, danke. Der Link wurde aktualisiert, um auf die relevante Antwort zu zeigen – Arunmu

1

Wenn ich diesen Code ausführen, scheint die Beschwerde bei der Schaffung der std::pair Klasse bezogen werden.

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

Für mich, das baut und es funktioniert, nicht, dass ich mit Sicherheit sagen kann, dass es wirklich tun wird, was Sie wünschen. Nur dass es für mich kompiliert und läuft.

Ich verbringe den Großteil meiner C++ Zeit mit QT-Bibliotheken und Klassen, aber es sieht so aus, als ob es keinen Weg findet, ein Paar mit FOO* an die unique_ptr<FOO> zu drehen.

+0

In der Tat! Als ich die explizite std :: pair-basierte Einfügung verwendete, funktionierte es. Sieht so aus, als ob emplace nicht so funktioniert, wie ich es mir vorgestellt habe (zumindest für meinen aktuellen Compiler). – chamibuddhika