template<class T,T Value> nicht erlaubt?



  • also, ich hab folgende kleine struct geschrieben:

    template<class T,T Value>
    struct var{
        typedef var<T,Value> Value;
    };
    

    daraufhin bekam ich folgende fehlermeldugnen:

    var_base.hpp:6: error: declaration of `typedef struct metapp::var<T, Value>
    metapp::var<T, Value>::Value'
    var_base.hpp:4: error:  shadows template parm `T Value'
    var_base.hpp:6: error: declaration of `typedef struct metapp::var<T, Value>
    metapp::var<T, Value>::Value'
    var_base.hpp:4: error: changes meaning of `Value' from `T Value'
    

    ich dachte, die sache mit den templateparametern ginge so, wieso macht der MinGW jetzt so nen terror?



  • Es darf eben nicht ein beliebiger Typ Templateparameter sein. Ich kann mir btw auch nicht vorstellen wo das Sinn machen sollte was du da vor hast.



  • var<int,5>, var sollte der werträger für werte innerhalb eines kleinen meta-kosntrukts werden^^



  • Das sind mir zu wenig Informationen um sagen zu können, ob es nicht auch anders geht. Kannst du grob erläutern was du mit diesem Meta-Konstrukt bezwecken willst?



  • beispiel:

    typedef Add<Var<int,5>,Var<int,10> >::Value add;
    int i=add();
    

    der compiler soll daraus

    int i=15;
    

    machen, also keine expression templates.

    anderes beispiel:

    typedef Cos<Var<double,45.678> >::Value cos_45;// value ist dann var<double,...>
    double j=cos_45();
    

    oder auch mal sowas:

    typedef typliste4(int,float,double,short) typs;
    typedef Static_Assert<HasType<char,typs> > typtest;//hier wird dann ein var<bool ,0> rumgereicht
    

    //edit snief der bcb 6.0 erlaubts-.-



  • template<class T,T Value>
    struct var{
        typedef var<T,Value> value;
    };
    
    template <class T, class U>
    struct Add : public Add<typename T::value, typename U::value>
    {
    };
    
    template <class A, A a, A b, template <class,A> class T>
    struct Add <T<A,a>, T<A,b> > 
    {
    	typedef T<A, a+b> value;
    };
    
    template <class T>
    struct Get : public Get<typename T::value>
    {
    };
    
    template <class A, A a, template <class,A> class T>
    struct Get<T<A,a> > 
    {
    	static const A final = a;
    	typedef T<A,a> value;
    };
    
    int main()
    {
    
    	cout << Get<Add< Add<var<int,5>,var<int,6> >, var<int,7> > >::final << endl;
    }
    

    kompiliert mit meinem g++ wunderbar (mingw verwendet den doch auch, nicht?)
    allerdings solltest du deine fehlermeldungen durchlesen:

    declaration of typedef struct metapp::var<T, Value> metapp::var<T, Value>::Value' shadows template parmT Value'

    und double kannst du sowieso nicht verwenden.



  • naargh ich trottel, ich nenn eine typedef wie einen template parameter, aua das tut weh, wie immer so ein winziger fehler 😡.

    btw: wieso funzt double nicht?



  • ich würde allerdings nicht zu sehr auf diese technik setzen und gleich einfach int nehmen, (fast) alles andere lässt sich schlecht aufzählen (enum) oder static const machen. 😉



  • hmpf float/double geht ja wirklich nicht 😮
    wieso mache ich mir denn dann die ganze arbeit? arrgh

    //edit *snief* keine vorberechnete sinus-/cosinuswert-liste *heul*



  • otze schrieb:

    hmpf float/double geht ja wirklich nicht

    Wenn du noch ein paar Jahre Zeit hast, kannst du ja auf den nächsten Standard warten. Soweit ich weiß wird darüber nachgedacht ob man dort dann floating-Point-Typen als non-type-Argumente zulässt.



  • HumeSikkins schrieb:

    otze schrieb:

    hmpf float/double geht ja wirklich nicht

    Wenn du noch ein paar Jahre Zeit hast, kannst du ja auf den nächsten Standard warten. Soweit ich weiß wird darüber nachgedacht ob man dort dann floating-Point-Typen als non-type-Argumente zulässt.

    Darf ich mal ganz bescheiden fragen: Wieso ist das nicht zulaessig?

    mfg
    v R



  • HumeSikkins schrieb:

    otze schrieb:

    hmpf float/double geht ja wirklich nicht

    Wenn du noch ein paar Jahre Zeit hast, kannst du ja auf den nächsten Standard warten. Soweit ich weiß wird darüber nachgedacht ob man dort dann floating-Point-Typen als non-type-Argumente zulässt.

    aber nur, wenn wenn die typed enums nicht durckommen, imho empfinde ich die sache mit var als absolut nutzlosen und design zerstörenden hack,der code wird dadurch sicherlich nicht lesbarer^^



  • ich geb nicht auf 😃

    da floating point nicht geht, hab ich ne nachtschicht(bzw frühschicht) eingelegt, und kam auf folgendes ergebnis:

    template<int N,int Z=1>
    struct var{
        typedef var<int N,int Z> Value;
    };
    
    template <class T>
    struct Get : public Get<typename T::Value>{};
    
    template <int N,int Z>
    struct Get<var<N,Z> >{
        static const double Value=N/Z;//hoffe das geht wenigstens^^
    };
    template <int N>
    struct Get<var<N,1> >{
        static const int Value=N;
    };
    

    jetzt muss ich mich zwar in jeder operation mit dem kuerzen rumschlagen, aber immerhin noch besser als nichts^^



  • virtuell Realisticer schrieb:

    HumeSikkins schrieb:

    otze schrieb:

    hmpf float/double geht ja wirklich nicht

    Wenn du noch ein paar Jahre Zeit hast, kannst du ja auf den nächsten Standard warten. Soweit ich weiß wird darüber nachgedacht ob man dort dann floating-Point-Typen als non-type-Argumente zulässt.

    Darf ich mal ganz bescheiden fragen: Wieso ist das nicht zulaessig?

    Also laut "C++ Templates" sind die Gründe historischer nicht aber technische Natur. Genaueres weiß ich allerdings nicht.



  • imho hat man wohl nicht geglaubt, was die kranken programmierer mit den templates anfangen wollen und können, ints waren wahrscheinlich nur dafür gedacht, verschiedene templates besser identifizieren zu können, von meta programmierung hat doch zu dem zeitpunkt noch keiner gewagt zu sprechen, sodass man sich im endeffekt dazu entschieden hat,floats rauszunehmen,und es somit den compiler-machern einfacher zu machen.



  • template <int N,int Z>
    struct Get<var<N,Z> >{
    static const double Value=N/Z;//hoffe das geht wenigstens^^
    };

    Wenn du daran denkst, das z.B. 2/3 == 0 ist, ... :p



  • wie meinen?



  • int x = 2;
    int y = 3;
    
    double z = x / y;
    

    Der wert von z ist jetzt 0.

    x hat den Typ int, y hat den Typ int, also ist das Ergebnis der Division auch int. 2/3 ist also 0 und diese 0 wird dann der Variable z (vom Typ double) zugewiesen, wobei umgewandelt werden muss.
    Das selbe kommt in deinem Code vor.

    Hätte ich hingegen geschreiben

    int x = 2;
    int y = 3;
    
    double z = static_cast<double>(x) / y;
    

    , dann würde y in double konvertiert werden, eine Fließkomma-Division stattfinden und .666666666666666 herauskommen.



  • hmm guter einwand 🙂



  • Man kann aber Referenzen verwenden:

    template<const float& f>
    class A
    {};
    
    A<5.0f> x;
    

    Vielleicht kannst du damit was anfangen.



  • Ich habe mal irgendwo gelesen, dass der gcc das vor der standardisirung konnte. Wurde aber rausgenommen um standard konformer zu werden.

    Der eigentlich Grund wieso man es rausgelassen hat ist glaub ich :

    const double a=5.8;
    char a[b];
    

    Damit du double als template parameter verwenden kannst, muss es eine compiletime Variable. Diese muss aber ganzahlig sein damit man damit ein Array erschaffen kann.

    Also braucht man dafür 2 compiletime Variablen und den Aufwand dies zu implementiren übersteigt den Nutzen.

    Wenn du Kommazahlen brauchst dann schreib dir doch einfach eine Bruch Klasse.


Anmelden zum Antworten