2

How can i simplify code below. Is it possibly to use here tuples? If yes, can u explain how.

template<typename Out, typename T1, typename T2, typename T3, typename T4>
void ProcessIncomingCommand(PClientContext pClientContext,
    DWORD & bytesProcessed,
    const std::function<Out(T1, T2, T3, T4)> &function,
    const std::vector<UINT> &params);

template<typename Out, typename T1, typename T2, typename T3>
static void ProcessIncomingCommand(PClientContext pClientContext,
    DWORD & bytesProcessed,
    const std::function<Out(T1, T2, T3)> &function,
    const std::vector<UINT> &params);

template<typename Out, typename T1, typename T2>
static void ProcessIncomingCommand(PClientContext pClientContext,
    DWORD & bytesProcessed,
    const std::function<Out(T1, T2)> &function,
    const std::vector<UINT> &params);

In template implementation is needed to invoke function with parameters passed by std::vector of UINT. Parameters may differ, so it is required to cast them to proper types.

auto resFromFunction= function(params.at(0),
    params.at(1),
    static_cast<T3>(params.at(2)),
    static_cast<T4>(params.at(3)));

How can i use log0 answer here?

template<typename Out, typename... T>static void ProcessIncomingCommand(PClientContext pClientContext,
DWORD & bytesProcessed,
const std::function<Out(T...)> &function,
const std::vector<UINT> &params)
Community
  • 1
  • 1
Smit Ycyken
  • 1,189
  • 1
  • 11
  • 25
  • 4
    What are you *really* trying to do here? What is the purpose of this code? –  May 11 '17 at 11:03
  • What would the tuples be used to ? – log0 May 11 '17 at 11:08
  • In realisation i invoke function with parameters passed by vector of UINT. types in vector may differ from template args (T...). I need to cast them to proper types. Ex: function(static_cast(params.at(0)), ... ) etc. Is it proper way to use templates here? – Smit Ycyken May 11 '17 at 11:10
  • Please specify, in the question post, what the parameters are supposed to do, how exactly you want it to be simplified, and try give a [mcve] – Passer By May 11 '17 at 11:10

3 Answers3

2

Not sure... but I suppose you need a function helper and std::index_sequence (or something similar).

A possible example

template <typename Out, typename ... Ts, std::size_t ... Is>
static Out PIC_helper (
   PClientContext pClientContext,
   DWORD & bytesProcessed,
   const std::function<Out(Ts...)> &function,
   const std::vector<UINT> &params,
   std::index_sequence<Is...> const &)
 { return function( static_cast<Ts>(params.at(Is))... ); }

template <typename Out, typename ... Ts>
static void ProcessIncomingCommand (
   PClientContext pClientContext,
   DWORD & bytesProcessed,
   const std::function<Out(Ts...)> &function,
   const std::vector<UINT> &params)
 {
   Out resFromFunction
      = PIC_helper(pClientContext, bytesProcessed, function, params,
                   std::make_index_sequence<sizeof...(Ts)>());

   // other ...
 }

Observere that std::index_sequence and std::make_index_sequence() are C++14 features; but if you need a C++11 solution, you can easily create something to substitute they.

max66
  • 65,235
  • 10
  • 71
  • 111
0

This compiles.

template<typename Out, typename... T>
static void ProcessIncomingCommand(PClientContext pClientContext,
    DWORD & bytesProcessed,
    const std::function<Out(T...)> &function,
    const T&... params) { function(params...); }

int main()
{
  PClientContext p;
  DWORD d = 0.5;
  std::function<int(double, int, char)> f;
  double a;
  int b;
  char c;
  ProcessIncomingCommand(p, d, f, a, b, c);
}

If you want to pass params as a tuple, it is going to be trickier: See How do I expand a tuple into variadic template function's arguments? Except of course if you change function to take a tuple instead of a list of parameters...

Community
  • 1
  • 1
log0
  • 10,489
  • 4
  • 28
  • 62
  • How can i invoke function with N parameters? Please look at comment above for imformation about template implementation. – Smit Ycyken May 11 '17 at 11:13
  • 1
    ok it was not clear for me that params were going to be passed to `function`. just edited the answer. – log0 May 11 '17 at 11:27
0

It looks like you want something like

template<typename ResultType, std::size_t... I>
ResultType tuple_from_vector_impl(std::vector<UINT> params, std::index_sequence<I...>)
{
    return std::make_tuple(static_cast<decltype(std::get<I>(std::declval<ResultType>()))>(params[I])...);
}

template<typename... Args, typename Indices = std::index_sequence_for<Args...>>
std::tuple<Args...> tuple_from_vector(std::vector<UINT> params)
{
    return tuple_from_vector_impl<std::tuple<Args...>>(params, Indices{});
}

template<typename Out, typename ... Args>
void ProcessIncomingCommand(PClientContext pClientContext,
                            DWORD & bytesProcessed,
                            const std::function<Out(Args...)> &function,
                            const std::vector<UINT> &params)
{
    // preamble
    std::tuple<Args...> args = tuple_from_vector<Args...>(params);
    Out result = std::apply(function, args);
    // postamble
}

template<typename ... Args>
void ProcessIncomingCommand(PClientContext pClientContext,
                            DWORD & bytesProcessed,
                            const std::function<void(Args...)> &function,
                            const std::vector<UINT> &params)
{
    // preamble
    std::tuple<Args...> args = tuple_from_vector<Args...>(params);
    std::apply(function, args);
    // postamble
}
Caleth
  • 52,200
  • 2
  • 44
  • 75