[solved] Vererbung von typedefs bei Klassentemplates



  • Hallo,
    bei normalen Klassen werden die typedefs ja vererbt:

    class B {
    public:
    	typedef int TI;
    };
    
    class D : public B {
    public:
    	void Foo( TI i ) {}
    };
    

    Kann man das bei Klassentemplates auch haben?
    So wie ich es hier mit D1 und D2 gemacht habe, finde ich es nicht wirklich elegant.

    template <typename T>
    class B {
    public:
    	typedef int TI;
    };
    
    template <typename T>
    class D1 : public B<T> {
    public:
    	typedef typename B<T>::TI TI;
    	void Foo( TI i ) {}
    };
    
    template <typename T>
    class D2 : public B<T> {
    public:
    	void Foo( typename B<T>::TI i ) {}
    };
    

    Dobi



  • Bei Klassentemplates werden die Typedefs genau so geerbt wie bei normalen Klassen. Der (das?) Typedef in D1 ist also redundant, und mMn. müsste auch einfach nur "T1" in D2 reichen.

    Nochwas: wenn du von einer Template-Klasse ableitest, dann musst du die Template-Parameter nicht extra nochmal angeben.
    Beispiel:

    #include <iostream>
    
    template <class T>
    class FooBase
    {
    public:
    	virtual void DoFoo()
    	{
    		std::cout << "type = " << typeid(T).name() << "\n";
    	}
    };
    
    class IntFoo : public FooBase<int>
    {
    public:
    	virtual void DoFoo()
    	{
    		std::cout << "IntFoo::DoFoo\n";
    		FooBase::DoFoo(); // <- FooBase<int> nicht nötig, einfach nur FooBase reicht
    	}
    };
    
    int main()
    {
    	IntFoo ifoo;
    	ifoo.DoFoo();
    	return 0;
    }
    


  • Danke, aber auch nachdem ich typeinfo includiert habe, funktioniert dein Beispiel bei mir (g++ (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5) trotzdem noch nicht.

    20: error: ‘template<class T> class FooBase’ used without template parameters
    

    Das Ursprungsproblem, geht auch nicht so einfach.

    template <typename T>
    class B {
    public:
        typedef int TI;
    };
    
    template <typename T>
    class D : public B<T> {
    public:
        void Foo( TI i ) {}
    };
    
    10: error: ‘TI’ has not been declared
    

    Sonst hätte ich nicht so doof gefragt. 😉

    Dobi

    edit: PS: Für mich hört sich "das typedef" am besten an.



  • Achja, das ist ja ein dependent-name. Sorry für den Unsinn 😞

    Die Basisklassen-Geschichte scheint auch ein MSVC-Fehlverhalten zu sein, das ich mir angewöhnt habe. Hm...

    Vererbt wird das typedef natürlich trotzdem, nur kann man in der Definition von D1 bzw. D2 nicht einfach so "darauf zugreifen", da das ja selbst Templates sind.
    Und "unqualified names" werden laut Standard als "non-dependent" interpretiert. TI ist aber nicht "non-dependent", und wird daher nicht gefunden.

    Was geht, ist typename D1::TI statt typename B<T>::TI . Immerhin ein wenig kürzer.
    Was IMO gehen sollte, ist "using":

    template <typename T> 
    class B { 
    public: 
    	typedef int TI; 
    }; 
    
    template <typename T> 
    class D1 : public B<T> { 
    public:
    	using typename B<T>::TI;
    	void Foo(TI i) {} 
    };
    

    MSVC und Comeau fressen das auch, GCC 4.5 mag es aber nicht.



  • Ok, thx.

    Dass using hier nicht mit der GCC funktioniert, ist für mich momentan kein Drama, weil wenn ich eh ne neue Zeile schreiben muss, ist es egal, ob statt ich

    using typename B<T>::TI;
    
    typedef typename B<T>::TI TI;
    

    oder

    typedef typename D1::TI TI;
    

    schreibe, wobei ich letzte Version schon irgendwie seltsam finde, denn wenn ich an irgendwas mit "D1::" drankomme, würde man ja intuitiv vermuten, dass man innerhalb von D1 dann nicht mehr qualifizieren muss, egal ob dependent oder nicht.
    Wenn man jetzt mehrere abgeleitete Klassen und viele typedefs hat, ist es ja schon verlockend, die einfach mit dem Präprozessor überall reinzurotzen. 😉
    Aber die "B<T>::"-Version ist mit gerade am sympathischsten. Danke nochmal. 👍


Anmelden zum Antworten