Calling methods of different signatures by name

I have a set of delegates using std::functionthat point to functions with different signatures. I want to get these delegates at runtime using string keys. I cannot use a map because they point to functions with different signatures. Can I have this functionality without a switch statement?

For example, the real use case in the world is the RPC system. Do they really just make the methods the same or generate code to generate the code?

E : useful links related to the selected answer, which will take quite a long time to understand

http://en.cppreference.com/w/cpp/utility/functional/function

http://en.cppreference.com/w/cpp/utility/forward

http://en.cppreference.com/w/cpp/utility/integer_sequence

http://en.cppreference.com/w/cpp/types/result_of

http://en.cppreference.com/w/cpp/types/remove_reference

http://www.boost.org/doc/libs/1_57_0/doc/html/any.html

+4
source share
2 answers

Start with a set of types:

template<class...Ts>struct types{
  using type=types;
  enum{count = sizeof...(Ts)};
};
template<class T> struct tag{using type=T;};

Now we define all of our supported types in one global package types.

The index into this global package is typessent over the wire and used to search for deserialization code.

( std) boost::any read( wire_data, T* unused ) T ( ), boost::any. wire_data , , T.

read :

template<size_t n> using index=std::integral_constant<size_t, n>;

template<class types, class T>
struct index_in;
template<class...Ts, class T>
struct index_in<types<T, Ts...>, T>:index<0> {};
template<class T0, class...Ts, class T1>
struct index_in<types<T0, Ts...>, T1>:index<
  index_in<types<Ts...>, T1>::value+1
> {};

T types<Ts...>. , .

, :

template<class types, size_t n>
struct type_at;
template<class types, size_t n>
using type_at_t=typename type_at<types,n>::type;
template<class T0, class...Ts>
struct type_at<types<T0, Ts...>,0>: tag<T0> {};
template<class T0, class...Ts, size_t n>
struct type_at<types<T0, Ts...>,n>:
  type_at<types<Ts...>, n-1>
{};

types<Ts...> .

template<class types>
struct to_any {
  template<size_t n>
  struct worker {
    boost::any operator()( wire_data w )const{
      using protocol_ns::read;
      return read( w, (type_at_t<types,n>*)nullptr );
    }
  };
};

read ADL.

:

namespace details {
  template<template<size_t>class action, class indexes>
  struct magic_switch;
  template<template<size_t>class action, size_t... Is>
  struct magic_switch<action, std::index_sequences<Is...>>
  {
    template<class...Ts, class R=std::result_of_t< action<max>(Ts...) >>
    R operator()(size_t i, Ts&&... ts)const {
      using entry = R(*)(std::remove_reference<Ts>*...);
      entry table[] = {
        [](std::remove_reference<Ts>*...args)->R{
          return action<Is>{}( std::forward<Ts>(*args)... );
        }...
      };
      if (i > sizeof(table)/sizeof(entry))
        throw std::out_of_range("i");
      return table[i]( (&ts)... );
    }
  };
}
template<template<size_t>class action, size_t max>
struct magic_switch:
  details::magic_switch<action,std::make_index_sequence<max>>
{};

magic_switch<
  to_any<all_types_supported>::template worker, 
  all_types_supported::count
>

- , n wire_data read boost::any.

, .

Z(Args...) , std::vector<boost::any> Args... boost::any Z.

std::function<boost::any(std::vector<boost::any>)> erased_func_t;

template<class... Args, class F>
erased_func_t erase_func(F&& f) {
  // TODO
}

, erased_func_t .

erased_func_t. std::vector<boost::any> . , , .

- .

, , , erased_func_t, wire_data, boost::any. , .

. ++ 14 ( , _t aliases), , , ++ 11, magic_switch, ( ++ 11, _t, ). , .

, , RPC . , .

+4

std::map , .

. () .

:

struct Base_Parameters;

struct Base_Functor
{
  virtual void execute(Base_Parameter * p_parameters) = 0;
};

, std::map:

typedef std::map<std::string, Base_Functor *> Function_Key_Container;

: struct My_Functor: Base_Functor { void execute (Base_Parameters * p_parameters) {   //... } };

, :

Function_Key_Container function_map;
function_map["Apple"] = new My_Functor;

.
, :

  • boost:: variant - .
  • Base_Parameters dynamic_cast Base_Parameters .
+2

All Articles