Content deleted Content added
m Task 70: Update syntaxhighlight tags - remove use of deprecated <source> tags |
|||
Line 22:
==Compile-time class generation==
What exactly "programming at compile-time" means can be illustrated with an example of a factorial function, which in non-template C++ can be written using recursion as follows:
<
unsigned int factorial(unsigned int n) {
return n == 0 ? 1 : n * factorial(n - 1);
Line 30:
// factorial(0) would yield 1;
// factorial(4) would yield 24.
</syntaxhighlight>
The code above will execute at run time to determine the factorial value of the literals 4 and 0.
By using template metaprogramming and template specialization to provide the ending condition for the recursion, the factorials used in the program—ignoring any factorial not used—can be calculated at compile time by this code:
<
template <unsigned int n>
struct factorial {
Line 47:
// factorial<0>::value would yield 1;
// factorial<4>::value would yield 24.
</syntaxhighlight>
The code above calculates the factorial value of the literals 4 and 0 at compile time and uses the results as if they were precalculated constants.
To be able to use templates in this manner, the compiler must know the value of its parameters at compile time, which has the natural precondition that factorial<X>::value can only be used if X is known at compile time. In other words, X must be a constant literal or a constant expression.
Line 58:
As another, more significant, example of compile-time [[loop unrolling]], template metaprogramming can be used to create length-''n'' vector classes (where ''n'' is known at compile time). The benefit over a more traditional length-''n'' vector is that the loops can be unrolled, resulting in very optimized code. As an example, consider the addition operator. A length-''n'' vector addition might be written as
<
template <int length>
Vector<length>& Vector<length>::operator+=(const Vector<length>& rhs)
Line 66:
return *this;
}
</syntaxhighlight>
When the compiler instantiates the function template defined above, the following code may be produced:{{citation needed|date=October 2015}}
<
template <>
Vector<2>& Vector<2>::operator+=(const Vector<2>& rhs)
Line 78:
return *this;
}
</syntaxhighlight>
The compiler's optimizer should be able to unroll the <code>for</code> loop because the template parameter <code>length</code> is a constant at compile time.
Line 86:
==Static polymorphism==
[[Type polymorphism|Polymorphism]] is a common standard programming facility where derived objects can be used as instances of their base object but where the derived objects' methods will be invoked, as in this code
<
class Base
{
Line 107:
return 0;
}
</syntaxhighlight>
where all invocations of <code>virtual</code> methods will be those of the most-derived class. This ''dynamically polymorphic'' behaviour is (typically) obtained by the creation of [[vtable|virtual look-up table]]s for classes with virtual methods, tables that are traversed at run time to identify the method to be invoked. Thus, ''run-time polymorphism'' necessarily entails execution overhead (though on modern architectures the overhead is small).
However, in many cases the polymorphic behaviour needed is invariant and can be determined at compile time. Then the [[Curiously Recurring Template Pattern]] (CRTP) can be used to achieve '''static polymorphism''', which is an imitation of polymorphism in programming code but which is resolved at compile time and thus does away with run-time virtual-table lookups. For example:
<
template <class Derived>
struct base
Line 130:
}
};
</syntaxhighlight>
Here the base class template will take advantage of the fact that member function bodies are not instantiated until after their declarations, and it will use members of the derived class within its own member functions, via the use of a <code>static_cast</code>, thus at compilation generating an object composition with polymorphic characteristics. As an example of real-world usage, the CRTP is used in the [[Boost library|Boost]] [[iterator]] library.<ref>http://www.boost.org/libs/iterator/doc/iterator_facade.html</ref>
|