C ++ 11 Variable Parameter templates and variable templates
Before C ++ 11, there were two typical problems, namely, function object and tuple, which were subject to the unsightly code repetition caused by poor template functions. 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 or 8 template classes repeatedly, but you can only support function objects with 7 or 8 parameters. In C ++ 11, a powerful variable-length parameter template is provided, and these problems are also solved.
Variable Parameter Template (Variadic Template) is a class/function Template that can accept any number of parameters. The declaration method is
template<typename... Args>class VariadicTemplate;
Of course, the non-type parameter is also supported, such as template <int... Args> class VariadicIntTemplate;
Here, Args represents 0-N type parameters, that is, VariadicTemplate <> is also a valid template instance.
The ellipsis (...) operator is updated in C ++ 11 to support access and use of such template parameters.
Type Expansion
Expand All template parameters at the current position to call other templates and declare function pointer types.
template<typename ...Args>int foo() { int (*p)(Args...) = bar<Args...>; p(1, 0.5); return bar<Args...>(1, 0.5); }
For a foo <int, float> instance, its p type is 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 <bar, barz> f; // This class inherits the bar and barz base classes.
Parameter Packs/Initialization Lists
The ellipsis operator can be used to declare parameter packages. These parameter packages can be expanded in the parameter positions of functions.
template<typename ...Args>void foo(Args... args) {}
When foo <int, float> is used, it has two parameters: One integer and one float. Therefore, the call method is foo <int, float> (1, 0.1f );
In addition, you can expand the parameter package to the initialization list of the constructor.
template<typename... Args>class foo : Args...{public: foo(Args...args):Args(args)...{ }};foo<bar, barz> f(bar(), barz());
Sizeof... operator
To obtain the real Parameter length of a variable-length template, use the sizeof... operator. It can also be used in Parameter Packs.
template<typename ... Args>size_t foo() { return sizeof...(Args);}template<typename ... Args>size_t fooz(Args ...args) { return sizeof...(args);}
The above is the basic usage of the variable length parameter, but it is often necessary to use the Template Specialization)
Variable Parameter templates and template features
Variable Parameter templates can be customized like common templates to implement meaningful models.
template<typename ... Args>void output(Args ... args) {}template<typename Arg0, typename ... Args>void output(Arg0 arg0, Args ... args) { std::cout << arg0; output<Args...>(args...);}template<>void output() {}/*------------------------------*/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);
Above code output
10.30stringc