CNS 3370
Executive Overview Template Parameters Function Template Issues 2 CNS Templates
Generic Programming Compile-time Code Generation Implicit Interfaces Template Terminology 3 CNS Templates
Not a new idea Object mega-hierarchy; void* in C Based on innovations from ML and Ada Statically-checked Allows efficient use of built-in types 4 CNS Templates
aka “Duck Typing” If it quacks like a duck, … (i.e., it fits the bill :-) The status quo for dynamically-typed languages Perl, Python, PHP, Ruby… C++ statically verifies that generic types support required operations template const T& min(const T& a, const T& b) { return (a < b) ? a : b; } … min(i,j) // T deduced 5 CNS Templates
Separate code versions are automatically generated On-demand code generation Implicit and explicit Potential for Code Bloat template class Stack { T* data; size_t count; public: void push(const T& t); // etc. }; // Explicit instantiation Stack s; 6 CNS Templates
7
If using a function template, the requested function definition is instantiated If using a class template, the requested version of the class definition is instantiated For the compiler’s use (just like regular classes) But only the member functions actually used are generated 8 CNS Templates
class X { public: void f() {} }; class Y { public: void g() {} }; template class Z { T t; public: void a() { t.f(); } void b() { t.g(); } }; int main() { Z zx; zx.a(); // Z ::b() not attempted Z zy; zy.b(); // Z ::a() not attempted } Question: When are the names f and g looked up by the compiler? 9 CNS Templates
Totally in header files The template code must be available during instantiation This is the Inclusion Model of template compilation 10 CNS Templates
Template Parameter Names inside <>’s after the template keyword ( ) Template Argument Names inside <>’s in a specialization ( ) Template Specialization What results when you provide arguments (Stack ) Instantiation The class or function generated for a complete set of template arguments An instantiation is always a specialization 11 CNS Templates
Templates are instructions for compile-time code generation They enable type-safe, type-transparent code Template parameters constitute implicit interfaces “Duck Typing” Classic OOP uses explicit interfaces and runtime polymorphism Templates and OOP can complement each other 12 CNS Templates
3 Kinds… Type parameters the most common (vector ) Non-type compile-time integral values (bitset, for example) Templates “template template parameters” 13 CNS Templates
Container logic is independent of the contained type template // T is a type parm class vector { T* data; … }; vector v;// int is a type argument 14 CNS Templates
Must be compile-time constant values integral expressions (including static addresses) Often used to place member arrays on the runtime stack Example: std::array And std::bitset see next 3 slides… 15 CNS Templates
A “replacement” for built-in arrays a template wrapper that holds a static array stored on stack Provides STL-like features: begin(), end(), size(), empty(), at(), front(), back() and of course operator[] (not range-checked) See array.cpp
Simulates a fixed-size collection of bits Like numbers, 0 (zero) is the right-most position Number of bits determined at compile-time No need for the heap Array is embedded in the object Example: bitset.cpp 17 CNS Templates
template class bitset { typedef unsigned int Block; enum {BLKSIZ = CHAR_BIT * sizeof (Block)}; enum {nblks_ = (N+BLKSIZ-1) / BLKSIZ}; Block bits_[nblks_]; // Embedded array … }; 18 CNS Templates
Like default function arguments if missing, the defaults are supplied only allowed in class templates template class FixedStack { T data[N]; … }; FixedStack<> s1; // = FixedStack s2; // = 19 CNS Templates
template > class vector; Note how the second parameter uses the first 20 CNS Templates
Templates are not types! They are instructions for generating types If you plan on using a template parameter itself as a template, the compiler needs to know Examples follow… 21 CNS Templates
// A simple, expandable sequence (like vector) template class Array { enum { INIT = 10 }; T* data; size_t capacity; size_t count; public: Array() { count = 0; data = new T[capacity = INIT]; } ~Array() { delete [] data; } void push_back(const T& t) {...} void pop_back() {...} T* begin() { return data; } T* end() { return data + count; } }; 22 CNS Templates
template class Seq> class Container { Seq seq; public: void append(const T& t) { seq.push_back(t); } T* begin() { return seq.begin(); } T* end() { return seq.end(); } }; int main() { Container container; // Pass template container.append(1); container.append(2); int* p = container.begin(); while(p != container.end()) cout << *p++ << endl; } 23 CNS Templates
Type Deduction of Arguments Function template overloading Partial Ordering of Function Templates 24 CNS Templates
The compiler usually deduces type parameters from the arguments in the function call the corresponding specialization is instantiated automatically Sometimes it can’t: when the arguments are different types ( min(1.0, 2) ) when the template argument is a return type 25 CNS Templates
// StringConv.h #include template T fromString(const std::string& s) { std::istringstream is(s); T t; is >> t; return t; } template std::string toString(const T& t) { std::ostringstream s; s << t; return s.str(); } 26 CNS Templates
int main() { // Implicit Type Deduction int i = 1234; cout << "i == \"" << toString(i) << "\"" << endl; float x = ; cout << "x == \"" << toString(x) << "\"" << endl; complex c(1.0, 2.0); cout << "c == \"" << toString(c) << "\"" << endl; cout << endl; // Explicit Function Template Specialization i = fromString (string("1234")); cout << "i == " << i << endl; x = fromString (string("567.89")); cout << "x == " << x << endl; c = fromString >(string("(1.0,2.0)")); cout << "c == " << c << endl; } 27 CNS Templates
You can define multiple functions and function templates with the same name The “best match” will be used You can also overload a function template by having a different number of template parameters 28 CNS Templates
template const T& min(const T& a, const T& b) { return (a < b) ? a : b; } const char* min(const char* a, const char* b) { return (strcmp(a, b) < 0) ? a : b; } double min(double x, double y) { return (x < y) ? x : y; } int main() { const char *s2 = "say \"Ni-!\"", *s1 = "knights who"; cout << min(1, 2) << endl; // 1: 1 (template) cout << min(1.0, 2.0) << endl; // 2: 1 (double) cout << min(1, 2.0) << endl; // 3: 1 (double) cout << min(s1, s2) << endl; // 4: "knights who" // (const char*) cout (s1, s2) << endl; // 5: say "Ni-!" // (template) } CNS Templates 29
With overloaded function templates, there needs to be a way to choose the “best fit” Plain functions are always considered better than templates Everything else being equal Some templates are better than others also More “specialized” if matches more combinations of arguments types than another Example follows 30 CNS Templates
template void f(T) { cout << "T" << endl; } template void f(T*) { cout << "T*" << endl; } template void f(const T*) { cout << "const T*" << endl; } int main() { f(0); // T int i = 0; f(&i); // T* const int j = 0; f(&j); // const T* } CNS Templates 31
Arguments that can be deduced will be The rest you must provide Put those first in the argument list so the others can be deduced by the compiler Standard Conversions do not apply when using unqualified calls to function templates Arguments must match parameters exactly Except const adornments are okay 32 CNS Templates
std::pair, std::tuple CNS Templates33
Holds a pair of any two types: pair p1(10,”ten”); auto p1 = make_pair(10,string(“ten”)); Used to hold the key and value in a map Retrieve values with first and second struct data members See pair.cpp
Holds an arbitrary number of items Handy for returning multiple items from a function Can retrieve by position with template args (get (tup), etc.) Can do item-wise assignment See tuple.cpp