Professional C__ - Marc Gregoire [358]
There is one small problem with the preceding implementation. Since it’s a recursive implementation, the parameters will be copied for each recursive call to processValues(). This can become costly depending on the type of the arguments. You might think that you can avoid this copying by passing references to the processValues() function instead of using pass-by-value. Unfortunately that also means that you cannot call processValues() with constant values anymore, because a reference to a constant value is not allowed.
To use references and still allow constant values, you can leverage another C++11 feature called rvalue references, which are discussed in Chapter 9. Doing that results in the following implementation:
template void processValuesRValueRefs(T&& arg) { handleValue(arg); } template void processValuesRValueRefs(T1&& arg1, Tn&&... args) { processValuesRValueRefs(arg1); processValuesRValueRefs(args...); } Code snippet from VarArgs\VarArgsWithVariadicTemplates.cpp Inside the body of a function using a parameter pack you can retrieve the number of arguments in the pack as follows: int numOfArgs = sizeof...(args); A practical example of using variadic templates is to write a secure and type-safe version of printf(). Variable Number of Mix-In Classes Parameter packs can be used almost everywhere. For example, the following code uses a parameter pack to define a variable number of mix-in classes for the MyClass class. Chapter 3 discusses the concept of mix-in classes. class Mixin1 { public: Mixin1(int i) : m_i(i) {} virtual void Mixin1Func() {cout << "Mixin1: " << m_i << endl;} protected: int m_i; }; class Mixin2 { public: Mixin2(int i) : m_i(i) {} virtual void Mixin2Func() {cout << "Mixin2: " << m_i << endl;} protected: int m_i; }; template class MyClass : public Mixins... { public: MyClass(const Mixins&... mixins) : Mixins(mixins)... {} }; Code snippet from VariadicMixins\VariadicMixins.cpp This code first defines two mix-in classes Mixin1 and Mixin2. They are kept pretty simple for this example. Their constructor accepts an integer, which is stored, and they have a function to print information about that specific instance of the class. The MyClass variadic template uses a parameter pack typename... Mixins to accept a variable number of mix-in classes. The class then inherits from all those mix-in classes and the constructor accepts the same number of arguments to initialize each inherited mix-in class. The class can be used as follows: MyClass a.Mixin1Func(); a.Mixin2Func(); MyClass b.Mixin1Func(); //b.Mixin2Func(); // Error: does not compile. Code snippet from VariadicMixins\VariadicMixins.cpp When you try to call Mixin2Func() on b you will get a compiler error because b is not inheriting from the Mixin2 class. The output of this program is as follows: Mixin1: 11 Mixin2: 22 Mixin1: 33 METAPROGRAMMING The goal of template metaprogramming is to perform some computation at compile time instead of at run time. It is basically a mini programming language on top of C++. The following section starts the discussion with a simple demonstration that calculates the factorial of a number at compile time and makes the result
This section touches on template metaprogramming. It is a very complicated subject and there are books written about it explaining all the little details. This book doesn’t have the space to go into all the details of metaprogramming. Instead, this section explains the most important concepts, with the aid of a couple of examples.