Download as pdf or txt
Download as pdf or txt
You are on page 1of 76

TEMPLATE

METAPROGRAMMING C++
Matthias Brischwein - matthias.brischwein@studium.uni-erlangen.de

Seminar Advanced C++ Programming


Friedrich-Alexander University Erlangen-Nuremberg
11/06/12
TEMPLATE METAPROGRAMMING C++
AGENDA

 Motivation
 Basic Concepts
 Applications
 The boost::mpl library
 Summary
TEMPLATE METAPROGRAMMING C++
AGENDA

 Motivation  Metafunctions
 Basic Concepts  Metafunction classes
 Applications  Metafunction forwarding
 The boost::mpl library
 Summary
TEMPLATE METAPROGRAMMING C++
AGENDA

 Motivation  Metafunctions
 Basic Concepts  Metafunction classes
 Applications  Metafunction forwarding
 The boost::mpl library
 Summary
 Compile-time Assertions
 Type Traits
 Dimensional Analysis
TEMPLATE METAPROGRAMMING (TMP) C++
INTRODUCTION

Goals of this presentation


 Reveiling basic concepts and conventions underlying TMP
 Show applications where TMP can be useful
 Enable and motivate for further individual studies of TMP

This presentation does not (cannot) substitute further reading!

Matthias Brischwein 5
TEMPLATE METAPROGRAMMING C++

For the next 30 minutes you may forget about


C++ and set your mind for new language!

Matthias Brischwein 6
TEMPLATE METAPROGRAMMING C++

Run-Time Compile-Time
OOP FP

Matthias Brischwein 7
TEMPLATE METAPROGRAMMING (TMP) C++
MOTIVATION

Example of a template metaprogram


1. template<unsigned i>  1. #include <iostream>
2. struct Fibonacci { 2. #include "fibonacci.hpp"
3.   static unsigned const value = 3.
4.     Fibonacci<i­1>::value +  4. using namespace std;
5.     Fibonacci<i­2>::value ; 5.
6. }; 6. int main(){
7. 7.   unsigned const value = 
8. template<> struct Fibonacci<1> { 8.   Fibonacci<8>::value;
9.   static unsigned const value = 1; 9.
10. }; 10.   cout << "Result: "
11. 11.        << value
12. template<> struct Fibonacci<0> { 12.        << endl;
13.   static unsigned const value = 0; 13. }
14. };
fibonacci.hpp fibonacci.cpp

Matthias Brischwein 8
TEMPLATE METAPROGRAMMING (TMP) C++
MOTIVATION

TMP is about pure functional programming


 No data types at compile-time
 type names and constant values are metadata
 Metadata is immutable
 No For/While loops (since metadata is immutable)
 Recursion by recursive template instantiation only
 Template specialization
 for (condt.) branches („if/else“)
 to stop recursive instantiations
 C++ Template mechanism is Turing complete!
 No interactive Input

Matthias Brischwein 9
TEMPLATE METAPROGRAMMING (TMP) C++
MOTIVATION

1995  Erwin Unruh computes prime numbers by exploiting template


mechanism
 Program did not compile but results were given in compiler
warning messages
 Veldhuizen: „Template Metaprograms“

1998  Czarnecki and Eisenecker present a TMP implementation of


LISP

2003  Veldhuizen: „C++ Templates are Turing complete“

Matthias Brischwein 10
TEMPLATE METAPROGRAMMING (TMP) C++
MOTIVATION

Example of a template metaprogram


1. template<unsigned i> 
2. struct Fibonacci {
3.   static unsigned const value =
4.     Fibonacci<i­1>::value + 
5.     Fibonacci<i­2>::value ;
6. };
7.
8. template<> struct Fibonacci<1> {
9.   static unsigned const value = 1;
10. };
11.
12. template<> struct Fibonacci<0> {
13.   static unsigned const value = 0;
14. };
fibonacci.hpp

Matthias Brischwein 11
TEMPLATE METAPROGRAMMING (TMP) C++
MOTIVATION

Example of a template metaprogram


1. template<unsigned i> 
2. struct Fibonacci {
3.   static unsigned const value =
4.     Fibonacci<i­1>::value + 
5.     Fibonacci<i­2>::value ;
6. };
7.
8. template<> struct Fibonacci<1> {
9.   static unsigned const value = 1;
10. };
11.
12. template<> struct Fibonacci<0> {
13.   static unsigned const value = 0;
14. };
fibonacci.hpp

Matthias Brischwein 12
TEMPLATE METAPROGRAMMING (TMP) C++
MOTIVATION

Example of a template metaprogram


1. template<unsigned i> 
2. struct Fibonacci {
3.   static unsigned const value =
4.     Fibonacci<i­1>::value + 
5.     Fibonacci<i­2>::value ;
6. };
7.
8. template<> struct Fibonacci<1> {
9.   static unsigned const value = 1;
10. }; Recursive
11. Template Instantiation
12. template<> struct Fibonacci<0> {
13.   static unsigned const value = 0;
14. };
fibonacci.hpp

Matthias Brischwein 13
TEMPLATE METAPROGRAMMING (TMP) C++
MOTIVATION

Example of a template metaprogram


1. template<unsigned i> 
2. struct Fibonacci {
3.   static unsigned const value =
4.     Fibonacci<i­1>::value + 
5.     Fibonacci<i­2>::value ;
6. };
7.
8. template<> struct Fibonacci<1> {
9.   static unsigned const value = 1;
10. };
11.
12. template<> struct Fibonacci<0> {
13.   static unsigned const value = 0;
14. };
fibonacci.hpp

Matthias Brischwein 14
TEMPLATE METAPROGRAMMING (TMP) C++
MOTIVATION

Example of a template metaprogram


1. template<unsigned i> 
2. struct Fibonacci {
3.   static unsigned const value =
4.     Fibonacci<i­1>::value + 
5.     Fibonacci<i­2>::value ;
6. };
7.
8. template<> struct Fibonacci<1> {
9.   static unsigned const value = 1; (Full) Template Specialization
10. };
11.
12. template<> struct Fibonacci<0> {
13.   static unsigned const value = 0;
14. };
fibonacci.hpp

Matthias Brischwein 15
TEMPLATE METAPROGRAMMING (TMP) C++
MOTIVATION

Partial Template Specialization:


Example of a template metaprogram
template<class T1, class T2>
1. template<unsigned i>  struct C{…};
2. struct Fibonacci {
3.   static unsigned const value = template<class T1> 
4.     Fibonacci<i­1>::value + 
5.     Fibonacci<i­2>::value ;
struct C<T1, aType> {...};
6. };
7.
8. template<> struct Fibonacci<1> {
9.   static unsigned const value = 1; (Full) Template Specialization
10. };
11.
12. template<> struct Fibonacci<0> {
13.   static unsigned const value = 0;
14. };
fibonacci.hpp

Matthias Brischwein 16
TEMPLATE METAPROGRAMMING (TMP) C++
MOTIVATION

Example of a template metaprogram


1. template<unsigned i>  1. #include <iostream>
2. struct Fibonacci { 2. #include "fibonacci.hpp"
3.   static unsigned const value = 3.
4.     Fibonacci<i­1>::value +  4. using namespace std;
5.     Fibonacci<i­2>::value ; 5.
6. }; 6. int main(){
7. 7.   unsigned const value = 
8. template<> struct Fibonacci<1> { 8.   Fibonacci<8>::value;
9.   static unsigned const value = 1; 9.
10. }; 10.   cout << "Result: "
11. 11.        << value
12. template<> struct Fibonacci<0> { 12.        << endl;
13.   static unsigned const value = 0; 13. }
14. };
fibonacci.hpp fibonacci.cpp

Matthias Brischwein 17
TEMPLATE METAPROGRAMMING (TMP) C++
MOTIVATION

Example of a template metaprogram


1. template<unsigned i>  1. #include <iostream>
2. struct Fibonacci { 2. #include "fibonacci.hpp"
3.   static unsigned const value = 3.
4.     Fibonacci<i­1>::value +  4. using namespace std;
5.     Fibonacci<i­2>::value ; 5.
6. }; 6. int main(){
7. 7.   unsigned const value = 
8. template<> struct Fibonacci<1> { 8.   Fibonacci<8>::value;
9.   static unsigned const value = 1; 9.
10. }; 10.   cout << "Result: "
11. Result: 21 11.        << value
12. template<> struct Fibonacci<0> { 12.        << endl;
13.   static unsigned const value = 0; 13. }
14. };
fibonacci.hpp fibonacci.cpp

Matthias Brischwein 18
BASIC CONCEPTS
Metafunctions
Metafunction classes
Metafunction forwarding
TEMPLATE METAPROGRAMMING (TMP) C++
BASIC CONCEPTS – Metafunction

1. template<class OP1, class OP2> struct metaFun {
2.   typedef typename plusMetaFun<OP1,OP2>::type type;
3. };

Matthias Brischwein 20
TEMPLATE METAPROGRAMMING (TMP) C++
BASIC CONCEPTS – Metafunction

Argument List Metafunction name

1. template<class OP1, class OP2> struct metaFun {
2.   typedef typename plusMetaFun<OP1,OP2>::type type;
3. };

Matthias Brischwein 21
TEMPLATE METAPROGRAMMING (TMP) C++
BASIC CONCEPTS – Metafunction

Argument List Metafunction name

1. template<class OP1, class OP2> struct metaFun {
2.   typedef typename plusMetaFun<OP1,OP2>::type type;
3. };

Metafunction call Metafunction return value


(called type by convention)
1. #include … //<boost/mpl/int.hpp>, <metaFun.hpp>
2. using namespace boost::mpl;
3. int main() {
4.   int const result = metaFun< int_<3>,int_<4> >::type::value; 
5. }

Matthias Brischwein 22
TEMPLATE METAPROGRAMMING (TMP) C++
BASIC CONCEPTS – Metafunction

Argument List Metafunction name

1. template<class OP1, class OP2> struct metaFun {
2.   typedef typename plusMetaFun<OP1,OP2>::type type;
3. };

Metafunction call Metafunction return value


(called type by convention)
1. template<unsigned i> 
2. struct Fibonacci {
3.   static unsigned const value =
4.     Fibonacci<i­1>::value + 
5.     Fibonacci<i­2>::value ;
6. };

Matthias Brischwein 23
TEMPLATE METAPROGRAMMING (TMP) C++
BASIC CONCEPTS – Metafunction class

Definition:
A metafunction class is a class with a publicly accessible nested
metafunction called apply.
1. #include "MetaFun.hpp"
2.
3. struct ClsMetaFun {
4.
5.   template<class OP1, class OP2>
6.   struct apply {
7.     typedef typename metaFun<OP1, OP2>::type type;
8.   };
9.
10. };

Matthias Brischwein 24
TEMPLATE METAPROGRAMMING (TMP) C++
BASIC CONCEPTS – Metafunction class

Metafunction classes allow to pass metafunctions as first class


citizens to other metafunctions
1. template<class OP1, class OP2, class OP>
2. struct BinaryOp {
3.   typedef typename OP::template apply<OP1, OP2>::type type;
4. };

1. #include … // ClsMetaFun, BinaryOp, boost/mpl/integral_c.
2. 
3. int main() {
4.   const int result = 
5.     BinaryOp<int_<3>,int_<4>, ClsMetaFun>::type::value;
6.   return 0;
7. }

Matthias Brischwein 25
TEMPLATE METAPROGRAMMING (TMP) C++
BASIC CONCEPTS – Metafunction forwarding

Instead of redirecting to another metafunction we can just rename it


using Metafunction forwarding
1. #include "MetaFun.hpp"
2.
3. struct ClsMetaFun {
4.
5.   template<class OP1, class OP2>
6.   struct apply {
7.     typedef typename metaFun<OP1, OP2>::type type;
8.   };
9.
10. };

Matthias Brischwein 26
TEMPLATE METAPROGRAMMING (TMP) C++
BASIC CONCEPTS – Metafunction forwarding

Instead of redirecting to another metafunction we can just rename it


using Metafunction forwarding
1. #include "MetaFun.hpp"
2.
3. struct ClsMetaFun {
4.
5.   template<class OP1, class OP2>
6.   struct apply : metaFun<OP1, OP2> {
7.
8.   };
9.
10. };

Matthias Brischwein 27
TEMPLATE METAPROGRAMMING (TMP) C++
BASIC CONCEPTS – Metafunction forwarding

Instead of redirecting to another metafunction we can just rename it


using Metafunction forwarding
1. template<class OP1, class OP2, class OP>
2. struct BinaryOp {
3.   typedef typename OP::template apply<OP1, OP2>::type type;
4. };

1. #include … // ClsMetaFun, BinaryOp, boost/mpl/integral_c.
2. 
3. int main() {
4.   const int result = 
5.     BinaryOp<int_<3>,int_<4>, ClsMetaFun>::type::value;
6.   return 0;
7. }

Matthias Brischwein 28
TEMPLATE METAPROGRAMMING (TMP) C++
BASIC CONCEPTS – Metafunction forwarding

Instead of redirecting to another metafunction we can just rename it


using Metafunction forwarding
1. template<class OP1, class OP2, class OP>
2. struct BinaryOp : OP::template apply<OP1, OP2> {
3.
4. };

1. #include … // ClsMetaFun, BinaryOp, boost/mpl/integral_c.
2. 
3. int main() {
4.   const int result = 
5.     BinaryOp<int_<3>,int_<4>, ClsMetaFun>::type;
6.   return 0;
7. }

Matthias Brischwein 29
APPLICATIONS
Compile-time assertions
Type-Traits
Dimensional Analysis
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Compile-time Assertions

Assertions
express developer's assumption about the truth of some condition at a certain
line of code.

Run-time assertions
 May be violated in rare (unforseen) cases
 Risk of failure in front of the customer

Compile-time assertions
 Assumptions about runtime-invariant conditions
 If assertion fails, it fails in front of the developer, not the customer

Matthias Brischwein 31
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Compile-time Assertions

Example, how compile-time assertions could be implemented:


1. STATIC_ASSERT(( Fibonacci<8>::value == 22 ));

1. #define STATIC_ASSERT(expr){ char unnamed[(expr) ? 1 : 0]; }

 Assertion invalid → definition of char unnamed[0]


→ illegal according to standard
 But: Error message not very illuminating

Matthias Brischwein 32
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Compile-time Assertions

First refinement using TMP:


1. template<bool> struct CompileTimeError;
2. template<> struct CompileTimeError<true>;
3.
4. #define STATIC_ASSERT(expr) {       \
5.   (CompileTimeError<(expr) != 0>()) \
6. }

src.cpp:38: error: invalid use of incomplete type ‘struct 
CompileTimeError<false>’ … 
GCC 4.4.3
Well, the error message could still be more informative...

Matthias Brischwein 33
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Compile-time Assertions

Second refinement using the preprocessor's „past token“ ##


1. template<bool> struct CompileTimeChecker {
2.   // absorb error message if assertion is true
3.   CompileTimeChecker( ... );
4. };
5.
6. template<> struct CompileTimeChecker<false>{};
7.
8. #define STATIC_ASSERT( expr, msg ) {                    \
9.   class ERROR_##msg{};                                  \
10.   (CompileTimeChecker< expr != 0 >( (ERROR_##msg()) )); \
11. }
Static_Assert.hpp

Matthias Brischwein 34
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Compile-time Assertions

Second refinement using the preprocessor's „past token“ ##


1. template<bool> struct CompileTimeChecker {
2.   // absorb error message if assertion is true
3.   CompileTimeChecker( ... );
4. };
5.
6. template<> struct CompileTimeChecker<false>{};
7.
8. #define STATIC_ASSERT( expr, msg ) {                    \
9.   class ERROR_##msg{};                                  \
10.   (CompileTimeChecker< expr != 0 >( (ERROR_##msg()) )); \
11. }
Static_Assert.hpp

Matthias Brischwein 35
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Compile-time Assertions

Second refinement using the preprocessor's „past token“ ##


1. template<bool> struct CompileTimeChecker {
2.   // absorb error message if assertion is true
3.   CompileTimeChecker( ... );
4. };
5.
6. template<> struct CompileTimeChecker<false>{};
7.
8. #define STATIC_ASSERT( expr, msg ) {                    \
9.   class ERROR_##msg{};                                  \
10.   (CompileTimeChecker< expr != 0 >( (ERROR_##msg()) )); \
11. }
Static_Assert.hpp

Matthias Brischwein 36
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Compile-time Assertions

Second refinement using the preprocessor's „past token“ ##


1. template<bool> struct CompileTimeChecker {
2.   // absorb error message if assertion is true
3.   CompileTimeChecker( ... );
4. };
5.
6. template<> struct CompileTimeChecker<false>{};
7.
8. #define STATIC_ASSERT( expr, msg ) {                    \
9.   class ERROR_##msg{};                                  \
10.   (CompileTimeChecker< expr != 0 >( (ERROR_##msg()) )); \
11. }
Static_Assert.hpp

Matthias Brischwein 37
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Compile-time assertions

1. #include "Static_Assert.hpp"
2.
3. STATIC_ASSERT(( Fibonacci<8>::value == 22 ), VALUE_MISMATCH );

src.cpp:4: error: no matching function for call to 
‘CompileTimeChecker<false>::CompileTimeChecker(
  main()::ERROR_VALUE_MISMATCH)’
Static_Assert.hpp:6: note: candidates are: 
CompileTimeChecker<false>::CompileTimeChecker()
… 
GCC 4.4.3

Matthias Brischwein 38
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Compile-time assertions

1. #include "Static_Assert.hpp"
2.
3. STATIC_ASSERT(( Fibonacci<8>::value == 22 ), VALUE_MISMATCH );

src.cpp:4: error: no matching function for call to 
Since C++11: static_assert(expr, msg)
‘CompileTimeChecker<false>::CompileTimeChecker(
  main()::ERROR_VALUE_MISMATCH)’
Static_Assert.hpp:6: note: candidates are: 
CompileTimeChecker<false>::CompileTimeChecker()
… 
GCC 4.4.3

► ►► Σ Matthias Brischwein 39
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Type Traits

Type Traits allow queries on types such as


 is_const<T>
 is_integralType<T>
 is_pointer<T>
 is_baseClassOf<Derived, Base>
 …

► ►► Σ Matthias Brischwein 40
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Type Traits

Very simple example: is_pointer<T>:


1. template<class U> struct is_pointer {
2.   static const bool value = false;
3. };
4.
5. // specialization
6. template<class U> struct is_pointer<U*>{
7.   static const bool value = true;
8. }

Matthias Brischwein 41
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Type Traits

What are type traits good for?


 Requirements on types
constrain generality of
algorithms

Matthias Brischwein 42
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Type Traits

What are type traits good for?


 Requirements on types
constrain generality of
algorithms
 Sometimes requirements can
be relaxed by providing templ.
specializations for certain types

covered by
specialization

Matthias Brischwein 43
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Type Traits

What are type traits good for?


 Requirements on types
constrain generality of
algorithms
 Sometimes requirements can
be relaxed by providing templ.
specializations for certain types
 Subsets of types may allow for
a more efficient implementation

Matthias Brischwein 44
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Type Traits

What are type traits good for?


 Requirements on types
Type Traits constrain generality of
algorithms
 provide information to select tmpl. specialization
 Requirements may can be
based on the type's properties (not on the
type itself) relaxed by providing templ.
specializations for certain types
 One tmpl. specialization for a whole family of
 Subsets of types may allow for
types
a more efficient implementation

► Σ Matthias Brischwein 45
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis

F = m*v
 What? N = kg*m*s-2 = kg*m*s-1 ??
→ We want to detect such errors before the code is sent to Mars

Can we statically check code for the validity of physical calculations?

 Dimensions are „types for numbers“


 Mul. / Div. of numbers requires Add. / Sub. of dimensions
→ Type computations

► Σ Matthias Brischwein 46
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis

According to SI standard (Systéme Internationale d' Units):


Every derived dimension can be expressed as combination of 7
fundamental dimensions:
 mass [kg]
 length [m]
 time [s]
 current [A]
 temperature [K]
 intensity [cd]
 amount of substance [mol]

Matthias Brischwein 47
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis

1. #include <boost/mpl/vector.hpp>
2. using namespace boost::mpl;
3.
4. // The seven fundamental physical dimensions
5. typedef vector<int_<1>, int_<0>, int_<0>, int_<0>, int_<0>,
6. int_<0>, int_<0> > _mass;
7.
8. typedef vector<int_<0>, int_<1>, int_<0>, int_<0>, int_<0>,
9. int_<0>, int_<0> > _length;
10.
11. …

 mpl::vector is a TMP-equivalent to std::vector


 Syntax is clumsy → use boost::mpl::vector_c

Matthias Brischwein 48
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis

1. #include <boost/mpl/vector_c.hpp>
2. namespace mpl = boost::mpl;
3.
4. // The seven fundamental physical dimensions
5. typedef mpl::vector_c<int, 1, 0, 0, 0, 0, 0, 0> _mass;
6. typedef mpl::vector_c<int, 0, 1, 0, 0, 0, 0, 0> _length;
7. typedef mpl::vector_c<int, 0, 0, 1, 0, 0, 0, 0> _time;
8. … 
9. typedef mpl::vector_c<int, 0, 0, 0, 0, 0, 0, 1> _substance;
10.
11. // Some composite dimension
12. typedef mpl::vector_c<int, 1, 1, ­2, 0, 0, 0, 0> _force;

Matthias Brischwein 49
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis

Class template quantity to associate value type with dimension


1. template<class V, class D>
2. struct quantity {
3.   quantity( V v ): v( v ) {}
4.
5.   V value() const { return v; }
6.    
7.   quantity<V, D>operator+( quantity<V, D> q ) {…}
8.   quantity<V, D>operator­( quantity<V, D> q ) {…}
9.
10.   quantity<V, ?>operator*( quantity<V, D2> q ) {…}
11.   quantity<V, ?>operator/( quantity<V, D2> q ) {…}
12. … 

Matthias Brischwein 50
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis

Class template quantity to associate value type with dimension


1. template<class V, class D>
2. struct quantity {
3.   quantity( V v ): v( v ) {}
4.
5.   V value() const { return v; }
6.    
7.   quantity<V, D>operator+( quantity<V, D> q ) {…}
8.   quantity<V, D>operator­( quantity<V, D> q ) {…}
9.
10.   quantity<V, ?>operator*( quantity<V, D2> q ) {…}
11.   quantity<V, ?>operator/( quantity<V, D2> q ) {…}
12. … 

Matthias Brischwein 51
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis

Addition of quantities is straight forward → no change of dimension


1. template<class V, class D>
2. struct quantity {
3.   quantity( V v ): v( v ) {}
4.
5.   V value() const { return v; }
6.    
7.   quantity<V, D>operator+( quantity<V, D> q ) {
8.     return quantity<V, D>( value() + q.value() ); 
9.   }
10.   quantity<V, D>operator­( quantity<V, D> q ) {…}
11.
12.   quantity<V, ?>operator*( quantity<V, D2> q ) {…}
13.   quantity<V, ?>operator/( quantity<V, D2> q ) {…}
14. … 

Matthias Brischwein 52
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis

Addition of quantities is straight forward → no change of dimension


1. template<class V, class D>
2. struct quantity {
3.   quantity( V v ): v( v ) {}
4.
5.   V value() const { return v; }
6.    
7.   quantity<V, D>operator+( quantity<V, D> q ) {…}
8.   quantity<V, D>operator­( quantity<V, D> q ) {…}
9.
10.   quantity<V, ?>operator*( quantity<V, D2> q ) {…}
11.   quantity<V, ?>operator/( quantity<V, D2> q ) {…}
12. … 

Matthias Brischwein 53
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis

Class template quantity to associate value type with dimension


1. template<class V, class D>
2. struct quantity {
3.   quantity( V v ): v( v ) {}
4.
5.   V value() const { return v; }
6.    
7.   quantity<V, D>operator+( quantity<V, D> q ) {…}
8.   quantity<V, D>operator­( quantity<V, D> q ) {…}
9.
10.   quantity<V, ?>operator*( quantity<V, D2> q ) {…}
11.   quantity<V, ?>operator/( quantity<V, D2> q ) {…}
12. … 

Matthias Brischwein 54
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis

Class template quantity to associate value type with dimension


1. template<class V, class D>
2. struct quantity {
3.   quantity( V v ): v( v ) {}
4.
5.   V value() const { return v; }
6.    
7.   quantity<V, D>operator+( quantity<V, D> q ) {…}
8.   quantity<V, D>operator­( quantity<V, D> q ) {…}
9.
10.   quantity<V, ?>operator*( quantity<V, D2> q ) {…}
11.   quantity<V, ?>operator/( quantity<V, D2> q ) {…}
12. … 

Matthias Brischwein 55
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis
Multiplication of different quantities is a bit more tricky
1. template<class V, class D>
2. struct quantity {
3.   quantity( V v ): v( v ) {}
4.
5.   V value() const { return v; }
6.    
7.   quantity<V, D>operator+( quantity<V, D> q ) {…}
8.   quantity<V, D>operator­( quantity<V, D> q ) {…}
9.
10.   template<class D2>
11.   quantity<V, typename mpl::transform<D, D2, plus_f>::type >
12.   operator*( quantity<V, D2> q ) {
13.     typedef typename mpl::transform<D, D2, plus_f>::type dim;
14.     return quantity<V, dim >(value() * q.value());
15.   }
16. … 

Matthias Brischwein 56
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis
Multiplication of different quantities is a bit more tricky
1. template<class V, class D>
2. struct quantity {
3.   quantity( V v ): v( v ) {}
4.
5.   V value() const { return v; }
6.    
7.   quantity<V, D>operator+( quantity<V, D> q ) {…}
8.   quantity<V, D>operator­( quantity<V, D> q ) {…}
9.
10.   template<class D2>
11.   quantity<V, typename mpl::transform<D, D2, plus_f>::type >
12.   operator*( quantity<V, D2> q ) {
13.     typedef typename mpl::transform<D, D2, plus_f>::type dim;
14.     return quantity<V, dim >(value() * q.value());
15.   }
16. … 

Matthias Brischwein 57
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis
Multiplication// metafunction class using metafunction forwarding
of different quantities is a bit more tricky
struct plus_f {
1. template<class V, class D>
2. struct quantity {
  template<class T1, class T2>
3.   quantity( V v ): v( v ) {}
  struct apply : mpl::plus<T1, T2> {};
4.
5.   V value() const { return v; }
};
6.    
7.   quantity<V, D>operator+( quantity<V, D> q ) {…}
8.   quantity<V, D>operator­( quantity<V, D> q ) {…}
9.
10.   template<class D2>
11.   quantity<V, typename mpl::transform<D, D2, plus_f>::type >
12.   operator*( quantity<V, D2> q ) {
13.     typedef typename mpl::transform<D, D2, plus_f>::type dim;
14.     return quantity<V, dim >(value() * q.value());
15.   }
16. … 

Matthias Brischwein 58
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis
Multiplication// metafunction class using metafunction forwarding
of different quantities is a bit more tricky
struct plus_f {
1. template<class V, class D>
2. struct quantity {
  template<class T1, class T2>
3.   quantity( V v ): v( v ) {}
  struct apply : mpl::plus<T1, T2> {};
4.
5.   V value() const { return v; }
};
6.    
7.   quantity<V, D>operator+( quantity<V, D> q ) {…}
8.   quantity<V, D>operator­( quantity<V, D> q ) {…}
9.
10.   template<class D2>
11.   quantity<V, typename mpl::transform<D, D2, plus_f>::type >
12.   operator*( quantity<V, D2> q ) {
13.     typedef typename mpl::transform<D, D2, plus_f>::type dim;
14.     return quantity<V, dim >(value() * q.value());
15.   } Elementwise metafunction application of plus_f
16. …  on the type-sequences of D and D2

Matthias Brischwein 59
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis
Multiplication of different quantities is a bit more tricky
1. template<class V, class D>
2. struct quantity {
3.   quantity( V v ): v( v ) {}
4.
5.   V value() const { return v; }
6.    
7.   quantity<V, D>operator+( quantity<V, D> q ) {…}
8.   quantity<V, D>operator­( quantity<V, D> q ) {…}
9.
10.   template<class D2>
11.   quantity<V, typename mpl::transform<D, D2, plus_f>::type >
12.   operator*( quantity<V, D2> q ) {
13.     typedef typename mpl::transform<D, D2, plus_f>::type dim;
14.     return quantity<V, dim >(value() * q.value());
15.   }
16. … 

Matthias Brischwein 60
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis
Multiplication of different quantities is a bit more tricky
1. template<class V, class D>
2. struct quantity {
3.   quantity( V v ): v( v ) {}
4.
5.   V value() const { return v; }
6.    
7.   quantity<V, D>operator+( quantity<V, D> q ) {…}
8.   quantity<V, D>operator­( quantity<V, D> q ) {…}
9.
10.   template<class D2>
11.   quantity<V, typename mpl::transform<D, D2, plus_f>::type >
12.   operator*( quantity<V, D2> q ) {
13.     typedef typename mpl::transform<D, D2, plus_f>::type dim;
14.     return quantity<V, dim >(value() * q.value());
15.   }
16. … 

Matthias Brischwein 61
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis
Multiplication of different quantities is a bit more tricky
1. template<class V, class D>
2. struct quantity {
3.   quantity( V v ): v( v ) {}
4.
5.   V value() const { return v; }
6.    
7.   quantity<V, D>operator+( quantity<V, D> q ) {…}
8.   quantity<V, D>operator­( quantity<V, D> q ) {…}
9.
10.   template<class D2>
11.   quantity<V, typename mpl::transform<D, D2, plus_f>::type >
12.   operator*( quantity<V, D2> q ) {
13.     typedef typename mpl::transform<D, D2, plus_f>::type dim;
14.     return quantity<V, dim >(value() * q.value());
15.   }
16. … 

Matthias Brischwein 62
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis

1. #include … // "dimensions"
2.
3. int main() {
4.   quantity< float, _mass > m( 3.0f );
5.   quantity< float, _acceleration > a( 2.0f );
6.
7.   quantity< float, _velocity> v = s / t;
8.   quantity< float, _force > f = m * a;
9.
10.   return 0;
11. }

Matthias Brischwein 63
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis

1. #include … // "dimensions"
2.
3. int main() {
4.   quantity< float, _mass > m( 3.0f );
5.   quantity< float, _acceleration > a( 2.0f );
6.
7.   quantity< float, _velocity> v = s / t;
8.   quantity< float, _force > f = m * a;
9.
10.   return 0;
11. }
One thing remains:
To make assignment work,
a form of static cast is to be
implemented (see Abrahams et. al.)

Matthias Brischwein 64
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS

Further applications for TMP:


 Domain Specific Embedded Languages (DSEL)
(Boost.Spirit provides a DSEL for writing EBNF descriptions within C++)
 Generative Programming
(static assembly of software product lines from generic components)
 Static Interface Checking
(e.g. boost Concept Check)
 Expression Templates

Σ Matthias Brischwein 65
THE boost::mpl LIBRARY
TEMPLATE METAPROGRAMMING (TMP) C++
THE boost::mpl LIBRARY

 Part of boost libraries since release 1.30.0


 Provides basic compile-time data structures and algorithms very
similiar to STL for runtime programs

1..n realizes 1..m
Sequence Concepts Forward Vector
List
Random Access
Deque
Iterator Concepts Front Extensible Set
Back Extensible Map
Algorithms … ...

Matthias Brischwein 67
TEMPLATE METAPROGRAMMING (TMP) C++
THE boost::mpl LIBRARY

 Part of boost libraries since release 1.30.0


 Provides basic compile-time data structures and algorithms very
similiar to STL for runtime programs

Sequence Concepts
Forward
Iterator Concepts Random Access
Bidirectional
Algorithms

Matthias Brischwein 68
TEMPLATE METAPROGRAMMING (TMP) C++
THE boost::mpl LIBRARY

 Part of boost libraries since release 1.30.0


 Provides basic compile-time data structures and algorithms very
similiar to STL for runtime programs

front_inserter
Sequence Concepts
Inserters back_inserter

Iterator Concepts Transform. Algos. copy


sort
Querying Algos.
Algorithms ... find
contains
...

Matthias Brischwein 69
TEMPLATE METAPROGRAMMING (TMP) C++
THE boost::mpl LIBRARY

 Part of boost libraries since release 1.30.0


 Provides basic compile-time data structures and algorithms very
similiar to STL for runtime programs

1. #include <boost/mpl.hpp>
2. #include <boost/mpl/vector_c.hpp>
3.
4. namespace mpl = boost::mpl;
5. typedef mpl::vector_c<int,3,4,0,­5,8,­1,7> numbers;
6. typedef mpl::vector_c<int,­5,­1,0,3,4,7,8> expected;
7. typedef mpl::sort<numbers>::type result;
8.
9. BOOST_MPL_ASSERT(( mpl::equal<result, expected> ));

Matthias Brischwein 70
SUMMARY
TEMPLATE METAPROGRAMMING (TMP) C++
SUMMARY

TMP enables
+ more expressive code (i.e. fibonacci<8> vs. „magic number“ 21)
+ higher quality code (i.e. static checks)
+ more efficient, generic and configurable „active“ libraries

… at the price of
- very hard to read and understand C++ code
 Recent efforts to decorate TMP syntax behind a Haskell like interface
- partial incompatibilities with different compilers
- in case of errors, often cryptic or even misleading compiler messages (if at all)
- lacking debugging facilities

Matthias Brischwein 72
TEMPLATE METAPROGRAMMING (TMP) C++
SUMMARY

 C++ Template mechanism is Turing complete


 TMP follows pure functional programming paradigm
 Basic Concepts:
 Metafunctions
 Metafunction classes
 Full/Partial Template Specialization
 Boost::mpl – the STL for compile-time programmers
 Not covered:
 Details of type sequences
 Lambda expressions
 Placeholder expressions
 …

Matthias Brischwein 73
TEMPLATE METAPROGRAMMING (TMP) C++

Run-Time Compile-Time
OOP FP

74
Thank you for you attention!
Questions are welcome
TEMPLATE METAPROGRAMMING C++
FURTHER READING

 D. Abrahams, A. Gurtovoy: C++ Template Metaprogramming. 1st Edt. Boston: Addison-Wesley


Professional, 2004.
 D. Abrahams, A. Gurtovoy: The Boost MPL library.
http://www.boost.org/doc/libs/1_49_0/libs/mpl/doc/index.html, 26 May 2012.
 A. Alexandrescu: Modern C++ Design. 1st Edt. Boston: Addison-Wesley Professional, 2001.
 K. Czarnecki et. al.: Generative Programming and Active Libraries. In: Generic Programming,
Bd. 1766, M. Jazayeri, R. G. K. Loos, und D. R. Musser, Hrsg. Berlin, Heidelberg: Springer Berlin
Heidelberg, 2000, S. 25–39.
 Z. Porkoláb: Functional Programming with C++ Template Metaprograms. In: Central
European Functional Programming School, Bd. 6299, Z. Horváth, R. Plasmeijer, und V. Zsók,
Hrsg. Berlin, Heidelberg: Springer Berlin Heidelberg, 2010, S. 306–353.
 T. Veldhuizen: C++ Templates are Turing complete. 2003.
 „Lambda calculus - Wikipedia, the free encyclopedia“, Wikipedia, 29-Dez-2012. [Online].
Available: https://en.wikipedia.org/w/index.php?title=Lambda_calculus&oldid=494886590.
[Accessed: 29-Mai-2012].

You might also like