目录
16.1.1 函数模板
练习16.4 模拟实现find标准库函数
练习16.5 print函数,打印任意元素类型,任意大小的数组。
练习16.6 模拟接收一个数组实参的begin end标准库函数的实现。
16.1.2 类模板
Blob 类模板和BlobPtr类模板实现
练习16.14 Screen类模板,用非类型模板参数定义Screen的高和宽
16.1.3 模板参数
默认模板实参: compare函数的进一步定义。
练习 16.19 16.20
16.1.4 成员模板
练习16.21 DebugDelete类实现,普通类的成员模板。
16.1.5 控制实例化
16.1.6 效率与灵活性
练习16.28
16.1.1 函数模板
template// 其实就是代表一个类型而已,也没啥。 int compare(const T &v1, const T &v2){ if(v1 < v2) return -1; if(v2 < v1) return 1; return 0; }
模板实现compare函数,用于任意两种相同类型的比较,前提是,此类型支持<运算符。
练习16.4 模拟实现find标准库函数
template
T1 my_find(const T1& beg,const T1& end,const T2& value){
for(auto i = beg; i != end; ++i){
if(*i == value)
return i;
}
return end;
}
练习16.5 print函数,打印任意元素类型,任意大小的数组。
template // sz是unsigned类型常量。
void print(const T (&arr)[sz]){
for(int i = 0; i != sz; ++i){
cout<
template// sz是unsigned类型常量。 void print(const T (&arr)[sz]){ for(int i = 0; i != sz; ++i){ cout<
这里用到了非类型模板参数,其中的unsigned int sz就是一个非类型模板参数,可用于模板中需要常量的地方,根据传来的函数实参进行推断此非类型模板参数的模板实参。比如 第一个print中sz = 5,第二个print中sz = 3
练习16.6 模拟接收一个数组实参的begin end标准库函数的实现。
template
T* my_begin(T (&arr)[sz]){
return &arr[0];
}
template
T* my_end(T (&arr)[sz]){
return &arr[0] + sz;
}
template
const T* my_cbegin(const T (&arr)[sz]){
const T* ret = &arr[0];
return ret;
}
template
const T* my_cend(const T (&arr)[sz]){
const T* ret = &arr[0] + sz;
return ret;
}
16.1.2 类模板
Blob 类模板和BlobPtr类模板实现
template class BlobPtr;
template class Blob;
template
bool operator==(const Blob&, const Blob&);
template
class Blob{
friend class BlobPtr;
friend bool operator== (const Blob&, const Blob&);
public:
using size_type = typename vector::size_type;
template Blob(It t1, It t2);
// : data(make_shared>(t1,t2)) {}
Blob(): data(make_shared>()) {}
Blob(initializer_list il):data(make_shared>(il)) {}
size_type size()const { return data->size(); }
bool empty()const { return data->empty(); }
void push_back(const T& ele) { data->push_back(ele); }
void push_back(T &&ele) { data->push_back(std::move(ele)); }
void pop_back();
T& back();
const T& back()const;
T& operator[](size_type i);
const T& operator[](size_type i)const;
private:
shared_ptr> data;
void check(size_type i, const string& msg)const;
};
template template Blob::Blob(It t1, It t2):data(make_shared>(t1,t2)) {}
template void Blob::check(size_type i, const string& msg)const{
if(i>=data->size())
throw out_of_range(msg);
}
template void Blob::pop_back(){
check(0,"pop_back on empty Blob");
data->pop_back();
}
template
T& Blob::back(){
check(0,"back on empty Blob");
return data->back();
}
template
const T& Blob::back()const{
check(0,"beck on empty Blob");
return data->back();
}
template
T& Blob::operator[](size_type i){
check(i,"subscript out of range");
return (*data)[i];
}
template
const T& Blob::operator[](size_type i)const{
check(i,"subscript out of range");
return (*data)[i];
}
template
class BlobPtr
{
public:
BlobPtr(): curr(0) {}
BlobPtr(Blob& a, size_t sz = 0): wptr(a.data), curr(sz) {} // 仅一个Blob对象作为参数,curr默认为0;
T& operator*() const{
auto p = check(curr, "dereference past end");
return (*p)[curr];
}
// prefix
BlobPtr& operator++();
BlobPtr& operator--();
// postfix
BlobPtr operator ++(int);
BlobPtr operator --(int);
private:
// returns a shared_ptr to the vector if the check succeeds;
shared_ptr> check(size_t, const string& msg)const;
weak_ptr> wptr;
size_t curr;
};
template
shared_ptr> BlobPtr::check(size_t index, const string& msg)const{
auto p = wptr.lock();
if (p) {
if (p->size() > index) {
return p;
} else {
throw std::out_of_range(msg);
}
} else {
throw "unbind BlobPtr";
}
}
// prefix ++
template BlobPtr& BlobPtr::operator++(){
check(curr, "increment past end of StrBlob");
++curr;
return *this;
}
template BlobPtr& BlobPtr::operator--(){
--curr;
check(-1, "decrease index pass the beg");
return *this;
}
template BlobPtr BlobPtr::operator++(int){
BlobPtr ret = *this;
++*this; // 利用前置加加检验递增是否合法
return ret;
}
template BlobPtr BlobPtr::operator--(int){
BlobPtr ret = *this;
--*this;
return ret;
}
Blob类模板,就是很简单的一个类模板的练习,模拟vector,根据模板实参确定保存的元素类型。剩余的就是一些定义,声明的规则了。还有,比如使用类模板的类型成员,需要声明typename,类模板的模板成员,如Blob类的接收两个迭代器参数的构造函数,就是一个函数模板,定义时,类模板的模板参数列表和函数模板的模板参数列表都需要声明。以及BlobPtr类定义时,在参数的作用域范围内,返回值BlobPtr可以省略模板实参,这都是一些小的规则而已。
练习16.14 Screen类模板,用非类型模板参数定义Screen的高和宽
#ifndef C__PRIMER_SCREEN_16_14_H
#define C__PRIMER_SCREEN_16_14_H
#include
#include
using namespace std;
template class Screen; // 声明这个,下面的<<>>声明才可以
template ostream& operator<<(ostream& os, const Screen&);
template istream& operator>>(istream& is, Screen&);
template
class Screen{
friend ostream& operator<< (ostream&,const Screen&);
friend istream& operator>> (istream&,Screen&);
public:
Screen() : contents(W*H,' ') {}
Screen(char c):contents(W*H, c) {}
char get()const { return contents[cursor]; } // 隐式内联
inline char get(int, int)const; // 显式内联
Screen& clear(char c = bkground);
private:
static const char bkground = ' ';
public:
Screen& move(int,int);
Screen& set(char);
Screen& set(int,int,char);
Screen& display(ostream& os)
{ do_display(os); return *this; }
const Screen& display(ostream& os)const
{ do_display(os); return *this;}
private:
//实际完成显式的函数
void do_display(ostream& os)const {os< inline char Screen::get(int r,int c)const{
return contents[r*W+c];
}
template Screen& Screen::clear(char c){
contents = string(H*W,c);
return *this;
}
template inline Screen& Screen::move(int r,int c){
cursor = r*W+c;
return *this;
}
template
Screen& Screen::set(char c){
contents[cursor] = c;
return *this;
}
template
Screen& Screen::set(int r,int col,char ch){
contents[r*W+col] = ch;
return *this;
}
template ostream& operator<<(ostream& os, const Screen& s){
os< istream& operator>>(istream& is, Screen& s){
string t;
cin >> t;
s.contents = t.substr(0,H*W);
return is;
}
#endif //C__PRIMER_SCREEN_16_14_H
用非类型模板实参确定Screen的高和宽,而不是之前的把高和宽定义为私有数据成员。也是一个练习而已。注意<< >> 运算符重载函数,仍然需要模板,且友元声明时,
friend ostream& operator<< (ostream&,const Screen&);
friend istream& operator>> (istream&,Screen&);
需要加上。还有类模板的声明,以及函数声明。
16.1.3 模板参数
Blob类模板,就是很简单的一个类模板的练习,模拟vector,根据模板实参确定保存的元素类型。剩余的就是一些定义,声明的规则了。还有,比如使用类模板的类型成员,需要声明typename,类模板的模板成员,如Blob类的接收两个迭代器参数的构造函数,就是一个函数模板,定义时,类模板的模板参数列表和函数模板的模板参数列表都需要声明。以及BlobPtr类定义时,在参数的作用域范围内,返回值BlobPtr可以省略模板实参,这都是一些小的规则而已。
#ifndef C__PRIMER_SCREEN_16_14_H #define C__PRIMER_SCREEN_16_14_H #include#include using namespace std; template class Screen; // 声明这个,下面的<<>>声明才可以 template ostream& operator<<(ostream& os, const Screen &); template istream& operator>>(istream& is, Screen &); template class Screen{ friend ostream& operator<< (ostream&,const Screen &); friend istream& operator>> (istream&,Screen &); public: Screen() : contents(W*H,' ') {} Screen(char c):contents(W*H, c) {} char get()const { return contents[cursor]; } // 隐式内联 inline char get(int, int)const; // 显式内联 Screen& clear(char c = bkground); private: static const char bkground = ' '; public: Screen& move(int,int); Screen& set(char); Screen& set(int,int,char); Screen& display(ostream& os) { do_display(os); return *this; } const Screen& display(ostream& os)const { do_display(os); return *this;} private: //实际完成显式的函数 void do_display(ostream& os)const {os< inline char Screen ::get(int r,int c)const{ return contents[r*W+c]; } template Screen & Screen ::clear(char c){ contents = string(H*W,c); return *this; } template inline Screen & Screen ::move(int r,int c){ cursor = r*W+c; return *this; } template Screen & Screen ::set(char c){ contents[cursor] = c; return *this; } template Screen & Screen ::set(int r,int col,char ch){ contents[r*W+col] = ch; return *this; } template ostream& operator<<(ostream& os, const Screen & s){ os< istream& operator>>(istream& is, Screen & s){ string t; cin >> t; s.contents = t.substr(0,H*W); return is; } #endif //C__PRIMER_SCREEN_16_14_H
用非类型模板实参确定Screen的高和宽,而不是之前的把高和宽定义为私有数据成员。也是一个练习而已。注意<< >> 运算符重载函数,仍然需要模板,且友元声明时,
friend ostream& operator<<
(ostream&,const Screen &);
friend istream& operator>>(istream&,Screen &); 需要加上
。还有类模板的声明,以及函数声明。
16.1.3 模板参数
默认模板实参: compare函数的进一步定义。
template < typename T, typename F = less >
int compare(const T& v1, const T& v2, F f = F()){
if(f(v1,v2))
return -1;
if(f(v2,v1))
return 1;
return 0;
}
练习 16.19 16.20
// 16.19
template
void print(const T& v){
for(typename T::size_type sz = 0; sz!=v.size();++sz) {
cout << v[sz] << " ";
}
}
template
void print_2(const T& v){
for(auto i = v.begin(); i != v.end(); ++i){
cout<<*i<<" ";
}
cout<
使用类的类型成员
16.1.4 成员模板
练习16.21 DebugDelete类实现,普通类的成员模板。
// 16.1.4
class DebugDelete
{
public:
explicit DebugDelete(ostream& o = cerr): os(o) {}
template void operator() (T* p)const { cout<<"deleting unique_ptr"<
16.1.5 控制实例化
........
16.1.6 效率与灵活性
练习16.28 shared_ptr unique_ptr简单实现
// 16.1.6 效率与灵活性 test16_28
template
class Shared_p{
public:
Shared_p():p(nullptr), use(nullptr){}
// shared_p p(new int(1));
explicit Shared_p(T* pt):p(pt), use(new size_t(1)) {}
Shared_p(const Shared_p& sp): p(sp.p),use(sp.use){
if(use) ++*use;
}
Shared_p& operator=(const Shared_p& sp);
~Shared_p();
T& operator*() { return *p; }
T& operator*()const { return *p; }
private:
T* p;
size_t* use;
};
template Shared_p& Shared_p::operator=(const Shared_p& rhs){
if(rhs.use)
++*use;
if(use && --*use == 0) {
delete p;
delete use;
}
p = rhs.p;
use = rhs.use;
return *this;
}
template Shared_p::~Shared_p(){
if(use && --*use == 0){
delete use;
delete p;
}
}
template
Shared_p make_shared(Args&&... args){
return Shared_p(new T(forward(args)...));
}
template
class UP
{
public:
UP():p(nullptr){}
explicit UP(T* pt):p(pt){}
UP(const UP&) = delete;
UP& operator=(const UP&)=delete;
~UP(){
if(p)
delete p;
}
T* release(){
T* ret = p;
p = nullptr;
return ret;
}
T* reset(T* new_p = nullptr){
if(p)
delete p;
p = new_p;
}
T& operator*() { return *p; }
T* operator*()const { return *p; }
private:
T* p;
};
// 16.19 templatevoid print(const T& v){ for(typename T::size_type sz = 0; sz!=v.size();++sz) { cout << v[sz] << " "; } } template void print_2(const T& v){ for(auto i = v.begin(); i != v.end(); ++i){ cout<<*i<<" "; } cout< 使用类的类型成员
16.1.4 成员模板
练习16.21 DebugDelete类实现,普通类的成员模板。
// 16.1.4 class DebugDelete { public: explicit DebugDelete(ostream& o = cerr): os(o) {} templatevoid operator() (T* p)const { cout<<"deleting unique_ptr"< 16.1.5 控制实例化
........
16.1.6 效率与灵活性
练习16.28 shared_ptr unique_ptr简单实现
// 16.1.6 效率与灵活性 test16_28 templateclass Shared_p{ public: Shared_p():p(nullptr), use(nullptr){} // shared_p p(new int(1)); explicit Shared_p(T* pt):p(pt), use(new size_t(1)) {} Shared_p(const Shared_p& sp): p(sp.p),use(sp.use){ if(use) ++*use; } Shared_p& operator=(const Shared_p& sp); ~Shared_p(); T& operator*() { return *p; } T& operator*()const { return *p; } private: T* p; size_t* use; }; template Shared_p & Shared_p ::operator=(const Shared_p& rhs){ if(rhs.use) ++*use; if(use && --*use == 0) { delete p; delete use; } p = rhs.p; use = rhs.use; return *this; } template Shared_p ::~Shared_p(){ if(use && --*use == 0){ delete use; delete p; } } template Shared_p make_shared(Args&&... args){ return Shared_p (new T(forward(args)...)); } template class UP { public: UP():p(nullptr){} explicit UP(T* pt):p(pt){} UP(const UP&) = delete; UP& operator=(const UP&)=delete; ~UP(){ if(p) delete p; } T* release(){ T* ret = p; p = nullptr; return ret; } T* reset(T* new_p = nullptr){ if(p) delete p; p = new_p; } T& operator*() { return *p; } T* operator*()const { return *p; } private: T* p; };



