template spezialisierung



  • Ich hab gut 2 Jahre kein C++ mehr programmiert und muss nun ins kalte Wasser ohne Bücher etc. und ich find grad nicht das passende in den FAQs oder Google.

    Ich bin in der spezialisierung von templates verunrsichert, da sich der VC8 hier merkwürdig verhält.

    Behauptung meinerseits:

    Wenn ich ein template spezialisiere , muss ich jede einzelne Methode der Klasse spezialisieren.

    Je nach Projekt erlaubt der VC8 folgenden Code:

    template <class T> struct  a
    {
    	T test();
    	T test2();
    };
    
    template <> struct a<int>
    {
    	int test();
    };
    
    template <class T> T a<T>::test(){}
    template <class T> T a<T>::test2(){}
    
    // template <> int a<int>::test(){return 0;}
    int a<int>::test(){return 0;}
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	a<int> A;
    	A.test2();
    	return 0;
    }
    

    Für A.test2 wird template <class T> T a<T>::test2(){} aufgerufen. Erzeuge ich eine Spezialisierung für a<int>::test2 , wird diese genommen.

    Stimmt meine Behauptung nach standard oder reicht es bei einer Spezialisierung nur das notwendigste zu machen ?

    Vielen Dank!



  • Ich versteh grad nicht was du willst. Natürlich wird das spezialisierteste genommen und sonst die allgemeine Version.

    Und spracherweiterungen sind im vc8 doch standardmäßig deaktiviert.



  • Das ist halt die frage, übersetzt man das ganze als reine Konsolenanwendung meckert der compiler, das es keine spezialisierung für

    template <> int a<int>::test2(); gibt.

    Ich finde es also als nicht natürlich, das immer das spezialisiertere genommmen wird. Ich bin der Meinung, das bei spezialisierung der gesammten Klasse (!) alle Methoden spezialisiert werden müssen (woran sich der VC8 im Mixedmode nicht hält). Hier liegt keine Überladung des Members durch eine spezialisierung vor.

    // Generische Klasse
    template <class T> struct  a
    {
    	T test();
    	T test2();
    };
    
    // Sepzialisierung der gesammten Klasse aus int
    template <> struct a<int>
    {
    	int test();
    };
    
    template <class T> T a<T>::test(){return 0;}
    // Überladung der Methode mit bool
    template <> bool a<bool>::test(){return false;}
    template <class T> T a<T>::test2(){return 0;}
    
    int a<int>::test(){return 0;}
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	a<int> A;
    	A.test();	// int a<int>::test(){return 0;}
    	A.test2();	// FEHLER test2 nicht vorhanden in a<int>
    
    	a<bool> B;
    	B.test();	// template <> bool a<bool>::test(){return false;}	
    
    	a<float> C;
    	C.test();	// template <class T> T a<T>::test(){return 0;}
    }
    

    Wie gesagt bin ich dem C++ ein wenig fern, daher hätt ich gern die Meinung von jenen die keine zwangspausen gemacht haben dazu 🤡 (Hume, Volker ?)



  • Knuddlbaer schrieb:

    Stimmt meine Behauptung nach standard oder reicht es bei einer Spezialisierung nur das notwendigste zu machen ?

    Deine Behauptung stimmt. (Wenn du dir bei sowas nicht sicher bist hilft oft schon www.comeaucomputing.com/tryitout/; keine ultimative Kontrollinstanz aber recht standardkonform und zumeist schon mal eine "zweite Meinung".)

    Wenn es dir wirklich nur um einzelne Methoden geht solltest du dir trotzdem Copy&Paste-Orgien ersparen:

    template <class T, class FooType>
    struct FooBase
    {
      T returnSomething() { return T(42); }
      FooType& doSomething() { return *static_cast<FooType*>(this); }
    };
    
    template <class T>
    struct Foo : FooBase<T, Foo<T> >
    {
      using FooBase<T, Foo<T> >::returnSomething;
      T returnSomethingElse() { return returnSomething() * 314; }
    };
    
    template <>
    struct Foo<double> : FooBase<double, Foo<double> >
    {
      using FooBase<double, Foo<double> >::returnSomething;
      double returnSomethingElse() { return returnSomething() * 3.14; }
    };
    
    // alt #1
    
    template <class T>
    struct GenerateSomething
    {
      T doIt() { return T(0); }
    };
    
    template <>
    struct GenerateSomething<int>
    {
      int doIt() { return 1; }
    };
    
    template<
      class T,
      template <class> class SomePolicy = GenerateSomething>
    struct Bar : SomePolicy<T>
    {
      using SomePolicy<T>::doIt;
      T returnSomething() { return doIt(); }
    };
    
    // alt #2
    
    template <class T>
    struct ClosedBar
    {
      T returnSomething()
      {
        GenerateSomething<T> g;
        return g.doIt();
      }
    };
    
    // etc
    


  • Hallo,

    vielen dank für den Link.

    Ist die Überladung der Methode in meinem obrigen Beispiel nach standard legal ?

    (template <> bool a<bool>::test(){return false;} )
    

    Wenn ja, könnte mir das sehr sehr viel Umbauarbeiten ersparen - und ärger in dem ich diese eine Methode überlade.



  • Knuddlbaer schrieb:

    Ist die Überladung der Methode in meinem obrigen Beispiel nach standard legal?

    Die Spezialisierung ist OK.



  • Vielen vielen Dank fürs drüber schauen und noch mal vielen Dank für den Link 🤡

    Gruß

    Michael


Anmelden zum Antworten