Funktionstemplate-Magie - sehe die Überladung nicht.



  • 314159265358979 schrieb:

    Memberfunktionen zu spezialisieren ist schlicht und ergreifend nicht erlaubt.
    http://ideone.com/WKRSq

    Gnarf. Okay. Wie dumm von mir, danke für den Hinweis *kopf->tisch*

    Nächster Versuch, vieeel einfacher (dachte ich):

    struct Dummy { 
      template <class T>
      typename std::enable_if<!std::is_same<T, void>::value, T>::type get(Dummy (*)(T)) 
      { return T();}
    
      static Dummy DUMMYvoid(void) { return Dummy(); }
      static Dummy DUMMYint(int) { return Dummy(); }
    };
    
    int main()
    {
      auto di = Dummy::DUMMYint(10);
      auto x = di.get(Dummy::DUMMYint);
      assert(x == 10);
    }
    

    Fehlermeldung:

    2>test.cpp(46): error C2664: 'int Dummy::get<int>(Dummy (__cdecl *)(T))' : cannot convert parameter 1 from 'Dummy (__cdecl *)(int)' to 'Dummy (__cdecl *)(T)'
    2>          with
    2>          [
    2>              T=int
    2>          ]
    2>          Incompatible calling conventions for UDT return value
    

    Is schon klar. Du kannst ein X nicht in ein X konvertieren. WTF??

    (ideone übersetzt problemlos)



  • MSVC Bug? 😋

    Btw: Memberfunktionen spezialisieren geht offenbar doch, nur nicht direkt innerhalb der Klasse. http://ideone.com/q2C94



  • #include <cassert>
    #include <type_traits>
    
    struct Dummy {
      static Dummy DUMMYvoid(void) { return Dummy(); }
      static Dummy DUMMYint(int) { return Dummy(); }
      typedef Dummy (*voidCreator)(void);
      typedef Dummy (*intCreator)(int);
    
      template <voidCreator creator>
      typename std::enable_if<creator == &Dummy::DUMMYvoid, void>::type get() const {}
    
      template <intCreator creator>
      typename std::enable_if<creator == &Dummy::DUMMYint,int>::type get() const { return 10; }
    };
    
    int main()
    {
      auto di = Dummy::DUMMYint(10);
      auto i = di.get<&Dummy::DUMMYint>(); //line 46
      assert(i == 10);
    }
    

    compiliert.

    314159265358979 schrieb:

    Btw: Memberfunktionen spezialisieren geht offenbar doch, nur nicht direkt innerhalb der Klasse. http://ideone.com/q2C94

    Das ist glaube ich ein GCC bug.

    EDIT: Alternative oben verbessert



  • pyhax schrieb:

    Das ist glaube ich ein GCC bug.

    Kann mir nicht vorstellen, dass GCC so fundamentale Bugs hat.



  • 314159265358979 schrieb:

    pyhax schrieb:

    Das ist glaube ich ein GCC bug.

    Kann mir nicht vorstellen, dass GCC so fundamentale Bugs hat.

    Kann sein das ich das mit was anderem verwechsele, ich meine ich hätte es mal irgendwo gelesen, finde es jetzt aber auch nicht.


  • Mod

    pyhax schrieb:

    314159265358979 schrieb:

    pyhax schrieb:

    Das ist glaube ich ein GCC bug.

    Kann mir nicht vorstellen, dass GCC so fundamentale Bugs hat.

    Kann sein das ich das mit was anderem verwechsele, ich meine ich hätte es mal irgendwo gelesen, finde es jetzt aber auch nicht.

    Mit Glauben hat es zum Glück nichts zu tun. Templatespezialisierungen müssen stets in dem umliegenden Namensraum (lies: namespace, nicht scope/deklarative Region!) deklariert werden, in dem sich das Primärtemplate befindet. Für Memberfunktionstemplates also der Namensraum, in dem die jeweilige Klasse definiert wurde.
    Weitere Besonderheiten sind im Prinzip nicht zu beachten.

    Außer nat. dass explizite Templatedefinitionen keine Templates darstellen, so dass für Membertemplates von Templateklassen immer auch das umliegende Template mit zu spezialisieren ist...



  • pyhax schrieb:

    [...]
    

    compiliert.

    Im MSVC2010 nicht:

    1>test.cpp(20): error C2446: '==': Keine Konvertierung von 'Dummy::voidCreator' in 'Dummy (__cdecl *)(int)'
    1>          Diese Konvertierung erfordert einen reinterpret_cast-Operator oder eine Typumwandlung im C- oder Funktionsformat
    1>test.cpp(20): error C2440: '==': 'Dummy::voidCreator' kann nicht in 'Dummy (__cdecl *)(int)' konvertiert werden
    1>test.cpp(20): error C2770: Ungültige explizite template-Argumente für "std::enable_if<creator==Dummy Dummy::DUMMYint(int),int>::type Dummy::get(void) const".
    


  • Ok, definitiv buggy:

    struct Dummy {
      static Dummy foo(int);
    };
    
    Dummy bar(int);
    
    template <class T> struct P1;
    
    template <class R, class T> 
    struct P1<R(*)(T)> { 
      typedef T type;
    };
    
    template <class T> 
    typename P1<T>::type 
      get(T) { return 1; }
    
    int main()
    {
      auto i = get(bar); //line 22
      auto j = get(Dummy::foo); //line 23
    }
    

    [code]2>test.cpp(23): error C2893: Failed to specialize function template 'P1<T>::type get(T)'
    2> With the following template arguments:
    2> 'Dummy (__cdecl *)(int)'
    2>test.cpp(23): fatal error C1903: unable to recover from previous error(s); stopping compilation[/cpp]

    bar und Dummy::foo haben den selben Typ, oder nicht?



  • pumuckl schrieb:

    bar und Dummy::foo haben den selben Typ, oder nicht?

    Nein, haben sie nicht. Dummy::foo ist vom Typ Dummy (Dumyy::)(int). Bar ist vom Typ Dummy()(int). Oder ist das bei static Funktionen anders?



  • pyhax schrieb:

    pumuckl schrieb:

    bar und Dummy::foo haben den selben Typ, oder nicht?

    Dummy::foo ist vom Typ Dummy (Dumyy::*)(int).

    Meinst du ::Dummy* ?



  • pyhax schrieb:

    Oder ist das bei static Funktionen anders?

    Richtig. Static Funktionen sind was das angeht wie freie Funktionen, gleiches gilt für static variablen.

    /edit: war nix. warum auch immer der Linker die letzten Stunden nicht angesprungen ist -.-


Anmelden zum Antworten