[Templates] Parametertyp eines Funktionszeigers ermitteln
-
Hallo!
folgendes:
// Diese Struktur ruft add<From>(f) auf, für einen Aufruf des op(). // Sie wird von mpl::for_each aufgerufen template<class Param> struct reg_type { PyObject* (*f)(Param); reg_type(PyObject* (*func)(Param)) : f(func) {} template <class From> void operator()(From /*unused*/) { add<From>(f); } };Aufrufen tue ich das ganze so (vereinfacht): (eigentlich von boost::mpl::for_each, deswegen die komische Syntax)
reg_type<long>(PyInt_FromLong) o; o.operator()<int>(); o.operator()<char>(); o.operator()<long>();Ich möchte das Objekt aber so erstellen können:
reg_type(PyInt_FromLong) o;Also ohne die explizite Angabe, dass PyInt_FromLong als Parameter ein long erwartet.
Ich bräuchte also eine Struktur o.ä. welche aus einem Funktionszeiger, welcher PyObject* zurückgibt und einen Parameter erwartet, den Typ des Parameters errechnet.
DAs heir ginge, wäre ja aber genauso schlimm, da ich den Parameter aufrufen wieder angeben muss:
template <class P, PyObject* (*f)(P)> struct get_ret_type { typedef P type; };Habt ihr eine Idee? Das kann man bestimmt irgendwie erreichen, da es ja schon nervig ist, diesen redundanten Parameter immer mit anzugeben.
-
*push*
Geht das überhaupt nicht, oder weiß es nur keiner?
-
Maxi schrieb:
*push*
Geht das überhaupt nicht, oder weiß es nur keiner?Es geht leider nicht. Mit dem nächsten Standard könnte man auto einsetzen:
template<typename T> reg_type<T> get_reg_type(PyObject* (*func)(T)) { return reg_type<T>( func ); } auto o = get_reg_type( PyInt_FromLong );
-
Das hier dürfte gehen. Allerdings musst du dann halt um dein Objekt zu erstellen über die Hilfsfunktion und nicht über den eigentlichen Konstruktor gehen (so ähnlich wie bei std::make_pair):
template<typename T> reg_type<T> CreateRegType(PyObject* (*f)(T)) { return reg_type<T>(f); }Felix
EDIT: Stimmt, jetzt wo ich campers post sehe, fällt mir ein, dass das auch nichts bringt, weil du ja den Typ immer noch angeben müsstest
Je nachdem, was du machst, könntest du höchstens eine gemeinsame Basisklasse für alle Instanziierungen des Templates machen (das habe ich für einen Callable-Object-Wrapper mal gemacht).
-
camper schrieb:
Es geht leider nicht. Mit dem nächsten Standard könnte man auto einsetzen:
Gibt es mit dem nächsten Standard nicht auch eine automatische Templateerkennung für Klassen? Wodurch solche Funktionen überflüssig werden? Oder hab ich das falsch in Erinnerung oder wars anders ... *kopfkratz*
Grüssli
-
Phoemuex schrieb:
template<typename T> reg_type<T> CreateRegType(PyObject* (*f)(T)) { return reg_type<T>(f); }Super, das reicht für meine Zwecke aus, hätt ich aber selbst drauf kommen können, ist ja wirklich bei bei std::make_pair oder std:.bind1st oder so

Eingesetzt wirds so:template <class T> struct wrap {}; template<class Param> struct reg_type { PyObject* (*f)(Param); reg_type(PyObject* (*func)(Param)) : f(func) {} template <class From> void operator()(wrap<From>) { add_to_python<From>(f); } }; template <class Param> reg_type<Param> get_reg_type(PyObject* (*f)(Param)) { return reg_type<Param>(f); } // Add integral types typedef mpl::vector<char, short, int, long, long long, unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long, signed char, signed short, signed int, signed long, signed long long >::type integrals; mpl::for_each<integrals, wrap<_1> >(get_reg_type(PyInt_FromLong));Vielen Dank
