I'm writing a plugin for software written in C++, here's a snippet where the plugin is defined:
extern "C"
irods::ms_table_entry* plugin_factory() {
// The number of msParam_t* arguments that it will accept
int numArguments = 2;
irods::ms_table_entry* msvc = new irods::ms_table_entry(numArguments);
msvc->add_operation(
"my_microservice",
std::function<int(msParam_t*, msParam_t*, ruleExecInfo_t*)>(MyMicroservice)
);
return msvc;
}
I'd like to be able to use numArguments to dynamically generate the std::function<int(msParam_t*, msParam_t*, ruleExecInfo_t*)> parameter pack. Where numArguments represents the number of msParam_t* arguments.
I'm not a C++ expert (especially with templating), so after some research I've found that this might be possible by implementing the following:
std::tuple
std::tuple_cat
std::index_sequence
std::make_integer_sequence
But I don't really know how to get started on implementing this. The examples I found were hard to understand, and I couldn't manage to translate them into my own needs. Can anyone provide tips, short examples, or references on how this might work? Any info is greatly appreciated!
I don't know if the following is exactly what you're asking but I think that what you want is being able to generate the right template parameters for the std::function based on the number of arguments that your MyMicroservice takes which is stored into the numParameters variable.
If that is the case you can simply omit writing them at all and use decltypeand let the compiler write them for you.
int myMicroservice1(int a,int b, int c){
return a+b+c;
}
int myMicroservice2(int a,int b, int c,int d){
return a*b*c-d;
}
int myMicroservice3(int a,int b, int c,int d,int e, int f){
return a*b*c+e+f;
}
template<typename... types_t>
void add_operation(const std::string & _op, std::function< int(types_t...)> _f ){
}
int main() {
add_operation("blabla",std::function<decltype(myMicroservice1)>(myMicroservice1));
add_operation("blabla",std::function<decltype(myMicroservice2)>(myMicroservice2));
add_operation("blabla",std::function<decltype(myMicroservice3)>(myMicroservice3));
return 0;
}
template<typename T>
struct toFunc;
template<typename...T>
struct toFunc<std::tuple<T...>>
{
using type = std::function<void(T...)>;
};
int main(int argc, char **argv) {
using t = std::tuple<int, int, int>;
using func = toFunc<t>::type;
auto f = func([](int a, int b, int c){std::cout << a << b << c << std::endl;});
f(1, 2, 3);
return 0;
}
toFunc typetrait will convert your tuple to a function type. not sure if you want that. If you want to call with the argument you maybe need to look for
http://en.cppreference.com/w/cpp/utility/apply
or you can use this implementation:
namespace detail
{
template <unsigned int N>
struct for_each_t_idx
{
template <template<std::size_t> class Functor, typename... ArgsT>
static void exec(const std::tuple<ArgsT...>& t, Functor<N> func)
{
for_each_t_idx<N - 1>::exec(t, func);
func<N - 1>(t);
}
};
template <>
struct for_each_t_idx<0>
{
template <template<std::size_t> class Functor, typename... ArgsT>
static void exec(const std::tuple<ArgsT...>& t, Functor<0> func)
{
}
};
}
template <template<std::size_t> class Functor, typename... ArgsT>
void for_each_idx(const std::tuple<ArgsT...>& t, Functor<sizeof...(ArgsT)> func)
{
detail::for_each_t_idx<sizeof...(ArgsT)>::exec(t, func);
}
This will call a given function for each element in a the tuple.
Related
I try to pass to a variadic template function a list of references and pass it to another function. The code that I wrote is the following:
template <typename T>
void fun(cv::Point_<T> & pt) { pt.x++; pt.y++; }
template <class ... args>
void caller(args & ... list) {
typedef typename std::tuple_element<0, std::tuple<args...> >::type T;
std::array<std::reference_wrapper<T>, sizeof...(list)> values {list ... };
for(int i=0; i<values.size(); i++)
fun(values[i]);
}
then I call the function caller in this way:
cv::Point2f a, b, c;
caller(a, b, c);
the compiler give me the following error:
No matching function for call to 'fun'
Candidate template ignored: could not match 'Point_' against 'reference_wrapper'
what I missing?
Although std::reference_wrapper<T> has an implicit conversion to T&, you cannot use both an implicit conversion and template argument deduction at the same time, and template argument deduction is necessary to call fun.
Try
fun(values[i].get());
Even simpler is
template <typename...Args>
void caller(Args&...args)
{
auto tmp = { (func(args),0)..., 0 };
}
This uses the fact that parameter pack expansion can occur in braced init lists. Since func() returns void, we cannot simply use { func(args)... }, but use (func(args),0) to have an int. Finally, the last 0 is to ensure that the code compiles (and does nothing) in case of an empty parameter pack.
You can generalise this and write a template that calls a given generic function for every element of a pack:
template <typename Func, typename...Args>
void call_for_each(Func &&func, Args&&...args)
{
auto unused = { (func(std::forward<Args>(args)),0)...,0 };
}
which may be used like this (C++14)
int main()
{
int a=1;
double b=2.4;
auto func = [](auto&x) { std::cout<<' '<<x++; };
call_for_each(func,a,b);
std::cout<<'\n';
call_for_each(func,a,b);
std::cout<<'\n';
}
This uses a C++14 lambda (taking an auto argument). Note that the parameter pack must come last among the template parameters of call_for_each.
Since the goal of this might be to iterate over all args, here's a more generic solution. We are going to implement for_pack:
template<typename... Args, typename F>
void for_pack(F function, Args&&... args) {
using expand = int[];
(void)expand{(function(std::forward<Args>(args)), void(), 0)..., 0};
}
This will execute function for every args in Args.
Now, your function caller is much more trivial to implement:
template <typename... args>
void caller(args&... list) {
for_pack([&](cv::Point_<T>& arg){
fun(arg);
}, list...);
}
Since a google search for "c++ pass reference parameters to variadic template" gives this as first result, I'll put this generic solution here.
struct HH { /*...*/ void change_me() { /*...*/ } };
template<typename...T> void parms_r_refs() {}
template<typename H, typename...T> void parms_r_refs(H &h, T&...t) { h.change_me(); parms_r_refs(t...); }
template<typename...T> void parms_r_refs(T&...t) { parms_r_refs(t...); }
HH a, b, c;
..
parms_r_refs(a, b, c);
..
I've spent many weeks on this puzzle and thought I might offer it as a challenge to the C++ variadic template crowd here. If it can be done I bet you'll show me how in about 10 seconds.
Suppose I have a collection of functions in C++ 17, each with its own return type (or void) and each with its own argument types. For simplicity, a mix of POD arguments and pointers to classes, variable numbers of args, etc. So two examples:
int somefunc(int x, double d) { return x + (int)d; }
void otherfunc(Foo *a, Bar *b, int x) { ... }
My goal is to do static compile-time reflection without annotation by building a variadic function that captures the full set of types here. So for discussion, we can say that our function is of type RT f(T1 a, T2 b, ...). My context is that I'm building a new (and far better) data marshalling layer for an RPC and multicast system, and these callbacks actually will be done on receipt of a byte array, which I need to demarshall and transform into things of the proper types: an int extracted from the first bytes of my byte array, or a new Foo(char*) where Foo itself has a factory method doing the lifting, etc.
What do I mean by static reflection? I want a const std::list, where I might put things like typeid(RT).hash_code() into my Info class, or perhaps a pointer to a constructor for each of my categories of arguments (a POD constructor would basically cast the incoming byte sequence to an int* and then return the int; a class constructor would call the factory method).
OK, long preamble, now the failed attempt: Here's my try. C++17 doesn't like it at all (seems to bind RT correctly but is unable to bind Rest, perhaps because Rest is actually a list of argument types within the overall function type that RT captures). Any ideas?
class Info
{
int rt, at; Info *next;
Info(int r, int a, Info* nxt) { rt = r; at = a; next = nxt; }
};
template<typename RT>
Info *Scan(RT cb())
{
return nullptr;
}
template<typename RT, typename T, typename Rest...> Info* Scan(RT cb(T x, Rest... args))
{
return new Info(typeid(RT).hash_code(), typeid(T).hash_code(), Scan<RT, Rest...>(cb(args...));
};
int TestMethod(int x, int y)
{
return 0;
}
int main()
{
Scan(TestMethod);
return 0;
}
You don't need a separate class or recursion for this, you could just return a std::array of the hash codes by expanding the argument parameter pack over the hash_code call:
template <typename RT, typename... Args>
std::array<size_t, (sizeof...(Args) + 1)>
Scan (RT (*) (Args...))
{
return { typeid(RT).hash_code(), typeid(Args).hash_code()... };
}
#include <typeinfo>
class Info
{
int rt, at; Info *next;
public:
Info(int r, int a, Info* nxt) { rt = r; at = a; next = nxt; }
};
template<typename RT>
Info *Scan() {
return nullptr;
}
template<typename RT, typename arg, typename ...args>
Info *Scan() {
return new Info(typeid(RT).hash_code(), typeid(arg).hash_code(), Scan<RT, args...>());
}
template<typename RT, typename ...Rest> Info* Extracter(RT (&)(Rest...))
{
return Scan<RT, Rest...>();
}
int TestMethod(int, int)
{
return 0;
}
int main()
{
Extracter(TestMethod);
return 0;
}
This uses the linked Info structure. I used one function to extract all the arguments of the targetted function, then another one to enumerate those one by one. No need to carry the function over all the calls.
TartanLlama's answer is more elegant though.
I have a variadic function like :
void test(int){}
template<typename T,typename...Args>
void test(int& sum,T v,Args... args)
{
sum+=v;
test(sum,args...);
}
I want to alias it to something like :
auto sum = test;//error : can not deduce auto from test
int main()
{
int res=0;
test(res,4,7);
std::cout<<res;
}
I tried using std::bind but it doesn't work with variadic functions because it needs placeholders ...
Is it possible to alias a variadic function ?
In C++1y :
#include <iostream>
void test(int){}
template<typename T,typename...Args>
void test(int& sum,T v,Args... args)
{
sum+=v;
test(sum,args...);
}
template<typename T,typename...Args>
decltype(test<T, Args...>)* sum = &(test<T, Args...>);
int main(void)
{
int res = 0;
sum<int, int>(res, 4, 7);
std::cout << res << std::endl;
}
Alternatively wrap it in another variadic function and std::forward the arguments :
template<typename T,typename...Args>
void other(int&sum, T v, Args&&... args)
{
test(sum, std::move(v), std::forward<Args>(args)...);
}
What you are trying is not much different from
void test(int)
{
}
void test(double, int)
{
}
auto a = test;
There is no way for the compiler to detect which overload you want to use.
You can be explicit about which test you want to assign to a by:
auto a = (void(*)(int))test;
If you want to add the variadic template version to the mix, you can use:
template<typename T,typename...Args>
void test(int& sum,T v,Args... args)
{
sum+=v;
test(sum,args...);
}
auto a = test<int, int, int>;
This is not aliasing.auto a = test tries to declare a variable a with the same type as test and make them equal. Since test isn't a single function, but a function template (and on the top of that you can even overload functions), the compiler can't decide on what the type of a should be.
To alias a template, or as a matter of fact any symbol, you can use the using keyword.
using a = test;
Edit: sorry this one only works for types not functions.
I am trying to build a statically bound delegate class, where the member function is bound at compile time, thereby aiding optimisation.
I have the following code which works exactly how I want it to:
#include <iostream>
namespace thr {
template<typename T, T func>
struct delegate;
template<typename R,
typename C,
typename... A,
R (C::* mem_fun)(A...)>
struct delegate<R(C::*)(A...), mem_fun>
{
delegate(C* obj_)
: _obj(obj_)
{}
R operator()(A... a)
{
return (_obj->*mem_fun)(a...);
}
private:
C* _obj;
};
} // namespace thr
struct foo
{
double bar(int i, int j)
{
return (double)i / (double)j;
}
};
int main()
{
foo f;
typedef thr::delegate<decltype(&foo::bar), &foo::bar> cb;
cb c(&f);
std::cout << c(4, 3);
return 0;
}
However, the usage is not very elegant:
thr::delegate<decltype(&foo::bar), &foo::bar>
I would like to use a function template which deduces the template parameters and returns a delegate instance; something along the lines of (this code does not compile):
template<typename C, typename T, T func>
thr::delegate<T, func> bind(T func, C* obj)
{
return thr::delegate<decltype(func), func>(obj);
}
This would allow for more elegant syntax:
auto cb = bind(&foo::bar, &f);
Is it possible to deduce a non-type parameter in a function template?
Is what I'm trying to achieve even possible?
Would std::function help? http://www2.research.att.com/~bs/C++0xFAQ.html#std-function Your example looks quite close.
I think the compiler supplied STL does pretty horrible things to make it work smoothly. You may want to have a look at as an example before giving up.
Edit: I went out and tried what you try to accomplish. My conclusion is a compile error:
The return type of the bind (delegate) must name the pointer to member because it is your own requirement.
bind should accept the name of the pointer to member to be elegant (i.e. your requirement)
Compiler requires you to not shadow the template parameter with a function parameter or use the name in both parameters and return type.
Therefore one of your requirements must go.
Edit 2: I took the liberty of changing your delegate so bind works as you wish. bind might not be your priority though.
#include <iostream>
namespace thr {
template<typename C,typename R,typename... A>
struct delegate
{
private:
C* _obj;
R(C::*_f)(A...);
public:
delegate(C* obj_,R(C::*f)(A...))
: _obj(obj_),_f(f)
{}
R operator()(A... a)
{
return (_obj->*_f)(a...);
}
};
} // namespace thr
template<class C,typename R,typename... A> thr::delegate<C,R,A...> bind(R(C::*f)(A...),C* obj){
return thr::delegate<C,R,A...>(obj,f);
}
struct foo
{
double bar(int i, int j)
{
return (double)i / (double)j;
}
};
int main()
{
foo f;
auto c = bind(&foo::bar, &f);
std::cout << c(4, 6);
return 0;
}
It is possible to deduce other entities than types in a function signature, but function parameters themselves cannot then be used as template parameters.
Given:
template <size_t I> struct Integral { static size_t const value = I; };
You can have:
template <size_t N>
Integral<N> foo(char const (&)[N]);
But you cannot have:
Integral<N> bar(size_t N);
In the former case, N as the size of the array is part of the type of the argument, in the latter case, N is the argument itself. It can be noticed that in the former case, N appeared in the template parameters list of the type signature.
Therefore, if indeed what you want is possible, the member pointer value would have to appear as part of the template parameter list of the function signature.
There may be a saving grace using constexpr, which can turn a regular value into a constant fit for template parameters:
constexpr size_t fib(size_t N) { return N <= 1 ? 1 : fib(N-1) + fib(N-2); }
Integral<fib(4)> works;
But I am not savvy enough to go down that road...
I do however have a simple question: why do you think this will speed things up ? Compilers are very good at constant propagation and inlining, to the point of being able to inline calls to virtual functions when they can assess the dynamic type of variables at compilation. Are you sure it's worth sweating over this ?
I'm trying to find a method to iterate over an a pack variadic template argument list.
Now as with all iterations, you need some sort of method of knowing how many arguments are in the packed list, and more importantly how to individually get data from a packed argument list.
The general idea is to iterate over the list, store all data of type int into a vector, store all data of type char* into a vector, and store all data of type float, into a vector. During this process there also needs to be a seperate vector that stores individual chars of what order the arguments went in. As an example, when you push_back(a_float), you're also doing a push_back('f') which is simply storing an individual char to know the order of the data. I could also use a std::string here and simply use +=. The vector was just used as an example.
Now the way the thing is designed is the function itself is constructed using a macro, despite the evil intentions, it's required, as this is an experiment. So it's literally impossible to use a recursive call, since the actual implementation that will house all this will be expanded at compile time; and you cannot recruse a macro.
Despite all possible attempts, I'm still stuck at figuring out how to actually do this. So instead I'm using a more convoluted method that involves constructing a type, and passing that type into the varadic template, expanding it inside a vector and then simply iterating that. However I do not want to have to call the function like:
foo(arg(1), arg(2.0f), arg("three");
So the real question is how can I do without such? To give you guys a better understanding of what the code is actually doing, I've pasted the optimistic approach that I'm currently using.
struct any {
void do_i(int e) { INT = e; }
void do_f(float e) { FLOAT = e; }
void do_s(char* e) { STRING = e; }
int INT;
float FLOAT;
char *STRING;
};
template<typename T> struct get { T operator()(const any& t) { return T(); } };
template<> struct get<int> { int operator()(const any& t) { return t.INT; } };
template<> struct get<float> { float operator()(const any& t) { return t.FLOAT; } };
template<> struct get<char*> { char* operator()(const any& t) { return t.STRING; } };
#define def(name) \
template<typename... T> \
auto name (T... argv) -> any { \
std::initializer_list<any> argin = { argv... }; \
std::vector<any> args = argin;
#define get(name,T) get<T>()(args[name])
#define end }
any arg(int a) { any arg; arg.INT = a; return arg; }
any arg(float f) { any arg; arg.FLOAT = f; return arg; }
any arg(char* s) { any arg; arg.STRING = s; return arg; }
I know this is nasty, however it's a pure experiment, and will not be used in production code. It's purely an idea. It could probably be done a better way. But an example of how you would use this system:
def(foo)
int data = get(0, int);
std::cout << data << std::endl;
end
looks a lot like python. it works too, but the only problem is how you call this function.
Heres a quick example:
foo(arg(1000));
I'm required to construct a new any type, which is highly aesthetic, but thats not to say those macros are not either. Aside the point, I just want to the option of doing:
foo(1000);
I know it can be done, I just need some sort of iteration method, or more importantly some std::get method for packed variadic template argument lists. Which I'm sure can be done.
Also to note, I'm well aware that this is not exactly type friendly, as I'm only supporting int,float,char* and thats okay with me. I'm not requiring anything else, and I'll add checks to use type_traits to validate that the arguments passed are indeed the correct ones to produce a compile time error if data is incorrect. This is purely not an issue. I also don't need support for anything other then these POD types.
It would be highly apprecaited if I could get some constructive help, opposed to arguments about my purely illogical and stupid use of macros and POD only types. I'm well aware of how fragile and broken the code is. This is merley an experiment, and I can later rectify issues with non-POD data, and make it more type-safe and useable.
Thanks for your undertstanding, and I'm looking forward to help.
If your inputs are all of the same type, see OMGtechy's great answer.
For mixed-types we can use fold expressions (introduced in c++17) with a callable (in this case, a lambda):
#include <iostream>
template <class ... Ts>
void Foo (Ts && ... inputs)
{
int i = 0;
([&]
{
// Do things in your "loop" lambda
++i;
std::cout << "input " << i << " = " << inputs << std::endl;
} (), ...);
}
int main ()
{
Foo(2, 3, 4u, (int64_t) 9, 'a', 2.3);
}
Live demo
(Thanks to glades for pointing out in the comments that I didn't need to explicitly pass inputs to the lambda. This made it a lot neater.)
If you need return/breaks in your loop, here are some workarounds:
Demo using try/throw. Note that throws can cause tremendous slow down of this function; so only use this option if speed isn't important, or the break/returns are genuinely exceptional.
Demo using variable/if switches.
These latter answers are honestly a code smell, but shows it's general-purpose.
If you want to wrap arguments to any, you can use the following setup. I also made the any class a bit more usable, although it isn't technically an any class.
#include <vector>
#include <iostream>
struct any {
enum type {Int, Float, String};
any(int e) { m_data.INT = e; m_type = Int;}
any(float e) { m_data.FLOAT = e; m_type = Float;}
any(char* e) { m_data.STRING = e; m_type = String;}
type get_type() const { return m_type; }
int get_int() const { return m_data.INT; }
float get_float() const { return m_data.FLOAT; }
char* get_string() const { return m_data.STRING; }
private:
type m_type;
union {
int INT;
float FLOAT;
char *STRING;
} m_data;
};
template <class ...Args>
void foo_imp(const Args&... args)
{
std::vector<any> vec = {args...};
for (unsigned i = 0; i < vec.size(); ++i) {
switch (vec[i].get_type()) {
case any::Int: std::cout << vec[i].get_int() << '\n'; break;
case any::Float: std::cout << vec[i].get_float() << '\n'; break;
case any::String: std::cout << vec[i].get_string() << '\n'; break;
}
}
}
template <class ...Args>
void foo(Args... args)
{
foo_imp(any(args)...); //pass each arg to any constructor, and call foo_imp with resulting any objects
}
int main()
{
char s[] = "Hello";
foo(1, 3.4f, s);
}
It is however possible to write functions to access the nth argument in a variadic template function and to apply a function to each argument, which might be a better way of doing whatever you want to achieve.
Range based for loops are wonderful:
#include <iostream>
#include <any>
template <typename... Things>
void printVariadic(Things... things) {
for(const auto p : {things...}) {
std::cout << p.type().name() << std::endl;
}
}
int main() {
printVariadic(std::any(42), std::any('?'), std::any("C++"));
}
For me, this produces the output:
i
c
PKc
Here's an example without std::any, which might be easier to understand for those not familiar with std::type_info:
#include <iostream>
template <typename... Things>
void printVariadic(Things... things) {
for(const auto p : {things...}) {
std::cout << p << std::endl;
}
}
int main() {
printVariadic(1, 2, 3);
}
As you might expect, this produces:
1
2
3
You can create a container of it by initializing it with your parameter pack between {}. As long as the type of params... is homogeneous or at least convertable to the element type of your container, it will work. (tested with g++ 4.6.1)
#include <array>
template <class... Params>
void f(Params... params) {
std::array<int, sizeof...(params)> list = {params...};
}
This is not how one would typically use Variadic templates, not at all.
Iterations over a variadic pack is not possible, as per the language rules, so you need to turn toward recursion.
class Stock
{
public:
bool isInt(size_t i) { return _indexes.at(i).first == Int; }
int getInt(size_t i) { assert(isInt(i)); return _ints.at(_indexes.at(i).second); }
// push (a)
template <typename... Args>
void push(int i, Args... args) {
_indexes.push_back(std::make_pair(Int, _ints.size()));
_ints.push_back(i);
this->push(args...);
}
// push (b)
template <typename... Args>
void push(float f, Args... args) {
_indexes.push_back(std::make_pair(Float, _floats.size()));
_floats.push_back(f);
this->push(args...);
}
private:
// push (c)
void push() {}
enum Type { Int, Float; };
typedef size_t Index;
std::vector<std::pair<Type,Index>> _indexes;
std::vector<int> _ints;
std::vector<float> _floats;
};
Example (in action), suppose we have Stock stock;:
stock.push(1, 3.2f, 4, 5, 4.2f); is resolved to (a) as the first argument is an int
this->push(args...) is expanded to this->push(3.2f, 4, 5, 4.2f);, which is resolved to (b) as the first argument is a float
this->push(args...) is expanded to this->push(4, 5, 4.2f);, which is resolved to (a) as the first argument is an int
this->push(args...) is expanded to this->push(5, 4.2f);, which is resolved to (a) as the first argument is an int
this->push(args...) is expanded to this->push(4.2f);, which is resolved to (b) as the first argument is a float
this->push(args...) is expanded to this->push();, which is resolved to (c) as there is no argument, thus ending the recursion
Thus:
Adding another type to handle is as simple as adding another overload, changing the first type (for example, std::string const&)
If a completely different type is passed (say Foo), then no overload can be selected, resulting in a compile-time error.
One caveat: Automatic conversion means a double would select overload (b) and a short would select overload (a). If this is not desired, then SFINAE need be introduced which makes the method slightly more complicated (well, their signatures at least), example:
template <typename T, typename... Args>
typename std::enable_if<is_int<T>::value>::type push(T i, Args... args);
Where is_int would be something like:
template <typename T> struct is_int { static bool constexpr value = false; };
template <> struct is_int<int> { static bool constexpr value = true; };
Another alternative, though, would be to consider a variant type. For example:
typedef boost::variant<int, float, std::string> Variant;
It exists already, with all utilities, it can be stored in a vector, copied, etc... and seems really much like what you need, even though it does not use Variadic Templates.
There is no specific feature for it right now but there are some workarounds you can use.
Using initialization list
One workaround uses the fact, that subexpressions of initialization lists are evaluated in order. int a[] = {get1(), get2()} will execute get1 before executing get2. Maybe fold expressions will come handy for similar techniques in the future. To call do() on every argument, you can do something like this:
template <class... Args>
void doSomething(Args... args) {
int x[] = {args.do()...};
}
However, this will only work when do() is returning an int. You can use the comma operator to support operations which do not return a proper value.
template <class... Args>
void doSomething(Args... args) {
int x[] = {(args.do(), 0)...};
}
To do more complex things, you can put them in another function:
template <class Arg>
void process(Arg arg, int &someOtherData) {
// You can do something with arg here.
}
template <class... Args>
void doSomething(Args... args) {
int someOtherData;
int x[] = {(process(args, someOtherData), 0)...};
}
Note that with generic lambdas (C++14), you can define a function to do this boilerplate for you.
template <class F, class... Args>
void do_for(F f, Args... args) {
int x[] = {(f(args), 0)...};
}
template <class... Args>
void doSomething(Args... args) {
do_for([&](auto arg) {
// You can do something with arg here.
}, args...);
}
Using recursion
Another possibility is to use recursion. Here is a small example that defines a similar function do_for as above.
template <class F, class First, class... Rest>
void do_for(F f, First first, Rest... rest) {
f(first);
do_for(f, rest...);
}
template <class F>
void do_for(F f) {
// Parameter pack is empty.
}
template <class... Args>
void doSomething(Args... args) {
do_for([&](auto arg) {
// You can do something with arg here.
}, args...);
}
You can't iterate, but you can recurse over the list. Check the printf() example on wikipedia: http://en.wikipedia.org/wiki/C++0x#Variadic_templates
You can use multiple variadic templates, this is a bit messy, but it works and is easy to understand.
You simply have a function with the variadic template like so:
template <typename ...ArgsType >
void function(ArgsType... Args){
helperFunction(Args...);
}
And a helper function like so:
void helperFunction() {}
template <typename T, typename ...ArgsType >
void helperFunction(T t, ArgsType... Args) {
//do what you want with t
function(Args...);
}
Now when you call "function" the "helperFunction" will be called and isolate the first passed parameter from the rest, this variable can b used to call another function (or something). Then "function" will be called again and again until there are no more variables left. Note you might have to declare helperClass before "function".
The final code will look like this:
void helperFunction();
template <typename T, typename ...ArgsType >
void helperFunction(T t, ArgsType... Args);
template <typename ...ArgsType >
void function(ArgsType... Args){
helperFunction(Args...);
}
void helperFunction() {}
template <typename T, typename ...ArgsType >
void helperFunction(T t, ArgsType... Args) {
//do what you want with t
function(Args...);
}
The code is not tested.
#include <iostream>
template <typename Fun>
void iteratePack(const Fun&) {}
template <typename Fun, typename Arg, typename ... Args>
void iteratePack(const Fun &fun, Arg &&arg, Args&& ... args)
{
fun(std::forward<Arg>(arg));
iteratePack(fun, std::forward<Args>(args)...);
}
template <typename ... Args>
void test(const Args& ... args)
{
iteratePack([&](auto &arg)
{
std::cout << arg << std::endl;
},
args...);
}
int main()
{
test(20, "hello", 40);
return 0;
}
Output:
20
hello
40