Generic Programming in C Giuseppe Attardi Universit di
- Slides: 29
Generic Programming in C++ Giuseppe Attardi Università di Pisa
Generic Parameters l Function for squaring a number: sqr(x) { return x * x; } l C version: int sqr(int x) { return x * x; } l Multiple versions: int sqr. Int(int x) { return x * x; } l C++ overloading: int sqr(int x) { return x * x; } double sqr(double x) { return x * x; }
C++ Templates template<class T> T sqr(T x) { return x * x; } l Compiler automatically generates a version for each parameter type used by a program: int a = 3; double b = 3. 14; int aa = sqr(a); double bb = sqr(b);
Notes: macros’ limits #define sqr(x) ((x) * (x)) int aa = sqr(a++); int aa = ((a++) * (a++)); int aaa = sqr(aa); #define fact(n) (n == 0) ? 1 : fact(n-1) * n #define SQR(T) T sqr(T x) {return x * x; } SQR(int); SQR(double); sqr(a); sqr(b);
Other types as well? class Complex { double real, imag; Complex operator *(Complex y) { return Complex( real * y. real – imag * y. imag, real * y. imag + imag * y. real); } } Complex c(1, 2); Complex cc = sqr(c);
Compile time checking template<class T> void swap(T& a, T& b) { const T temp = a; a = b; b = temp; } int a = 5, b = 9; int& ar = a; int* ap = *a; ar++; *ap = (*ap)+1 swap(a, b); // OK double c = 9. 0; swap(a, c); // error
C++ Standard Template Library l l l Goal: represent algorithms in as general form as possible without compromising efficiency Extensive use of templates Only uses static binding (an inlining) Use of iterators for decoupling algorithms from containers Iterator: abstraction of pointers
STL Organization l Containers § vector, deque, list, set, map, … l Algorithms § for_each, find, transform, sort l Iterators § forward_iterator, reverse_iterator, istream_iterator, … l Function Objects § plus, equal, logical_and, project 1 l Allocators
Examples from C++ Annotations vector l inner_product l sort l
Forward Iterator int main(int argc, char **argv) { vector<string> args(argv, argv + argc); vector<string>: : iterator iter = args. begin(); for ( ; iter != args. end(); ++iter ) cout << *iter << " "; cout << endl;
Reverse Iterator vector<string>: : reverse_iterator iter = args. rbegin(); for (; iter != args. rend(); ++iter ) cout << *iter << " "; cout << endl;
Inner Product vector<unsigned> ia 1 = {1, 2, 3, 4, 5, 6, 7}; vector<unsigned> ia 2 = {7, 6, 5, 4, 3, 2, 1}; // dot product inner_product(ia 1. begin(), ia 1. end(), ia 2. begin(), 0);
inner_product: definition T inner_product(Input. Iterator first 1, Input. Iterator last 1, Input. Iterator first 2, T init, Binary. Function op 1, Binary. Function op 2); l Initializes result to init l For each iterator i 1 in [first 1, last 1), and i 2 = first 2 + (i 1 - first 1)) updates result as follows: result = op 1(result, op 2(*i 1, *i 2))
Inner Product (string concat) class Join { public: Join(string const &sep): sep(sep) {} string operator()(string const& s 1, string const& s 2) { return s 1 + sep + s 2; } private: string sep; }; vector<string> names 1= {"Frank", "Karel", "Piet"}; vector<string> names 2 = {"Brokken", "Kubat", "Plomp"}; inner_product(names. begin(), names 1. end(), names 2. begin(), "t“, Join("n"), Join(" ")) ;
Parametrized Bubblesort template<class T> struct greater { bool operator()(const T& a, const T& b) const { return a > b; }; template<class T> struct less { bool operator()(const T& a, const T& b) const { return a < b; };
Note int x = 3, y = 5; bool b = greater<int>()(x, y);
Function object version template<class T, class C=less<T> > void bubblesort(vector<T> a, const C& comp) { for (unsigned i = 0; i < a. size(); ++i) for (unsigned j = i+1; j < a. size(); ++j) if (comp(a[i], a[j])) swap(a[i], a[j]); };
Traditional Functional version template<class T> void bubblesort(vector<T> a, bool (*comp)(T&, T&)) { for (unsigned i = 0; i < size; ++i) for (unsigned j = i+1; j < size; ++j) if (comp(a[i], a[j])) swap(a[i], a[j]); };
Bubblesort usage vector<int> x = {1, 5, 3, 4, 2}; bubblesort(x, greater<int>()); bubblesort(x, less<int>()); // implicit type inference vector<float> f; bubblesort(f); // uses less<float>
(Partial) Template Specialization an alternate version of the class template code can be provided for certain template parameters template<> void bubblesort<vector<string&> >(…) { } l l partial specialization: when only some of the template parameters are supplied
Template Enumeration template<class T> class Vector : public vector<T> { public: Enumeration get. Enumeration() { return (Enumeration(*this)); } class Enumeration { … } };
Enumeration (2) class Enumeration { private: vector<T> const& v; unsigned idx; public: Enumeration(vector<T> const& vector) : v(vector), idx(0) { } T const& next() { // uses T if (idx == vp. size()) throw No. Such. Element. Exception(index); return vp[idx++]; } bool has. Next() { return idx < vp. size(); } };
Enumeration (3) Vector<int> vector; … Vector<int>: : Enumeration en = vector. get. Enumeration(); while (en. has. Next()) cout << en. next() << endl;
Issue: template instantiation // file sum. Vector. h template <class T> T sum. Vector(T* array, unsigned n) { T sum(0); for (int i = 0; i < n; ++i) sum += array[i]; return sum; }
Instantiation (1) #include "sum. Vector. h" int x[] = {1, 2}; double y[] = {1. 1, 2. 2}; cout << sum. Vector(x, 2) << endl << sum. Vector(y, 2) << endl; l If the same template function definition is included in different source files, separately compiled and linked, there will be only one instantiation, per type of template function
Instantiation (2) l declare a template function, if it is known that the required instantiation is available in another source file: template<class T> T sum. Vector(T* tp, unsigned n); int v[] = {1, 2}; sum. Vector(v, 2);
Instantiation (3) l declare template functions in header files, keep the definition in a template source file: template<class T> T sum. Vector(T* tp, unsigned n) { return *tp; } static void* p 1 = static_cast<int (*)(int*, unsigned)>(sum. Vector);
Forcing Instantiations static void* p[] = { static_cast<int (*)(int*, unsigned)>(sum. Vector), static_cast<double (*)(double*, unsigned)>(sum. Vector), static_cast<unsigned (*)(unsigned *, unsigned)>(sum. Vector) };
Explicit Instantiations template<class T> T sum. Vector(T *tp, unsigned n) { return (*tp); } template int sum. Vector<int>(int *, unsigned); template double sum. Vector<double>(double *, unsigned); template unsigned sum. Vector<unsigned>(unsigned *, unsigned);
- Gerardo attardi
- Erasmus university rotterdam economics
- London universit
- Organigramme nanterre
- Universit
- Universit sherbrooke
- C generic programming
- Generic programming and the stl
- Generic subroutines
- Generic programming
- Linear vs integer programming
- Perbedaan linear programming dan integer programming
- Perbedaan linear programming dan integer programming
- Greedy vs dynamic
- What is system programing
- Giuseppe gionta
- Giuseppe de marinis
- Giuseppe della ricca
- Giuseppe rossi unical
- Ungaretti mappa concettuale
- Giuseppe lo re
- Giuseppe tizza
- Istituto comprensivo san giuseppe calasanzio
- Ungaretti il poeta soldato
- Giuseppe matematico logico e glottoteta piemontese
- Scuola san giuseppe foggia
- Giuseppe letizia la mafia uccide solo d'estate
- Istituto comprensivo borgo san giuseppe
- Giuseppe verdi composities
- Giuseppe verdi sävellykset