Designfrage zum thema "fähigkeiten bekanntmachen"



  • späte uhrzeit..naja, das thema hat mich heute abend nicht mehr in ruhe gelassen 😃

    also, ich hab ein komplexes Klassensystem, das auf traits basiert. dh jede klasse hat einen eigenen traitssatz, der abgefragt werden kann, um den code entsprechend optimieren zu können, zb ein vector, der sich bei nicht POD typen anders verhält, als für POD, oder dass er bei Typen, die keinen default ctor haben, nicht versucht, diesen Aufzurufen.

    die frage ist nun, wie ich diese speziellen infos übermitteln soll,zb die sache mit den POD typen, Es ist nicht bekannt, wie der Compiler ermitteln kann, dass ein Typ ein POD ist. Diese Info wird also der User für jede Klasse mitgeben müssen.

    Die Frage ist nur, welcher Ansatz besser wäre:

    hier am Beispiel des IsPod Wertes für die Klasse POD

    //1: Vererbung
    struct IsPod{};
    
    struct POD:public IsPod{
       int a;
       int b;
    };
    
    //implementierung in den Traits
    template<class T>
    struct Traits{
        enum{isPod=isDerived<T,IsPod>::Result};
    };
    
    //2: template spezialisierung
    template<class T>
    struct IsPod{
        enum{Result=false};
    };
    
    struct POD{
       int a;
       int b;
    };
    template<> struct IsPod<POD>{
        enum{Result=true};
    };
    
    //implementierung in den Traits
    template<class T>
    struct Traits{
        enum{isPod=isPod<T>::Result};
    };
    

    die erste version sollte klar sein, die klasse erbt die Eigenschaft, und in den Traits wird nur geprüft, ob die Klasse davon geerbt hat. Die Frage ist nun, ob sich das Erben von einer komplett leeren Klasse irgendwie auswirkt...
    Als deutlicher nachteil wäre noch zu nennen, dass man bei jeder template spezialisation einer Klasse, die komplette liste copy&pasten müsste

    die 2. version arbeitet mit template spezialisation. Zu sagen ist dazu eigentlich nicht soviel, ausser dass es generell ne größere Menge code ist, wenn man mehrere Eigenschaften zu vergeben hat.
    vorteil ist natürlich, dass man nicht wie bei der vererbung copy&pasten müsste.

    was würdet ihr lieber verwenden? vererbung oder template spezialisation?





  • Hallo,
    die Idee mit der Vererbung finde ich lustig wo ein POD-Type schließlich keine Basisklassen besitzen darf...



  • @Hume deshalb hab ich ja auch geschrieben, dass ich mir nicht sicher bin, was eine leere basisklasse anrichtet,hatte das in der nacht noch schnell getestet, und da hat es sich überhaupt nicht ausgewirkt, dh bitwise copy war möglich, aber wenns der standard nicht erlaubt...

    @kingruedi
    der sagt dazu auch nichts weiter(immerhin besitze ich das buch), da er das ganze nie über den status von IsPod hinausgehen lässt-wo wir ja jetzt schon erfahren haben, dass dies im Falle von IsPod nur so geht, da der standard es nicht erlaubt-, aber zb so sachen wie "IsCopyAble" oder "hasDefaultCtor" die man ja auch einfach über vererbung reinpacken könnte werden nicht angesprochen.

    //edit im falle von Klassen, die aber auch nicht instanziert werden, wie zb typlisten oder anderes, könnte man doch die vererbung einfach benutzen oder? spräche irgendwas dagegen(nützlichkeit/einfachkeit/komplexität?)



  • mir gehts eigentlich ja darum,dass ich dem user(dh mir^^) nicht die ganze arbeit aufhalsen will, 5-6 templates zu spezialisieren, damit das system optimal arbeiten kann. Andererseits will ich den user auch nicht dazu zwingen, immer die komplette Traits klasse zu spezialisieren, änderungen im design würden sich dann nämlich fatal auswirken 🙄

    Mir kam grade eine neue idee,vielleicht könnt ihr dazu was schreiben, obs vielleicht irgendwelche probleme geben könnte:

    //in irgendeiner header datei
    class IsCopyAble{};
    class IsClassType{};
    class IsAssignable{};
    class HasDefaultCtor{};
    //...
    template<class T> class TypeInfo{};
    
    //im programm 
    class Test{/.../};
    template<> TypeInfo<Test>:public IsCopyAble,public isClassType,public IsAssignable,public HasDefaultCtor{};
    
    //in den Traits
    template<class T>
    struct Traits{
        enum{CopyAble=IsDerived<TypeInfo<T>,IsCopyAble>::Result};
        //...
    };
    


  • dann schau dir mal boost::type_traits an, da gibt es ja ein is_pod



  • ja, da wird so gemacht,wie ichs bisher gemacht hab,es wird halt eine template-spezialisierung für jeden "Wert" durchgeführt-im worst case sind das ca 10 spezialisierungen ;):

    //boost lösung
    namespace boost
    {
    template<>
    struct is_pod<my_pod> 
       : public mpl::true_{};
    template<>
    struct is_union<my_union> 
       : public mpl::true_{};
    template<>
    struct is_class<my_union> 
       : public mpl::false_{};
    }
    

    es geht mir eben darum,das ganze so komfortabel wie möglich zu halten, und das geht halt nur dann gut, wenn man nicht so viele redundante codezeilen hat.


Anmelden zum Antworten