I discovered template metaprogramming more than 5 years ago and got a huge kick out of reading Modern C++ Design but I never found an opertunity to use it in real life.
Have you ever used this technique in real code?
Contributors to Boost need not apply ;o)
Template metaprogramming (TMP) is a metaprogramming technique in which templates are used by a compiler to generate temporary source code, which is merged by the compiler with the rest of the source code and then compiled.
Metaprogramming can be used to move computations from run-time to compile-time, to generate code using compile time computations, and to enable self-modifying code. The ability of a programming language to be its own metalanguage is called reflection.
Generics are used for metaprogramming in Ada. They are useful for abstract algorithms that share common properties with each other.
C++ templates are checked at least twice. First, when a template is declared & defined, second when it is instantiated. After a template successfully instantiated it is in a type safe state.
I once used template metaprogramming in C++ to implement a technique called "symbolic perturbation" for dealing with degenerate input in geometric algorithms. By representing arithmetic expressions as nested templates (i.e. basically by writing out the parse trees by hand) I was able to hand off all the expression analysis to the template processor.
Doing this kind of thing with templates is more efficient than, say, writing expression trees using objects and doing the analysis at runtime. It's faster because the modified (perturbed) expression tree is then available to the optimizer at the same level as the rest of your code, so you get the full benefits of optimization, both within your expressions but also (where possible) between your expressions and the surrounding code.
Of course you could accomplish the same thing by implementing a small DSL (domain specific language) for your expressions and the pasting the translated C++ code into your regular program. That would get you all the same optimization benefits and also be more legible -- but the tradeoff is that you have to maintain a parser.
I've found policies, described in Modern C++ Design, really useful in two situations:
When I'm developing a component that I expect will be reused, but in a slightly different way. Alexandrescu's suggestion of using a policy to reflect a design fits in really well here - it helps me get past questions like, "I could do this with a background thread, but what if someone later on wants to do it in time slices?" Ok fine, I just write my class to accept a ConcurrencyPolicy and implement the one I need at the moment. Then at least I know the person who comes behind me can write and plug in a new policy when they need it, without having to totally rework my design. Caveat: I have to reign myself in sometimes or this can get out of control -- remember the YAGNI principle!
When I'm trying to refactor several similar blocks of code into one. Usually the code will be copy-pasted and modified slightly because it would have had too much if/else logic otherwise, or because the types involved were too different. I've found that policies often allow for a clean one-fits-all version where traditional logic or multiple inheritance would not.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With