Template erweitern?
-
Hallo,
ich hab eine Methode in einer Klasse die sieht so aus:class A { public: static A * createFactory() { return new AImpl(); } };Man merke, es wird ein AImpl returned, nicht A. (AImpl erbt von A)
Die Klasse B hat den gleichen Code für BImpl usw.
(Allocation usw ist hier ein Beispiel, wird im eigentlich Code anders gehändelt)Was ich wissen will, ist es irgendwie möglich eine template Factory zu haben, wo der Benutzer nur die Klasse A angibt, aber eine AImpl zurück bekommt?
So etwas wie:
template<class T> static T * createFactory() { return new T+"Impl"; }Templates werden ja zur Compilezeit aufgelöst, also würd ich defakto ja nicht irgendwie von einer Klasse das Impl erzeugen können, wenn es keinen gibt. aber gibt es einen Weg, irgendwie das T zu erweitern?
Wichtig ist: Der Benutzer sieht *Impl nicht, nur die A, B usw. Daher kann ich auch schlecht zwei Templateparameter oder so übergeben
-
Hab Deine Ziele nicht verstanden. Evtl sowas?
class A { public: typedef AImpl Impl; // static A * createFactory() { return new AImpl(); } };template<class T> static T * createFactory() { return new T::Impl(); }
-
Das hier könnte es ganz gut treffen:
template <class T> T *create(); template <> A *create<A>() { return new AImpl(); }
-
Ok, dann mal detailierter:
class A // abstraktes interface { public: virtual ~A() = 0; static A* createInstance() { return new AImpl(); } }; class B // abstraktes interface { public: virtual ~B() = 0; static B* createInstance() { return new BImpl(); } }; class C // abstraktes interface { public: virtual ~C() = 0; static C* createInstance() { return new CImpl(); } };Die createInstance wiederholt sich hier ja recht häufig und ist immer sehr ähnlich, in einer abstrakten Klasse "N" wird immer "NImpl" , die von "N" erbt zurückgegeben.
Meine Frage ist, kann ich eine Factory Klasse oder so etwas erzeugen, um den sich wiederholenden Code rauszuziehen, den Code zu generalisieren in dem ich optimaler weise nur eine (template-basierende) Methode habe, die das übernimmt.
Anforderung ist aber, dass man diese Methode nur mit "N" instatiieren kann und nicht auch noch mit "NImpl"
Edit: @Tyrox, dann muss ich aber immernoch in jeder Klasse ein Impl returnen
-
Das Problem habe ich noch immer nicht ganz verstanden, aber das ist eine Möglichkeit:
template <class TBase, class TClass> class umstandsvermeider { public: static TBase *create() { return new TClass(); } }; class AImpl; class A : public umstandsvermeider<A, AImpl> { }; class AImpl : public A { public: AImpl() { cout << "AAA" << endl; } }; int main() { A *a = A::create(); delete a; }
-
@Seikilos,
Nur damit es klar ist, du kannst keinen Typnamen zusammenbauen mit Templates. Entweder wird der Typ durch irgendwelche Parameter übergeben oder du kommst nicht an ihn ran. Es gibt theoretisch ein paar Möglichkeiten, wie man Typzuordnungen machen kann, entweder über Makromagie oder Templatemagie. Vielleicht ist es ja dies, was du suchst:// Zum Beispiel mit Makromagie & Templatespezialisierungen: template<typename KeyT> struct TypeAssociation { typedef KeyT Key; // typedef ValueT Value; }; #define EVIL_MACRO_CREATE_TYPE_ASSOCIATION(K, V) \ template<> \ struct TypeAssociation<K> \ { \ typedef K Key; \ typedef V Value; \ }; class A { }; class AImpl : public A { }; EVIL_MACRO_CREATE_TYPE_ASSOCIATION(A, AImpl) template<typename T> struct Factory { T* create() { return new typename TypeAssociation<T>::Value(); } };Theoretisch könnte man dies auch ganz ohne Makros mit Template-Typlisten machen. Braucht aber ein wenig mehr Aufwand und dazu war ich jetzt zu faul. Empfehlen würde ich diese Sache aber trotzdem nicht, wenn es nur darum, dass du zu faul bist, die paar Spezialisierungen zu schreiben

Grüssli