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!