Name für Basisklasse + Typedef gesucht



  • class Control
    {
        private:
        shared_ptr<Control> shared_from_control()
        {//KA, was Control::shared_from_this vorher machte
        }
        public:
        template<typename DERIVED>
        static shared_ptr<DERIVED> shared_from(DERIVED* d)//Ich benutze den Typ von this
        {
            return static_pointer_cast<DERIVED>(d->shared_from_control());
        }
    };
    
    class HappyFooControl : public FooControl
    {
    public:
        typedef FooControl Base;//jetzt nur noch private Bequemlichkeit
    
        virtual void PostConstructor()
        {
            Base::PostConstructor();
            ConnectToEvent(someEvent, &HappyFooControl::FunFunFun, shared_from(this));//eh netterer aufruf, oder?
        }
    


  • Hmja, das wäre ne Möglichkeit.

    eh netterer aufruf, oder?

    Nö, gefällt mir eigentlich nicht so gut.

    Hier zieht auch wieder das "zusätzliche Abstraktion" Argument: shared_from_this() ist die Signatur die die Leute kennen und erwarten, etwas anderes muss man erst wieder lernen/kennen.
    Obwohl ich zugeben muss dass es weniger "versteckt" ist als das automagische Vorhandensein von shared_from_this() mit dem passenden Returntyp.

    Muss ich mal, wenn ich Musse habe, die Vor- und Nachteile der beiden Varianten gegeneinander abwägen. Das "Doxygen-Problem" wäre dadurch natürlich gelöst, und das fände ich nicht schlecht. Hmmm...

    🙂



  • shared_from_this() aus boost kannte ich nicht. Schade, daß es dort nicht schon shared_from(this) heißt.

    Ich würde trotzdem ungern eine Zwischenklasse in die Vererbungshierarchie einhängen, nur um einen kleinen Trick abzuziehen, der nicht soo wichtig ist. Das Makro wäre ja auch keine Schande.

    Also nicht

    class HappyFooControl : public ControlProxyEnableSharedFromThis<HappyFooControl, FooControl>
    

    wo gemeint ist

    class HappyFooControl : public FooControl
    

    Vielleicht wäre das genehm?

    template<typename BASE,typename DERIVED>
    class ControlMixinEnableSharedFromThis
    {
        typedef BASE Base;
        shared_ptr<DERIVED> shared_from_this() {
            return static_pointer_cast<DERIVED>(static_cast<DERIVED*>(this)->Control::shared_from_this());
        }
    };
    class HappyFooControl : public FooControl, ControlMixinEnableSharedFromThis<HappyFooControl,FooControl>
    {
    


  • Auch nicht doof 🙂

    Wobei... wird das nicht ambiguous? Muss ich morgen ausprobieren.



  • hustbaer schrieb:

    Auch nicht doof 🙂
    Wobei... wird das nicht ambiguous? Muss ich morgen ausprobieren.

    Es wird ambig.



  • lol, dann kommen wir heute zu einem sehr sehr seltenen Gast, der virtuellen Vererbung. Oder mein Compiler ist nur müde geworden und ist zu erschöpft, mir noch zu widersprechen.

    #include <iostream>
    #include <boost/shared_ptr.hpp>
    #include <boost/enable_shared_from_this.hpp>
    using namespace boost;
    
    class Control:virtual public enable_shared_from_this<Control>
    {
    };
    
    template<typename DERIVED>
    struct EnableSharedFromThisControlMixin:virtual public enable_shared_from_this<Control>
    {
        shared_ptr<DERIVED> shared_from_this()
        {
            return static_pointer_cast<DERIVED>(enable_shared_from_this<Control>::shared_from_this());
        }
    };
    
    class FooControl : public Control
    {
    public:
        void SomeFunction()
        {
        }
    };
    
    class HappyFooControl : public FooControl, public EnableSharedFromThisControlMixin<HappyFooControl>
    {
    public:
        typedef FooControl Base;
    
        using Base::SomeFunction;
    
        static void test(shared_ptr<HappyFooControl>)
        {
            std::cout<<"sphfc\n";
        }
    
        virtual void PostConstructor()
        {
            test(shared_from_this());
        }
    
    private:
        void FunFunFun(int& eventData);
    };
    
    int main()
    {
        shared_ptr<HappyFooControl> hfc(new HappyFooControl);
        hfc->PostConstructor();
    }
    


  • hustbaer schrieb:

    Man kann durchaus direkt ableiten. Nur tu' ich es nicht, weil ich es mit der Zwischenbasisklasse praktischer finde.

    Das selbe würde sich mit einem Makro erreichen lassen

    Auch wenn Makros per se nicht so schön sind, würde ich diese Lösung favorisieren; aber halt nur als einer von etlichen potentiellen Nutzern deiner Library (bin übrigens gespannt, hoffe du schaffst es das durchzuziehen!).

    Das typedef könnte man dann ja noch weglassen, statt Base:: dann OwnerDrawControl:: oder BaseControl:: o.Ä. zu schreiben, wäre ja in Ordnung und direkter ersichtlich. Nennt man das Makro dann noch z.B. CONTROL_IMPL_SHAREDFROMTHIS , ist das ganze IMO ein sehr, sehr verständliches Ding 🙂



  • Ja, das Typedef ist noch mehr als der shared_from_this() Override Bequemlichkeit.
    Viele GUI Controls enthalten viel ähnlichen Code, und wenn die Basisklasse überall über den selben Namen referenziert wird, muss man weniger anpassen, wenn man Code aus einer Klasse als Vorlage für Code einer neuen Klasse kopiert.
    Mag jetzt doof und kleinlich klingen, aber ich finde das schon recht praktisch.

    Und es hilft beim Refactoring, wenn man Klassen umbenennt. Wenn ich FooControl mal in QuuxControl umbenenne, dann muss ich an deutlich weniger Stellen was ändern, wenn abgeleitete Klassen nur an jeweils 1-2 Stellen "FooControl" stehen haben, und die restlichen Stellen einfach "Base::" verwenden.
    Obwohl das mit Visual Assist X schon recht schön automatisiert ist, aber auch der übersieht mal was.

    Bzw. auch wenn man ein Control "rebased", also das Basis-Control umstellt. Mach' ich zwar nicht oft, aber ist durchaus schon mehr als 1x vorgekommen.

    aber halt nur als einer von etlichen potentiellen Nutzern deiner Library (bin übrigens gespannt, hoffe du schaffst es das durchzuziehen!).

    Ich hoffe bloss du rechnest jetzt nicht mir irgendwas open-sourcigem - die Library mach' ich für meine Firma, da wird sich leider nix veröffentlichen lassen.



  • Oder die Bedeutung aus dem Namen weitgehend rausmachen, und nur noch sagen: Da sind halt praktische Sachen drin.

    class HappyFooControl : public FooControl, public ControlUtils<HappyFooControl>
    
    class HappyFooControl : public FooControl, public ControlMixin<HappyFooControl>
    
    class HappyFooControl : public FooControl, public ControlUtilsMixin<HappyFooControl>
    


  • Falls sich noch jemand für die ursprüngliche Frage interessiert, ich mag den Bezeichner 'ThisT' oder etwas ähnlichem mit 'this' dafür. 😉



  • Verstehe nicht... "ThisT" für was?
    Als Name für das Zwischen-Basisklassen-Template?
    Oder als Name für nen Template-Parameter?
    Oder ...?
    😕



  • Ich glaube, er meint Template-Parameter, weil nach dem This ein großes T kommt, und betitelt damit die von int(PI*10^?) aufgeworfene Frage auf Seite 1 als ursprüngliche solche.

    Und ich find das nicht gut, weil this für mich etwas auf Objektebene Stattfindendes ist und Template-Parameter auf Klassenebene laufen.



  • fdfdg schrieb:

    hustbaer schrieb:

    Man kann durchaus direkt ableiten. Nur tu' ich es nicht, weil ich es mit der Zwischenbasisklasse praktischer finde.

    Das selbe würde sich mit einem Makro erreichen lassen

    Auch wenn Makros per se nicht so schön sind, würde ich diese Lösung favorisieren; aber halt nur als einer von etlichen potentiellen Nutzern deiner Library (bin übrigens gespannt, hoffe du schaffst es das durchzuziehen!).

    Das typedef könnte man dann ja noch weglassen, statt Base:: dann OwnerDrawControl:: oder BaseControl:: o.Ä. zu schreiben, wäre ja in Ordnung und direkter ersichtlich. Nennt man das Makro dann noch z.B. CONTROL_IMPL_SHAREDFROMTHIS , ist das ganze IMO ein sehr, sehr verständliches Ding 🙂

    Weiss nicht ob's noch jmd. interessiert, aber ich hab die Änderung jetzt endlich gemacht.
    Sieht jetzt so aus:

    #define GLAZE_DEFAULT_CONTROL_MEMBERS(THIS_TYPE, BASE_CONTROL) \
    	public: \
    		typedef BASE_CONTROL BaseControl; \
    		 \
    		shared_ptr<THIS_TYPE> shared_from_this() \
    		{ \
    			::Glaze::Gui::Detail::AssertControlTypes<THIS_TYPE, BASE_CONTROL>(this); \
    			return static_pointer_cast<THIS_TYPE>(this->::Glaze::Gui::Control::shared_from_this()); \
    		} \
    		 \
    		shared_ptr<THIS_TYPE const> shared_from_this() const \
    		{ \
    			::Glaze::Gui::Detail::AssertControlTypes<THIS_TYPE, BASE_CONTROL>(this); \
    			return static_pointer_cast<THIS_TYPE const>(this->::Glaze::Gui::Control::shared_from_this()); \
    		} \
    		 \
    	private: \
    		// end GLAZE_DEFAULT_CONTROL_MEMBERS
    
    	/////////////////////////////////////////////////////////////////////////////
    
    	namespace Detail {
    
    		//! Helper function for GLAZE_DEFAULT_CONTROL_MEMBERS macro
    		template <class THIS_TYPE, class BASE_CONTROL, class T>
    		inline void AssertControlTypes(T const*)
    		{
    			BOOST_STATIC_ASSERT(::boost::is_same<T BOOST_PP_COMMA() THIS_TYPE>::value);
    			BOOST_STATIC_ASSERT(::boost::is_base_and_derived<BASE_CONTROL BOOST_PP_COMMA() THIS_TYPE>::value);
    		}
    
    	} // namespace Detail
    

    ("Glaze" ist der Name der Library)
    Netter Nebeneffekt: die Doxygen Doku ist nun wieder "hübsch".


Anmelden zum Antworten