why templates?
-
suppose you need a list of X and a list of Y
- the lists would use similar code
- they differ by the type shored in the list
-
choices
- require common base class 方案1
- may not be desirable
- clone code 方案2
- preserves type-safety
- hard to manage 难以管理维护
- untyped lists 方案3 没有类型的list
- type unsafe 不安全
- require common base class 方案1
templates 方案4
函数模板(用来做出函数) 类模板 模板函数 模板类
- reuse source code
- generic programming
- use types as parameters in class or function definitions 类型成为参数
- template functions
- example : sort function
- template classes
- example:contains such as stack,list, queue...
- stack operations are independent of the type of items in the stack
- template member functions
- example:contains such as stack,list, queue...
function templates
-
perform similar operations on different types of data
-
swap function for two int arguments:
void swap(int& x,int& y){ int temp = x; x = y; y = temp; }
-
what if we want to swap flats ,strings,Currency,Person?
example:swap function template
template <class T> // 声明而不是定义
void swap(T& x,T& y){ // 函数模板 T代表一个类型
T temp = x;
x = y;
y = temp;
}
- the template keyword introduces the template
- the class T specifies a parameterized type name
- class means any built-in type or user-defined type
- inside the template,use T as a type name
function template Syntax
- parameter types represent:
- types of arguments to the function
- return type of the function
- declare variables within the function
template instantiation
- generating a declaration from a template class/function and template arguments:
- types are substituted into template
- new body of function or class definition is created
- syntax errors,type checking
- specialization -- a version of a template for a particular argument(s)
example:using swap
int i = 3; int j = 4; swap(i,j); //use explicit int swap float k = 4.5; float m = 3.7; swap(k,m); //instanstiate float swap 编译器给制造出来了一个相应函数 std::string s("hello"); std::string t("world"); swap(s,t); //std::string swap
- a template function is an instantiation of a function template
interactions
-
only exact match on types is used
-
no conversion operations are applied
swap(int, int); //ok swap(double, double); //ok swap(int, double) //error
-
even implicit conversions are ignored
-
template functions and regular functions coexist
overloading rules
-
check first for unique function match
-
then check for unique function template match
-
then do overloading on functions
void f(float i,float k)(); template <class T> void f(T t,T u){}; f(1.0,2.0); f(1,2); f(1,2.0)
function instantiation
-
the compiler deduces the template type from the actual arguments passed into the function
-
can be explicit:
-
for example,if the parameter is not in the function signature(older compilers won't allow this)
template <class T> void foo(void){...} foo<int>();//type T is int foo<float>();//tyoe T is float
-
class templates
-
classes parameterized by types
- abstract operations form the types being operated upon
- define potentially infinite set of classes
- another step towards reuse
-
typical use:container classes
stack <int> //is a stack that is parameterized over int list <Person&> queer <Job>
example:Vector
template <class T> class Vector{ public: Vector(int); ~Vector(); Vector(const Vector&); Vector& operator=(const Vector&); T& operator[] (int); private: T* m_elements; int m_size; };
usage
Vector<int> v1(100); Vertor<Complex> v2(256); v1[20] = 10; v2[20] = v1[20]; //ok if int -> Comlex defined
Vector members
template <class T> // 每一个都是函数模板 Vector<T>::Vector(int size):m_size(size){ m_elementds = new T[m_size]; } template <class T> T& Vertor<T>::operator[](int indx){ if(indx < m_size && indx > 0){ return m_elments[indx]; }else{ ... } }
类模板里面的每一个函数都是函数模板
a simple sort function
//bubble sort -- don't use it template <class T> void sort(vector<T>& arr){ // 函数模板 声明 const size_t last = arr.size()-1; for(int i = 0;i < last; i++){ for(int j = last; i < j; j--){ if(arr[j] < arr[j-1]){ //which swap? swap(arr[j], arr[j-1]); } } } }
sorting the vector
vector<int> vi(4);
vi[0] = 4;vi[2] = 7; vi[1]=3; vi[3] = 1;
sort(vi); //sort(vector<int>&)
vector<string> vs;
vs.push_back("Fred");
vs.push_back("Willma");
vs.push_back("Barney");
vs.push_back("Dino");
vs.push_back("Prince");
sort(vs); //sort (vector<string>&)
//note:sort uses operator < for comparation
templates
-
templates can use multiple types
template<class Key,class Value> class HashTable{ const Value& lookup(const Key&) const; void install(const Key& ,const Value&); ... };
-
templates nest ---they're just new types!
Vector< Vector<double*> > //note sapce > > 空格
-
type arguments can be complicated
Vector<int (*)(Vector<double>&,int)>//内层是函数
expression parameters
-
template arguments can be constant expressions
-
non-Type parameters
- can have a default argument
template <class T, int bounds = 100> class FixedVector{ public: FixedVector(); //... T& oprator[](int); private: T elements[bounds];//fixed size array }
usage:Non-type parameters
-
usage
FixedVector<int,50> v1; FixedVector<int,10*5> v2; FixedVector<int> v3;//uses default
-
summary
- embedding sizes not necessarily
- can make code faster
- makes use more complicated
- size argument appears everywhere
- can lead to (even more) code bloat
templates and inheritance
-
templates can inherit from non-template classes
template <class A> class Deried:public Base{...}
-
templates can inherit form template classes
template<class A> class Derived : pubic List<A>{...}
-
non-templates classes can inherit from templates
class SupervisorGroup:public List<Emoloyee*>
writing templates
- get a non-template version working first
- establish a good set of test cases
- measure performance and tune