[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?


  • Mod

    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).


  • Administrator

    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 👍


Anmelden zum Antworten