Before C++11, there were two typical problems that were constrained by the bad template functionality that caused the code to repeat itself, which is the function object and tuple. For function objects, a return type parameter and n parameter type parameters are required. However, because the variable length parameter template is not supported, you have to write 7, 8 template classes repeatedly, but ultimately only support function object of 7, 8 parameters. C++11 finally brought us a powerful variable-length parameter template function, and these problems have been solved.
Variable parameter templates (Variadic template) Hence the name meaning, that is, a class/function template that can accept any number of parameters. It is declared in the form
Template<typename... Args>class variadictemplate;
Of course the Non-type parameter is also supported such as Template<int ... Args> class Variadicinttemplate;
Here, args represents the 0-n type parameter, which means that variadictemplate<> is also a valid template instance.
C++11 refurbished ellipsis (...) operator to support access to and use of this template parameter.
Type expansion
Expands all template parameters to the current location to invoke other templates, declare function pointer types
Template<typename ... args>int foo () { int (*p) (Args ...) = bar<args...>; P (10.5); return bar<args...> (10.5);}
For Foo<int, the float> instance, whose p is of type int (*) (int, float) and the return statement calls Bar<int, float> (1, 0.5)
You can also expand the type parameter to specify the base class list
Template<typename... Args>class Foo:args ... {};foo// This class inherits bar, Barz two base classes
Parameter packs/initialization Lists
The ellipsis operator allows you to declare parameter packages that can be expanded at the function's parameter position.
Template<typename ... args>void foo (args ... args) {}
When using Foo<int, float>, it has two parameters, an integer, a float, so the calling method is Foo<int, float> (1, 0.1f);
You can also expand the parameter pack to the constructor's initialization list
Template<typename... Args>class Foo:args ... {public: foo (Args...args): args (args) ... { }};foo<bar, barz> F (Bar (), Barz ());
sizeof ... operator
To get the argument length of the template variable length parameter, use sizeof ... operator, which can also be used for Parameter Packs
Template<typename ... args>size_t foo () { returnsizeof... (Args);} Template <TypeName ... Args>size_t fooz (args ... args) {returnsizeof... (args);}
The above is the basic usage of variable-length parameters, but it is often useful to use template-specific specialization
Variable parameter templates and template specificity
Variadic templates, like normal templates, can be customized to achieve some meaningful patterns
Template<TypeName... Args>voidoutput (args ... args) {}template <TypeNameARG0,TypeName... Args>voidoutput (Arg0 arg0, args ... args) {std::cout<<arg0; Output<Args...>(args ...); Template <>voidoutput () {}/*------------------------------*/ typedef decltype(std::cout) Cout_type; Auto Endl= Std::endl<cout_type::char_type, cout_type::traits_type>; output (1,0.3, (void*)nullptr,"string",'C', Endl);
The above code output
10.30stringc
C++11 Variable parameter templates