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 即可。
仿函数配接器的就比较多,这里不叙述了