Professional Documents
Culture Documents
7 Template Metaprogramming
7 Template Metaprogramming
METAPROGRAMMING C++
Matthias Brischwein - matthias.brischwein@studium.uni-erlangen.de
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
Matthias Brischwein 5
TEMPLATE METAPROGRAMMING C++
Matthias Brischwein 6
TEMPLATE METAPROGRAMMING C++
Run-Time Compile-Time
OOP FP
Matthias Brischwein 7
TEMPLATE METAPROGRAMMING (TMP) C++
MOTIVATION
Matthias Brischwein 8
TEMPLATE METAPROGRAMMING (TMP) C++
MOTIVATION
Matthias Brischwein 9
TEMPLATE METAPROGRAMMING (TMP) C++
MOTIVATION
Matthias Brischwein 10
TEMPLATE METAPROGRAMMING (TMP) C++
MOTIVATION
Matthias Brischwein 11
TEMPLATE METAPROGRAMMING (TMP) C++
MOTIVATION
Matthias Brischwein 12
TEMPLATE METAPROGRAMMING (TMP) C++
MOTIVATION
Matthias Brischwein 13
TEMPLATE METAPROGRAMMING (TMP) C++
MOTIVATION
Matthias Brischwein 14
TEMPLATE METAPROGRAMMING (TMP) C++
MOTIVATION
Matthias Brischwein 15
TEMPLATE METAPROGRAMMING (TMP) C++
MOTIVATION
Matthias Brischwein 16
TEMPLATE METAPROGRAMMING (TMP) C++
MOTIVATION
Matthias Brischwein 17
TEMPLATE METAPROGRAMMING (TMP) C++
MOTIVATION
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
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
1. template<class OP1, class OP2> struct metaFun {
2. typedef typename plusMetaFun<OP1,OP2>::type type;
3. };
Matthias Brischwein 22
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 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
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
Matthias Brischwein 26
TEMPLATE METAPROGRAMMING (TMP) C++
BASIC CONCEPTS – Metafunction forwarding
Matthias Brischwein 27
TEMPLATE METAPROGRAMMING (TMP) C++
BASIC CONCEPTS – Metafunction forwarding
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
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
1. #define STATIC_ASSERT(expr){ char unnamed[(expr) ? 1 : 0]; }
Matthias Brischwein 32
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Compile-time Assertions
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
Matthias Brischwein 34
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Compile-time Assertions
Matthias Brischwein 35
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Compile-time Assertions
Matthias Brischwein 36
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Compile-time Assertions
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
► ►► Σ Matthias Brischwein 40
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Type Traits
Matthias Brischwein 41
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Type Traits
Matthias Brischwein 42
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Type Traits
covered by
specialization
Matthias Brischwein 43
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Type Traits
Matthias Brischwein 44
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Type Traits
► Σ 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
► Σ Matthias Brischwein 46
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis
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. …
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
Matthias Brischwein 50
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis
Matthias Brischwein 51
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis
Matthias Brischwein 52
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis
Matthias Brischwein 53
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis
Matthias Brischwein 54
TEMPLATE METAPROGRAMMING (TMP) C++
APPLICATIONS – Dimensional Analysis
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
Σ Matthias Brischwein 65
THE boost::mpl LIBRARY
TEMPLATE METAPROGRAMMING (TMP) C++
THE boost::mpl LIBRARY
Matthias Brischwein 67
TEMPLATE METAPROGRAMMING (TMP) C++
THE boost::mpl LIBRARY
Sequence Concepts
Forward
Iterator Concepts Random Access
Bidirectional
Algorithms
Matthias Brischwein 68
TEMPLATE METAPROGRAMMING (TMP) C++
THE boost::mpl LIBRARY
front_inserter
Sequence Concepts
Inserters back_inserter
Matthias Brischwein 69
TEMPLATE METAPROGRAMMING (TMP) C++
THE boost::mpl LIBRARY
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
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