<<

++ Meta Programming

Introduction C++ Template Meta Programming Template Metaprogram- ming

A Bad Francesco Nidito Example A Good Example

Conclusions Programmazione Avanzata AA 2005/06 Outline

C++ Template Meta Programming 1 Introduction

Introduction 2 Template Template Metaprogram- ming

3 A Bad Example A Bad Example

A Good 4 A Good Example Example Conclusions 5 Conclusions

Reference: K. Czarnecki, U. W. Eisenecker, “Generative Programming: Methods, Tools, and Applications”, Chapter 10 What Is Template Metaprogramming?

C++ Template Meta Programming

Introduction

Template At this moment is quite difficult to give a definition. First Metaprogram- ming define two terms: A Bad Template Example Metaprogramming A Good Example

Conclusions What Are Templates?

C++ Template Meta Programming

Templates are a C++ technique to create Generic Code Introduction Template Some templates are in C++ Standard and can be found in Metaprogram- STL ming A Bad The first version of STL architecture was made by Example A Good Alexander Stepanov Example Some examples of templates in STL are: std::vector, Conclusions std::map and std::list C++ Templates Example: Very Simple Array

C++ Template Meta template Programming class VerySimpleArray{

T a[L]; Introduction

public: Template Metaprogram- VerySimpleArray(){ ming

for(int i=0; i < L; ++i) a[i] = T(); A Bad } Example A Good T& Get(unsigned int i){return a[i];} Example void Set(unsigned int i, T& v){a[i] = v;} Conclusions };

VerySimpleArray vsa; vsa.Set(3, 6.0); C++ Templates Example: Template specialization

C++ Template template > Meta class vector : protected _Vector_base<_Tp, _Alloc> Programming { __glibcpp_class_requires(_Tp, _SGIAssignableConcept) Introduction Template Metaprogram- typedef _Vector_base<_Tp, _Alloc> _Base; ming

... A Bad template Example class vector: public _Bvector_base<_Alloc> A Good Example { Conclusions public: typedef bool value_type; ...

/usr/include/c++/3.3.2//std vector.h /usr/include/c++/3.3.2/bits/std bvector.h What Is Metaprogramming?

C++ Template Meta Metaprogramming means writing programs that can Programming modify other programs or themselves The modification can happen at run time or at compile Introduction Template time Metaprogram- ming

Compilers are an example of metaprograming: they take a A Bad program in an input language (C, Java...) and produce Example A Good another program (with same semantic) in an output Example

language (machine code, ... ) Conclusions Metaprograms have three advantages: Produce code quickly Lift abstraction Produce correct code (if the metaprogram is correct) What Is Template Metaprogramming?

C++ Template Meta Programming

Introduction Now it is time for the replay, Template Metaprograming Template Metaprogram- is... ming A Bad Producing metaprograms in C++ using templates Example But... wait a second... why do I need Template A Good Example Metaprogramming? Conclusions The Need For Speed

C++ Template int Fact(int x){ Meta Programming int acc = 1;

for(;x>0;--x) acc*=x; Introduction

return acc; Template Metaprogram- } ming

A Bad int a, b; Example A Good a = read_int_from_stdin(); Example

b = Fact(a); //we compute at run time Conclusions ... b = Fact(5); //we can compute at compile //time but we do not

We pay the time to compute something that is a constant! Naive Solution

C++ ... Template Meta Programming b = 120; //b = Fact(5); Introduction

Template The solution is not elegant. We need to place a lot Magic Metaprogram- ming Numbers in the code. And the magic number does not keep its A Bad meaning (5! = 120 or 42 + 78 = 120 ...). Example We can use a but it is not better: we must provide a A Good #define Example

define for all possible value of the input of Fact. Conclusions ... #define FACT_4 (24) #define FACT_5 (120) ...

b = FACT_5; Template Metaprogramming Solution

C++ Template Meta Programming The general idea is to use the to do some computation at . Introduction Template To do this we need a only a C++ compiler that provides Metaprogram- ming Templates A Bad This can be done because the compiler, when compiles Example A Good Templates, produces code Example If we produce the right code (e.g. the sum of constant Conclusions terms), the compiler optimize and do constant folding But we can do more... First Step

C++ Template Meta Programming

template< int i> Introduction

struct C { Template Metaprogram- enum { RES = i }; ming

}; A Bad Example

A Good cout <<_ C<2>::RES; Example

Conclusions

C<2>::RES is substituted by the compiler with 2: it is a cost ant and we can optimize. Back To Factorial

C++ Template Meta template Programming struct Fact {

enum { RET = n * Fact::RET }; Introduction

}; Template Metaprogram- ming

template<> A Bad struct Fact<1> { Example A Good enum { RET = 1 }; Example }; Conclusions

int b = Fact<5>::RET; // == 120

To do computation we must unroll templates: a kind of recursion Where is The Trick?

C++ Template Meta Programming

enum { RET = 5 * Fact<4>::RET }; Introduction

enum { RET = 5 * 4 * Fact<3>::RET }; Template Metaprogram- enum { RET = 5 * 4 * 3 * Fact<2>::RET }; ming

enum { RET = 5 * 4 * 3 * 2 * Fact<1>::RET }; A Bad enum { RET = 5 * 4 * 3 * 2 * 1 }; Example A Good enum { RET = 120 }; Example

Conclusions b = 120; //Fact<5>::RET; C++ Template Metaprogramming Operators

C++ Template Meta Programming template struct IF { Introduction Template typedef T RET; Metaprogram- }; ming A Bad Example template A Good Example struct IF { Conclusions typedef E RET; }; C++ Template Metaprogramming Operators

C++ Template Meta class CopyingGC { Programming public: void Collect() /*...*/ Introduction Template }; Metaprogram- ming

A Bad class MarkAndSweepGC { Example

public: A Good void Collect() /*...*/ Example }; Conclusions

IF::RET gc; gc.Collect(); C++ Template Metaprogramming Functions

C++ Template Meta Programming

Introduction Template Template struct Max { Metaprogram- ming enum { RET = (n1 > n2) ? n1 : n2 }; A Bad }; Example A Good Example _ cout << Max<42, 6>::RET; //prints 42 Conclusions C++ Template Metaprogramming Code Generation

C++ inline int Power(const int x, int n){ Template Meta int p = 1; Programming for(;n>0; --n) p *= x; return p; Introduction } Template Metaprogram- ming

A Bad We can specialize Power code for particular cases: Example A Good inline int Power3(const int x){ Example int p = 1; Conclusions p *= x; p *= x; p *= x; return p; } C++ Template Metaprogramming Code Generation

C++ template Template Meta inline int Power(const int x){ Programming return Power(x) * x; } Introduction Template Metaprogram- template<> ming A Bad inline int Power<1>(const int x){ Example

return 1; A Good } Example Conclusions template<> inline int Power<0>(const int x){ return 1; }

cout <<_ Power<4>(m); C++ Template Metaprogramming Code Generation

C++ Template _ Meta cout << Power<4>(m); Programming

_ cout << Power<3>(m) * m; Introduction

Template Metaprogram- cout <<_ Power<2>(m) * m * m; ming

A Bad cout <<_ Power<2>(m) * m * m * m; Example A Good Example cout <<_ Power<1>(m) * m * m * m * m; Conclusions

cout <<_ 1 * m * m * m * m;

cout <<_ m * m * m * m; C++ Template Metaprogramming (1)

C++ Template Meta Programming template struct FOR { Introduction static void loop(int m) { Template for (int i = 0; i < m/n; i++) { Metaprogram- ming UNROLL::iteration(i * n); A Bad } Example A Good for (int i = 0; i < m%n; i++) { Example

B::body(n * m/n + i); Conclusions } } }; C++ Template Metaprogramming Loop Unrolling(2)

C++ Template Meta template Programming struct UNROLL{ static void iteration(int i) { Introduction Template B::body(i); Metaprogram- UNROLL::iteration(i + 1); ming A Bad } Example

}; A Good Example template Conclusions struct UNROLL<0, B> { static void iteration(int i){ } }; C++ Template Metaprogramming Code Generation

C++ Template Meta Programming

Introduction

We can generate code for multiple purposes: Template Metaprogram- Vector operations ming

Math functions A Bad ... Example A Good Exercise: try to write some C++ Template Example

Metaprograming functions and control structures (WHILE) Conclusions C++ Template Metaprogramming Structures

C++ Template Meta Programming

Introduction Lisp lovers know very well this code: Template Metaprogram- (cons 1 (cons 2 (cons 3 (cons 4 (cons nil)))) ming A Bad The previous code represents the list: Example

(1 2 3 4) A Good Example C++ Template Metaprogrammers have this too... Conclusions C++ Template Metaprogramming Data Structures

C++ Template Meta template Programming struct Cons { enum { item = n }; Introduction typedef T next; Template Metaprogram- }; ming A Bad struct Nil { }; Example

A Good typedef Cons<1, Cons<2, Nil()> > V; Example //V::item == 1; Conclusions //V::next::item == 2; //V::next::next == Nil;

Exercise: try to create a Tree Total Loop Unroll

C++ Template Meta Programming

Introduction

Template We want to copy all elements of an int array into another Metaprogram- ming

We want to do it fast A Bad Example We can use an approach similar to FOR template A Good metastructure Example Conclusions Total Loop Unroll (C++ Code 1)

C++ Template Meta Programming template inline void Copy(int n, int* from, int* to){ Introduction Template for (int i = 0; i < n/N; ++i) { Metaprogram- TMP_COPY_UNROLL::iteration(i * N, from, to);ming A Bad } Example for (int i = 0; i < n%N; ++i) { A Good Example *to++ = *from++; Conclusions } } Total Loop Unroll (C++ Code 2)

C++ Template template Meta struct TMP_COPY_UNROLL { Programming static void iteration(int i, int *f, int* t){ *t++ = *f++; Introduction Template TMP_COPY_UNROLL::iteration(i + 1, f, t); Metaprogram- } ming A Bad }; Example

A Good template <> Example Conclusions struct TMP_COPY_UNROLL<1> { static void iteration(int i, int* f, int* t){ *t++ = *f++; } }; Performance Results

C++ Template Meta We measure the “ Time” of various values of Programming unroll and...... surprise Introduction Template # Loop Unroll Execution Time Metaprogram- 1 3.16 ming A Bad 10 1.79 Example 50 2.23 A Good Example 100 2.70 Conclusions 500 2.81 1000 2.84 2000 4.83 5000 19.48 Performance Results (Chart)

C++ Template Meta Programming 19.48

Introduction

Template Metaprogram- ming

A Bad Example

A Good Example

Conclusions 3.16

1.79 Performance Results (An Explanation)

C++ Template Meta Programming

Introduction

Template Why? Metaprogram- ming

Loop unroll produce very big files A Bad Big executable files cannot be kept in the code cache Example A Good We have a lot of cache misses Example Conclusions .MPL

C++ Template Meta Programming Meta Programming is part of Boost library

Boost is a portable C++ library that provides a big Introduction number utilities: Template Metaprogram- Threads ming

Containers A Bad Math Example I/O A Good Example Much more (circa 70 sub libraries)... Conclusions “The Boost.MPL library is a general-purpose, high-level C++ template metaprogramming framework of compile-time , sequences and metafunctions” Boost.MPL (Example)

C++ Template Meta Programming typedef list_c::type numbers; typedef list_c::type answer; Introduction typedef copy_if, ming push_back<_1,_2>, A Bad Example less<_1,int_<5> > A Good >::type result; Example Conclusions BOOST_STATIC_ASSERT(size::value == 5); BOOST_STATIC_ASSERT((equal::type::value)); Conclusions

C++ Template Meta Programming

Introduction C++ template metaprogramming is a powerful method to Template do computational tasks at compile time Metaprogram- ming

First approach is not very easy A Bad Example Some lib is present (general, matrix/math...) A Good Must be careful on compile errors (the templates tree is Example unrolled!) Conclusions