STL 所提供的各種配接器中,改變仿函數 (functors) 接口者,我們稱爲 function adapter,改變容器 (containers) 接口者,我們稱爲 container adapter,改變迭代器 (iterators) 接口者,我們稱爲 iterator adapter。
//
//
應用於容器:STL 所提供的兩個容器,queue 和 stack,其實都是一種配接器。它們的內部都有一個 deque 容器。所有的操作都是通過這個 deque 容器來實現的,即轉調用這個容器的操作。同時,根據 stack 或者 deque 自己的需求定義出需要的接口即可。
//
//
應用於迭代器:包括 insert iterators,reverse iterators,iostream iterators。
//
//
應用於仿函數:functor adapters 是所有配接器中數量最龐大的一個族羣,其配接靈活度也是前兩者所不能及,可以配接、配接、再配接。這些配接操作主要包括 繫結(bind),否定(negate),組合(compose),以及對一般函數或成員函數的修飾 (使其成爲一個仿函數)。
//
//
插入迭代器,insert iterators
back_insert_iterators 源碼:
template <class Container>
class back_insert_iterator {
protected:
Container* container; // 底層容器
public:
typedef output_iterator_tag iterator_category; // 注意類型
typedef void value_type;
typedef void difference_type;
typedef void pointer;
typedef void reference;
// 下面這個 constructor 使 back_insert_iterator 與容器綁定起來
explicit back_insert_iterator(Container &x) : container(&x) { }
back_insert_iterator<Container>&
operator= (const typename Container::value_type &value) {
container -> push_back(value); // 這裏是關鍵,轉而調用 push_back()
return *this;
}
// 以下三個操作符對 back_insert_iterator 不起作用
// 都是返回 back_insert_iterator 自己
back_insert_iterator<Container>& operator*() { return *this; }
back_insert_iterator<Container>& operator++() { return *this; }
back_insert_iterator<Container>& operator++(int) { return *this; }
};
// !! 通常,我們都調用這個輔助函數來使用 back_insert_iterator
template <class Container>
inline back_insert_iterator<Container> back_inserter(Container &x) {
return back_insert_iterator<Container>(x);
}
對於 front_insert_iterator 實現源碼,幾乎和上面一樣。除了在第 17 行採用的是 push_front 之外沒有差別。
//
//
而對於 insert_iterator 實現源碼,根據 insert() 函數,我們知道,不僅需要知道容器是哪個,而且還要指明插入的位置。所以 insert_iterator 源碼是這樣的:
template <class Container>
class insert_iterator {
protected:
Container* container; // 底層容器
typename Container::iterator iter;
public:
// 與上面一樣的 5 個 typedef
// 下面這個 constructor 使 insert_iterator 與容器綁定起來
insert_iterator(Container &x, typename Container::iterator i) : container(&x), iter(i) { }
insert_iterator<Container>&
operator= (const typename Container::value_type &value) {
iter = container -> insert(iter, value);
++ iter; // !!這裏需要注意,使 insert iterator 永遠隨着其目標貼身移動
return *this;
}
// 與上面相同的不起作用的 operator*(), operator++(), operator++(int)
};
// !! 通常,我們都調用這個輔助函數來使用 insert_iterator
template <class Container, class Iterator>
inline back_insert_iterator<Container> inserter(Container &x, Iterator i) {
typedef typename Container::iterator iter;
return insert_iterator<Container>(x, iter(i));
}
反向迭代器 reverse iterators
反向迭代器 reverse iterators,就是將迭代器的行爲倒轉。它的所有操作都和正向迭代器相反。例如,對反向迭代器,++ iter 其實就是正向迭代器的 – iter。
//
//
同時,調用這個迭代器,會從尾到頭處理序列。例如:find(v.rbegin(), v.rend(), value),就會從尾到頭進行對 value 的查找操作。
//
//
而且還需要知道一點,反向迭代器的位置其實是其正向迭代器的對應位置 - 1,這一點很重要。原正向迭代器表示的範圍爲 [begin(), end());到反向迭代器,就應該是(rbegin(), rend()],所以會有上面的關係。
//
//
有了上面那一點,其實 reverse iterators 的實現就並不複雜了。在類中記錄對應的正向迭代器的位置 cur 即可,解引用即解引用 cur - 1 的位置;其他操作通通反着寫(operator++,其實是 – cur 這樣。)
這裏就不貼上代碼了。
//
//
iostream iterators
分爲 istream _iterator 有 ostream_iterator,會分別綁定到一個輸入流,輸出流。與插入迭代器很類型,對其的賦值操作就分別相當於在綁定的輸入流上進行輸入,或者在綁定的輸出流上進行輸出。
//
//
所以我們可以想象大體實現,除了與之前類似的 5 個 typedef 之外,我們需要在類內部指定一個 istream 流或者 ostream 流,在構造函數中進行綁定。然後重載 operator*() 等運算符即可。
//
//
istream_iterator 中,迭代器每前進一次就代表進行一次輸入。而 ostream_iterator 中,每進行一次賦值就代表要輸出一次。
//
//
不過需要注意:istream_iterator 的讀入需要每一次都確定流的狀態。(是否遇到了 eof 或者 讀入的類型與要求的類型不符)。對於 ostream_iterator 中直接進行輸出即可。
貼上一份具體的 istream_iterator 代碼:
template <class T, class Distance = ptrdiff_t>
class istream_iterator {
friend bool
operator== __STL_NULL_TMPL_ARGS(const istream_iterator<T, Distance>& x,
const istream_iterator<T, Distance>& y);
protected:
istream *stream;
T value;
bool end_marker;
void read() {
end_marker = (*stream) ? true : false;
if(end_marker) *stream >> value; // 關鍵
// 以上,輸入之後,stream 的狀態可能改變,所以下面再判斷一次以決定 end_marker
end_marker = (*stream) ? true : false;
}
public:
typedef input_iterator_tag iterator_category;
typedef T value_type;
typedef Distance difference_type;
typedef const T* pointer; // 流不可複製
typedef const T& reference;
istream_iterator() : stream(&cin), end_marker(false) {}
istream_iterator(istream &s): stream(&s) { read(); }
// 以上兩行的用法:
// istream_iterator<int> eof; 造成 end_marker 爲 false,所以可以當做一個流的 eof 使用
// istream_iterator<int> initer(cin); 會引發一個 read()! 所以創建時,
// 會一直保持着等待這個輸入
reference operator*() const { return value; }
pointer operator->() const { return &(operator*()); }
// 迭代器前進一個位置就代表要讀取一次
istream_iterator<T, Distance>& operator++() {
read();
return *this;
}
istream_iterator<T, Distance>& operator++(int) {
istream_iterator<T, Distance> tmp = *this;
read();
return tmp;
}
};
所以我們配合插入迭代器和 copy 函數,可以很簡單的是進行輸入:
vector<int> v;
istream<int> in(cin);
istream<int> eof;
copy(in, eof, back_inserter(v));
ostream_iterator 代碼就不貼上了。主要是 重載 operator=(),而 operator*() 以及前置後置 operator++ 則沒有任何意義,直接返回 *this 即可。
仿函數配接器的就比較多,這裏不敘述了