Reference from: In-depth understanding of c++11
Variable length stencil:
Variable-length functions and variable-length template parameters
Variable-length function:
Double sum (int n, ...) Find the sum of n double data
{
Double sum = 0;
va_list args; // to accept the data structure of the input data, you need to declare stdarg.h,
Va_start (args,n); // Initializing Data
while (n>0)
{
sum + = va_arg(args,double); // Remove the data one by one from args , take the number once per sizeof (double), and sum
--n;
}
Va_end (args);
return sum;
}
Variable-length template parameters:
pair<int,double> Pairnum
std::tuple<>double,char, int, std::string > Collections
Variable length Template: template parameter package and function parameter package
Template parameter pack:
Variable-length type templates:
Template<typename... Elements>classtuple;
The ellipsis was used before the identifier elements ... To indicate that the parameter is variable length. Elements is called the 31 "template parameter Pack". This allows the tuple to accept any number of parameters as template parameters. In fact, the example of a tuple template class:
Tuple<int,char,double>
The compiler can package multiple template parameters into a Big Brother's template parameter package elements, that is, elements in the template deduction, is a int,char,double contains three types of type collection.
You can also declare non-type template parameter packages, such as:
Template<int ... a>classnontypevariadictemplate{}
nontypevariadictemplate<1,2,3>ntvt;
is a definition of:
Template<int,int,int>class nontypevariadictemplate{}
nontypevariadictemplate<1,2,3>ntvt;
A template parameter package is considered a single parameter of the template when the template is deduced. In order to use the template parameter pack, we always need to unpack it (Unpack). In c++11, this usually needs to be done through an expression called a package extension:
Template <typename ... A>classtemplate:private b<a...>{};
Expressions in the formula a ... is a package extension. Such a parameter package expands to multiple parameters at the location of the package extension. Such as:
Template<typenameT1, TypeNameT2>classB{};
Template<typename ... a>classTemplate :privateB<A...>{};
Template<X,Y> xy;
In this way, we declare a parameter package A for the class template, and use the parameter package a ... is in the private base class b<a...> of the template, then the last expression declares an object xy of the template class template<x,y> the base class is b<x,y>. Base class B always accepts two parameters, and if the parameter pack has more than two parameters, we will have an error when we make the template deduction.
In fact, C++11 gives a solution. The way to implement a tuple template gives an answer using the template parameter pack.
Template<typename... Elements>classtuple ;//variable-length template declaration
Recursive definition of partial specificity
Template<typenameHead, TypeName ... Tail>classtuple<Head,Tail...>:private Tuple < Tail... > {head head;};
Template <> classtuple<> {};//boundary condition
If we instantiate tuple<double,int,char,float>, then we need to construct tuple<int,char,float>, and then set head to double. Construct tuple<char,float> and set int Head,tuple<float>,char head,tuple<> float head in turn, so that the instantiation is completed.
Template<long...nums>struct Multiply;
Template<longFirst,long ... last>
struct Multiply<First,last...>
{
Static Const Long val =First *Multiply<last...>::val;
};
template<> structMultiply < > { static const Longval = 1; };
Function Parameter package:
Template<typename... T>void f(t... args);
T is a variable-length template parameter, and args is the data that corresponds to these variable-length types, which is the function parameter package. In c++11, the function parameter package must be unique and the last parameter of the function (the template parameter package does not have such a requirement).
void Printf (const Char *s)
{
while (*s)
{
if (*s = ='% '&&*++s ! ='%')
{
Throw Runtime_error ("Invalid formatstring:missing arguments");
}
cout << *s+ +;
}
}
Template<typenameT,TypeName... Args>
void Printf (const Char *s, T value, Args...) args)
{
while (*s)
{
if (*s= ='% '&&*++s! ='%')
{
cout << value;
return Printf (+ +s, args...);
}
cout << *s+ +;
}
Throw Runtime_error ("extraarguments provided to Printf");
}
int Main ()
{
Printf ("Hello%s\n",std::string("World"));
return 0;
}
The variable-length function template does not discard the parameter's type information, compared to the variable-length function. Therefore, overloaded cout can always print a variable of the type correctly. This is where the variable-length template function is stronger than the variable-length function.
C++11 defines the locations where seven parameter packages can be expanded:
1. Expressions
2. Initialize the list
3. Base class description List
4. class member Initialization list
5. Template parameter list
6. General Properties List
7. Snap List of lambda functions
If our life arg is a parameter package, then you can use Arg&& Such a package extension expression, which is equivalent to arg1&&,..., argn&& (ARG1 is the first parameter in the package, ARGN is the nth parameter in the package).
1. Template<typename ... A>classt:private B<a> {};
2. Template<typename ... A>classt:private b<a...>{};
Same instantiation of t<x,y>;
1 after unpacking for classt<x,y>:private B<x>,private b<y>{};
2 after unpacking for Classt<x,y>:private B<x, y>{};
The operator sizeof ..., whose function is to calculate the number of parameters in a parameter package.
C++11 variable length template parsing (in-depth understanding of c++11)