Abstract
This chapter deals with templates that generate code—partly static, partly executed at runtime. Suppose you have to perform a simple comparison of powers:
Access this chapter
Tax calculation will be finalised at checkout
Purchases are for personal use only
Notes
- 1.
Usually, this requires the additional assumption that a, b, and c point to unrelated areas of memory, but modern compilers will try to understand if these optimizations can be safely applied.
- 2.
This is commonly called code bloat.
- 3.
There are 26N sequences of N letters, and “only” say 264 different hash values, so for N>14, no hash can be injective; however a good hashing algorithm will “scatter” conflicts, so strings having the same hash will be really different.
- 4.
As an exercise, the reader might generalize the idea to wchar_t, which in this implementation always picks the locale-based function set.
- 5.
The motivation will be evident when you see an application to string hashing, later in the paragraph.
- 6.
There’s no need for a complete mimesis implementation: a cast operator is not needed.
- 7.
This syntax will be used only in this section, where there’s no possibility of confusion.
- 8.
Another common error is the argument crossover. Suppose a class C has two template parameters T1 and T2. If you partially specialize C<T1,Y> and C<X,T2> for some fixed X and Y, C<X,Y> is ambiguous, so it must be explicitly specialized too.
- 9.
The problem actually falls under the opaque type principle. If the return type of a function is “complex,” you should either publish a convenient typedef to the users or allow them to use the object by ignoring its type (refer to Chapter 9 for more details).
- 10.
As follows from the opaque type principle, it’s not necessary to document what the exact return type is, just state that it works like a std::pair with an extra operator>>. In principle, it would be reasonable to add a conversion operator from dynamic_hash_result to std::pair<size_t,iterator_t>.
- 11.
Since there’s a single function in the class, this example does not derive from static_interface but replicates the code.
- 12.
This is an online problem. In offline problems, all the input values are given at the same time. There’s a data structure by David Eppstein (see http://www.ics.uci.edu/∼eppstein/pubs/kbest.html) that solves the online problem using memory proportional to N and exhibits amortized constant-time operations. This example focuses on how to improve a naive implementation, not on creating an efficient algorithm.
- 13.
Here, update and its auxiliary subroutines are global functions. This just makes the illustration easier, because it allows you to focus on one feature at a time. You can safely declare all these functions as private static members of the container.
- 14.
It seems that this kind of “greedy compact style” for small values of N gets most benefit from an aggressive optimizing compiler. A rudimentary stress test with 10.000.000 insertions and N<32 showed a very large runtime difference (30–40%) between a “normal” and an “extreme” release build. Greedy algorithms and compact code take advantage of technological factors, such as processor caches.
- 15.
is means derives from.
- 16.
So you cannot generate patterns like YYYYMMDDYY.
- 17.
Hint: Use a const array of char of length SSTRING_BASE and initialize it with { 0, int2char<1>::value, int2char<2>::value, ... }.
Author information
Authors and Affiliations
Rights and permissions
Copyright information
© 2015 Davide Di Gennaro
About this chapter
Cite this chapter
Gennaro, D.D. (2015). Code Generators. In: Advanced Metaprogramming in Classic C++. Apress, Berkeley, CA. https://doi.org/10.1007/978-1-4842-1010-9_7
Download citation
DOI: https://doi.org/10.1007/978-1-4842-1010-9_7
Publisher Name: Apress, Berkeley, CA
Print ISBN: 978-1-4842-1011-6
Online ISBN: 978-1-4842-1010-9
eBook Packages: Professional and Applied ComputingProfessional and Applied Computing (R0)Apress Access Books