Problem mit Forward Declaration bei selbstgeschriebenem shared_ptr



  • wxSkip schrieb:

    krümelkacker schrieb:

    ...

    ich meinte den Vorschlag mit dem Template-Funktionspointer. Nachlesen!

    Was Du mit "mein Vorschlag" gemeint hast, war nicht eindeutig.

    void* -> T* geht auch mit einem static_cast

    Um bei dem Ansatz die Konvertierung shared_ptr<derived> --> shared_ptr<base> zulassen zu können, müsstest Du einen zusätzlichen void* im shared_ptr speichern. Dann hättest Du drei Zeiger:
    - T*
    - void*
    - void()(void)
    Warum müsstest Du das? Weil derived* -> base* -> void* -> derived* nicht garantiert verlustfrei ist (Stichwort pointer adjustments)

    Was hindert Dich den daran, folgendes zu benutzen:

    struct sp_control_block
    {
        size_t m_strong_refs;
        size_t m_weak_refs;
        sp_control_block() : m_strong_refs(0), m_weak_refs(0) {}
        virtual void do_delete() = 0;
        virtual ~sp_control_block() {}
    };
    
    template <class T, class D>
    struct sp_cb_plus_deleter : sp_control_block
    {
        T* m_ptr;
        D  m_deleter;
    
        explicit sp_cb_plus_deleter(T* p, D d = D()) : m_ptr(p), m_deleter(d) {}
    
        virtual void do_delete()
        {
            m_deleter(m_ptr);
            m_ptr = 0;
        }
    };
    
    template<class T>
    struct default_deleter
    {
      void operator()(T* ptr) const {delete ptr;}
    };
    
    template<class T, class D>
    inline sp_control_block* alloc_control_block(T* obj, D del)
    {
      return sp_cb_plus_deleter<T,D>(obj,del);
    }
    
    template<class T>
    inline shared_count_base* alloc_control_block(T* obj)
    {
      return alloc_control_block(obj,default_deleter<T>());
    }
    

    ?

    oder gar std::tr1::shared_ptr?



  • wxSkip schrieb:

    Der shared_count ist bei mir durch die ref_count-Map realisiert

    Damit kommst Du zwar um einen zusätzlichen Zeiger im shared_ptr herum, bedeutet aber auch Nachteile (globales Objekt muss entsprechend geschützt werden falls Du mehrere Threads laufen lässt, und Du kannst keine eigenen Deleter verwenden)



  • 1. Ja, das war nicht eindeutig 🙄 . Ich habe bloß vermisst, dass jemand auf meinen Beitrag/meine Frage eingeht.
    2. "pointer adjustments": Wieder was gelernt 😉
    3. Dein Code entspricht da sicherlich mehr den ganzen Pitfalls. Ich wollte bloß wissen, aus welchen Gründen ich meinen umändern sollte.
    4. Wenn ich das richtig verstanden habe, ist die Map langsamer (auch wenns eine unordered_map ist). D.h. so etwas würde dann nicht funktionieren:

    T *t = new T();
    shared_ptr<T> p1(t);
    shared_ptr<T> p2(t);
    

    Brauche ich aber eigentlich auch nicht.



  • @kk:
    Gegen std::tr1::shared_ptr spricht folgendes:
    1. Wenn's nicht sein muss, will ich nicht unbedingt vom TR1 abhängig sein.
    2. Ich brauche einen shared_ptr, dem man die Aufsicht über das Löschen des Pointers wieder entziehen kann (für GUI-Systeme, wo Parents ihre Children selbst verwalten). So was habe ich beim std::shared_ptr nicht gefunden.

    P.S.: Bin gerade beim Implementieren eurer Vorschläge, melde micht dann nochmal 😉



  • > Ich brauche einen shared_ptr, dem man die Aufsicht über das Löschen des Pointers wieder entziehen kann

    Dann ist der Name "shared_ptr" IMHO unangebracht.



  • krümelkacker schrieb:

    > Ich brauche einen shared_ptr, dem man die Aufsicht über das Löschen des Pointers wieder entziehen kann

    Dann ist der Name "shared_ptr" IMHO unangebracht.

    Dann mach mir einen besseren Vorschlag 😉
    Er ist ja meistens shared, aber eben nicht immer.
    -> Die Aufsicht soll natürlich allen shared_ptr-Objekten, die den selben Pointer beinhalten, entzogen werden.

    EDIT: Beispiel:

    shared_ptr<MyWidget> widget(new MyWidget);
    
    widget.DisableManaging();
    widget->SetParent(window);  //widget wird von window gemanaged
    
    //...
    
    widget->SetParent(NULL);
    widget.EnableManaging();
    


  • wxSkip schrieb:

    Dann mach mir einen besseren Vorschlag

    divided_ptr 🙄
    oder unshared_ptr 🤡



  • HighLigerBiMBam schrieb:

    wxSkip schrieb:

    Dann mach mir einen besseren Vorschlag

    divided_ptr 🙄

    😃

    template<typename T> class divided_ptr;
    
    template<typename T> class ptr
    {
        template<int n> class divided
        {
            typedef divided_ptr<T> type;
        }
    };
    


  • wxSkip schrieb:

    Ich brauche einen shared_ptr, dem man die Aufsicht über das Löschen des Pointers wieder entziehen kann (für GUI-Systeme, wo Parents ihre Children selbst verwalten). So was habe ich beim std::shared_ptr nicht gefunden.

    Du könntest auch "einfach" den Deleter manipulieren.

    Gruß



  • wxSkip schrieb:

    EDIT: Beispiel:

    shared_ptr<MyWidget> widget(new MyWidget);
    
    widget.DisableManaging();
    widget->SetParent(window);  //widget wird von window gemanaged
    
    //...
    
    widget->SetParent(NULL);
    widget.EnableManaging();
    

    Du könnest weiterhin shared_ptr/weak_ptr verwenden, indem Du
    im Child ein weak_ptr zum Parent speicherst und
    im Parent ein shared_ptr zum Child speicherst

    Oder Du erfindest diese ganzen Räder nicht alle nochmal neu und nimmst einfach Qt oder gtkmm.



  • wxSkip schrieb:

    HighLigerBiMBam schrieb:

    wxSkip schrieb:

    Dann mach mir einen besseren Vorschlag

    divided_ptr 🙄

    😃
    ...

    Ich meinte divided im Sinne von "geteilte Nutzung" nicht wie shared "gemeinsame Nutzung". Ich finde es passend, und außerdem klingt es cool 🕶



  • shared heißt doch auch geteilt im Sinne von "geteilte Nutzung". divided heißt für mich klar "getrennt". Selbst falls das Wörterbuch eine andere Bedeutung noch vorschlägt, bin ich dennoch ziemlich sicher, dass das die erste Denotation ist, die man im Kopf hat.

    Vll. distributed_ptr?

    Ansonsten mostly_shared_ptr oder most_of_the_time_shared_ptr oder sometimes_shared_ptr oder maybe_shared_ptr oder under_certain_circumstances_shared_ptr 🙂



  • shared ownership = geteilter Besitz



  • krümelkacker schrieb:

    Oder Du erfindest diese ganzen Räder nicht alle nochmal neu und nimmst einfach Qt oder gtkmm.

    Ich muss dazu sagen, dass ich shared_ptrs momentan an 2 Stellen verwenden will:
    1. Ein Projekt ganz ohne externe Libraries. Bisher verwende ich std::shared_ptr, da ich mit TDM-GCC 4.5.1 arbeite. Ich fände es aber geschickt, wenn das Projekt auch mit Compilern ohne TR1 kompilierbar ist (auch ohne boost). Hier benutze ich manchmal auch rohe Pointer wegen der zyklischen Abhängigkeiten, ich könnte mir aber auch vorstellen, auf weak_ptr umzusteigen.
    2. Ein Projekt mit Qt. Dieses Projekt erfordert sowieso C++0x-Support, daher steht std::shared_ptr zur Verfügung. Dort bräuchte ich aber auch diese Managed-Unmanaged-Wechsel. QPointer stellt also 1. keine Bereicherung im Vergleich zu std::shared_ptr dar und 2. erfordert dieser ja, dass nur QObjects als Typ verwendet werden. (was bei mir wahrscheinlich nicht der Fall sein wird)



  • Dann halt andere Vorschläge:

    split_ptr
    forked_ptr
    separated_ptr
    cleft_ptr
    appointed_ptr
    

    Und shared-ownership (mit Bindestrich) ist das Beteiligungsverhältnis. Ich finde nur ein anderes Wort sollte her.



  • Ich plädiere für managed_ptr. (Dass der Pointer sich manchmal nicht managed ist IMHO auch eine Form von Management)



  • Pass bloss auf dass du dir damit nicht selbst in den Fuss schiesst.

    Die übliche Vorgehensweise wäre AFAIK den Parent als Raw-Pointer abzuspeichern, und die Klasse von enable_shared_from_this abzuleiten.
    Dadurch kann GetParent einen shared_ptr zurückgeben, und man hat trotzdem keinen Cycle.



  • hustbaer schrieb:

    Pass bloss auf dass du dir damit nicht selbst in den Fuss schiesst.

    Die übliche Vorgehensweise wäre AFAIK den Parent als Raw-Pointer abzuspeichern, und die Klasse von enable_shared_from_this abzuleiten.
    Dadurch kann GetParent einen shared_ptr zurückgeben, und man hat trotzdem keinen Cycle.

    Wie meinst du das? Ich kann ja nicht einfach die ganzen Qt-Klassen ableiten. Geht es dir um die zyklischen Abhängigkeiten (welche ja nicht das Problem waren)?



  • Mir geht es darum:

    wxSkip schrieb:

    shared_ptr<MyWidget> widget(new MyWidget); 
    
    widget.DisableManaging(); 
    widget->SetParent(window);  //widget wird von window gemanaged 
    
    //... 
    
    widget->SetParent(NULL); 
    widget.EnableManaging();
    


  • Dann verstehe ich nicht, was du gemeint hast.


Anmelden zum Antworten