類模板需在前方加上 template <typename T>,將所有需泛型化的型別位置替換為 T。使用時需指定具體型別如 Class<T>。成員函數定義時同樣需加模板參數列表,且類名需改為 Class<T>:: 形式。
/*
* cppprimer.cpp - 類模板與迭代器範例
* Created on: 2013.11.21
* Author: Caroline
* eclipse cdt, gcc 4.8.1
*/
#include <iostream>
#include <vector>
#include <initializer_list>
#include <memory>
#include <cstddef>
template <typename T> class BlobPtr;
template <typename T> class Blob;
template <typename T>
class Blob {
friend class BlobPtr<T>;
public:
typedef T value_type;
typedef typename std::vector<T>::size_type size_type;
Blob() : data(std::make_shared<std::vector<T>>()) {}
Blob(std::initializer_list<T> il)
: data(std::make_shared<std::vector<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;
void check(size_type i, const std::string &msg) const;
};
// 成員函數定義需雙重模板參數
template <typename T>
void Blob<T>::check(size_type i, const std::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");
data->pop_back();
}
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];
}
BlobPtr& operator++(); // 前綴
BlobPtr& operator--();
BlobPtr operator++(int); // 後綴
BlobPtr operator--(int);
private:
std::shared_ptr<std::vector<T>> check(std::size_t, const std::string&) const;
std::weak_ptr<std::vector<T>> wptr; // 弱引用避免循環參考
std::size_t curr;
};
// 前綴遞增:先檢查再遞增
template <typename T>
BlobPtr<T>& BlobPtr<T>::operator++() {
check(curr, "increment past end of BlobPtr");
++curr;
return *this;
}
// 後綴遞增:回傳舊值
template <typename T>
BlobPtr<T> BlobPtr<T>::operator++(int) {
BlobPtr ret = *this;
++*this;
return ret;
}
lock() 檢查有效性{1,2,3} 語法push_back(T&&)