//类模板
//与函数模板不同之处是,编译器不能为类模板推断模板参数类型
//一个类模板的每个实例都形成一个独立的类。
//默认情况下一个实例化的类模板,其成员只有在使用时才被实例化
template<typename T>
class Blob {
public:
typedef T value_type;
typedef typename std::vector<T>::size_type size_type;
//构造函数
Blob() = default;
Blob(std::initializer_list<T> il);
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(T&& t) { data->push_back(std::move(t)); }
void pop_back();
T& back();
T& operator[](size_type i);
private:
std::shared_ptr<std::vector<T>> data;
//若data[i]无效,则抛出msg
void check(size_type i, const string& msg)const;
};
//在类外定义一个成员时
//必须说明成员属于哪个类。而且,从一个模板生成的类的名字中必须包含其模板实参。
//模板实参与模板形参相同
//成员函数
template<typename T>
void Blob<T>::check(size_type i, const string& msg) const
{
if (i >= data->size())
{
throw std::out_of_range(msg);
}
}
template<typename T>
T& Blob<T>::back()
{
check(0, "back on empty Blob");
return data->back();
}
template<typename T>
T& Blob<T>::operator[](size_type i)
{
check(i, "subscript out of range");
return (*data)[i];
}
template<typename T>
void Blob<T>::pop_back()
{
check(0, "pop_back on empty Blob");
}
//构造函数
template<typename T>
Blob<T>::Blob(std::initializer_list<T> il) :
data(std::make_shared<vector<T>>(il)) {}
//在类代码内简化模板类名的使用
//在类模板自己的作用域中可以使用模板名而不提供实参
template<typename T>
class BlobPtr {
public:
BlobPtr() :curr(0) {}
BlobPtr(Blob<T>& a, size_t sz = 0) :wptr(a.data), curr(sz) {}
T& operator*()const
{
auto p = check(curr, "dereference past end");
return (*p)[curr];//(*p)为对象指向的vector
}
//递增和递减,返回的是BlobPtr&而不是BlobPtr<T>&
BlobPtr& operator++();
BlobPtr& operator--();
private:
//若检查成功,check返回一个指向vector的shared_ptr
std::shared_ptr<std::vector<T>> check(std::size_t, const string&)const;
//保存一个weak_ptr,表示底层vector可能被销毁
std::weak_ptr<std::vector<T>> wptr;
std::size_t curr;//数组中的当前位置
};
//在类模板外使用类模板名
//在类模板外定义其成员时,并不在类的作用域中,直到遇到类名才表示进入类的作用域。
template<typename T>
BlobPtr<T> BlobPtr<T>::operator++(int)
{
BlobPtr<T> ret = *this;
++* this;
return ret;
}
int main()
{
//类模板
Blob<int> ia;
Blob<int> ia2 = { 0,1,2,3,4 };
Blob<string> istr = { "aaa","bbb","ccc" };
cout << istr.size() << endl;
return 0;
}