Template metaprogramming (TMP, templating Meta programming) is the process of writing template-based C + + programs and compilations. Template metaprogramming is written in C + +, and the compiler compiles the materialized process. In other words, after the TMP program executes, from the templates materialized C + + source code, is no longer a template.
TMP has two functions, one is that it makes something easier. For example, write an STL container, use a template, but store any type of element. The second is to transfer some of the work performed at run time to the compile time. Another result is that C + + programs that use TMP may be more efficient in other ways: smaller executables, shorter runs, and less memory requirements. However, the run-time work is transferred to the compile time, and the compilation period may become longer.
Take a look at the advance pseudo code in clause 47
template<typenametypename DistT> void advance(IteT& iter,DistT d) { if(iter is a random access iterator) iter+=d; else { if(d>=0) while(d--) ++iter; else while(d++) --iter; } }
typeID can be used to determine the pseudo code operation of the ITER type
template <typename Iter, typename distt> void advance (itet& iter,distt D) {if (typeid (typename STD :: iterator_traits<itert>::iterator_category) ==typeid (std :: Random_access_iterator_tag)) Iter+=d; else {if (D>=0 ) while (d--) ++iter; else while (d++)--iter; } }
The typeid-based solution is less efficient than the traits solution, because in this scenario, the 1 type test occurs at run time rather than compile time, and the 2 run-time type test code is in (or is connected to) the executable file. This example shows that TMP is more efficient than a normal C + + program because the traits solution is TMP.
Some things are easier in tmp than in normal C + +, Advance provides a good example. Advance typeid-based implementations may cause compile-time issues
STD:: list<int>:: Iterator iter; ... advance (ITER,Ten);voidAdvanceSTD:: list<int>::iterator& ITER,intD) {if(typeID(TypeName STD::iterator_traits<STD:: list<int>:: iterator>::iterator_category) = =typeID(STD:: Random_access_iterator_tag)) Iter+=d;//Error Else{if(d>=0) while(d--) ++iter;Else while(d++)--iter; } }
Error is called on the + = operator. Because List::iterator does not support + =, it is an bidirectional iterator. We know that the + = line is not executed because the typeID line is always unequal, but the compile time ensures that all the source code is valid, even if it is not executed. The traits-based TMP solution performs different code for different types without the above problems.
TMP has been shown to be a Turing complete machine, which means it is powerful enough to calculate anything. You can use TMP to declare variables, execute loops, write calling functions .... Sometimes this looks very different from normal C + + counterparts, such as the TMP if-else shown in clause 47 is represented by Templas and its specificity. But that is the assembly language level of TMP. A more advanced syntax is provided for the TMP-designed library, such as the boost ' s mpl,** clause **55.
To see how things work in TMP again, look at the loop. The TMP does not have a true loop, and the loop is completed by recursion (recursion). TMP recursion is not even normal recursion, because the TMP recursion does not involve recursive function calls, but rather involves recursive templating (recursive template instantiation).
The TMP's starting-up program calculates the factorial at compile time. The factorial transport of TMP demonstrates how to implement loops through recursive template materialization, and how to create and use variables in TMP
template<unsigned n> struct Factorial{ enum {value=n*Factorial<n-1>::value}; }; template<> struct Factorial<0//特殊情况,Factorial<0>的值是1 enum {value=1}; };
With this template metaprogram, the n factorial value can be obtained as long as the referent factorial::value. The loop occurs when the template materialized factorial refers to another template materialized factorial. The special case of the template-specific version of factorial<0> is the end of recursion.
Each factorial template materialization is a struct, and each struct declares a TMP variable with the name value, which is used to hold the factorial value obtained by the current calculation. TMP replaces loops with recursive template materialization, each of which has its own value, and each value has an appropriate value within its loop.
Demonstrating TMP with factorial is like using the Hello World Model programming language. In order to understand that TMP is worth learning, it is necessary to have a better understanding of what it can achieve. Here are three examples:
- Ensure that the unit of measurement is correct. Using TMP ensures that the combination of all measurement units is correct at compile time.
- Optimize matrix operations. clause 21 has mentioned that some functions including operator * must return a new object, and there is a squarematrix in clause 44. If this is used
typedef SquareMatrix<double,1000> BigMatrix; BigMatrix m1,m2,m3,m4,m5; …… BigMatrix result=m1 * m2 * m3 * m4 * m5;
The multiplication above produces four temporary matrices, and the multiplication may also produce 4 loops that act on the elements of a matrix. If you use advanced, TMP-related template (that is, expression templates), it is possible to eliminate those temporary objects and merge loops. Therefore, TMP uses less memory, and the execution speed is improved.
- Custom design pattern implementations can be generated. Using the tmp-based technology of policy-based design, it is possible to generate some templates to express independent design items (so-called policies), and then can combine them arbitrarily, resulting in the pattern implementation of the product with customer-specific behavior.
TMP is not yet fully mature, the syntax is not intuitive, the supporting tools are not enough. However, TMP is attractive for performance that is difficult or even impossible to achieve in the run-time. Although TMP will not become mainstream, it will become the main food for some programmers (especially developers of libraries).
Summarize
- Template metaprogramming (TMP, templating meta-programming) moves the work from the runtime to the compile time, enabling early error detection and higher execution efficiency.
- TMP can be used to generate custom code based on the policy choice combination (based on combinations of policy choices), or to avoid generating code that is not appropriate for certain special types.
"Effective C + +": Clause 48: Understanding template meta-programming