Typen checken?



  • Hi,

    ich habe folgendes problem, aber erstmal code:

    void foo (irgendwas value)
    {
       if (value == float)
       {
           glVector3f (1.0f, 1.0f, 1.0f);
       }
       else if (value == double)
       {
           glVector3d (1.0, 1.0, 1.0);
       }
       else if (value == unsigned int)
       {
           glVector3ui (1, 1, 1);
       }
       // usw.
    }
    

    Jetzt meine frage: WIE MACH ICH DAS? Wie kann ich herausfinden ob "value" irgendein bestimmter typ ist? und was muss ich vor value schreiben (typ) ???



  • 1. für das was du da vor hast, wurden template-spezialisierung erfunden.

    2. Du kannst die typen über die RTTI checken (muss allerdings beim compilieren an sein - beim VC++ ist es der parameter /CR )
    bsp:

    template<class irgendwas>
    void foo (irgendwas value)
    {
       if (typeid( irgendwas ) == typeid(float))
       {
           glVector3f (1.0f, 1.0f, 1.0f);
       }
       else if (typeid( irgendwas ) == typeid(double))
       {
           glVector3d (1.0, 1.0, 1.0);
       }
       else if (typeid( irgendwas ) == typeid(unsigned int))
       {
           glVector3ui (1, 1, 1);
       }
       // usw.
    }
    


  • 1. Spezialisieren kannst du nur Klassen.
    2. Das, was du da machst, ist ziemlicher unsinn. Durch dein Template-Argument steht schon zur Compilezeit fest, um welchen Typ es sich handelt die Überprüfung zur Laufzeit mittels typeid ist demzufolge sinnlos.

    Man könnte überladen.

    template>typename T>
    struct Type2Type {
       typedef T Type;
    }
    
    void foo (Type2Type<int>)
    {
       glVector3ui (1, 1, 1);
    }
    
    void foo (Type2Type<float>)
    {
       glVector3f (1.f, 1.f, 1.f);
    }
    
    void foo (Type2Type<double>)
    {
       glVector3f (1., 1., 1.);
    }
    
    // Autfruf:
    
    foo(Type2Type<int>());
    


  • *** schrieb:

    Jetzt meine frage: WIE MACH ICH DAS? Wie kann ich herausfinden ob "value" irgendein bestimmter typ ist? und was muss ich vor value schreiben (typ) ???

    es gibt zwei Lösungen, die du benutzen könntest:
    1. function overloading

    void foo(float value)
    {
    	glVector3f (1.0f, 1.0f, 1.0f);
    }
    
    void foo(double value)
    {
    	glVector3d (1.0, 1.0, 1.0);
    }
    
    void foo(unsigned int value)
    {
    	glVector3ui (1, 1, 1);
    }
    

    2. template specialization:

    template<typename T>
    void foo(T value);
    
    template<>
    void foo(float value)
    {
    	glVector3f (1.0f, 1.0f, 1.0f);
    }
    
    template<>
    void foo(double value)
    {
    	glVector3d (1.0, 1.0, 1.0);
    }
    
    template<>
    void foo(unsigned int)
    {
    	glVector3ui (1, 1, 1);
    }
    


  • Helium schrieb:

    1. Spezialisieren kannst du nur Klassen.

    😕

    template<class T>
    void foo(T) { }
    
    template<>
    void foo(int) { }
    
    template<class T, class U>
    void foo1(T, U) { }
    
    template<class T>
    void foo1(T, unsigned) { }
    


  • [quote="Shlo"]

    Helium schrieb:

    1. Spezialisieren kannst du nur Klassen.

    IMHO eine falsche Meinung, die keine Begründung hat



  • Helium schrieb:

    1. Spezialisieren kannst du nur Klassen.

    seit wann!?!? o_O

    2. Das, was du da machst, ist ziemlicher unsinn. Durch dein Template-Argument steht schon zur Compilezeit fest, um welchen Typ es sich handelt die Überprüfung zur Laufzeit mittels typeid ist demzufolge sinnlos.

    Versteh nicht ganz warum ein Template-Argument einen laufzeitcheck mit typeid sinnlos macht 😕
    Macht doch genau das was er oben in seinem ersten code machen will.



  • Ja, man kann Funktionen überladen. Was willst du mir jetzt damit sagen?

    es gibt zwei Lösungen, die du benutzen könntest:
    [snip]
    2. template specialization:

    Ja sicher könnte man spezialisieren:

    tempalte <typename T>
    struct Foo {};
    
    tempalte <>
    struct Foo<float> {
       void foo()
       {
          glVector3f (1.0f, 1.0f, 1.0f);
       }
    };
    
    tempalte <>
    struct Foo<double> {
       void foo()
       {
          glVector3d (1.0, 1.0, 1.0);
       }
    };
    
    tempalte <>
    struct Foo<unsigned int> {
       void foo()
       {
           glVector3ui (1, 1, 1);
       }
    };
    

    Der Sinn ist allerdings fraglich. Deine erste version übergibt sinnloserweise einen Wert, obwohl sie das nicht müsste.



  • Helium schrieb:

    Ja, man kann Funktionen überladen. Was willst du mir jetzt
    Der Sinn ist allerdings fraglich. Deine erste version übergibt sinnloserweise einen Wert, obwohl sie das nicht müsste.

    🙄
    dann mache ich so:

    void foo(float)
    {
    	glVector3f (1.0f, 1.0f, 1.0f);
    }
    
    void foo(double)
    {
    	glVector3d (1.0, 1.0, 1.0);
    }
    
    void foo(unsigned int)
    {
    	glVector3ui (1, 1, 1);
    }
    
    //und werde es so benutzen:
    foo(float());
    foo(double());
    foo(unsigned int());
    

    😃



  • Helium schrieb:

    Ja sicher könnte man spezialisieren:

    tempalte <typename T>
    struct Foo {};
    
    tempalte <>
    struct Foo<float> {
       void foo()
       {
          glVector3f (1.0f, 1.0f, 1.0f);
       }
    };
    

    Ich verstehe immer noch nicht warum du statt eines Funktions-Templates und entsprechenden Spezialisierung, eine Klasse benutzt...



  • Warum unsinnig? Mach foo static und er kann schoen

    Foo<type>::foo();
    

    schreiben. Ist das denn wirklich so schlecht, wenn er sowas in der Art
    macht:

    template<typename T>
    struct Foo {
    };
    
    template<>
    struct Foo<int> {
        static int bar() {
    	return 0;
        }
    };
    
    template<>
    struct Foo<float> {
        static int bar() {
    	return 1;
        }
    };
    
    int main() {
        std::cout<<Foo<float>::bar()<<endl;
        std::cout<<Foo<int>::bar()<<endl;
        return 0;
    }
    

    mfg
    v R



  • Warum unsinnig? Mach foo static

    Wollte ich eigentlich auch 🙄



  • Helium schrieb:

    Warum unsinnig? Mach foo static

    Wollte ich eigentlich auch 🙄

    Achso, hab mir eigentlich auch gedacht, dass es ein vertippsler war 😃

    mfg
    v R



  • CMatt schrieb:

    1. für das was du da vor hast, wurden template-spezialisierung erfunden.

    2. Du kannst die typen über die RTTI checken (muss allerdings beim compilieren an sein - beim VC++ ist es der parameter /CR )
    bsp:

    template<class irgendwas>
    void foo (irgendwas value)
    {
       if (typeid( irgendwas ) == typeid(float))
       {
           glVector3f (1.0f, 1.0f, 1.0f);
       }
       else if (typeid( irgendwas ) == typeid(double))
       {
           glVector3d (1.0, 1.0, 1.0);
       }
       else if (typeid( irgendwas ) == typeid(unsigned int))
       {
           glVector3ui (1, 1, 1);
       }
       // usw.
    }
    

    Hi,

    danke den code find ich von all den vorgeschlagenen am einfachsten zu handhaben 🙂 Oder gehts noch besser jedoch bei selbem handling?

    Also die funktion sollte so benutzt werden:

    float x=1.0f;
    foo (x);
    

    Dabei soll dann in der funktion der wert an die jeweiligen funktionen übergeben werden.



  • *** schrieb:

    Also die funktion sollte so benutzt werden:

    float x=1.0f;
    foo (x);
    

    Dabei soll dann in der funktion der wert an die jeweiligen funktionen übergeben werden.

    in diesem Fall passt am besten function overloading, wie ich shon schrieb



  • Ich kann aber nicht für jede meiner 40 mathestrukturen 10 überladene funktionen machen für 100 Operatoren! (würde 1.000 Funktionen machen!)



  • Ich kann aber nicht für jede meiner 40 mathestrukturen 10 überladene funktionen machen für 100 Operatoren! (würde 1.000 Funktionen machen!)

    40*10*100=1000??? eher 40000.
    Aber 40000 if-Zweige sind in Ordnung? Sicher, das da nicht ein prinzipfehler hintersteckt.

    Und überleg mal.
    Ist es so wirklich übersichtlicher:

    tempalte <typename T>
    void foo (T value)
    {
       if (typeid(T) == typeid(float))
       {
           glVector3f (value, value, value);
       }
       else if (typeid(T) == typeid(double))
       {
           glVector3d (value, value, value);
       }
       else if (typeid(T) == typeid(unsigned int))
       {
           glVector3ui (value, value, value);
       }
       // usw.
    }
    

    Als so:

    void foo (float value)
    {
       glVector3f (value, value, value);
    }
    void foo (double value)
    {
        glVector3d (value, value, value);
    }
    void foo (unsigned int value)
    {
        glVector3ui (value, value, value);
    }
    

    Also auf jeden Fall ist die Variante mit dem Überladen deutlich kürzer und zudem wird garantiert zur Compilezeit entschieden, welche Version benötigt wird.
    Ich mein ja nur gl... hört sich so an, als ob Geschwindigkeit eine Rolle spielen könnte.



  • [quote="ssm"]

    Shlo schrieb:

    Helium schrieb:

    1. Spezialisieren kannst du nur Klassen.

    IMHO eine falsche Meinung, die keine Begründung hat

    Funktionstemplates kann man explizit nicht aber partiell spezialisieren.

    Das ist ok und eine explizite Spezialisierung:

    template <class T>
    void foo(T t);
    
    template <>
    void foo(int);
    

    Das ist auch ok aber *keine* partielle Spezialisierung sondern eine
    Überladung, hier haben wir jetzt zwei Base-Templates:

    template<class T, class U> 
    void foo1(T, U) { } 
    
    template<class T> 
    void foo1(T, unsigned) { }
    

    Der feine Unterschied zwischen Ünerladung und Spezialisierung wird hier sehr schön erlärt:
    http://www.gotw.ca/publications/mill17.htm



  • to HumeSikkins

    es ging nich um partielle Spezialisierung 😉 😃



  • ssm schrieb:

    to HumeSikkins

    es ging nich um partielle Spezialisierung 😉 😃

    Das Zitat sowie mein Beitrag sollten ausdrücken, dass ihr beide auf gewisse Art und Weise recht habt. Das Wort "spezialisieren" ist hier einfach nicht "speziell" genug 🙂


Anmelden zum Antworten