Derived class als Template-Argument zu Base class



  • Hallo zusammen,

    ich versuche mir gerade einen Container für derived Klassen von abstrakten Typen zu basteln. Der macht intern im Prinzip sowas hier (beispielhaft):

    #include <vector>
    #include <memory>
    #include <iostream>
    
    struct A {
        virtual void foo() const = 0;
    };
    
    struct B : A {
        void foo() const { std::cout << "B::foo()" << '\n'; }
    };
    
    int main() {
        std::vector<std::shared_ptr<A>> vec;
        vec.push_back(std::make_shared<B>());
        vec.push_back(std::make_shared<B>());
        vec.push_back(std::make_shared<B>());
    
        for (auto const &b : vec) {
            b->foo();
        }
    }
    

    Das klappt auch soweit.

    Jetzt will ich aber um meinen abstrakten Typ noch einen weiteren umschließenden Typen bauen:

    #include <vector>
    #include <memory>
    #include <iostream>
    
    struct A {
        virtual void foo() const = 0;
    };
    
    struct B : A {
        void foo() const { std::cout << "B::foo()" << '\n'; }
    };
    
    template <typename T>
    struct C {
    
    };
    
    int main() {
        std::vector<std::shared_ptr<C<A>>> vec;
        vec.push_back(std::make_shared<C<B>>());
        vec.push_back(std::make_shared<C<B>>());
        vec.push_back(std::make_shared<C<B>>());
    
        for (auto const &c : vec) {
            c->foo();
        }
    }
    

    Jetzt geht das nicht mehr, Fehler: "no matching function for call to ‘std::vector<std::shared_ptr<C<A> > >::push_back(std::shared_ptr<C<B> >)".

    Warum klappt der erste Code, aber der zweite nicht? A ist doch in beiden Fällen abstrakt, wieso kann es als template Argument nicht implizit zu B konvertiert werden?


  • Mod

    Bloß weil A mit B verwandt ist, bedeutet das nicht, dass foo<A> irgendetwas mit foo<B> zu tun haben muss.



  • Ein C<A> ist halt etwas ganz anderes als ein C<B>. Du könntest ja irgendwelche Spezialisierungen haben, so dass C<B> ganz andere Funktionen als C<B> hat. Die beiden Typen haben für den Compiler nichts miteinander zu tun.



  • Hm stimmt, an Spezialisierungen hab ich gar nicht gedacht...

    Jetzt wo ich mir das vorstelle macht es wirklich nicht viel Sinn, Danke 👍


Anmelden zum Antworten