Spezialisierung von Template: Abgeleitete Klasse



  • Hallo zusammen,

    ich habe folgenden Code:

    #include <iostream>
    
    template<typename T>
    void init(T& t){
            std::cout << "no init" << std::endl;
    }
    
    class A{
    
    };
    
    class B : public A{
    
    };
    
    template<>
    void init(A& t){
            std::cout << "init my A object" << std::endl;
    }
    
    int main(){
            A a;
            init(a);
            B b;
            init(b);
            return 0;
    }
    

    Die Ausgebe dieses Codes ist:

    init my A object
    no init
    

    Ich hätte aber gerne, dass er auch für B die A-spezifische Funktion aufruft,
    da es sich ja auch um ein A handelt.

    Klar, kann ich in diesem Fall casten, aber krieg ich es auch ohne explizites
    Casten hin, denn ich befinde mich in meinem komplexeren Bsp. in einem Template,
    wo ich folglich nicht einfach casten kann.

    Gruß,
    CSpille



  • So in etwa:

    #include <iostream>
    #include  <boost/type_traits/is_base_of.hpp>
    
    class A
    {
    
    };
    
    class B : public A
    {
    
    };
    
    class C
    {
    };
    
    template<typename T, bool>
    struct HasBase;
    
    template<typename T>
    struct HasBase<T, true>
    {
        static void init(T & t)
        {
            std::cout << "init my A object" << std::endl;
        }
    };
    
    template<typename T>
    struct HasBase<T, false>
    {
        static void init(T & t)
        {
            std::cout << "no init" << std::endl;
        }
    };
    
    template<typename T>
    void init(T& t)
    {
        HasBase<T, boost::is_base_of<A, T>::value >::init(t);
    }
    
    int main()
    {
        A a;
        init(a);
        B b;
        init(b);
        C c;
        init(c);
    
        return 0;
    }
    

    😕

    PS: Ist allerdings jetzt nur partiell spezialisiert...



  • Danke Tachyon!

    Interessant, allerdings funktioniert das (wohl) nicht, wenn ich verschiedene
    Vererbungen habe...

    also wenn B von A ableitet und D von C und ich jeweils eine init für A und C habe.



  • CSpille schrieb:

    Danke Tachyon!

    Interessant, allerdings funktioniert das (wohl) nicht, wenn ich verschiedene
    Vererbungen habe...

    also wenn B von A ableitet und D von C und ich jeweils eine init für A und C habe.

    Nicht ohne zusätzlichen Code, nein. Aber das ist bei Spezialisierung nun einmal so (auch bei dem, was Du versucht hast, wenn es denn gehen würde).



  • Danke Tachyon!

    Dann werde ich es wohl so lösen:

    #include <iostream>
    
    class A{};
    class B : public A{};
    class C{};
    class D : public C{};
    
    void initInternal(A* t){
            std::cout << "init my A object" << std::endl;
    }
    
    void initInternal(C* t){
            std::cout << "init my C object" << std::endl;
    }
    
    void initInternal(void* t){
            std::cout << "no init" << std::endl;
    }
    
    template<typename T>
    void init(T& t){
            initInternal(&t);
    }
    
    int main(){
            A a;
            init(a);
            B b;
            init(b);
            C c;
            init(c);
            D d;
            init(d);
            return 0;
    }
    

    Ausgabe:

    init my A object
    init my A object
    init my C object
    init my C object

    Auch wenn die Deklarationen von

    void initInternal(A* t);
    void initInternal(C* t);
    

    vor

    template<typename T> 
    void init(T& t); // EDIT: Hier stand die falsche Funktion
    

    stehen müssen (zumindest, wenn A und C in einem anderen(?) namespace sind)

    Gruß,
    CSpille



  • Nachtrag:

    #include <iostream>
    
    class C{};
    class D : public C{};
    
    void initInternal(void* t){
            std::cout << "no init" << std::endl;
    }
    
    template<typename T>
    void init(T& t){
            initInternal(&t);
    }
    
    namespace csp{
    class A{};
    class B : public A{};
    void initInternal(A* t);
    }
    
    void csp::initInternal(csp::A* t){
            std::cout << "init my A object" << std::endl;
    }
    
    void initInternal(C* t){
            std::cout << "init my C object" << std::endl;
    }
    
    int main(){
            csp::A a;
            init(a);
            csp::B b;
            init(b);
            C c;
            init(c);
            D d;
            init(d);
            return 0;
    }
    

    Wenn die Funktion im gleichen Namespace ist, klappt es auch ohne vorherige
    Deklaration. 🙂


Anmelden zum Antworten