Templatemethoden Spezialisierung



  • Hi,

    ich hab ein Template Vector3 und das hat eine Funktion, die die Länge ausrechnet. Dazu brauche ich die Wurzel, rufe also sqrt() auf. Nur wenn das Template mit float als Typ instantiiert wird, soll stattdessen sqrtf() aufgerufen werden.

    Was ich also machen will, ist sozusagen eine Art Spezialisierung, nur nicht für das ganze Template (das wär dann die Alternative, wenn das hier nicht geht), sondern nur für eine einzelne Methode.

    So hab ich das schon probiert:

    T getLength(void) const { return sqrt(x * x + y * y + z * z); }
    float getLength(void) const { return sqrtf(x * x + y * y + z *z); }

    (also einfach überladen)

    Nur wenn ich jetzt als Typ float habe, habe ich logischerweise eine fatale Doppeldefinition.

    ChrisM



  • ganz einfach:
    sqrt für float überladen.
    ach je, das ist es ja schon 🙂

    #include <cmath>
    double sqrt(double);
    float sqrt(float);
    long double sqrt(long double);
    

    oder eine noch andere methode:

    template <class T> class test;
    template <class T>
    class test_base {
    	T t;
    public:
    	friend class test<T>;
    	test_base (const T &x) : t(x) {}
    	void foo () { cout << "foo\n"; }
    	void bar () { cout << "bar\n"; }
    	void fubar () { cout << "fubar\n"; }
    };
    
    template <class T>
    class test : public test_base<T> {
    public:
    	test (const T &t) : test_base<T>(t) {}
    	void faz () { cout << t << '\n'; }
    };
    
    template <>
    class test <float> : public test_base<float> {
    public:
    	test (float f) : test_base<float>(t) {}
    	void faz () { cout << "float-faz\n"; }
    };
    
    int main () {
    	test<float> f(2.);
    	f.foo();
    	f.bar();
    	f.fubar();
    	f.faz();
    
    	test<int> i(10);
    	i.foo();
    	i.bar();
    	i.fubar();
    	i.faz();
    }
    

    😃 wie immer - ohne Gewähr



  • Hi,

    thx, die überladene sqrt()-Kapselung gefällt mir. Die werd' ich dann schön inline machen und dann wird aber Vektorlängen berechnet bis zum geht nichtmehr 😃

    ChrisM



  • Hallo,
    mal abgesehen davon, dass die Verwendung der sqrt-Überladung mehr sinn macht, kannst du auch die entsprechende Methode spezalisieren:

    template <class T>
    class Foo
    {
    public:
        T func();
    };
    
    template <class T>
    T Foo<T>::func()
    {
    // Standardimplementation
    }
    
    template <>
    float Foo<float>::func()
    {
    // Implementation für T = float
    }
    


  • Hi,

    das geht aber nicht, wenn meine Klasse vollkommen inline ist, also die Implementation auch bei der Definition steht, was ja bei Templates meistens so ist, oder? (würde VC++ doch endlich export unterstützen...)

    ChrisM



  • das geht aber nicht, wenn meine Klasse vollkommen inline ist, also die Implementation auch bei der Definition steht, was ja bei Templates meistens so ist, oder?

    Erstens: Hä? 🙂
    Zweitens: Nö. Templates sollten nicht mehr inline sein, als andere Methoden auch. Ich glaube du verwechselst da inline mit "Definition im Header". Richtig ist, dass du ein Template (ohne export) genau wie inline-Funktionen überall dort definieren musst, wo selbiges verwendet wird (-> sprich im Header). Dadurch wird das Template aber nicht inline. Inline ist eine Methode nur, wenn du sie a) inline deklarierst oder b) innerhalb der Klassendefinition definiertst. Das gilt auch für Templates.

    Richtig ist auch, dass du eine Methode eines Templates *nicht* innerhalb der Klassendefinition spezialisieren kannst.

    Deine Schlussfolgerung ist aber falsch. Auch mit einem nicht-export fähigen Compiler (insbesondere auch mit dem VC 6) kannst du mein Beispiel verwenden. Du musst die Methoden des Templates nur *außerhalb* der Klassendefinition aber *im* Header der Klasse definieren.


Anmelden zum Antworten