Date post: | 10-May-2015 |
Category: |
Technology |
Upload: | ganesh-samarthyam |
View: | 1,706 times |
Download: | 0 times |
Unleashing the power of C++ Templates
An Introduction to Meta-programming
2
Why Meta-Programming?
3
Introduction
Generic programming becoming a dominant paradigm in C++The unexplored power of functional programming languages Higher levels of abstraction, design and reusabilityA code-generation mechanism (programs that generate programs!) Greater efficiency on what can be found at compile-time
4
Generic Programming
Early 90s when templates were used for container<T>STL How standardization helpedDesign patterns The ability for templates to model many design patterns
directly Idea of meta-programming possibility Boost Loki Other libraries
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
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
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
8
Efficiency
Templates can be unimaginably powerful and efficientExecution is moved on to compile-time The compiler does the work for you instead of the
program! Higher levels of abstraction, design and reusabilityA code-generation mechanism (programs that generate programs!) Greater efficiency on what can be found at compile-time
9
Template (tricky) Basics
10
Parameterized Types
Templates started Stroustrup’s desire to provide "parameterized types" for containers. A simple example would be a stack:
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;
};
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!
13
Templates for Reusable Components
An example: Making classes non-inheritableC++ 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.
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 // ...
};
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
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>{};
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.
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
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;
20
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; }
Template Template Parameters …
21
Meta-Programming
22
How it started?
Started with a mistake which led to infinite recursion in instantiating templatesInitial 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++
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.
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;
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).
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).
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
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 };
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
30
Improved If-Then
template <typename T, bool isSigned> class myContainer {
typedef typename if_select<signed T, unsigned T, isSigned>::type signType; signType member; // ...
};
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
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; // ...
};
33
Usage Example – if_select
class CompactingGC {void GC() { … }
};class MarkAndSweepGC {
void GC() { … }};
If_cond <GC == COPY, CopyingGC, MarkAndSweepGC>::value gc;
gc.GC();
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;
35
Application of meta-programming
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) };
};
37
Unrolling vector addition
inline void addVect(int size, double* a, double* b, double* c) {
while (size--) *c++ = *a++ + *b++;}
38
Template Unrollingtemplate<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);
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);
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;
} };
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 << "dot_product(3,a,b) = "
<< dot_product(3,a,b) << '\n'; std::cout << "dot_product(3,a,a) = " << dot_product(3,a,a);
}
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);}
};
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) { }};
44
Meta-programmingLibraries
45
Loki
By Andrei Alexaderescu “Modern C++ Design” book Covers in DetailImportant components: Small object allocator Typetraits and Typelists Implementing Singletons Smart Pointers Object Factories Visitor
46
Boost
Major and wildly growing libraryCompatible with STL Important components: Regex Threads Typetraits Lambda Binder Function Object Wrapper FC++ (Functional C++) …
47
Future of Meta-programming
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 ;-)
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