Basisklassenzeiger als Template Argument?



  • Hi

    Wenn ich einer Templatefunktion Basisklassenzeiger auf abgeleitete Objekte übergebe werden diese als Basisklassen ausgewertet.
    Kann ich das irgendwie umgehen, so dass er erkennt, welche Subklasse ein Objekt hat?
    Grund, ich probier type traits aus( : Boost Type Traits )

    Minimalbeispiel zum Testen:

    #include <iostream>
    #include <cstdlib>
    #include <boost/type_traits/is_same.hpp>
    
    using namespace std;
    
    class BaseTag{};
    class Sub1Tag: public BaseTag{};
    class Sub2Tag: public BaseTag{};
    
    template< typename ClassT >
    struct ClassTraits
    {
        typedef typename ClassT::ClassCategory ClassCategory;
    };
    
    class Base
    {
    public:
        typedef BaseTag ClassCategory;
        virtual void do_it() const
        {
            cout << "Hello from Base" << endl;
        }
    };
    
    class Sub1: public Base
    {
    public:
        typedef Sub1Tag ClassCategory;
        virtual void do_it() const
        {
            cout << "Hello from Sub1" << endl;
        }
    };
    
    class Sub2: public Base
    {
    public:
        typedef Sub2Tag ClassCategory;
        virtual void do_it() const
        {
            cout << "Hello from Sub2" << endl;
        }
    };
    
    template< typename LeftT, typename RightT >                         // Dieses Template wird 2 mal mit Base instanziert...
    bool is_same_type( const LeftT* lhs, const RightT* rhs )
    {
        lhs->do_it();          
        rhs->do_it();
        return boost::is_same<
            typename ClassTraits<LeftT>::ClassCategory,
            typename ClassTraits<RightT>::ClassCategory
                                >::value;
    }
    
    int main(int argc, char *argv[])
    {
        Base* p1 = new Sub1();
        Base* p2 = new Sub2();
        p1->do_it();
        p2->do_it();
        if( is_same_type( p1, p2 ) )                                        // ...mit diesem Aufruf
        {
            cout << "Are the same" << endl;
        }
        else
        {
            cout << "Not the same" << endl;
        }
        delete p1;
        delete p2;
    
        return EXIT_SUCCESS;
    }
    

    Hello from Sub1
    Hello from Sub2
    Hello from Sub1
    Hello from Sub2
    Are the same

    Danke im voraus für jeden noch so kleinen Tipp
    Grüsse



  • Hab das Beispiel noch minimiert:

    #include <iostream>
    #include <cstdlib>
    #include <boost/type_traits/is_same.hpp>
    
    using namespace std;
    
    class Base {};
    
    class Sub1: public Base {};
    
    class Sub2: public Base {};
    
    template< typename LeftT, typename RightT >
    bool is_same_type( const LeftT* lhs, const RightT* rhs )
    {
        return boost::is_same< LeftT, RightT >::value;
    }
    
    int main(int argc, char *argv[])
    {
        Base* p1 = new Sub1();
        Base* p2 = new Sub2();
        Sub1 s1;
        Sub2 s2;
        if( is_same_type( p1, p2 ) )
        {
            cout << "Are the same" << endl;
        }
        else
        {
            cout << "Not the same" << endl;
        }
        if( is_same_type( &s1, &s2 ) )
        {
            cout << "Are the same" << endl;
        }
        else
        {
            cout << "Not the same" << endl;
        }
        if( is_same_type( p1, &s1 ) )
        {
            cout << "Are the same" << endl;
        }
        else
        {
            cout << "Not the same" << endl;
        }
        delete p1;
        delete p2;
    
        return EXIT_SUCCESS;
    }
    

    Are the same
    Not the same
    Not the same

    Schade, das scheint nicht zu gehen..



  • Was du suchst heißt RTTI.



  • Hmm..meinst du typeid()?
    Die Benutzung davon will ich eben vermeiden..



  • Ja, anders geht es nicht wenn der Typ erst zur Laufzeit feststeht.

    Wenn du in deinem Beispiel folgendes schreibst, wird dir schnell klar, warum man es nicht zur Compile-Zeit feststellen kann:

    Base* p1 = rand() % 2 ? new Sub1() : new Sub2;
    Base* p2 = rand() % 2 ? new Sub1() : new Sub2;
    


  • Jo, danke.

    Dann werd ich anders an die Sache rangehen müssen.
    Es gibt doch auch Compile time polymorphismus? Werde mich da noch weiter informieren..



  • Gibt es, sieht so aus:

    template< class Derived >
    class MyClass
    {
     public:
      void stuff()
      {
         Derived* self = static_cast< Derived* >( this );
         self->do_stuff();
      }
    };
    
    class Derived : public MyClass< Derived >
    {
      public:
      void do_stuff()
      {
         cout << "hello world!\n";
      }
    };
    
    template< class Derived >
    void handler( MyClass< Derived >& obj )
    {
      obj.stuff();
    }
    
    int main()
    {
      Derived myObj;
    
      handler( myObj );
    }
    


  • Cool danke, das schubst mich mal in ne andere Richtung.



  • sry doppel..


Anmelden zum Antworten