tamplateparameter: compilezeit-konstante ausdrücke; templates+vererbung



  • ich benutze grade, nach 2 jahren c++-pause (und ohne früher was mit templates gemacht zu haben) und der nächtlichen lektüre von "effektiv c++ programmieren" sprachmittel die ich eigentlich gar nicht verstanden habe. daher ergeben sich so einige probleme.

    (vorneweg: ich brauch' allerhöchste performance!)

    ich möchte in einem klassentemplate mit int-parametern a,b ein (c-)array mit konstanter größe haben.
    kein problem ist: T foo[a*b] //der compiler wertet das wohl beim compilieren aus

    problem: float foo[pow(a,b)].

    meine lösung:

    T mat[(b == 1) ? a : ( (b==2) ? a*a : ( (b==3) ? a*a*a : a*a*a*a ))];
    //größer wird es hoffentlich nicht
    

    aber das finde ich hässlich. ich habe sowas versucht:

    //in der gleichen .h
         template<unsigned short a, int b>  
    	class Aux {
    	public:
    		static const size_t intPow() {
    			return (b == 1) ? a : ( (b==2) ? a*a : a*a*a)
    		//	int res = 1;
    		//	for (int i=0; i < b; ++i)
    		//		res*=a;
    		//	return res;
    		}
    	};  
    
     //...
     //in meiner eigentlichen klasse dann:
      T mat[Aux<n,rank>::intPow()];
    

    (sowohl mit (das wäre natürlich optimal) als auch ohne dem auskommentierten teil)

    Oder auch (wieder ganz in der klasse um die es geht)

    private:
    const unsigned int size;  //wird im konstruktor mit templateparametern initiallisiert,
    // mit der standard pow-funktion (wenn ich pow z.b. global einer konstanten zuweise, schaffts der compiler offenbar plötzlich, 
    //es zur compilezeit auszuwerten, aber ich bekomme trotzdem den fehler, dass size unbekannt ist)
    
    		T mat[size];
    

    Also ich vermute ja, dass der letzte ansatz ein ganz anderes problem hat als das davor. aber auch hier würde mich interessieren: warum geht das nicht? zur compilezeit wird doch bei jeder instanziierung der konstruktor als funktionsaufruf reinkopiert, aber da steht doch die initiallisierung der konstante bereits drin. im moment der instanziierung ist die konstante also bestimmt. erst dann muss doch auch das array angelegt werden. warum passiert das dann nicht einfach?



  • stock schrieb:

    Also ich vermute ja, dass der letzte ansatz ein ganz anderes problem hat als das davor. aber auch hier würde mich interessieren: warum geht das nicht? zur compilezeit wird doch bei jeder instanziierung der konstruktor als funktionsaufruf reinkopiert, aber da steht doch die initiallisierung der konstante bereits drin. im moment der instanziierung ist die konstante also bestimmt. erst dann muss doch auch das array angelegt werden. warum passiert das dann nicht einfach?

    Das geht nicht weil wie du schon geschrieben hast der Konstruktor die Variable belegt, und das geschieht eben erst zur Laufzeit. Ein Compilezeit-pow ist aber einfach per Rekursion zu machen:

    template <int base, unsigned int exponent>
    struct Pow
    {
      const static long value = base * Pow<base, exponent-1>::value;
    };
    
    template <int base>
    struct Pow<base, 0>
    {
      const static long value = 1;
    };
    


  • wunderbar, klappt einwandfrei, danke.


Anmelden zum Antworten