Class 20 C++ template metaprogramming

Document Sample
Class 20  C++ template metaprogramming Powered By Docstoc
					      Class 20 – C++ template
         metaprogramming
- Work of Todd Veldhuizen and others
- Using C++ template system to do compile-
  time calculations
- Using C++ template system to do compile-
  time code generation (partial evaluation)
     Remaining class schedule

4/11 – Template metaprogramming
4/13 – FFTW
4/18 – Stratego
4/20, 4/25 – Type systems for program
  generation
4/27 – Paper presentation by Peter
5/2 – Wrap-up
Date to be chosen – project presentations
            Outline of class

- Review C++ template system
- Compile-time calculations
- Compile-time code generation (partial
  evaluation)
- Compile-time lists
Crucial features of C++ templates

1.   Templated classes and functions
2.   Pattern-matching in template instantiation
3.   The inline keyword
4.   Enumerated types
5.   The C++ scope operator
 Templated classes and functions
Definitions:
template <typename t, int i>
class C { t item; C next; ... use t as type, i as
                              int constant ...}
template <typename t>
t* f(t* a) { ... use t as type ... }


Uses:
C<float, 4> aC;
C<C<float,4>, 2> aWeirdValue;
... f(&n) ...   // template argument inferred
... f<double>(0.5) ... // template argument supplied
     Pattern-matching in template
             instantiation
Definitions:
 template <int i>
 void f(int x) { ... i ... }
 template <>
 void f<0>(int x) { ... }


Note handling of recursion:
 template <int i>
 void f(int x) { ... f(x-1) ... f<i-1>(...) ... }


Works the same for type parameters, and for
  templated classes.
        Enumerated types
enum {mon, tues, wed, thurs}
enum {mon=2, tues=7, wed=5, thurs=4}




        Scope operator (::)
class C {
   static int x;
   enum {mon=2, tues=7, wed=5, thurs=4}
   typedef int Cint;
}
... C::x ... C::mon ...
C::cint x = 3;
       Compile-time calculations
Calculate power function at compile time, such that
you can write:
const int z = ctime_pow<5,3>::result; // z=125
template<int x, int y>
struct ctime_pow {
   static const int result = x*ctime_power<x,y-1>::result;
}
template<int x>
struct ctime_pow<x,0> {
   static const int result = 1;
}
         Compile-time code gen
Almost correct version:
template<int i>
inline float meta_dot(float* a, float* b){
   return meta_dot<i-1>(a,b) + a[i]*b[i];
}
template<>
inline float meta_dot<0>(float* a, float* b){
   return a[0]*b[0];
}
Use:
float z = meta_dot<2>(x, y)
Produces code equivalent to
  z = x[0]*y[0] + x[1]*y[1] + x[2]*y[2];
        Compile-time code gen
Correct version:
 template<int i> class meta_dot {
   inline float f(float* a, float* b){
    return meta_dot<i-1>::f(a,b) + a[i]*b[i];
 }}
 template<> class meta_dot<0> {
   inline float f(float* a, float* b){
    return a[0]*b[0];
 }
 Use:
 float z = meta_dot<2>::f(x, y)
 Produces code equivalent to
    z = x[0]*y[0] + x[1]*y[1] + x[2]*y[2];
        Compile-time code gen
Bigger example: Bubble sort. The following code
generates a fully unrolled bubble sort:
template<int n> class BubbleSort {
  static inline void sort (int* data) {
     BubbleSortLoop<n-1,0>::loop(data);
     BubbleSort<n-1>::sort(data);
   }
};
template<> class BubbleSort<1> {
   static inline void sort(int* data) {}
};
        Compile-time code gen
template<i,j> class BubbleSortLoop {
   enum {go = (j<=i-2)} ;
   static inline void loop(int* data) {
     Swap<j,j+1>::compareAndSwap(data);
     BubbleSortLoop<go?i:0, g?j+1:0>::loop(data);
   }
}
template<> class BubbleSortLoop<0,0> {
   static inline void loop(int*) {}
}
template<i,j> class Swap {
   static inline void compareAndSwap(int* data){
      if (data[i] > data[j]) swap(data[i], data[j]);
   }
}
           Compile-time lists
struct empty {};
template<typename Head, typename Tail>
struct node {
   typedef Head hd;
   typedef Tail tl;
}
typedef node<int, node<char, node<char, empty>>> list1;
typedef node<float, node<char, empty>> list2;




Pattern-matching and recursion allow us to write
ordinary list operations:
           Compile-time lists
template<typename T1, typename T2>
struct concat {
   typedef node<typename T1::hd,
                concat<typename T1::tl, T2>::type> type;
}
template<T2>
struct concat<empty, T2> { typedef T2 type; }
typedef concat<list1, list2> list3;
template<typename T> struct length {
   enum {leng = length<T.tl>::leng+1};
}
template<> struct length<empty> {
   enum {leng = 0};
}
int t3leng = length<list3>.leng;   // assigns 5

				
DOCUMENT INFO