Exercise 16.9:
function template --> Definition from which specific functions can be instantiated. A function template is defined using thetemplate keyword followed by a comma-separated list of one or more template parameters enclosed in < and > brackets, followed by a function definition.
class template --> Definition from which specific classes can be instantiated. Class templates are defined using the template keyword followed by a comma-separated list of one or more template parameters enclosed in < and > brackets, followed by a class definition.
Exercise 16.10:
Compiler process whereby the actual template argument(s) are used to generate a specific instance of the template in which the parameter(s) are replaced by the corresponding argument(s). Functions are instantiated automatically based on the argument used in a call. We must supply explicitly template arguments whenever we use a class template.
Exercise 16.11:
we must supply template argument when we use a class template type. inside the scope of the class template itself, we may use the name of the template without arguments. so in the definition of List, has something wrong with ListItem without argument.
Exercise 16.12:
#include
using std::shared_ptr; using std::make_shared;
#include
using std::vector;
#include
using std::out_of_range;
// forward declarations needed for friend declarations in Blob
template
class Blob_ptr;
template
class Blob; template
bool operator==(const Blob
&, const Blob
&); template
class Blob { // each instantiation of Blob grants access to the version of // Blob_ptr and the equality operator instantiated with the same type friend class Blob_ptr
; friend bool operator==
(const Blob
&, const Blob
&); public: typedef T value_type; typedef typename std::vector
::size_type size_type; // constructors Blob(); template
Blob(it b, it e); // number of elements in the Blob size_type size() const { return data->size(); } bool empty() const { return data->empty(); } // add and remove elements void push_back(const T &t) { data->push_back(t); } // move version void push_back(const T &&t) { data->push_back(std::move(t))}; void pop_back(); // element access T &back(); T &operator[](size_type i); private: std::shared_ptr
> data; // throws msg if data[i] isn't valid void check(size_type i, const std::string &msg) const; }; // constructor template
Blob
::Blob() : data(std::make_shared
>()) { } template
// type parameter for the class template
// type parameter for the constructor Blob
::Blob(it b, it e) : data(std::make_shared
>(b, e)) { } // check member template
void Blob
::check(size_type i, const std::string &msg) const { if (i >= data->size()) { throw std::out_of_range(msg); } } template
void Blob
::pop_back() { check(0, "pop_back on empty Blob"); data->pop_back(); } // element access template
T &Blob
::back() { check(0, "back on empty Blob"); return data->back(); } template
T &Blob
::operator[](size_type i) { // if i is too bit, cheick will throw // preventing access to a nonexistent element check(i, "subscript out of range"); return *(data + i); } // equality operator template
bool operator==(const Blob
&lhs, const Blob
&rhs) { if (lhs.size() != rhs.size()) { return false; } for (size_t i = 0; i < lhs.size(); ++i) { if (lhs[i] != rhs[i]) { return false; } } return true; } // Blob_ptr throws an exception on attempts to access a nonexistent element template
class Blob_ptr { public: // constructor Blob_ptr() : curr(0) { } Blob_ptr(Blob
&a, size_t sz = 0) : wptr(a.data), curr(sz) { } // dereference access T &operator*() const { std::shared_ptr
> p = check(curr, "dereference past end"); return (*p)[curr]; } // increment and decrement Blob_ptr
&operator++(); // prefix Blob_ptr
&operator--(); Blob_ptr
operator++(int); // postfix private: // check returns a shared_ptr to the vector if the check succeeds std::shared_ptr
> check(std::size_t i, const std::string &msg) const; // store a weak_ptr, which means the underlying vector might be destroyed std::weak_ptr
> wptr; std::size_t curr; // current position within the array }; // check member template
std::shared_ptr
> Blob_ptr
::check(std::size_t i, const std::string &msg) const { // is the vector still around std::shared_ptr
> ret = wptr.lock(); if (!ret) // if expired is true, returns a null shared_ptr { throw std::runtime_error("unbound Blob_ptr"); } if (i >= ret->size()) { throw std::out_of_range(msg); } return ret; } // prefix: return a reference to the incremented/decremented object template
Blob_ptr
&Blob_ptr
::operator++() { // if curr already points past the end of the container, // can't increment it check(curr, "increment past end of Blob_ptr"); ++curr; // advance the current state return *this; } template
Blob_ptr
&Blob_ptr
::operator--() { // if curr is zero, decrementing it will yield an invalid subscript --curr; check(-1, "decrement past begin of Blob_ptr"); return *this; } // postfix: increment/decrement the object but return the unchanged value template
Blob_ptr
Blob_ptr
::operator++(int) { // no check needed here; the call to prefix increment will do the check Blob_ptr
ret = *this; // save the current value ++*this; // advance one element; prefix ++ checks the increment return ret; // return the saved state }
/***************************************************
* IDE: VS2010
* FILE: Screen.h
***************************************************/
#include
// forward declaration needed for friend declarations in Screen
template
class Screen;
template
std::istream &operator>>(std::istream &is, Screen
&item);
template
std::ostream &operator<<(std::ostream &os, Screen
&item); template
class Screen { friend std::istream &operator>>
(std::istream &is, Screen
&item); friend std::ostream &operator<<
(std::ostream &os, Screen
&item); public: Screen() : height(N), width(M) { } Screen(unsigned h, unsigned w) : height(h), width(w) { } private: unsigned height; unsigned width; }; // input operator template
std::istream &operator>>
(std::istream &is, Screen
&item) { is >> item.height >> item.width; return is; } // output operator template
std::ostream &operator<<
(std::ostream &os, Screen
&item) { os << "height: " << item.height << ", width: " << item.width << std::endl; return os; } /*************************************************** * IDE: VS2010 * FILE: use_Screen.cpp ***************************************************/ #include "Screen.h" #include
using std::cin; using std::cout; using std::endl; int main(void) { Screen<10, 10> s1; Screen<10, 10> s2(20, 20); cin >> s1; cout << s2; return 0; }