Templateklasse teilweise spezifizieren



  • Hey,

    Also erstmal abstrakt zu meinem Problem:
    Ich habe eine Templaste-Klasse mit zwei Parametern. Der erste Parameter soll tatsächlich ein Typ sein. Der zweite Template-Parameter ist eine Zahl.

    Jetzt habe ich einerseits ein typedef innerhalb der Klasse gemacht, das ich teil-spezifiziere (Parameter 1 soll Template bleiben, Parameter 2 möchte ich jetzt setzen). Mein zweites Problem ist, dass ich eine Methode definieren möchte, wo Parameter 1 weiterhin Template ist, aber Parameter 2 gesetzt.

    Konkreter hier der Code:

    template<typename PointType, unsigned char Degree>
    class BezierCurve
    {
    public:
    	typedef	Vector<PointType> TypedVector;
    
    private:
    	TypedVector*		controlPoints_;
    	int					numberOfBezierPoints_;
    	TypedVector*		bezierPoints_;
    
    public:
    	BezierCurve(int numberOfBezierPoints) : controlPoints_(0),
    											numberOfBezierPoints_(0),
    											bezierPoints_(0),
    											numberOfBezierPoints_(numberOfBezierPoints)
    					{
    						controlPoints_ = new TypedVector[Degree];
    					}
    
    	void		SetControlPoints(	int numberOfControlPoints,
    									TypedVector* controlPoints);
    
    	void		SetNumberOfBezierPoints(int numberOfBezierPoints);
    	void		CalculateBezierPoints();
    
    private:
    	PointType	CalculateBezierPoint(float ratio);
    };
    

    Und jetzt die Implementierung. Bei der Teilspezifikation bin ich nicht sicher, ob ich das in den Header oder in die Quellcodedatei schieben muss, jedenfalls ist der Code dafür erstmal:

    template<typename PointType>
    BezierCurve<PointType, 4>::TypedVector BezierCurve<PointType, 4>::CalculateBezierPoint(float ratio)
    {
    // [...]	
    }
    

    Wird klar, was ich erreichen möchte?

    Die Fehlermeldungen sind jetzt erstmal.

    1>c:\users\mischa\documents\visual studio 2008\projects\sdl ogl\heightmap\beziercurve.cpp(6) : warning C4346: 'BezierCurve<PointType,4>::TypedVector': Abhängiger Name ist kein Typ
    1>        Präfix mit 'typename' zum Angeben eines Typs
    

    Verstehe ich nicht, habe doch template<typename PointType> davor geschrieben.

    Vielleicht bedingt diese Fehlermeldung auch diese nächste, aber die verstehe ich auch erstmal nicht:

    1>c:\users\mischa\documents\visual studio 2008\projects\sdl ogl\heightmap\beziercurve.cpp(6) : error C3860: Eine template-Argumentliste, die dem Klassen-template-Namen folgt, muss Parameter in der in der template-Parameterliste verwendeten Reihenfolge auflisten.
    

    In template<x,y> schreibe ich ja nur den Einen hin, weil ich den andren ja fix machen will.

    Allmählich hab ich das Gefühl Visual C++ 9.0. Express Edition (um auch das Mal zu klären) unterstützt meine Idee einfach nicht. 😞 Kennt dann wer nen netten Workaround?

    Edit:
    Interessant ist auch, dass folgender Code nicht funktioniert:

    template<typename PointType, unsigned int dummy>
    BezierCurve<PointType, dummy>::TypedVector BezierCurve<PointType, dummy>::CalculateBezierPoint(float ratio)
    {
    // [...]
    }
    

    Gleiche Fehlermeldungen...

    Viele Grüße



  • Zum ersten:
    BezierCurve<PointType, 4>::TypedVector ist ein abhängiger Name, und der wird laut Standard nicht als Typ anerkannt, da TypedVector auch ein Feld oder eine Methode sein könnte. Das weiss der Compiler aber erst endgültig, wenn PointType bekannt ist. Deshalb musst Du ihm mitteilen, dass es sich um einen Typ handelt: typename BezierCurve<PointType, 4>::TypedVector .

    Zum zweiten:
    Du kannst keine einzelne Methode eines Klassentemplate spezialisieren, sondern wenn, dann nur die ganze Klasse. Als "Workaround" könntest Du die Methode in ein befreundetes Hilfstemplate auslagern:

    template<struct PointType, unsigned char Degree>
    struct CalculateBezierPointHelper 
    {
        typedef PointType ResultType;
        static ResultType CalculateBezierPoint(BezierCurve<PointType, Degree>& ref, float ratio);
    };
    
    template<struct PointType>
    struct CalculateBezierPointHelper<PointType, 4>
    {
        typedef Vector<PointType> ResultType;
        static ResultType CalculateBezierPoint(BezierCurve<PointType, 4 >& ref, float ratio);
    };
    
    template<typename PointType, unsigned char Degree>
    class BezierCurve
    {
        typename CalculateBezierPointHelper<PointType, Degree>::ResultType
            CalculateBezierPoint(float ratio)
        {
            return CalculateBezierPointHelper<PointType, Degree>::CalculateBezierPoint(*this, ratio);
        }
    };
    


  • Super. 🙂 Genau das habe ich gesucht! Vielen Dank!

    Ach. Und gibt es einen Grund, dass dein Helper ne Struct ist? Technisch ist das mit dem public klar, aber hat das nen stilistischen Grund?



  • Okay, aber jetzt habe ich bei Deinem Code Probleme mit der Implementierung der Methode der spezialisierten Klasse.

    template<typename PointType>
    typename BezierCurveHelper<PointType, 4>::TypedVector BezierCurveHelper<PointType, 4>::calculateBezierPoint(const BezierCurve& ref, float ratio)
    {
    // [...]
    }
    

    Fehler ist dann:

    1>c:\users\mischa\documents\visual studio 2008\projects\sdl ogl\heightmap\beziercurve.hpp(111) : error C2955: "BezierCurve": Für die Verwendung der template-Klasse ist eine template-Argumentliste erforderlich.
    

    Oder muss die Definition oben erfolgen?



  • Du mußt jetzt explizit die Template-Parameter bei "BezierCurve" angeben, da du ja jetzt innerhalb der "BezierCurveHelper"-Klasse (bzw. Struktur) bist, d.h.

    template<typename PointType>
    typename BezierCurveHelper<PointType, 4>::TypedVector BezierCurveHelper<PointType, 4>::calculateBezierPoint(const BezierCurve<PointType, 4>& ref, float ratio)
    {
    // [...]
    }
    

Anmelden zum Antworten