function parameter from function pointer at compile time



  • hey; ich mal wieder...

    habe ich auf irgend nem weg eine chance, die zu übergebenden parameter an eine funktion herauszufinden?

    ich habe so eine art interpreter gebaut und funktionen werden wie folgt hinzugefügt:

    namespace cmd_impl
    {
      struct foo
      {
        void operator()( context_t& context )
        { /*...*/ }
      };
    
      struct bar
      {
        void operator()( context_t& context, unsigned p1, std::string p2 )
        { /* ... */ }
      };
    }
    
    auto create_fct_map()
    {
    	std::map<
    		std::string,
    		std::function<void(parser_t&, context_t&)>
    	> fct_map;
    
    #define ADD_CMD(NAME, PARAM) \
    	do{ \
    	using caller = command::base< \
    		PARAM, \
    		command_impl::NAME \
    	>;\
    	\
    	std::function<void(parser_t&, context_t&)> fct(&caller::do_it);\
    	fct_map.insert( std::make_pair(#NAME, fct) );\
    	\
    	} while( false )
    #define COMMA ,
    
    	ADD_CMD(foo, parameter<void>);
    	ADD_CMD(bar, parameter<unsigned COMMA std::string>);
    
    #undef ADD_CMD
    #undef COMMA
    
    	return fct_map;
    }
    

    parameter ist das ding, was mir die parameter aus dem parser rausnimmt.
    command::base die verpackung.

    das ganze funktioniert, wie gewünscht.
    was mich aber stört, ist die tatsache, dass ich zweimal die parameter angeben muss...

    danke, bb 🙂



  • hi

    was hats da mit dem COMMA auf sich ?

    du willst also in zeile 36 und 37 nur foo und bar angeben und dann soll der compiler (ist das ueberhaupt der compiler?) automatisch wissen wie der operator() von foo und bar aussieht ?

    Meep Meep


  • Mod

    Meep Meep schrieb:

    was hats da mit dem COMMA auf sich ?

    Ein richtiges Komma wird vom Präprozessor als Trenner von Makroargumenten interpretiert, soll hier aber Teil eines einzelnen Arguments sein..
    Das dadurch entstehende Problem könnte auch durch ein variadisches Makro umgangen werden.

    decltype(&command_impl::NAME::operator()) (innerhalb von command::base) liefert einen geeigneten Typen, aus dem man die Parameterliste extrahieren kann - vorausgesetzt operator() ist weder überladen noch ein Template.



  • Meep Meep schrieb:

    du willst also in zeile 36 und 37 nur foo und bar angeben und dann soll der compiler (ist das ueberhaupt der compiler?) automatisch wissen wie der operator() von foo und bar aussieht ?

    genau

    camper schrieb:

    Meep Meep schrieb:

    was hats da mit dem COMMA auf sich ?

    Ein richtiges Komma wird vom Präprozessor als Trenner von Makroargumenten interpretiert, soll hier aber Teil eines einzelnen Arguments sein..
    Das dadurch entstehende Problem könnte auch durch ein variadisches Makro umgangen werden.

    ja, ganz schön nervig; zu mal das einiges an selbstzweifel gekostet hat, bis ich als makro-muffel darauf gekommen bin, dass es das sein könnte^^ aber jetzt... 😃
    @variadisches Makro: hab ich auch noch nicht gekannt... variadic oder COMMA?

    camper schrieb:

    decltype(&command_impl::NAME::operator()) (innerhalb von command::base) liefert einen geeigneten Typen, aus dem man die Parameterliste extrahieren kann - vorausgesetzt operator() ist weder überladen noch ein Template.

    jo, das ist es nicht.
    aber decltype hab ich davor auch schon versucht und bin auf nichts sinnvolles gestoßen... also ganz konrekt:

    struct T {};
    
    #include <string>
    
    struct foo
    {
      void operator() (T t, std::string p1) {}
    };
    
    int main()
    {
      using X = decltype( &foo::operator() );
    }
    

    und wie komm ich jetzt an std::string?
    vermutlich fehlt mir was für dich offensichtliches; aber ich komm einfach nicht drauf : (

    danke


  • Mod

    In diesem Beispiel könnte man es einfach so machen (ich nehme std::tuple, weil da schon alles fertig eingebaut ist, um auf ein einzelnes Element zuzugreifen)

    struct T {};
    
    #include <string>
    
    struct foo
    {
      void operator() (T t, std::string p1) {}
    };
    
    #include <tuple>
    
    template <typename T>
    struct unpack_mem_fun_ptr;
    
    template <typename R, typename C, typename... Args>
    struct unpack_mem_fun_ptr<R (C::*)(Args...)>
    {
      using args = std::tuple<Args...>;
    };
    
    int main()
    {
      using X = decltype( &foo::operator() );
      static_assert( std::is_same<std::tuple_element_t<1,unpack_mem_fun_ptr<X>::args>,std::string>{}, "" );
    }
    

Log in to reply