I have a function which takes one parameter with a default value. Now I also want it to take a variable number of parameters and forward them to some other function. Function parameters with default value have to be last, so... can I put that parameter after the variadic pack and the compiler will detect whether I'm supplying it or not when calling the function?
(Assuming the pack doesn't contain the type of that one last parameter. If necessary, we can assume that, because that type is generally not supposed to be known to the user, otherwise it's considered as wrong usage of my interface anyway....)
template <class... Args>
void func (Args&&... args, SomeSpecialType num = fromNum(5))
{
}
No, packs must be last.
But you can fake it. You can detect what the last type in a pack is. If it is SomeSpecialType, you can run your func. If it isn't SomeSpecialType, you can recursively call yourself with your arguments forwarded and fromNum(5) appended.
If you want to be fancy, this check can be done at compile time (ie, a different overload) using SFINAE techniques. But that probably isn't worth the hassle, considering that the "run-time" check will be constant on a given overload, and hence will almost certainly be optimized out, and SFINAE shouldn't be used lightly.
This doesn't give you the signature you want, but it gives you the behavior you want. You'll have to explain the intended signature in comments.
Something like this, after you remove typos and the like:
// extract the last type in a pack. The last type in a pack with no elements is
// not a type:
template<typename... Ts>
struct last_type {};
template<typename T0>
struct last_type<T0> {
typedef T0 type;
};
template<typename T0, typename T1, typename... Ts>
struct last_type<T0, T1, Ts...>:last_type<T1, Ts...> {};
// using aliases, because typename spam sucks:
template<typename Ts...>
using LastType = typename last_type<Ts...>::type;
template<bool b, typename T=void>
using EnableIf = typename std::enable_if<b, T>::type;
template<typename T>
using Decay = typename std::decay<T>::type;
// the case where the last argument is SomeSpecialType:
template<
typename... Args,
typename=EnableIf<
std::is_same<
Decay<LastType<Args...>>,
SomeSpecialType
>::value
>
void func( Args&&... args ) {
// code
}
// the case where there is no SomeSpecialType last:
template<
typename... Args,
typename=EnableIf<
!std::is_same<
typename std::decay<LastType<Args...>>::type,
SomeSpecialType
>::value
>
void func( Args&&... args ) {
func( std::forward<Args>(args)..., std::move(static_cast<SomeSpecialType>(fromNum(5))) );
}
// the 0-arg case, because both of the above require that there be an actual
// last type:
void func() {
func( std::move(static_cast<SomeSpecialType>(fromNum(5))) );
}
or something much like that.
Another approach would be to pass variadic arguments through a tuple.
template <class... Args>
void func (std::tuple<Args...> t, SomeSpecialType num = fromNum(5))
{
// don't forget to move t when you use it for the last time
}
Pros : interface is much simpler, overloading and adding default valued arguments is quite easy.
Cons : caller has to manually wrap arguments in a std::make_tuple or std::forward_as_tuple call. Also, you'll probably have to resort to std::index_sequence tricks to implement the function.
Since C++17 there is way to work around this limitation, by using class template argument deduction and user-defined deduction guides.
This is espactialy useful for C++20 std::source_location.
Here is C++17 demo:
#include <iostream>
int defaultValueGenerator()
{
static int c = 0;
return ++c;
}
template <typename... Ts>
struct debug
{
debug(Ts&&... ts, int c = defaultValueGenerator())
{
std::cout << c << " : ";
((std::cout << std::forward<Ts>(ts) << " "), ...);
std::cout << std::endl;
}
};
template <typename... Ts>
debug(Ts&&...args) -> debug<Ts...>;
void test()
{
debug();
debug(9);
debug<>(9);
}
int main()
{
debug(5, 'A', 3.14f, "foo");
test();
debug("bar", 123, 2.72);
}
Live demo
Demo with source_location (should be available since C++20, but still for compilers it is experimental).
This is coming a bit late, but in C++17 you can do it with std::tuple and it would be quite nice overall. This is an expansion to #xavlours 's answer:
template <class... Args>
void func (std::tuple<Args&&...> t, SomeSpecialType num = fromNum(5))
{
// std::apply from C++17 allows you to iterate over the tuple with ease
// this just prints them one by one, you want to do other operations i presume
std::apply([](auto&&... args) {((std::cout << args << '\n'), ...);}, t);
}
Then, make a simple function to prepare them:
template<typename... Args>
std::tuple<Args&&...> MULTI_ARGS(Args&&... args) {
return std::tuple<Args&&...>(args...);
}
Now you can call the function like this:
func(MULTI_ARGS(str1, int1, str2, str3, int3)); // default parameter used
func(MULTI_ARGS(str1, int1, str2)); // default parameter used
func(MULTI_ARGS(str1, int1, str2, str3, int3, otherStuff), fromNum(10)); // custom value instead of default
Disclaimer: I came across this question as I was designing a logger and wanted to have a default parameter which contains std::source_location::current() and as far as I was able to find, this is the only way that ensures the caller's information is passed accurately. Making a function wrapper will change the source_location information to represent the wrapper instead of the original caller.
Related
I am pretty new to c++ and for my first project am trying to write an ioc container expanding the concept described in this blog post by adding variadic arguments to the registering functions. So one parameter pack would be used for variadic arguments and the other one to declare the dependencies of the type to register.
After reading a bit I came across stuff similar to what I tried to do in the end. The function looks like this:
template <class T,
template<typename ...TDependencies> typename TUnused, typename... TDependencies,
typename ...TArgs>
void RegisterSingletonClassFactory(TArgs...args)
{
std::string typeKey = typeid(T).name();
creatorMap_[typeKey] = [this, args...](){
return new T(GetInstance<TDependencies>()..., args...);
};
std::shared_ptr<IHolder> iHolder = instanceMap_[typeKey];
auto * holder = dynamic_cast<Holder<T>*>(iHolder.get());
if(holder != nullptr)
holder->instance_ = nullptr;
}
And I call it with iocContainer_.RegisterSingletonClassFactory<boost::asio::io_context, std::tuple<>>(30);.
This however gives me the error "error: no matching function for call to"... with clang telling me "candidate template ignored: invalid explicitly-specified argument for template parameter 'TUnused'".
Is there a way to do this? And what exactly does the error mean?
Thanks
And what exactly does the error mean?
The error mean that your call
iocContainer_.RegisterSingletonClassFactory<boost::asio::io_context, std::tuple<>>(30);
doesn't matches the declaration of your template function
template <class T,
template<typename ...TDependencies> typename TUnused, typename... TDependencies,
typename ...TArgs>
void RegisterSingletonClassFactory(TArgs...args)
because your template functions waits for
a type parameter (T),
a template-template parameter (TUnused)
and other template parameters when you pass
a type paramer (boost::asio::io_context)
another type template parameter (std::tuple<>)
If you want to pass std::tuple as template-template parameter, you have to pass it without template parameters (std::tuple, not std::tuple<>).
Given that your TUnused parameter is... well, unused,... I suppose that your intention was to use it as type container.
But there is no needs for it.
Not sure but seems to me that your looking for something similar
template <typename T, typename... TDependencies, typename ...TArgs>
void foo (TArgs...args)
So you can explicit T and a (maybe empty) TDependecies... list of types.
The TArgs... list is deduced from the arguments
The following is a silly, but compiling, C++17 example
#include <iostream>
template <typename T, typename... TDependencies, typename ...TArgs>
void foo (TArgs...args)
{
std::cout << "T:" << typeid(T).name() << std::endl;
std::cout << "TDependecies list:" << std::endl;
((std::cout << "- " << typeid(TDependencies).name() << std::endl), ...);
std::cout << "TArgs list:" << std::endl;
((std::cout << "- " << typeid(TArgs).name() << std::endl), ...);
}
int main()
{
foo<std::string, short, int, long, long long>(0, 1l, 2ll);
}
where T is std::string (the first explicit template parameters), TDependencies... is short, int, long, long long (the following explicit template parameters) and TArgs... is int, long, long long (deduced from the 0, 1l, 2ll arguments).
Observe that you don't need the TUnused template parameter.
It is clear now that std::tuple was not really needed in the original problem, but for completeness let me give an example of how Dependencies could be extracted from the std::tuple-like types1. All we need is an additional level of indirection:
template<class T>
struct wrapper {};
template<class T, template<class...> class Unused,
class... Dependencies, class... Args>
void RegisterSingletonClassFactoryImpl(
wrapper<Unused<Dependencies...>>, Args... args) {
std::string typeKey = typeid(T).name();
creatorMap_[typeKey] = [this, args...]() {
return new T(GetInstance<Dependencies>()..., args...);
};
// ...
}
template<class T, class Unused, class... Args>
void RegisterSingletonClassFactory(Args... args) {
RegisterSingletonClassFactoryImpl<T>(wrapper<Unused>{}, args...);
}
Now
RegisterSingletonClassFactory<T, std::tuple<A, B, C>>()
will call RegisterSingletonClassFactoryImpl() with Dependencies pack being A, B, C.
1 Any other type list
template<class...>
class type_list;
can be used instead of std::tuple.
Using std::function, we can get the type of an argument using the argument_type, second_argument_type etc. typedefs, but I can't see a way to do the same thing with lambdas. Is it possible? (I'm using VS2010)
Say I want something like the following in my deserialization system used to read an object and pass it to a setter function:
template<typename F>
static void forward(F f)
{
// Create an object of the type of the first
// parameter to the function object F
typedef typename F::argument_type T;
T t;
//...do something with 't' here (deserialize in my case)
// Forward the object to the function
f(t);
}
It can be used like this and everything works fine:
std::function<void(int)> f = [](int i) -> void { setValue(i); };
forward(f);
But it will not work directly with lambdas:
forward([](int i) -> void { setValue(i); });
//error C2039: 'argument_type' : is not a
//member of '`anonymous-namespace'::<lambda1>'
Is there a way to access the parameter types in a way that will work for both lambdas and std::function objects? Maybe a way to get the std::function type of a lambda first, and then the argument_type from that?
Following on from the answer below, a version that works with lambdas and std::function is:
template<typename T, typename F>
static void forward(F f)
{
T t;
//...do something with 't' here (deserialize in my case)
f(t);
}
forward<int>([](int i) -> void { setValue(i); });
Since int is repeated here I was hoping to get rid of it - not so bad for int but more annoying for long-named types in a couple of namespaces. C'est la vie!
It's not desirable in the general case. (Note that it's quite easy for std::function<T(A)> to specify what e.g. argument_type is: it's just A! It's available in the type definition.)
It would be possible to require each and every function object type to specify its argument types, and in turn mandate that the closure types generated from lambda expression do so. In fact, pre-C++0x features like adaptable functors would only work for such types.
However, we're moving from that with C++0x and for good reasons. The simplest of which is simply overloading: a functor type with a templated operator() (a.k.a a polymorphic functor) simply takes all kind of arguments; so what should argument_type be? Another reason is that generic code (usually) attempts to specify the least constraints on the types and objects it operates on in order to more easily be (re)used.
In other words, generic code is not really interested that given Functor f, typename Functor::argument be int. It's much more interesting to know that f(0) is an acceptable expression. For this C++0x gives tools such as decltype and std::declval (conveniently packaging the two inside std::result_of).
The way I see it you have two choices: require that all functors passed to your template use a C++03-style convention of specifying an argument_type and the like; use the technique below; or redesign. I'd recommend the last option but it's your call since I don't know what your codebase looks like or what your requirements are.
For a monomorphic functor type (i.e. no overloading), it is possible to inspect the operator() member. This works for the closure types of lambda expressions.
So we declare these helpers
template<typename F, typename Ret, typename A, typename... Rest>
A
helper(Ret (F::*)(A, Rest...));
template<typename F, typename Ret, typename A, typename... Rest>
A
helper(Ret (F::*)(A, Rest...) const);
// volatile or lvalue/rvalue *this not required for lambdas (phew)
that accept a pointer to member function taking at least one argument. And now:
template<typename F>
struct first_argument {
typedef decltype( helper(&F::operator()) ) type;
};
[ an elaborate trait could successively query the lvalue-rvalue/const/volatile overloads and expose the first argument if it's the same for all overloads, or use std::common_type.]
#Luc's answer is great but I just came across a case where I also needed to deal with function pointers:
template<typename Ret, typename Arg, typename... Rest>
Arg first_argument_helper(Ret(*) (Arg, Rest...));
template<typename Ret, typename F, typename Arg, typename... Rest>
Arg first_argument_helper(Ret(F::*) (Arg, Rest...));
template<typename Ret, typename F, typename Arg, typename... Rest>
Arg first_argument_helper(Ret(F::*) (Arg, Rest...) const);
template <typename F>
decltype(first_argument_helper(&F::operator())) first_argument_helper(F);
template <typename T>
using first_argument = decltype(first_argument_helper(std::declval<T>()));
This can be used on both functors and function pointers:
void function(float);
struct functor {
void operator() (int);
};
int main() {
std::cout << std::is_same<first_argument<functor>, int>::value
<< ", "
<< std::is_same<first_argument<decltype(&function)>, int>::value
<< std::endl;
return 0;
}
Using std::function, we can get the type of an argument using the argument_type, second_argument_type etc. typedefs, but I can't see a way to do the same thing with lambdas. Is it possible? (I'm using VS2010)
Say I want something like the following in my deserialization system used to read an object and pass it to a setter function:
template<typename F>
static void forward(F f)
{
// Create an object of the type of the first
// parameter to the function object F
typedef typename F::argument_type T;
T t;
//...do something with 't' here (deserialize in my case)
// Forward the object to the function
f(t);
}
It can be used like this and everything works fine:
std::function<void(int)> f = [](int i) -> void { setValue(i); };
forward(f);
But it will not work directly with lambdas:
forward([](int i) -> void { setValue(i); });
//error C2039: 'argument_type' : is not a
//member of '`anonymous-namespace'::<lambda1>'
Is there a way to access the parameter types in a way that will work for both lambdas and std::function objects? Maybe a way to get the std::function type of a lambda first, and then the argument_type from that?
Following on from the answer below, a version that works with lambdas and std::function is:
template<typename T, typename F>
static void forward(F f)
{
T t;
//...do something with 't' here (deserialize in my case)
f(t);
}
forward<int>([](int i) -> void { setValue(i); });
Since int is repeated here I was hoping to get rid of it - not so bad for int but more annoying for long-named types in a couple of namespaces. C'est la vie!
It's not desirable in the general case. (Note that it's quite easy for std::function<T(A)> to specify what e.g. argument_type is: it's just A! It's available in the type definition.)
It would be possible to require each and every function object type to specify its argument types, and in turn mandate that the closure types generated from lambda expression do so. In fact, pre-C++0x features like adaptable functors would only work for such types.
However, we're moving from that with C++0x and for good reasons. The simplest of which is simply overloading: a functor type with a templated operator() (a.k.a a polymorphic functor) simply takes all kind of arguments; so what should argument_type be? Another reason is that generic code (usually) attempts to specify the least constraints on the types and objects it operates on in order to more easily be (re)used.
In other words, generic code is not really interested that given Functor f, typename Functor::argument be int. It's much more interesting to know that f(0) is an acceptable expression. For this C++0x gives tools such as decltype and std::declval (conveniently packaging the two inside std::result_of).
The way I see it you have two choices: require that all functors passed to your template use a C++03-style convention of specifying an argument_type and the like; use the technique below; or redesign. I'd recommend the last option but it's your call since I don't know what your codebase looks like or what your requirements are.
For a monomorphic functor type (i.e. no overloading), it is possible to inspect the operator() member. This works for the closure types of lambda expressions.
So we declare these helpers
template<typename F, typename Ret, typename A, typename... Rest>
A
helper(Ret (F::*)(A, Rest...));
template<typename F, typename Ret, typename A, typename... Rest>
A
helper(Ret (F::*)(A, Rest...) const);
// volatile or lvalue/rvalue *this not required for lambdas (phew)
that accept a pointer to member function taking at least one argument. And now:
template<typename F>
struct first_argument {
typedef decltype( helper(&F::operator()) ) type;
};
[ an elaborate trait could successively query the lvalue-rvalue/const/volatile overloads and expose the first argument if it's the same for all overloads, or use std::common_type.]
#Luc's answer is great but I just came across a case where I also needed to deal with function pointers:
template<typename Ret, typename Arg, typename... Rest>
Arg first_argument_helper(Ret(*) (Arg, Rest...));
template<typename Ret, typename F, typename Arg, typename... Rest>
Arg first_argument_helper(Ret(F::*) (Arg, Rest...));
template<typename Ret, typename F, typename Arg, typename... Rest>
Arg first_argument_helper(Ret(F::*) (Arg, Rest...) const);
template <typename F>
decltype(first_argument_helper(&F::operator())) first_argument_helper(F);
template <typename T>
using first_argument = decltype(first_argument_helper(std::declval<T>()));
This can be used on both functors and function pointers:
void function(float);
struct functor {
void operator() (int);
};
int main() {
std::cout << std::is_same<first_argument<functor>, int>::value
<< ", "
<< std::is_same<first_argument<decltype(&function)>, int>::value
<< std::endl;
return 0;
}
I'm writing a generalized function wrapper, that can wrap any function into a lua-style call, which has the form
int lua_function( lua_State *L)
And I wish the wrapper function is generated on-the-fly, so I'm thinking of passing the function as a template argument. This is trivial if you know the number (e.g, 2) of arguments:
template <typename R, typename Arg1, typename Arg2, R F(Arg1, Args)>
struct wrapper
However, I don't know the number, so I beg for variadic template argument for help
// This won't work
template <typename R, typename... Args, R F(Args...)>
struct wrapper
The above won't compile, since variadic argument has to be the last one. So I use two level template, the outer template captures types, the inner template captures the function:
template <typename R, typename... Args>
struct func_type<R(Args...)>
{
// Inner function wrapper take the function pointer as a template argument
template <R F(Args...)>
struct func
{
static int call( lua_State *L )
{
// extract arguments from L
F(/*arguments*/);
return 1;
}
};
};
That works, except that to wrap a function like
double sin(double d) {}
the user has to write
func_type<decltype(sin)>::func<sin>::apply
which is tedious.
The question is: is there any better, user-friendlier way to do it? (I can't use a function template to wrap the whole thing, coz a function parameter can't be used as a template argument.)
Things like std::function and std::result_of use the following technique to do what you want regarding variadic templates:
template<typename Signature>
struct wrapper; // no base template
template<typename Ret, typename... Args>
struct wrapper<Ret(Args...)> {
// instantiated for any function type
};
You could expand the above to add a non-type Ret(&P)(Args...) template parameter (pointers to function work just as well) but you'd still need a decltype at the user level, i.e. wrapper<decltype(sin), sin>::apply. Arguably it would be a legitimate use of the preprocessor if you decide to use a macro to remove the repetition.
template<typename Sig, Sig& S>
struct wrapper;
template<typename Ret, typename... Args, Ret(&P)(Args...)>
struct wrapper<Ret(Args...), P> {
int
static apply(lua_State*)
{
// pop arguments
// Ret result = P(args...);
// push result & return
return 1;
}
};
// &wrapper<decltype(sin), sin>::apply is your Lua-style wrapper function.
The above compiles with gcc-4.5 at ideone.
Good luck with implementing the apply that (variadically) pops the arguments (leave me a comment if you open a question about that). Have you considered using Luabind?
As #Juraj says in his comment, the function pointer can be a template argument, see the following simple example:
#include <iostream>
#include <boost/typeof/typeof.hpp>
void f(int b, double c, std::string const& g)
{
std::cout << "f(): " << g << std::endl;
}
template <typename F, F* addr>
struct wrapper
{
void operator()()
{
std::string bar("bar");
(*addr)(1, 10., bar);
}
};
int main(void)
{
wrapper<BOOST_TYPEOF(f), &f> w;
w();
return 0;
}
working version: http://www.ideone.com/LP0TO
I'm using BOOST_TYPEOF as normally I always provide examples in the current standard, but it does something similar to decltype. Is this what you were after?
I have seen a lot of links introducing the variadic templates. But I have never seen any compilable example that demonstrates this approach.
Could someone provide me with some links in which such compilable examples can be found?
One of the simplest possible examples is the following implementation of max which isn't even templated on types.
int maximum(int n)
{
return n;
}
template<typename... Args>
int maximum(int n, Args... args)
{
return max(n, maximum(args...));
}
Only slightly more complex is the canonical printf implementation:
void printf(const char *s)
{
while (*s)
{
if (*s == '%' && *(++s) != '%')
throw "invalid format string: missing arguments";
std::cout << *s++;
}
}
template<typename T, typename... Args>
void printf(const char* s, T value, Args... args)
{
while (*s)
{
if (*s == '%' && *(++s) != '%')
{
std::cout << value;
printf(s, args...); // call even when *s == 0 to detect extra arguments
return;
}
std::cout << *s++;
}
throw "extra arguments provided to printf";
}
Variadic templates are a C++0x feature that primarily targets authors of generic libraries. I would not expect to see them in "user code". For example, in the C++0x standard library they are used in a lot of places: std::function, std::async, std::reference_wrapper, std::tuple, std::packaged_task, ...
To give you an example I'll show you how a reference_wrapper might be implemented with respect to variadic templates:
template<class T>
class reference_wrapper
{
T *ptr;
public:
explicit reference_wrapper(T& thing) : ptr(&thing) {}
explicit reference_wrapper(T&& ) = delete;
operator T&() const {return *ptr;}
template<class... Args>
decltype( declval<T&>()(declval<Args>()...) )
operator()(Args&&... args) const
{
return (*ptr)(forward<Args>(args)...);
}
};
This is not perfectly conforming to the standard draft but it is supposed to be compilable with little modification. It demonstrates multiple C++0x features:
deleted functions (disabling the constructor for rvalues)
rvalue references (detecting rvalue arguments to the constructor, perfect forwarding)
type deduction via decltype
standard library function template declval to create objects for the purpose of building an expression for decltype (GCC does not yet offer this function template. You have to write it yourself)
variadic templates (accepting an arbitrary number of parameters)
The purpose of the variadic member template is to forward arguments to the object referred to by ptr. This should work in case T is a function pointer type or a class type with overloaded function call operator.
cheers!
s
Wikipedia is good starting point.
Gregor, Douglas; Jaakko Järvi; Gary Powell (9 September 2006). "Variadic Templates (Revision 3)".
A very simple example of variadic template:
Suppose we want to have a function which takes variable number of arguments and prints them all. For ex:
print("Hello", 1, 3.14, 5L);
For that functionality to work, we would basically require two functions:
First one, a function which takes variable number of arguments:
template<typename T, typename... Args>
void print(T t, Args ...args){
std::cout << t << ", ";
print(args...);
}
Some explanation:
1.) Parameter Packs denoted by ellipsis(...), that appear in parameter list.
typename...Args
| | << Optional whitespace. Can have multiple whitespaces in between them
Args...args
That means, these all are same.
typename ...args
typename...args
typename ... args
So, you don't have to worry about the correct position of the whitespace in there. Though, IMO at most one whitespace should be used as a best practice.
2.) Pack Expansion: A pattern followed by an ellipsis.
print(args...); //expand when you wish to use them
3.) Parameter pack accepts zero or more template args. So, print(T t, Args... args) accepts one or more args.
Once you understand that, we can visualize the call flow as below:
print("Hello", 1, 3.14, 5L);
translates into:
print(string, int, float, long);
which calls
print(int, float, long);
which calls
print(float, long); // say Level 2
which calls
print(long); // say Level 1
which calls
print(); // say Level 0
If you have followed the Point#3 carefully, you must have realized that print(T t, Args... args) can't handle call at Level 0.
So we need another function here with same name to catch up at any level >=0.
Second one, a function to grab the call at the top of call stack:
Catch at level 0:
void print(){}
or, Catch at level 1:
template<typename T>
void print(T t){ std::cout << t;}
or, Catch at level 2:
template<typename T, typename U>
void print(T t, U u){ std::cout << t << ", " << u;}
so on...
Any of these would work. Hope this helps you next time you go about writing such function or class.
This is an example of variadic templates that I put up on my blog:
http://thenewcpp.wordpress.com/2011/11/23/variadic-templates-part-1-2/
It compiles. It demonstrates finding the largest type from a group of types.
#include <type_traits>
template <typename... Args>
struct find_biggest;
//the biggest of one thing is that one thing
template <typename First>
struct find_biggest<First>
{
typedef First type;
};
//the biggest of everything in Args and First
template <typename First, typename... Args>
struct find_biggest<First, Args...>
{
typedef typename find_biggest<Args...>::type next;
typedef typename std::conditional
<
sizeof(First) >= sizeof(next),
First,
next
>::type type;
};
Variadic templates are part of the C++0x standard which is not yet officially released. They are supported by gcc since version 4.3, but you need to enable support for C++0x by adding the compiler switch -std=c++0x.
Before C++11, you can create template only with the fixed count of parameters.
Firts template for the function with one parameter.
Second template for the function with two parameters.
... i.e.
Since C++11 you can write only one template, compiler will generate required function itself.
Good example
http://eli.thegreenplace.net/2014/variadic-templates-in-c/
another syntax: expanding, e.g.
template<typename VAL, typename... KEYS>
class MyMaps
{
typedef std::tuple< std::map<KEYS,VAL>... > Maps;
}
hence:
MyMaps<int,int,string>:Maps
is now actually:
std::tuple<std::map<int,int>,std::map<string,int> >