In
computer programming
Computer programming is the process of performing a particular computation (or more generally, accomplishing a specific computing result), usually by designing and building an executable computer program. Programming involves tasks such as ana ...
, variadic templates are
template
Template may refer to:
Tools
* Die (manufacturing), used to cut or shape material
* Mold, in a molding process
* Stencil, a pattern or overlay used in graphic arts (drawing, painting, etc.) and sewing to replicate letters, shapes or designs
Co ...
s that take a variable number of arguments.
Variadic templates are supported by
C++
C++ (pronounced "C plus plus") is a high-level general-purpose programming language created by Danish computer scientist Bjarne Stroustrup as an extension of the C programming language, or "C with Classes". The language has expanded significan ...
(since the
C++11
C++11 is a version of the ISO/IEC 14882 standard for the C++ programming language. C++11 replaced the prior version of the C++ standard, called C++03, and was later replaced by C++14. The name follows the tradition of naming language versions by ...
standard), and the
D programming language
D, also known as dlang, is a multi-paradigm system programming language created by Walter Bright at Digital Mars and released in 2001. Andrei Alexandrescu joined the design and development effort in 2007. Though it originated as a re-engineeri ...
.
C++
The variadic template feature of C++ was designed by Douglas Gregor and Jaakko Järvi
and was later standardized in C++11.
Prior to C++11, templates (classes and functions) could only take a fixed number of arguments, which had to be specified when a template was first declared. C++11 allows template definitions to take an arbitrary number of arguments of any type.
template class tuple; // takes zero or more arguments
The above template class will take any number of typenames as its template parameters. Here, an instance of the above template class is instantiated with three type arguments:
tuple, std::map>> some_instance_name;
The number of arguments can be zero, so will also work.
If the variadic template should only allow a positive number of arguments, then this definition can be used:
template class tuple; // takes one or more arguments
Variadic templates may also apply to functions, thus not only providing a type-safe add-on to variadic functions (such as printf), but also allowing a function called with printf-like syntax to process non-trivial objects.
template void my_printf(const std::string &str_format, Params... parameters);
The
ellipsis
The ellipsis (, also known informally as dot dot dot) is a series of dots that indicates an intentional omission of a word, sentence, or whole section from a text without altering its original meaning. The plural is ellipses. The term origin ...
(...) operator has two roles. When it occurs to the left of the name of a parameter, it declares a parameter pack. Using the parameter pack, the user can bind zero or more arguments to the variadic template parameters. Parameter packs can also be used for non-type parameters. By contrast, when the ellipsis operator occurs to the right of a template or function call argument, it unpacks the parameter packs into separate arguments, like the in the body of below. In practice, the use of an ellipsis operator in the code causes the whole expression that precedes the ellipsis to be repeated for every subsequent argument unpacked from the argument pack, with the expressions separated by commas.
The use of variadic templates is often recursive. The variadic parameters themselves are not readily available to the implementation of a function or class. Therefore, the typical mechanism for defining something like a C++11 variadic replacement would be as follows:
// base case
void my_printf(const char *s)
// recursive
template
void my_printf(const char *s, T value, Args... args)
This is a recursive template. Notice that the variadic template version of calls itself, or (in the event that is empty) calls the base case.
There is no simple mechanism to iterate over the values of the variadic template. However, there are several ways to translate the argument pack into a single argument that can be evaluated separately for each parameter. Usually this will rely on
function overloading
In some programming languages, function overloading or method overloading is the ability to create multiple functions of the same name with different implementations. Calls to an overloaded function will run a specific implementation of that f ...
, or — if the function can simply pick one argument at a time — using a dumb expansion marker:
template inline void pass(Args&&...)
which can be used as follows:
template inline void expand(Args&&... args)
expand(42, "answer", true);
which will expand to something like:
pass(some_function(arg1), some_function(arg2), some_function(arg3) /* etc... */ );
The use of this "pass" function is necessary, since the expansion of the argument pack proceeds by separating the function call arguments by commas, which are not equivalent to the comma operator. Therefore, will never work. Moreover, the solution above will only work when the return type of is not . Furthermore, the calls will be executed in an unspecified order, because the order of evaluation of function arguments is undefined. To avoid the unspecified order, brace-enclosed initializer lists can be used, which guarantee strict left-to-right order of evaluation. An initializer list requires a non- return type, but the comma operator can be used to yield for each expansion element.
struct pass
;
pass;
Instead of executing a function, a lambda expression may be specified and executed in place, which allows executing arbitrary sequences of statements in-place.
pass;
However, in this particular example, a lambda function is not necessary. A more ordinary expression can be used instead:
pass;
Another way is to use overloading with "termination versions" of functions. This is more universal, but requires a bit more code and more effort to create. One function receives one argument of some type ''and'' the argument pack, whereas the other receives neither. (If both had the same list of initial parameters, the call would be ambiguous — a variadic parameter pack alone cannot disambiguate a call.) For example:
void func() // termination version
template
void func(const Arg1& arg1, const Args&&... args)
If contains at least one argument, it will redirect to the second version — a parameter pack can be empty, in which case it will simply redirect to the termination version, which will do nothing.
Variadic templates can also be used in an exception specification, a base class list, or the initialization list of a constructor. For example, a class can specify the following:
template
class ClassName : public BaseClasses...
;
The unpack operator will replicate the types for the base classes of , such that this class will be derived from each of the types passed in. Also, the constructor must take a reference to each base class, so as to initialize the base classes of .
With regard to function templates, the variadic parameters can be forwarded. When combined with universal references (see above), this allows for perfect forwarding:
template
struct SharedPtrAllocator
;
This unpacks the argument list into the constructor of TypeToConstruct. The syntax perfectly forwards arguments as their proper types, even with regard to rvalue-ness, to the constructor. The unpack operator will propagate the forwarding syntax to each parameter. This particular factory function automatically wraps the allocated memory in a for a degree of safety with regard to memory leaks.
Additionally, the number of arguments in a template parameter pack can be determined as follows:
template
struct SomeStruct
;
The expression will yield 2, while will give 0.
D
Definition
The definition of variadic templates in D is similar to their C++ counterpart:
template VariadicTemplate(Args...)
Likewise, any argument can precede the argument list:
template VariadicTemplate(T, string value, alias symbol, Args...)
Basic usage
Variadic arguments are very similar to constant array in their usage. They can be iterated upon, accessed by an index, have a property, and can be
sliced
''Sliced'' is an American television series that premiered on on The History Channel. The program was hosted by John McCalmont and Budd Kelley, who "slice" everyday objects in half to uncover how they work. The show aired on Thursdays at 10:00 ...
. Operations are interpreted at compile time, which means operands can't be runtime value (such as function parameters).
Anything which is known at compile time can be passed as a variadic arguments. It makes variadic arguments similar t
template alias arguments but more powerful, as they also accept basic types (char, short, int...).
Here is an example that print the string representation of the variadic parameters. and produce equal results.
static int s_int;
struct Dummy
void main()
template StringOf(Args...)
template StringOf()
template StringOf2(Args...)
Outputs:
"Hello world"uintDummy42s_int
"Hello world"uintDummy42s_int
AliasSeq
Variadic templates are often used to create a sequence of aliases, name
The definition of an AliasSeq is actually very straightforward:
alias AliasSeq(Args...) = Args;
This structure allows one to manipulate a list of variadic arguments that will auto-expand. The arguments must either be symbols or values known at compile time. This includes values, types, functions or even non-specialized templates. This allows any operation you would expect:
import std.meta;
void main()
template isEven(int number)
See also
For articles on variadic constructs other than templates
*
Variadic function
In mathematics and in computer programming, a variadic function is a function of indefinite arity, i.e., one which accepts a variable number of arguments. Support for variadic functions differs widely among programming languages.
The term ''varia ...
*
Variadic macro
A variadic macro is a feature of some computer programming languages, especially the C preprocessor, whereby a macro may be declared to accept a varying number of arguments.
Variable-argument macros were introduced in 1999 in the ''ISO/IEC 9899: ...
in the
C preprocessor
The C preprocessor is the macro preprocessor for the C, Objective-C and C++ computer programming languages. The preprocessor provides the ability for the inclusion of header files, macro expansions, conditional compilation, and line control ...
References
{{reflist
External links
Working draft for the C++ language, January 16, 2012
Computer programming
Articles with example C++ code