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) {
}
, 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 . , .