c++11--Variable parameter templates

Source: Internet
Author: User

Before c++11, class templates and function templates can contain only a fixed number of template parameters, and c++11 adds variable template parameter properties: allows 0 to any template parameter in the template definition. When declaring a variadic template, you need to add the ellipsis "..." after TypeName or class.
The ellipsis has two effects:
1. Declare a parameter package, which can contain 0 to any template parameter
2. On the right side of the template definition, you can expand the parameter pack to a single parameter

1. Variable parameter template function

The variable parameter template function is defined as follows:

Template<class ... T>void f (T ... args) {    cout << sizeof ... (args) << Endl; sizeof ... (args) Gets the number of variable arguments}f (); F (1, 2); F (1, 2.3, "Hello");

A parameter pack can contain 0 or more parameters, and if you need parameters in a parameter pack, you must expand the parameter pack. There are two ways to expand the parameter package: (1) to expand the parameter package through a recursive template function, (2) to expand the parameter package by means of a comma expression and an initialization list.

Expand the Parameter pack
(1) Recursive function expansion parameter package
You need to provide a parameter package expansion function and a recursive termination function with the same name. The parameters of the recursive termination function can be 0,1,2 or multiple (typically 0 or 1), and when the number of arguments remaining in the parameter pack equals the number of arguments to the recursive termination function, the function terminates.

#include <iostream>using namespace std;//recursive termination function void print () {    cout << "Empty" << Endl;} Expand function Template<class T, class ... Args>void Print (T head, Args ... rest) {    cout << "parameter =" << head << Endl;    Print (rest ...); int main () {    print (1,2,3,4);    return 0;} When print (1,2,3,4) is called, print (2,3,4), print (3,4), print (4) are called successively, and the final call to print () terminates. If the recursive termination function is template<typename t>void print (T a) {    cout << a << Endl;} The function call to print (4) terminates.

It is also possible to define functions with the same name but with different parameters by type_traits, implement recursive termination and expansion functions separately, and expand the parameter package

Equivalent to the recursive termination function Template<typename I = 0, typename tuple>typename std::enable_if<i==std::tuple_size<tuple>: : Value>::type printtp (Tuple t) {    }//equals expansion function Template<typename I = 0, typename Tuple>typename std::enable_if <i < Std::tuple_size<tuple>::value>::type printtp (tuple t) {    std::cout << std::get<i> ( t) << Std::endl;   Print out the    printtp<i+1> (t) in the tuple;} Template<typename ... Args>void print (args ... args) {    printtp (std::make_tuple (args ...);}

(2) initialize list mode expand parameter Pack
The recursive function expands the parameter package and requires a terminating function with the same name to terminate the recursion, and the initialization list can be used to avoid multiple definitions of a terminating function with the same name.

Template<typename t>void Printarg (T a) {    cout << a << Endl;} Template<class ... Args>void expand (args ... args) {    int arr[] = {(Printarg (args), 0) ...};    or improved for std::initializer_list<int>{(Printarg (args), 0) ...};} {(Printarg (args), 0) ...} will be expanded to {(Printarg (arg1), 0), (Printarg (ARG2), 0), (Printarg (ARG3), 0)}expand ("Hello");


This way of expanding the parameter package, do not need to pass the recursive termination function, but directly in the expand function in the body expansion, Printarg is not a recursive termination function, just a function to handle each parameter in the parameter package. The key to this approach is the comma expression.

The comma expression executes the preceding expression sequentially, such as D = (A = b, c), B is assigned to a, and the comma expression in parentheses returns the value of C, so D is assigned C
c++11 using the list initialization method to initialize an array of edge lengths, you can use int arr[] = {args ...}; Where args is a variable-length set of parameters.

Template<typename ... Args>void print (args ... args) {    int arr[] = {(args, 0) ...};//named Args ... (or anonymous ...) Represents all mutable parameter sets that can be args and ... Separate, at this point the args says ... In each parameter. }

You can also use lambda expressions to improve the list initialization described above:

Template<typename ... Args>void expand (args ... args) {    std::initializer_list<int>{([&]{cout << args << Endl;} (), 0) ...};}

2. Variable parameter template class

A tuple is a mutable parameter template class:

    Template<class ... Types>    class tuple;    This variable-parameter template class can carry any number of template parameters of any type    std::tuple<int> TP1 = std::make_tuple (1);    Std::tuple<int, double> TP2 = Std::make_tuple (1,2.4);    std::tuple<> TP;

parameter expansion for variable parameter template classes (1) template recursion and special mode expansion parameter package

The expansion of a Variadic template class typically requires two or three classes, including a class declaration and a template class for a specific specification. A basic mutable parameter template class is defined as follows:

Template<typename ... Args>  //forward declaration struct Sum;template<typename first, TypeName ... Rest>  //class definition struct Sum<first, rest...>{             enum {value = Sum<first>::value + sum<rest...>:: value};}; Template<typename last>//recursive termination class, template parameters are not necessarily 1, may be 0 or 2 struct sum<last>{    enum{value = sizeof (last)}; The function of this sum class is to compute a size sum of the parameter types in the parameter package at compile time. Or can be modified by std::integral_constant: Template<typename ... Args>      //Pre-declaration struct Sum;template<typename first, TypeName ... Rest>  //recursive definition of struct sum<first, rest...>: Std::integral_constant<int, Std::integral_constant<int, sizeof (first) >::value + sum<rest...>::value{};template<typename last>//recursive terminating struct SUM<LAST>: Std::integral_constant<int, sizeof (last) >{};


(2) Inheritance mode expansion parameter package
Definition of integer sequence template<int ... >struct indexseq{};//inherit mode, start expand parameter Package template<int N, int ... Indexes>struct makeindexes:makeindexes<n-1, N-1, indexes...>{};//template Special, terminate the conditions of the expansion parameter pack template<int ... Indexes>struct makeindexes<0, indexes...>{    typedef indexseq<indexes...> type;}; int main () {    using T = makeindexes<3>::type;  The output is struct indexseq<0,1,2>    cout << typeid (T). Name () << Endl;    Return 0;};/ /makeindexes can be implemented by using if it is not generated by inheritance recursively. Template<int N, int ... Indexes>struct makeindexes{    Using type = makeindexes<n-1,n-1,indexes>::type;}; Template<int ... Indexes>struct makeindexes<0, ... indexes>{    Using type =  indexseq<indexes...>;};

You can use the indexseq above to expand and print variable template parameters, such as: Template<int ... Indexes, TypeName ... Args>void Print_helper (indexseq<indexes...>, std::tuple<args...>&& tup) {    print (std:: Get<indexes> (Tup) ...);} Template<typename ... Args>void print (args ... args) {    print_helper (typename makeindexes<sizeof ... (args) >::type (), std::make_tuple (args ...));



c++11--Variable parameter templates

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.