Tree mit unique_ptr?



  • Ist mir selbst schon passiert und ich hab stundenlang nach meinem Fehler gesucht 😃

    Naja, wenn du den Destruktor nicht deklarierst und definierst, dann erzeugt der Compiler dir den, das sollte ja klar sein.

    Aber das macht der halt zum Zeitpunkt, wo er die Klassendefinition zu Ende gelesen hat

    class A
    {
    } // <-- quasi hier
    ;
    

    Aber fertig ist er damit eigentlich nocht nicht, denn er kennt damit noch nicht seine gesamte eigenen Definition.

    D.h. er will jetzt von sich selbst den Destruktor generieren (kein Problem), aber er weil den vorher schon benutzen, nämlich durch die Definition des unique_ptr.

    So würde ichs in etwa erklären, ist zwar falsch, aber legt in etwa die Funktionswese dar.

    Gibt so lustige Tabellen im Interwebz, wo drin steht, was ein unique_ptr für was braucht. Sowas z.b.

    Complete type rquirements for unique_ptr and shared_ptr
    
                                unique_ptr       shared_ptr
    +------------------------+---------------+---------------+
    |          P()           |      I        |      I        |
    |  default constructor   |               |               |
    +------------------------+---------------+---------------+
    |      P(const P&)       |     N/A       |      I        |
    |    copy constructor    |               |               |
    +------------------------+---------------+---------------+
    |         P(P&&)         |      I        |      I        |
    |    move constructor    |               |               |
    +------------------------+---------------+---------------+
    |         ~P()           |      C        |      I        |
    |       destructor       |               |               |
    +------------------------+---------------+---------------+
    |         P(A*)          |      I        |      C        |
    +------------------------+---------------+---------------+
    |  operator=(const P&)   |     N/A       |      I        |
    |    copy assignment     |               |               |
    +------------------------+---------------+---------------+
    |    operator=(P&&)      |      C        |      I        |
    |    move assignment     |               |               |
    +------------------------+---------------+---------------+
    |        reset()         |      C        |      I        |
    +------------------------+---------------+---------------+
    |       reset(A*)        |      C        |      C        |
    +------------------------+---------------+---------------+
    

    von Stackoverflow



  • Super, kapiert, dankeschön! 🙂

    Jetzt muss ich aber wieder alles über den Haufen werfen, weil mein bescheidener MSVC2010 tatsächlich für vector noch copy-ctor statt move-ctor benötigt -.- (Upgrade wäre toll, aber meine blöde Visual Assist-Lizenz ist abgelaufen [sagt er beim Update immer], also kann ich das Ding nicht für das neue MSVC neu installieren 😞 und ohne VAssist will ich nicht oder ist MSVC12 so gut, dass man das da auch nicht mehr braucht?)



  • Mh?

    Unique_ptr und Vector geht eigentlich, für deine Klasse (also den tree) brauchst du deswegen dann noch keinen Copy-C-Tor...

    Aber den zu schreiben sollte auch nicht schwer sein, und den Move-C-Tor kriegt man auch ganz gut hin...



  • Ne, eigentlich reicht logisch move für vector aus, aber das scheint ab MSVC2010 noch nicht im der STL angekommen zu sein. Meine Klasse hat move-assignment-operator und move-ctor, aber wenn ich das Ding in einen vector stecken möchte, meckert er, dass der copy-ctor private ist (vorher, dass der wegen unique_ptr nicht erzeugt werden kann, dann hab ich ihn explizit gelöscht).

    Code:

    class ConvertibleRange
    	{
    	public:
    		struct Group
    		{
    			typedef std::unique_ptr<ConvertibleRange> RangePtr;
    
    			std::string name;
    			RangePtr range;
    
    			Group(std::string name, RangePtr&& range) : name(name), range(std::move(range)) {}
    			Group(Group&& other) : name(std::move(other.name)), range(std::move(other.range)) {}
    			Group& operator=(Group&& other);
    
    		private:
    			Group(Group&);
    			Group& operator=(Group&);
    		};
    
    		typedef std::vector<Group> Groups;
    
    		// Methods
                    ConvertibleRange();
                    ConvertibleRange(ConvertibleRange&& other);
                    ConvertibleRange& operator=(ConvertibleRange&& other);
                    ~ConvertibleRange() {}
    
                private:
                    Groups groups;
                };
    

    Sorry fürs Einrücken, irgendwie verballert der das...

    Edit: geht aber mit boost1_53::vector auch nicht. 😞

    Edit:
    Und noch den Fehler:

    1>d:\entwicklungsbibliotheken\boost_1_53_0\boost\container\vector.hpp(629): error C2248: "Ranges::ConvertibleRange::Group::operator =": Kein Zugriff auf private Member, dessen Deklaration in der Ranges::ConvertibleRange::Group-Klasse erfolgte.
    1> c:\...\convertiblerange.h(30): Siehe Deklaration von 'Ranges::ConvertibleRange::Group::operator ='
    1> c:\...\convertiblerange.h(18): Siehe Deklaration von 'Ranges::ConvertibleRange::Group'
    1> d:\entwicklungsbibliotheken\boost_1_53_0\boost\container\vector.hpp(495): Siehe Verweis auf die Instanziierung der gerade kompilierten Funktions-template "void boost::container::vector<T>::assign<T*>(InIt,InIt,void *)".
    1> with
    1> [
    1> T=Ranges::ConvertibleRange::Group,
    1> InIt=Ranges::ConvertibleRange::Group *
    1> ]
    1> d:\entwicklungsbibliotheken\boost_1_53_0\boost\container\vector.hpp(491): Bei der Kompilierung der Klassen-template der boost::container::vector<T>::vector(const boost::container::vector<T> &)-Memberfunktion
    1> with
    1> [
    1> T=Ranges::ConvertibleRange::Group
    1> ]
    1> c:\...\convertiblerange.h(88): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "boost::container::vector<T>".
    1> with
    1> [
    1> T=Ranges::ConvertibleRange::Group
    1> ]

    Edit: Gut, da fehlen auch noch consts, damit es überhaupt richtige copy-ctor, =-operators sind, aber das ändert ja auch nichts.



  • Mh, bei mir (Visual Studio 2012 Ultimate) funktioniert dein Code

    #include "xxx.h"
    
    #include <iostream>
    
    int main()
    {
    	ConvertibleRange cr;
    
    	return 0;
    }
    

    Da du ja nix mit Templates hast sollte alles übersetzt werden und demnach sollten etwaige Fehler auch angezeigt werden.
    Das einzige was ich geändert habe ist, dass ich die 3 Konstruktoren der ConvertibleRange definiert habe (also {} dahinter geschrieben habe).



  • Ja, die sind bei mir in der cpp definiert.

    An der STL scheint's ja nicht zu liegen, weil boost::vector dieselben Probleme hat. std::list auch, wobei ich dachte, da sei eine Kopie wegen unnötiger Umstrukturierung wirklich egal (aber wegen so einem Zeug wie resize wahrscheinlich nicht).

    Aber wenn es nicht an der STL liegt und move eigentlich von MSVC10 unterstützt wird, welches Sprachfeature fehlt denn dann, weswegen die Container alle so einen Mist machen? Ich weiß ja, dass MSVC10 nicht alles kann, aber ich dachte, dass vector<onlyMoveableType> geht...



  • Ich verwende auch VS 2010 und hatte nie Probleme mit std::vector<std::unique_ptr<T>> .

    Also schreib vielleicht mal ein Minimalbeispiel auf, sodass wir uns sicher sein können, dass der Fehler im gezeigten Code liegt.



  • Skym0sh0 schrieb:

    Gibt so lustige Tabellen im Interwebz, wo drin steht, was ein unique_ptr für

    Da du nicht geklaert hast, was C oder I in der Tabelle bedeuten, haettest du dir auch die Tiparbeit sparen koennen, da man eh zum Link muss.



  • Complete/Incomplete Definition...



  • *snip*


Anmelden zum Antworten