Funktionstemplate-Magie - sehe die Überladung nicht.
-
Ich spiele grade ein wenig mit Methodentemplates herum, folgender Code:
struct Dummy { static Dummy DUMMYvoid(void) { return Dummy(); } typedef Dummy (*voidCreator)(void); template <voidCreator> void get() const; //17 template<> void get<&DUMMYvoid>() const {} static Dummy DUMMYint(int) { return Dummy(); } typedef Dummy (*intCreator)(int); template <intCreator> int get() const; template<> int get<&DUMMYint>() const {} //24 }; int main() { auto di = Dummy::DUMMYint(10); auto x = intevt.get<Dummy::DUMMYint>(); //line 46 assert(x == 10); }Compilerfehler:
2>test.cpp(46): error C2668: 'Dummy::get' : ambiguous call to overloaded function 2>test.cpp(24): could be 'int Dummy::get<Dummy Dummy::DUMMYint(int)>(void) const' 2>test.cpp(17): or 'void Dummy::get<Dummy Dummy::DUMMYint(int)>(void) const' 2> while trying to match the argument list '(void)'Ich kapier nicht ganz, wo der Compiler da die zweideutigkeit sieht, schließlich ist DUMMYint vom Typ Dummy(int) und nicht vom Typ Dummy(void), also passt für Zeile 17 der Parameter doch garnicht. Wo ist der Haken?
Hintergrund: ich möchte ein Objekt mit einer Erzeugerfunktion erzeugen, und dann später mit der Get-Funktion herausbekommen, was auch immer ich der Erzeugerfunktion als Parameter mitgegeben habe. Den Rückgabetyp von get möchte ich (anders als z.B. boost::any) nicht direkt bestimmen sondern indirekt durch Übergabe des Funktoinspointers der Erzeugerfunktion.
Klingt jetzt wirr, aber vielleicht verstehts ja jemand

Alternative Ideen sind auch immer wollkommen
-
Memberfunktionen zu spezialisieren ist schlicht und ergreifend nicht erlaubt.
http://ideone.com/WKRSq
-
./main.cpp:6:12: Fehler: explizite Spezialisierung in Gültigkeitsbereich des Nicht-Namensbereiches »struct Dummy« ./main.cpp:6:37: Fehler: Template-ID »get<Dummy::DUMMYvoid>« in Deklaration des ersten Templates ./main.cpp:11:29: Fehler: zu viele Templateparameterlisten ./main.cpp:12:12: Fehler: explizite Spezialisierung in Gültigkeitsbereich des Nicht-Namensbereiches »struct Dummy« ./main.cpp:12:35: Fehler: Template-ID »get<Dummy::DUMMYint>« in Deklaration des ersten Templates ./main.cpp:12:18: Fehler: »int Dummy::get() const« kann nicht überladen werden ./main.cpp:6:19: Fehler: mit »void Dummy::get() const« ./main.cpp: In Elementfunktion »int Dummy::get() const«: ./main.cpp:12:42: Warnung: keine return-Anweisung in nicht void zurückgebender Funktion [-Wreturn-type] ./main.cpp: In Funktion »int main()«: ./main.cpp:19:12: Fehler: »intevt« wurde in diesem Gültigkeitsbereich nicht definiert ./main.cpp:19:40: Fehler: expected primary-expression before »)« token ./main.cpp:19:40: Fehler: »auto« kann nicht aus »<Ausdrucksfehler>« hergeleitet werden ./main.cpp:20:17: Fehler: »assert« wurde in diesem Gültigkeitsbereich nicht definiert
-
Edit: Hab den Fehler nicht geleesen, sry

-
314159265358979 schrieb:
Memberfunktionen zu spezialisieren ist schlicht und ergreifend nicht erlaubt.
http://ideone.com/WKRSqGnarf. 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 valueIs 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.
-
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 -.-