Templates erben rekursiv von Spezialisierungen, was passiert genau?



  • Hallo,

    ich habe ungefähr* diesen Code.
    Beim Versuch, deu zu Übersetzen sagt mir g++ folgendes:

    ich@du:~/Documents$ g++ help.hpp
    help.hpp: In constructor ‘Mod<T1, T2, T3, T4, T5>::Mod(const std::string&) [with T1 = A, T2 = B, T3 = C, T4 = empty, T5 = empty]’:
    help.hpp:58: instantiated from here
    help.hpp:48: error: no matching function for call to ‘Mod<B, empty, empty, empty, empty>::Mod()’
    help.hpp:35: note: candidates are: Mod<T1, empty, empty, empty, empty>::Mod(const std::string&) [with T1 = B]
    help.hpp:44: note: Mod<B, empty, empty, empty, empty>::Mod(const Mod<B, empty, empty, empty, empty>&)
    help.hpp:48: error: no matching function for call to ‘Mod<C, empty, empty, empty, empty>::Mod()’
    help.hpp:35: note: candidates are: Mod<T1, empty, empty, empty, empty>::Mod(const std::string&) [with T1 = C]
    help.hpp:44: note: Mod<C, empty, empty, empty, empty>::Mod(const Mod<C, empty, empty, empty, empty>&)

    Das passiert nicht, wenn ich das letzte typedef auf

    typedef Mod<A, B> MyMod
    

    ändere. Leider ist der Code nicht von mir und ich blicke nicht ganz durch.

    So wie ich das sehe, wird ein parameterloser Konstruktor von einer Klasse ungleich Mod< 5 x empty > aufgerufen, was zu einem Fehler führt, du nur diese
    vollständige Spezialisierung einen besitzt. Allerdings kann ich beim besten Willen nicht ausmachen, warum das passiert: Der einzige Ort, wo so ein Konstruktor aufgerufen wird ist doch in Zeile 32 Mod<>(), aber Mod<> ist doch
    das gleiche wie Mod< 5 x empty >.

    Kann mir einer erklären, was hier genau passiert?

    -- Panke

    * Ich habs natürlich aufs wichtigste Zusammengestrichen



  • Dein Problem dürfte durch eine reine public Vererbung nicht auftauchen.

    class Mod : public Mod<T1>, public Mod<T2, T3, T4, T5, empty>
    

    Ein Beispiel:

    #include <iostream>
    using namespace std;
    template<typename T1, typename T2>
    class Foo: public Foo<T2, int> //wenn hier virtual genutzt wird, so wird Foo<int,int>::Foo() aufgerufen
    {
    public:
    	Foo(int i):Foo<T2, int>(4) {cout << "Foo<T1,T2>Foo(int i)\n";}
    };
    template <>
    class Foo<int, int>
    {
    public:
    	Foo() {cout <<"Foo<int, int>::Foo()\n";} //wenn virtuelle-Vererbung
    	Foo(int i) { cout <<"Foo<int, int>Foo(int i)\n";} //ohne virtuelle Vererbung
    };
    
    int main()
    {
    	Foo<int,char> a(5);
    }
    

    Problem ist, dass durch virtual-Vererbung die, durch die Rekursion entstehende, Vererbungshierachie so verändert wird, dass der benutzerdefinierte Konstruktoraufruf (Foo<int,int>(4)) in der Initialisierungsliste von Foo<char,int>::Foo(int i) nicht sichtbar ist und damit nach einem Standardkonstruktor in Foo<int,int> gesucht wird



  • Hallo,

    das funktioniert wunderbar, da wäre ich selbst nicht darauf gekommen.

    Vielen, vielen Dank!


Anmelden zum Antworten