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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With