CNS 3370
Jan 16, 2016
CNS 3370
Executive OverviewTemplate ParametersFunction Template Issues
2CNS 3370 - Templates
Generic ProgrammingCompile-time Code Generation Implicit InterfacesTemplate Terminology
3CNS 3370 - Templates
Not a new idea Object mega-hierarchy; void* in C
Based on innovations from ML and Ada
Statically-checkedAllows efficient use of built-in types
4CNS 3370 - 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<class T>const T& min(const T& a, const T& b){ return (a < b) ? a : b;}
…
min(i,j) // T deduced
5CNS 3370 - Templates
Separate code versions are automatically generated
On-demand code generation
Implicit and explicit
Potential for Code Bloat
template<typename T> class Stack { T* data; size_t count;public: void push(const T& t); // etc.};
// Explicit instantiationStack<int> s;
6CNS 3370 - Templates
CNS 3370 - 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
8CNS 3370 - Templates
class X {public: void f() {}};
class Y {public: void g() {}};
template<typename T> class Z { T t;public: void a() { t.f(); } void b() { t.g(); }};
int main() { Z<X> zx; zx.a(); // Z<X>::b() not attempted Z<Y> zy; zy.b(); // Z<Y>::a() not attempted}
Question: When are the names f and g looked up by the compiler?
9CNS 3370 - Templates
Totally in header filesThe template code must be available
during instantiation This is the Inclusion Model of template
compilation
10CNS 3370 - Templates
Template Parameter Names inside <>’s after the template keyword
(<class T>) Template Argument
Names inside <>’s in a specialization (<int>) Template Specialization
What results when you provide arguments (Stack<int>)
Instantiation The class or function generated for a complete set
of template arguments An instantiation is always a specialization
11CNS 3370 - 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
12CNS 3370 - Templates
3 Kinds…Type parameters
the most common (vector<int>)Non-type
compile-time integral values (bitset<10>, for example)
Templates “template template parameters”
13CNS 3370 - Templates
Container logic is independent of the contained type
template<class T> // T is a type parmclass vector { T* data; …};
vector<int> v; // int is a type argument
14CNS 3370 - 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<T,N> And std::bitset see next 3 slides…
15CNS 3370 - 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
positionNumber of bits determined at
compile-time No need for the heap Array is embedded in the object
Example: bitset.cpp17CNS 3370 - Templates
template<unsigned int N>class bitset { typedef unsigned int Block; enum {BLKSIZ = CHAR_BIT * sizeof (Block)}; enum {nblks_ = (N+BLKSIZ-1) / BLKSIZ}; Block bits_[nblks_]; // Embedded array …};
18CNS 3370 - Templates
Like default function arguments if missing, the defaults are supplied only allowed in class templates
template<class T = int, size_t N = 100>class FixedStack { T data[N]; …};FixedStack<> s1; // = <int, 100>FixedStack<float> s2; // = <float,100>
19CNS 3370 - Templates
template<class T, class Allocator = allocator<T>>class vector;
Note how the second parameter uses the first
20CNS 3370 - 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…
21CNS 3370 - Templates
// A simple, expandable sequence (like vector) template<typename T>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; }};
22CNS 3370 - Templates
template<typename T, template<typename> class Seq>class Container { Seq<T> seq;public: void append(const T& t) { seq.push_back(t); } T* begin() { return seq.begin(); } T* end() { return seq.end(); }};
int main() { Container<int, Array> container; // Pass template container.append(1); container.append(2); int* p = container.begin(); while(p != container.end()) cout << *p++ << endl;}
23CNS 3370 - Templates
Type Deduction of ArgumentsFunction template overloadingPartial Ordering of Function
Templates
24CNS 3370 - Templates
The compiler usually deduces type parameters from the arguments in the function call the corresponding specialization is
instantiated automaticallySometimes it can’t:
when the arguments are different types ( min(1.0, 2) )
when the template argument is a return type
25CNS 3370 - Templates
// StringConv.h#include <string>#include <sstream>
template<class T>T fromString(const std::string& s) { std::istringstream is(s); T t; is >> t; return t;}
template<class T>std::string toString(const T& t) { std::ostringstream s; s << t; return s.str();}
26CNS 3370 - Templates
int main() { // Implicit Type Deduction int i = 1234; cout << "i == \"" << toString(i) << "\"" << endl; float x = 567.89; cout << "x == \"" << toString(x) << "\"" << endl; complex<float> c(1.0, 2.0); cout << "c == \"" << toString(c) << "\"" << endl; cout << endl;
// Explicit Function Template Specialization i = fromString<int>(string("1234")); cout << "i == " << i << endl; x = fromString<float>(string("567.89")); cout << "x == " << x << endl; c = fromString<complex<float>>(string("(1.0,2.0)")); cout << "c == " << c << endl;}
27CNS 3370 - Templates
You can define multiple functions and function templates with the same name
The “best match” will be usedYou can also overload a function
template by having a different number of template parameters
28CNS 3370 - Templates
template<class T>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 << min<>(s1, s2) << endl; // 5: say "Ni-!" // (template)}
CNS 3370 - 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 follows30CNS 3370 - Templates
template<class T> void f(T) { cout << "T" << endl;}
template<class T> void f(T*) { cout << "T*" << endl;}
template<class T> 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 3370 - 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 compilerStandard Conversions do not apply
when using unqualified calls to function templates Arguments must match parameters exactly Except const adornments are okay
32CNS 3370 - Templates
std::pair, std::tuple
CNS 3370 - Templates 33
Holds a pair of any two types: pair<int,string> 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 itemsHandy for returning multiple items
from a functionCan retrieve by position
with template args (get<1>(tup), etc.)Can do item-wise assignmentSee tuple.cpp