C++ primer 5th 课后练习
熟悉模板的编写
将之前的StrBlob及其伴随类改写成模板 支持多种类型
其中Blob的数据成员是shared_ptr<vector> 多个对象共享一个vetor<T> 支持一些基于vector<T>的操作
BlobPtr和ConstBlobPtr分别是Blob的非常量、常量的自定义迭代器
//16.12 16.13 编写自己版本的Blob和BlobPtr模板 并为BlobPtr的相等和关系运算符选择合适的友好关系类型
//声明 重载operator和在Blob中声明友元时用到
template<typename> class Blob;
template<typename> class BlobPtr;
template<typename> class ConstBlobPtr;
//==============================================================================
//
// Blob - custom vector
//
//==============================================================================
//.h
//二元运算符要根据不同模板实参类型分别定义 因此需要用到和Blob(Ptr,consPtr)相同的模板实参 使用模板实参就需要在前面声明模板实参
//前置声明 在BlobPtr中声明友元所需要的
template<typename T> bool operator==(const Blob<T>&,const Blob<T>&);
template<typename T> bool operator!=(const Blob<T>&,const Blob<T>&);
template<typename T> bool operator< (const Blob<T>&,const Blob<T>&);
template<typename T> bool operator<=(const Blob<T>&,const Blob<T>&);
template<typename T> bool operator> (const Blob<T>&,const Blob<T>&);
template<typename T> bool operator>=(const Blob<T>&,const Blob<T>&);
template<typename T> class Blob {
//注:类内作用域 使用模板时 可以省略模板参数列表 但是在类外定义或声明时必须加上模板参数列表 template<typename T>
friend class BlobPtr<T>;
friend class ConstBlobPtr<T>;
//注:类模板中 将运算符重载函数声明为友元时 必须在运算符后跟上模板实参<T>
friend bool operator==<T>(const Blob<T>&, const Blob<T>&);
friend bool operator!=<T>(const Blob<T>&, const Blob<T>&);
friend bool operator< <T>(const Blob<T>&, const Blob<T>&);
friend bool operator<=<T>(const Blob<T>&, const Blob<T>&);
friend bool operator> <T>(const Blob<T>&, const Blob<T>&);
friend bool operator>=<T>(const Blob<T>&, const Blob<T>&);
public:
using size_type = typename vector<T>::size_type;
Blob() :data(make_shared<vector<T>>()) {
}//构造一个新的shared_ptr
Blob(initializer_list<T> il):data(make_shared<vector<T>>(il)){
}
Blob(const Blob<T>& blob) :data(blob.data){
}
Blob(const Blob<T>&& blob)noexcept :data(std::move(blob.data)){
}//移动构造函数
Blob& operator=(const Blob<T>&);
Blob& operator=(Blob<T>&&) noexcept;//移动赋值运算符
T& operator[](size_t n) ;//注 容器大小类型一般使用size_type 下标一般使用size_t
const T& operator[](size_t n) const;
size_type size()const {
return data->size();
}
bool empty() const {
return data->empty();
}
void push_back(const T& t) {
data->push_back(t);
}
void push_back(const T&& t) {
data->push_back(std::move(t));
}
void pop_back();
T& front();
const T& front() const;
T& back();
const T& back() const;
BlobPtr<T> begin();
BlobPtr<T> end();
ConstBlobPtr<T> cbegin() const;
ConstBlobPtr<T> cend() const;
private:
shared_ptr<vector<T>> data;
void check(size_type,const string&) const;
};
//.cpp
//------------------------------------------------------------------------------
// friend function.
//------------------------------------------------------------------------------
template<typename T> bool operator==(const Blob<T>& lhs,const Blob<T>& rhs) {
return *lhs.data == *rhs.data;
}
template<typename T> bool operator!=(const Blob<T>& lhs,const Blob<T>& rhs) {
return !(lhs == rhs);
}
template<typename T> bool operator<(const Blob<T>& lhs,const Blob<T>& rhs) {
//小于符号重载使用标准库函数lexicographical_compare比较 按字典序列比较两个列表
return lexicographical_compare(lhs.data->begin(),lhs.data->end(),rhs.data->begin(),rhs.data->end());
}
template<typename T> bool operator>(const Blob<T>& lhs,const Blob<T>& rhs) {
return rhs<lhs;
}
template<typename T> bool operator<=(const Blob<