Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic template for calling function with vector elements

I would like to call a function with the arguments coming from a vector. This alone is certainly very easy, but I would like to write a generic wrapper that does the assignment for me. Later it should also do the conversion from a generic type like boost::variant, but I think I can handle that after this problem is solved.

This is my first try:

#include <iostream>
#include <functional>
#include <vector>

using namespace std;

void foo(int a, int b)
{
  cout << a*10+b << endl;
}

template<class... Args>
void callByVector(std::function<void(Args...)> f, vector<int>& arguments)
{
  int i = 0;
  f(static_cast<Args>(arguments[i++])...);
}

int main()
{
  vector<int> arguments;
  arguments.push_back(2);
  arguments.push_back(3);

  callByVector(std::function<void(int,int)>(foo),arguments);
}

It works, but as you might guess, the order of execution of the increments is not defined. Therefore, the overall result can be 23 or 32 (I can confirm that with different compilers).

Any ideas or do I have to forget about that?

Greetings, Florian

like image 219
koalo Avatar asked Jun 14 '13 17:06

koalo


1 Answers

You can use indices for that purpose. Given this generator of compile-time integer sequences:

template<int... Is>
struct seq { };

template<int N, int... Is>
struct gen_seq : gen_seq<N - 1, N - 1, Is...> { };

template<int... Is>
struct gen_seq<0, Is...> : seq<Is...> { };

You can let your original function delegate the work to a helper function called with an additional argument that allows deducing the sequence of integers. Argument pack expansion would do the rest:

template<class... Args, int... Is>
void callByVector(
    std::function<void(Args...)> f, vector<int>& arguments, seq<Is...>)
{
  f(arguments[Is]...);
}

template<class... Args>
void callByVector(std::function<void(Args...)> f, vector<int>& arguments)
{
  callByVector(f, arguments, gen_seq<sizeof...(Args)>());
}

Here is a live example.

like image 124
Andy Prowl Avatar answered Oct 26 '22 00:10

Andy Prowl