c++ - Variadic Template Dispatcher -


i use variadic templates solve issue using va-args. basically, want call singular function, pass function "command" along variable list of arguments, dispatch arguments function.

i've implemented using tried , true (but not type safe) va_list. here's attempt made @ doing using variadic templates. example doesn't compile below find out why...

#include <iostream>  using namespace std; typedef enum cmd_t {     cmd_zero,     cmd_one,     cmd_two, } commands;   int cmd0(double a, double b, double c) {     cout << "cmd0  " << << ", " << b << ", " << c << endl;     return 0; }  int cmd1(int a, int b, int c) {     cout << "cmd1  " << << ", " << b << ", " << c << endl;     return 1; }  template<typename... args> int dispatchcommand(commands cmd, args... args) {     int stat = 0;     switch (cmd)     {     case cmd_zero:         cmd0(args...);         break;     case cmd_one:         cmd1(args...);         break;     default:         stat = -1;         break;     }     return stat; }  int main() {     int stat;     stat = dispatchcommand(cmd_zero, 1, 3.141, 4);     stat = dispatchcommand(cmd_one, 5, 6, 7);     stat = dispatchcommand(cmd_two, 5, 6, 7, 8, 9);      system("pause");     return 0; } 

does have idea on how can modify function use variadic templates correctly?

write code that, given function pointer , set of arguments, calls longest prefix of arguments works.

template<class...>struct types{using type=types;}; template<class types0, size_t n, class types1=types<>> struct split;  template<class t00, class...t0s, size_t n, class...t1s> struct split<types<t00,t0s...>,n,types<t1s...>>:   split<types<t0s...>,n-1,types<t1s...,t00>> {}; template<class...t0s, class...t1s> struct split<types<t0s...>,0,types<t1s...>> {   using right=types<t0s...>;   using left=types<t1s...>; }; template<class>using void_t=void; template<class sig,class=void> struct valid_call:std::false_type{}; template<class f, class...args> struct valid_call<f(args...), void_t<   decltype( std::declval<f>()(std::declval<args>()...) ) >>:std::true_type {};  template<class r, class types> struct prefix_call;  template<class r, class...args> struct prefix_call<r, types<args...>> {   template<class f, class... extra>   std::enable_if_t< valid_call<f(args...)>::value, r >   operator()(r default, f f, args&&...args, extra&&...) const   {     return std::forward<f>(f)(args...);   }   template<class f, class... extra>   std::enable_if_t< !valid_call<f(args...)>::value, r >   operator()(r default, f f, args&&...args, extra&&...) const   {     return prefix_call<r, typename split<types<args...>, sizeof...(args)-1>::left>{}(       std::forward<r>(default), std::forward<f>(f), std::forward<args>(args)...     );   } };  template<class r> struct prefix_call<r, types<>> {   template<class f, class... extra>   std::enable_if_t< valid_call<f()>::value, r >   operator()(r default, f f, extra&&...) const   {     return std::forward<f>(f)();   }   template<class f, class... extra>   std::enable_if_t< !valid_call<f()>::value, r >   operator()(r default, f f, extra&&...) const   {     return std::forward<r>(default);   } }; 

the above code may contain typos.

template<typename... args> int dispatchcommand(commands cmd, args... args) {   int stat = 0;   switch (cmd) {     case cmd_zero: {       stat = prefix_call<int, args...>{}(-1, cmd0, std::forward<args>(args)...);     } break;     case cmd_one: {       stat = prefix_call<int, args...>{}(-1, cmd1, std::forward<args>(args)...);     } break;     default: {       stat = -1;     } break;   }   return stat; } 

if cmd0 or cmd1 overridden, you'll have use overload set technique.


Comments

Popular posts from this blog

javascript - how to protect a flash video from refresh? -

android - Associate same looper with different threads -

visual studio 2010 - Connect to informix database windows form application -