Title: Abstraction: Generic Programming, pt. 2
1AbstractionGeneric Programming, pt. 2
Templates
2Overloading
- Recall overloading
- Same function name used for different parameter
types - Compiler decides which function to use according
to signature - Legal to do in C, not in C
- Allows for generic programming
3Overloading
- Recall overloading
- Same function name used for different parameter
types - Compiler decides which function to use according
to signature - Can also be used with class hierarchy
- Subclass can override superclass function, handle
subclass concerns
4Function Templates
- Acts like a blueprint for instantiating a
function - Type is abstracted in template
- Function is actually instantiated when it is used
in program then and only then is the type
determined and bound to the abstract type(s) in
the template - Unlike overloading, the functions with same name
are not all written out in code
5Function Templates
Two implementations overload compare() int
compare (const char c1, const char c2) if
(c1 lt c2) return -1 if (c2 lt c1) return 1
return 0 int compare (const int i1, const
int i2) if (i1 lt i2) return -1 if (i2 lt
i1) return 1 return 0
6Function Templates
One function template does the same
thing! template lttypename Tgt int compare (const T
v1, const T v2) if (v1 lt v2) return -1
if (v2 lt v1) return 1 return 0 Note that
the template lttypename Tgt declaration creates a
scope in which T is known to the compiler Compare
only requires lt overloading for T
7Function Templates
Now compare() can be called on for any two
objects for which lt is defined for their type!
int i1, i2 string s1, s2 double d1, d2 ...
cout ltlt compare (i1, i2) ltlt endl // works cout
ltlt compare (s1, s2) ltlt endl // works cout ltlt
compare (d1, d2) ltlt endl // works
8Function Templates
Now compare() can be called on for any two
objects for which lt is defined for their type!
When the code with compare is compiled, formal
type T is replaced with actual type ... It is as
though you wrote the compare function three (or
more) times, once for each type but the
compiler does it for you!
9Function Templates
Function templates can be declared
as inline Constexpr Example template
lttypename Tgt inline T min(const T, const
T) Functions can return template type
10Function Templates
Function templates can have multiple formal
types template lttypename T, typename Ugt T
fun(const T, const U) Can use either
typename or class - makes no difference
11Function Templates
Can have non-type parameters in
templates template ltunsigned N, unsigned Mgt int
compare(const char (p1)N,
const char (p2)M) return strcmp(p1,
p2) compare(Go, Gators) compiles to int
compare(const char (p1)3,
const char (p2)7)
12Function Templates
Compiling the template itself does not generate
any code - - only when the function is actually
used is code generated - hence function
definition is needed in header with template
(can't just give declaration) - compiler can only
verify that the objects declared with the same
formal type are declared with the same actual
type when the template is encountered in code
13Function Templates
Compiling the template itself does not generate
any code - - only when the function is actually
used is code generated - most errors only show
up after instantiation - compiler can only catch
syntax errors in template definition itself -
compiler can check number and type agreement of
arguments when use is seen - only on
instantiation can type-related problems be
detected but where to report the error??? The
code is generated!!!
14Function Templates
Rules of thumb - Make as few obligations on the
types used as possible (lt but not gt, e.g.) -
Use const if possible in parameters - When
calling, make sure type used satisfies the
obligations - A template not used with a type
that does not satisfy obligations is NOT a
problem! - Do your development with actual types
before you convert to templates - Convert
incrementally until you become comfortable with
the process
15Questions?
16Class Templates
- Acts like a blueprint for instantiating a class
- Type is abstracted in template
- Compiler cannot deduce the type from use must
declare the type in angle brackets following the
template's name - Types in list are types to use in template formal
type list
17Class Templates
template lttypename Tgt class Blob public
typedef T value_type // for decls typedef
typename vectorltTgtsize_type size_type
Blob() Blob(initializer_listltTgt) size_type
size() const return data-gtsize() bool
empty() const return data-gtempty() void
push_back(const T t) data-gtpush_back(t)
void pop_back() T back() T
operator(size_type) private
shared_ptrltvectorltTgtgt data void
check(size_type, const string msg) const
18Class Templates
template lttypename Tgt class Blob public
typedef T value_type // for decls typedef
typename vectorltTgtsize_type size_type
Blob() Blob(initializer_listltTgt) size_type
size() const return data-gtsize() bool
empty() const return data-gtempty() void
push_back(const T t) data-gtpush_back(t)
void pop_back() T back() T
operator(size_type) private
shared_ptrltvectorltTgtgt data void
check(size_type, const string msg) const
value_type is T, which will be declared when
Blob is instantiated (as a class) with some
actual type (say, int or string). value_type and
size_type are useful for generic declarations
relative to a particular class without knowing
what the details of the class happen to be
19Class Templates
template lttypename Tgt class Blob public
typedef T value_type // for decls typedef
typename vectorltTgtsize_type size_type
Blob() Blob(initializer_listltTgt) size_type
size() const return data-gtsize() bool
empty() const return data-gtempty() void
push_back(const T t) data-gtpush_back(t)
void pop_back() T back() T
operator(size_type) private
shared_ptrltvectorltTgtgt data void
check(size_type, const string msg) const
Blob has two initializers one default (for
empty blob of desired type) and one
with initializer list (of multiple instances of
objects or literals of desired
type). Initializer list can do the things
initializer lists do, like cause the same value
to be repeated N times, or list a bunch of
different values.
20Class Templates
template lttypename Tgt class Blob public
typedef T value_type // for decls typedef
typename vectorltTgtsize_type size_type
Blob() Blob(initializer_listltTgt) size_type
size() const return data-gtsize() bool
empty() const return data-gtempty() void
push_back(const T t) data-gtpush_back(t)
void pop_back() T back() T
operator(size_type) private
shared_ptrltvectorltTgtgt data void
check(size_type, const string msg) const
Methods defined inside class template have the
scope of both the class AND the template, so the
class naming scope is assumed, and the type(s) in
the template can be used.
21Class Templates
template lttypename Tgt class Blob public
typedef T value_type // for decls typedef
typename vectorltTgtsize_type size_type
Blob() Blob(initializer_listltTgt) size_type
size() const return data-gtsize() bool
empty() const return data-gtempty() void
push_back(const T t) data-gtpush_back(t)
void pop_back() T back() T
operator(size_type) private
shared_ptrltvectorltTgtgt data void
check(size_type, const string msg) const
The type(s) in the template can be used in the
bracketed list of other class templates or
functions
22Class Templates
template lttypename Tgt class Blob public
typedef T value_type // for decls typedef
typename vectorltTgtsize_type size_type
Blob() Blob(initializer_listltTgt) size_type
size() const return data-gtsize() bool
empty() const return data-gtempty() void
push_back(const T t) data-gtpush_back(t)
void pop_back() T back() T
operator(size_type) private
shared_ptrltvectorltTgtgt data void
check(size_type, const string msg) const
shared_ptrltUgt is a safe pointer (see Ch
12) that keeps track of how many pointers point
to a dynamically allocated object, and delete it
when there are no pointers left. Use ltmemorygt
header.
23Questions?
24Class Templates
template lttypename Tgt bool BlobltTgtempty()
const return data-gtempty() template
lttypename Tgt void BlobltTgtcheck(size_type index,
const string msg)
const if (index gt data-gtsize()) Throw
out_of_range(msg)
For functions defined outside of class, not only
must you include the class name for scoping
(Blob) with the scope operator (), but you
must also include the formal type list (ltTgt) and
first declare the whole thing to be a template
(as you would for a non-member function template)
25Class Templates
template lttypename Tgt bool BlobltTgtempty()
const return data-gtempty() template
lttypename Tgt void BlobltTgtcheck(size_type index,
const string msg)
const if (index gt data-gtsize()) Throw
out_of_range(msg)
The check() function serves to make sure an
index is safe to use by throwing an appropriate
exception if it is not
26Class Templates
template lttypename Tgt T BlobltTgtback()
check(0, Back on empty Blob) return
data-gtback() template lttypename Tgt T
BlobltTgtoperator(size_type index) check(0,
Blob subscript out of range) return
(data)i
The template type T can be used as the return
type, and can have all the usual modifiers on
it, like , , const, etc.
27Class Templates
template lttypename Tgt T BlobltTgtback()
check(0, Back on empty Blob) return
data-gtback() template lttypename Tgt T
BlobltTgtoperator(size_type index) check(0,
Blob subscript out of range) return
(data)i
Both back () and subscript operator should be
overloaded on const so that both can return
values to use when const is needed and when the
value is to be changed
28Class Templates
template lttypename Tgt BlobltTgtBlob()
data(make_sharedltvectorltTgtgt()) template
lttypename Tgt BlobltTgtBlob(initializer_listltTgt
il) data(make_sharedltvectorltTgtgt(il)
Both initializers make use of safe pointer
structures shared pointer and instantiation
using make_shared so automatic garbage
collection can be done. Typename T is carried
forward to the type list needed by vector when
it is instantiated
29Class Templates
template lttypename Tgt class BlobPtr public
BlobPtr() curr(0) T operator() const
auto p check(curr, Dereference past end)
return (p)curr // (p) is the vector ...
BlobPtr operator() BlobPtr
operator--() private shared_ptrltvectorltTgtgt
check(size_t, const
string) const weak_ptrltvectorltTgtgt wptr
size_t curr // current position in array
Here we have another class template for pointers
to classes instantiated from the Blob class
template. curr keeps track of where we are in the
object the pointer is pointing at.
30Class Templates
template lttypename Tgt class BlobPtr public
BlobPtr() curr(0) T operator() const
auto p check(curr, Dereference past end)
return (p)curr // (p) is the vector ...
BlobPtr operator() BlobPtr
operator--() private shared_ptrltvectorltTgtgt
check(size_t, const
string) const weak_ptrltvectorltTgtgt wptr
size_t curr // current position in array
Overloading the dereference operator Check now
returns a shared pointer (safe) so long as it
does not point to someplace off the end of the
storage
31Class Templates
template lttypename Tgt class BlobPtr public
BlobPtr() curr(0) T operator() const
auto p check(curr, Dereference past end)
return (p)curr // (p) is the vector ...
BlobPtr operator() BlobPtr
operator--() private shared_ptrltvectorltTgtgt
check(size_t, const
string) const weak_ptrltvectorltTgtgt wptr
size_t curr // current position in array
Note that BlobPtr type for the declarations of
and -- operators does NOT require the type
parameter list ltTgt as needed outside the class
declaration
32Class Templates
template lttypename Tgt class BlobPtr public
BlobPtr() curr(0) T operator() const
auto p check(curr, Dereference past end)
return (p)curr // (p) is the vector ...
BlobPtr operator() BlobPtr
operator--() private shared_ptrltvectorltTgtgt
check(size_t, const
string) const weak_ptrltvectorltTgtgt wptr
size_t curr // current position in array
When defined outside the class declaration, they
would have to be BlobPtrltTgt operator()
... BlobPtrltTgt operator--() ...
33Class Templates
Postfix operator defined outside class
template body template lttypename Tgt BlobPtrltTgt
BlobPtrltTgtoperator(int) BlobPtr retVal
this // remember old value this
// increment value return retVal
When defined outside the class declaration, must
include type list for return type as well as for
naming scope
34Questions?
35Class Template Friends
template lttypenamegt class BlobPtr template
lttypenamegt class Blob template lttypename Tgt bool
operator(const BlobltTgt, const
BlobltTgt) template lttypename Tgt Class Blob
friend class BlobPtrltTgt friend bool
operatorltTgt (const BlobltTgt, const
BlobltTgt) ...
Forward declarations needed for friend
declarations in Blob Forward declaration needed
for parameters in operator
36Class Template Friends
template lttypenamegt class BlobPtr template
lttypenamegt class Blob template lttypename Tgt bool
operator(const BlobltTgt, const
BlobltTgt) template lttypename Tgt Class Blob
friend class BlobPtrltTgt friend bool
operatorltTgt (const BlobltTgt, const
BlobltTgt) ...
Grants friend access to versions of BlobPtr and
operator instantiated in same type
37Class Template Friends
template lttypenamegt class Blob template
lttypename Tgt ostream operatorltlt(ostream, const
BlobltTgt) template lttypename Tgt Class Blob
friend ostream operatorltlt ltTgt
(ostream, const BlobltTgt) ... template
lttypename Tgt ostream operatorltlt(ostream os,
const BlobltTgt b) ...
Forward declaration needed for parameters in
operatorltlt Typename list does not need formal
types since it is forward decl
38Class Template Friends
template lttypenamegt class Blob template
lttypename Tgt ostream operatorltlt(ostream, const
BlobltTgt) template lttypename Tgt Class Blob
friend ostream operatorltlt ltTgt
(ostream, const BlobltTgt) ... template
lttypename Tgt ostream operatorltlt(ostream os,
const BlobltTgt b) ...
Forward declaration of operatorltlt for friend
declaration in class
39Class Template Friends
template lttypenamegt class Blob template
lttypename Tgt ostream operatorltlt(ostream, const
BlobltTgt) template lttypename Tgt Class Blob
friend ostream operatorltlt ltTgt
(ostream, const BlobltTgt) ... template
lttypename Tgt ostream operatorltlt(ostream os,
const BlobltTgt b) ...
Friend declaration of operatorltlt with partial
specialization in class
40Class Template Friends
template lttypenamegt class Blob template
lttypename Tgt ostream operatorltlt(ostream, const
BlobltTgt) template lttypename Tgt Class Blob
friend ostream operatorltlt ltTgt
(ostream, const BlobltTgt) ... template
lttypename Tgt ostream operatorltlt(ostream os,
const BlobltTgt b) ...
Definition of operatorltlt with template type for
Blob