An Introduction to Meta-
      programming

Unleashing the power of C++ Templates
Why Meta-Programming?




                        2
Introduction
Generic programming becoming a dominant
paradigm in C++
The unexplored power of functional programming
langua...
Generic Programming
Early 90s when templates were used for
container<T>
STL
How standardization helped
Design patterns
  ...
Functional programming
Functional programming is there for a long time
   Lambda calculus, Lisp, Scheme, Haskell…
   fun...
Abstraction, Design and
Reusability
The much hyped ‘component software’
   ‘Plug-and-play’ software
Design Patterns
   T...
Program Generating Programs

That is what TMP is all about
Template is not the code that executes
   Generates the code t...
Efficiency
Templates can be unimaginably powerful and
efficient
Execution is moved on to compile-time
   The compiler doe...
Template (tricky) Basics




                           9
Parameterized Types

Templates started Stroustrup’s desire to
provide quot;parameterized typesquot; for
containers.
A simp...
“Parameterized” Stack
template <class T>
class stack{
   stack(int start_size = 10);
   int is_empty() const;
   int is_fu...
Comparing with Java example
  Making use of Object base class
      Not type safe – the single biggest problem Java
     ...
Templates for Reusable
Components
An example: Making classes non-inheritable
C++ has no equivalent of Java's final
   (fo...
Example: ‘Plain’ Code
class Usable;
struct Usable_lock {
       friend class Usable;
   private:
       Usable_lock(){}
  ...
Example: ‘Plain’ Code …
 Usable a;

 class DD : public Usable { };

 DD dd;
// error: DD::DD() cannot access
// Usable_loc...
Example: ‘Templatized’ Code
template <typename T> struct nonderivable;

template< class T > class nonderivable_base{
     ...
Example: ‘Templatized’ Code …
class Test: nonderivable <Test> {};

Test t;
// okay, you can create objects

class Deri: Te...
Template Template Parameters

One of the interesting properties of
templates
   parameter can be an instantiation of the ...
Template Template Parameters
  …
template <
    typename type,
   template <typename T, typename A>
       class container...
Template Template P arameters …


   In many cases, you can live without it.
   For example,std <stack> container
   names...
Meta-Programming




                   21
How it started?
Started with a mistake which led to infinite
recursion in instantiating templates
Initial examples seem si...
Serendipity
  Infinite instantiation:
template <int n>
struct Factorial {
   static const int val =
             n * Facto...
Adding Terminating Condition
template <int n>
struct Factorial {
   static const int val = n * Factorial<n-1>::val;
};

te...
Programming Constructs

Metaprograms can be thought in terms of
productions (just like recursive programs).
Implementing p...
Template for If-Then
One example: Representing If-Then-Else
condition
   How to select a class member type based on a
   ...
Template for If-Then
template <typename T, bool isSigned>
struct myMemberSignTrait{
  typedef signed T signType;
}; // sel...
Template for If-Then
template <typename T, bool isSigned>
class myContainer {
   typedef myMemberSignTrait<T, isSigned>
  ...
Improved If-Then
  Not elegant to extend (not scalable)
  Better to have a separate template class for
  doing such a sele...
Improved If-Then
template <typename T, bool isSigned>
class myContainer {
   typedef typename if_select<signed T, unsigned...
Still better If-Then
template <bool isSigned>
struct if_cond {
   template<typename T, typename F>
   struct then_select {...
Still better If-Then
template <typename T, bool isSigned>
class myContainer {
   typedef typename if_cond<isSigned>::templ...
Usage Example – if_select
class CompactingGC {
   void GC() { … }
};
class MarkAndSweepGC {
   void GC() { … }
};

If_cond...
Another Example- isPointer
template <typename T>
class type_traits{
   template <class U> struct pointer_traits{
       st...
Application
of meta-programming




                      35
Conversion Check Tool
template <class T, class U>
class Conversion{
   typedef char Small;
   class Big { char dummy[2]; }...
Unrolling vector addition
inline void addVect(int size, double* a, double* b,
  double* c) {
  while (size--)
    *c++ = *...
Template Unrolling
template<int size>
inline void addVect(double* a, double* b,
  double* c) {
   *c = *a + *b;
   addVect...
Effect of unrolling
addVect<3>(a, b, c);
 *c = *a + *b;
 addVect<2>(a+1, b+1, c+1);
    *(c+1) = *(a+1) + *(b+1);
    addV...
Dot Product
template <int DIM, typename T>
struct DotProduct {
   static T result (T* a, T* b){
   return *a * *b +
      ...
Dot Product
template <int DIM, typename T>
inline T dot_product (T* a, T* b) {
  return DotProduct<DIM,T>::result(a,b);
}
...
For Loop Unrolling
template<int n, class B>
struct FOR {
   static void loop(int m) {
       for (int i = 0; i < m/n; i++)...
Loop Unrolling …
template <int n, class B>
struct UNROLL {
   static void iteration(int i) {
       B::body(i);
       UNR...
Meta-programming
    Libraries




                   44
Loki
By Andrei Alexaderescu
“Modern C++ Design” book Covers in Detail
Important components:
   Small object allocator
  ...
Boost
Major and wildly growing library
Compatible with STL
Important components:
   Regex
   Threads
   Typetraits
   ...
Future of
Meta-programming




                   47
Future Looks Rosy
Templates as a means for reusable and adaptive
software
Generic programming
   poised to become dominan...
But it won’t be easy

Using templates have their own problems
 Generic programming is inherently difficult in
  nature
 ...
Upcoming SlideShare
Loading in …5
×

Metaprogramming

1,962 views

Published on

Published in: Technology, Business
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,962
On SlideShare
0
From Embeds
0
Number of Embeds
6
Actions
Shares
0
Downloads
54
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Metaprogramming

  1. 1. An Introduction to Meta- programming Unleashing the power of C++ Templates
  2. 2. Why Meta-Programming? 2
  3. 3. Introduction Generic programming becoming a dominant paradigm in C++ The unexplored power of functional programming languages Higher levels of abstraction, design and reusability A code-generation mechanism (programs that generate programs!) Greater efficiency on what can be found at compile-time 3
  4. 4. Generic Programming Early 90s when templates were used for container<T> STL How standardization helped Design patterns  The ability for templates to model many design patterns directly Idea of meta-programming possibility  Boost  Loki  Other libraries 4
  5. 5. Functional programming Functional programming is there for a long time  Lambda calculus, Lisp, Scheme, Haskell…  functions are treated as regular values Functional programming advantages  Idioms, patterns and techniques Polymorphic “higher-order” functions  Functions that take other functions as arguments and returns functions! The ‘lambda’ thing  Creating functions ‘on-the-fly’ is very common TMP is inspired by functional programming 5
  6. 6. Abstraction, Design and Reusability The much hyped ‘component software’  ‘Plug-and-play’ software Design Patterns  The GoF (Gang of Four) ‘Design Patterns’ book  Elements of reusable software  Language independent Library as the basis of reusable software (as opposed to frameworks) The proverbial ‘adding a level of indirection’ as a means for better reusable components 6
  7. 7. Program Generating Programs That is what TMP is all about Template is not the code that executes  Generates the code that will do the actual work Abstract the details  Select the behavior  Instruct the components you want to generate Evaluate whatever is possible at compile- time 7
  8. 8. Efficiency Templates can be unimaginably powerful and efficient Execution is moved on to compile-time  The compiler does the work for you instead of the program! Higher levels of abstraction, design and reusability A code-generation mechanism (programs that generate programs!) Greater efficiency on what can be found at compile-time 8
  9. 9. Template (tricky) Basics 9
  10. 10. Parameterized Types Templates started Stroustrup’s desire to provide quot;parameterized typesquot; for containers. A simple example would be a stack: 10
  11. 11. “Parameterized” Stack template <class T> class stack{ stack(int start_size = 10); int is_empty() const; int is_full() const; // these members remain the same void push(const T& t); T& pop(); // templatizing the required members private: T* stack; // Note T* here int top_of_stack; int size; }; 11
  12. 12. Comparing with Java example Making use of Object base class  Not type safe – the single biggest problem Java programmers face after performance issues “Generic types” for typesafety – not for genericity per se class Stack<Type> { public void push(Type t){ /* … */ } public Type pop() { /*... */ } private int topOfStack; private int size = 10; T stack []; { stack = new stack[size]; } } Similarity of C++ templates and Java generics end here! 12
  13. 13. Templates for Reusable Components An example: Making classes non-inheritable C++ has no equivalent of Java's final  (for class non-inheritable classes) You can make destructor of base class private  disallows creating objects (except in heap) Disadvantage: imposes constraints  on kind of type of allocation being done. 13
  14. 14. Example: ‘Plain’ Code class Usable; struct Usable_lock { friend class Usable; private: Usable_lock(){} // copy ctr also private }; struct Usable : public virtual Usable_lock{ Usable(); // copy ctr also public // ... }; 14
  15. 15. Example: ‘Plain’ Code … Usable a; class DD : public Usable { }; DD dd; // error: DD::DD() cannot access // Usable_lock::Usable_lock() // which is a private member 15
  16. 16. Example: ‘Templatized’ Code template <typename T> struct nonderivable; template< class T > class nonderivable_base{ friend T; // warning, this is non-standard! friend class nonderivable<T>; nonderivable_base(){} nonderivable_base(const nonderivable_base&){} }; template <typename T> struct nonderivable: public virtual nonderivable_base<T>{}; 16
  17. 17. Example: ‘Templatized’ Code … class Test: nonderivable <Test> {}; Test t; // okay, you can create objects class Deri: Test{}; // no, you can't inherit & use the object Deri d; // Error, in-accessible base class constructor. //See, compiler won't allow you to do so. 17
  18. 18. Template Template Parameters One of the interesting properties of templates  parameter can be an instantiation of the same template. For example, vector < vector<int> > Template Template provide next level of abstraction  The template (not its instance) itself can become an argument 18
  19. 19. Template Template Parameters … template < typename type, template <typename T, typename A> class container = std::vector, // default is vector if you don’t provide one explicitly typename allocator = std::allocator<type> > class my_container { container<type, allocator> _container; //instantiate template template parameter }; // instantiation of my_container my_container<int, std::list> container; 19
  20. 20. Template Template P arameters … In many cases, you can live without it. For example,std <stack> container namespace std { template <class T, class Container = deque<T> > class stack; } Another example is allocator used for containers namespace std { template <class T, class Allocator = allocator<T> > class vector; } 20
  21. 21. Meta-Programming 21
  22. 22. How it started? Started with a mistake which led to infinite recursion in instantiating templates Initial examples seem simple and for fun  But has appeal for serious design and industrial use Earliest documented example is by Erwin Unruh for computing Prime numbers. Initially popularized by Todd Veldhuizen  Used in Blitz++ 22
  23. 23. Serendipity Infinite instantiation: template <int n> struct Factorial { static const int val = n * Factorial<n-1>::val; }; static const int val = Factorial<3>::val; aCC complains: Error 588:Template generation nesting too deep; discovered during generation of specialization 'Factorial<(int)-251>'. You may have an infinite recursive generation. 23
  24. 24. Adding Terminating Condition template <int n> struct Factorial { static const int val = n * Factorial<n-1>::val; }; template <> struct Factorial<1> { static const int val = 1; }; const int factorial_of_3 = Factorial<3>::val; 24
  25. 25. Programming Constructs Metaprograms can be thought in terms of productions (just like recursive programs). Implementing productions in algorithms requires control flow constructs. If, do, while, for, switch… can be expressed in terms of templates (expression templates). 25
  26. 26. Template for If-Then One example: Representing If-Then-Else condition  How to select a class member type based on a condition?  Say signed or a unsigned one  One way to achieve this is to have a traits class and make the selection over there using a boolean non-type parameter (basis for typetraits library).  Part of all major meta-programming libraries (Loki, Boost etc). 26
  27. 27. Template for If-Then template <typename T, bool isSigned> struct myMemberSignTrait{ typedef signed T signType; }; // selected in case isSigned is true template <typename T, false> // partial specialization for false struct myMemberSignTrait{ typedef unsigned T signType; }; // selected if isSigned is false 27
  28. 28. Template for If-Then template <typename T, bool isSigned> class myContainer { typedef myMemberSignTrait<T, isSigned> memberSignTrait; typedef typename containerMemberTrait::signType signType; signType member; // member will be signed or unsigned // depending on the isSigned bool value }; 28
  29. 29. Improved If-Then Not elegant to extend (not scalable) Better to have a separate template class for doing such a selection. template <typename T, typename F, bool isSigned> struct if_select { typedef T type; }; // selected in case isSigned is true // partial specialization for false template <typename T, typename F> struct if_select <typename T, typename F, false> { typedef F type; }; // selected if isSigned is false 29
  30. 30. Improved If-Then template <typename T, bool isSigned> class myContainer { typedef typename if_select<signed T, unsigned T, isSigned>::type signType; signType member; // ... }; 30
  31. 31. Still better If-Then template <bool isSigned> struct if_cond { template<typename T, typename F> struct then_select { typedef T type; }; }; // selected in case isSigned is true template <bool isSigned> // partial specialization for false struct if_select <false> { template<typename T, typename F> struct then_select { typedef F type; }; }; // selected in case isSigned is true 31
  32. 32. Still better If-Then template <typename T, bool isSigned> class myContainer { typedef typename if_cond<isSigned>::template then_select<signed T, unsigned T>::type signType; signType member; // ... }; 32
  33. 33. Usage Example – if_select class CompactingGC { void GC() { … } }; class MarkAndSweepGC { void GC() { … } }; If_cond <GC == COPY, CopyingGC, MarkAndSweepGC>::value gc; gc.GC(); 33
  34. 34. Another Example- isPointer template <typename T> class type_traits{ template <class U> struct pointer_traits{ static const int result = false; } // specialization for pointer type template <class U *> struct pointer_traits{ static const int result = true; } public: static const int is_pointer = pointer_traits<T>:: result; }; // const bool is_ptr = type_traits<someTypedef>::is_pointer; 34
  35. 35. Application of meta-programming 35
  36. 36. Conversion Check Tool template <class T, class U> class Conversion{ typedef char Small; class Big { char dummy[2]; } static Small Test(U); static Big Test(...); static T MakeT(); public: enum { exists = sizeof(Test(MakeT())) == sizeof(Small) }; }; 36
  37. 37. Unrolling vector addition inline void addVect(int size, double* a, double* b, double* c) { while (size--) *c++ = *a++ + *b++; } 37
  38. 38. Template Unrolling template<int size> inline void addVect(double* a, double* b, double* c) { *c = *a + *b; addVect<size-1>(a+1, b+1, c+1); } template<> inline void addVect(double* a, double* b, double* c) { } addVect<3>(a, b, c); 38
  39. 39. Effect of unrolling addVect<3>(a, b, c); *c = *a + *b; addVect<2>(a+1, b+1, c+1); *(c+1) = *(a+1) + *(b+1); addVect<1>(a+2, b+2, c+2); *(c+2) = *(a+2) + *(b+2); addVect<0>(a+3, b+3, c+3); 39
  40. 40. Dot Product template <int DIM, typename T> struct DotProduct { static T result (T* a, T* b){ return *a * *b + DotProduct<DIM-1,T>::result(a+1,b+1); } }; template <typename T> struct DotProduct<1,T> { static T result (T* a, T* b) { return *a * *b; } }; 40
  41. 41. Dot Product template <int DIM, typename T> inline T dot_product (T* a, T* b) { return DotProduct<DIM,T>::result(a,b); } // usage: int main() { int a[3] = { 1, 2, 3}; int b[3] = { 5, 6, 7}; std::cout << quot;dot_product(3,a,b) = quot; << dot_product(3,a,b) << 'n'; std::cout << quot;dot_product(3,a,a) = quot; << dot_product(3,a,a); } 41
  42. 42. For Loop Unrolling template<int n, class B> struct FOR { static void loop(int m) { for (int i = 0; i < m/n; i++) { UNROLL<n, B>::iteration(i * n); } for (int i = 0; i < m%n; i++) { B::body(n * m/n + i); } }; 42
  43. 43. Loop Unrolling … template <int n, class B> struct UNROLL { static void iteration(int i) { B::body(i); UNROLL<n-1, B>::iteration(i + 1); } }; template <class B> struct UNROLL<0, B> { static void iteration(int i) { } }; 43
  44. 44. Meta-programming Libraries 44
  45. 45. Loki By Andrei Alexaderescu “Modern C++ Design” book Covers in Detail Important components:  Small object allocator  Typetraits and Typelists  Implementing Singletons  Smart Pointers  Object Factories  Visitor 45
  46. 46. Boost Major and wildly growing library Compatible with STL Important components:  Regex  Threads  Typetraits  Lambda  Binder  Function Object Wrapper  FC++ (Functional C++)  … 46
  47. 47. Future of Meta-programming 47
  48. 48. Future Looks Rosy Templates as a means for reusable and adaptive software Generic programming  poised to become dominant paradigm in C++ Metaprogramming libraries  Started - to be used widely  10 Boost libraries – candidates for becoming part standard  More and more programmers are attracted towards Functional programming in C++  From structured => object-oriented => generic => functional ! Don’t faint ;-) 48
  49. 49. But it won’t be easy Using templates have their own problems  Generic programming is inherently difficult in nature  Using templates needs expertise in C++  Cryptic error messages  Readability gets affected, negatively  Metaprograms doesn’t look like C++ code!  Too soon to tell how industry will receive it 49

×