[gelöst] Template "automatisch" spezialisieren
-
Hi,
habe folgendes Problem:
Um Sachen umzurechnen habe ich ein Klassentemplate, das etwa so aussieht:template <typename T, typename U = T> class Foo { public: struct Functor { U operator()(U) const { return 12 * value + 7; } //Beispiel } Foo (Functor* f):m_func(f) {} T bar(const T& value) const { return (*m_func)(value); } private: Functor* m_func; }Da ist spezialisiert für den Fall eines Vectors, so dass in dem Fall der Funktor elementweise angewendet wird:
template<> std::vector<int> Foo<std::vector<int>, int>::bar(const std::vector<int>& value) const { // *m_func auf jedes Element des Vectors anwenden und neuen Vector zurückgeben }Frage: Wie kann ich erreichen, dass das "automatisch" gemacht wird, wenn ein Vektor auftritt? Also so das folgendes passiert:
Baz<int> => typedeft Foo<int> = Foo<int, int> Baz<std::vector<int> > => typedeft Foo<std::vector<int>, int>Zusammengefasst: Ich möchte den Typen "bestellen" können, den ich möchte, aber wenn das ein vector ist, soll das zweite template-argument der Elementtyp des Vektors sein.
Hoffe, ich konnte es verständlich erklären. Schönen sonnigen Montag noch

Phil
-
Okay, habe ein bißchen gebastelt. Hier ist mein erster Ansatz:
template <typename T> struct FooFrontend { typedef Foo<T> Type; typedef T BasicT; }; template <> struct FooFrontend<std::vector<int> > { typedef Foo<std::vector<int>, int> Type; typedef int BasicT; };und ggfs. weitere spezilaisierungen für gloat-vectoren usw.
Ein Problem habe ich jetzt allerdings, wenn ich von Foo erbe, um andere Funktoren zu definieren. Beispiel:
template <typename T> class CocreteFoo: public Foo<T, FooFrontend<T>::BasicT> { struct ConcreteFunctor: public Foo<T, FooFrontend<T>::BasicT>::Functor { FooFrontend<T>::BasicT operator()(FooFrontend<T>::BasicT value) const { // mach irgendwas } }; };Dann erzählt mir gcc:
error: type/value mismatch at argument 2 in template parameter list for `template<class T, class U> class Foo' error: expected a type, got ` FooFrontend<T>::BasicT'Aber BasicT ist doch ein Typ!
Irgendwo in meinem Hinterkopf geistert gerade "typedef typename" rum, muss mal den Meyers aus dem Schrank holen
In der Zeit bin ich weiter für konstruktive Vorschläge offen

Phil
-
Schreib mal ein typename davor, dein Compiler muss nämlich noch wissen, dass er
FooFrontend<T>::BasicTals Typenbezeichnung interpretieren darf/soll. Denn es geht aus dem Kontext nicht hervor, dass es sich um einen Typen handelt.FooFrontend<T>::BasicTkönnte ja auch beispielsweise ein int sein. Genaues weiß man erst, wenn man T kennt. Der Compiler will es aber vorher wissen, damit er hinterher weiß ob das T das er bekommt auch passt.
-
Bingo!!!
class ConcreteFoo: public Foo<T, typename FooFrontend<T>::BasicT> { typedef typename FooFrontend<T>::BasicT BasicType; ...Klasse. Das geht!
War meine Intuition ja gar nicht so verkeht.
Aktenvermerk an mich selbst: Und schon wieder ein Stück Code produziert, was keiner mehr lesen kann, seufz.
-
PhilippM schrieb:
Aktenvermerk an mich selbst: Und schon wieder ein Stück Code produziert, was keiner mehr lesen kann, seufz.
Ach, das ist relativ harmlos. Ein C++_Programmierer mit 1-2 Jahren Erfahrung kann das recht flüssig lesen. Und wenn das Funktionstemplate gut ist, sollte ja auch im Idealfall niemals wieder jemand den Code zu lesen brauchen.