迭代器库-流迭代器
迭代器库提供了五种迭代器的定义,同时还提供了迭代器特征、适配器及相关的工具函数。
迭代器分类
迭代器共有五 (C++17 前)六 (C++17 起)种:遗留输入迭代器 (LegacyInputIterator) 、遗留输出迭代器 (LegacyOutputIterator) 、遗留向前迭代器 (LegacyForwardIterator) 、遗留双向迭代器 (LegacyBidirectionalIterator) 、遗留随机访问迭代器 (LegacyRandomAccessIterator) ,及 遗留连续迭代器 (LegacyContiguousIterator) (C++17 起)。
迭代器的分类的依据并不是迭代器的类型,而是迭代器所支持的操作。换句话说,某个类型只要支持相应的操作,就可以作为迭代器使用。例如,完整对象类型指针支持所有遗留随机访问迭代器 (LegacyRandomAccessIterator) 要求的操作,于是任何需要遗留随机访问迭代器 (LegacyRandomAccessIterator) 的地方都可以使用指针。
迭代器的所有类别(除了遗留输出迭代器 (LegacyOutputIterator) 和遗留连续迭代器 (LegacyContiguousIterator) )能组织到层级中,其中更强力的迭代器类别(如遗留随机访问迭代器 (LegacyRandomAccessIterator) )支持较不强力的类别(例如遗留输入迭代器 (LegacyInputIterator) )的所有操作。若迭代器落入这些类别之一且亦满足遗留输出迭代器 (LegacyOutputIterator) 的要求,则称之为可变 迭代器并且支持输入还有输出。称非可变迭代器为常迭代器。
从 std::basic_streambuf 读取的输入迭代器
std::istreambuf_iterator
| template< class CharT, class Traits = std::char_traits<CharT> > class istreambuf_iterator : public std::iterator< std::input_iterator_tag, | (C++17 前) | |
| template< class CharT, class Traits = std::char_traits<CharT> > | (C++17 起) |
std::istreambuf_iterator 是单趟迭代器,从为之构造迭代器的 std::basic_streambuf 对象读取相继字符。
默认构造的 std::istreambuf_iterator 迭代器被称为流尾迭代器。合法的 std::istreambuf_iterator 抵达底层流结尾时,它变得等于流尾迭代器。解引用或进一步自增它导致未定义行为。
std::istreambuf_iterator 拥有平凡复制构造函数、 constexpr 默认构造函数和平凡析构函数。
成员类型
| 成员类型 | 定义 |
iterator_category | std::input_iterator_tag |
value_type | CharT |
difference_type | Traits::off_type |
pointer | /* unspecified, usually CharT* */ |
reference | CharT |
char_type | CharT |
traits_type | Traits |
int_type | typename traits::int_type |
streambuf_type | std::basic_streambuf<CharT, Traits> |
istream_type | std::basic_istream<CharT, Traits> |
| /* proxy */ | 实现定义的类类型。名称 proxy 仅为说明。proxy 对象保有一个 char_type 字符和一个 streambuf_type* 指针。以 operator* 解引用 proxy 对象得到存储的字符。 |
获得当前字符的副本 若 CharT 拥有成员,则访问当前字符的成员
std::istreambuf_iterator<CharT,Traits>::operator*, operator->
| CharT operator*() const; | (1) | |
| pointer operator->() const; | (2) | (C++11 起) (C++17 前) |
以调用 sbuf_->sgetc() 读取单个字符,其中 sbuf_ 是存储的指向流缓冲的指针。
若迭代器是流尾迭代器则行为未定义。
参数
(无)
返回值
1) 获得字符的值。
2) 未指定类型对象,满足给定一个 istreambuf_iterator i ,表达式 (*i).m 与 i->m 拥有相同效果。
异常
(无)
推进迭代器
std::istreambuf_iterator<CharT,Traits>::operator++, operator++(int)
| istreambuf_iterator& operator++(); | (1) | |
| /* proxy */ operator++(int); | (2) |
以调用 sbuf_->sbumpc() 推进迭代器,其中 sbuf_ 是存储的指向流缓冲的指针。
若迭代器是流尾迭代器则行为未定义。
参数
(无)
返回值
1) *this 。
2) 保有经由 operator*() 获得的当前字符和 sbuf_ 指针的 proxy 对象。以 operator* 解引用 proxy 对象得到存储的字符。
名称 proxy 仅为说明。
异常
(无)
调用示例
#include <iostream>
#include <sstream>
#include <iterator>
#include <numeric>
#include <algorithm>
#include <vector>struct Cell
{int x;int y;Cell() = default;Cell(int a, int b): x(a), y(b) {}Cell(const Cell &cell){x = cell.x;y = cell.y;}Cell(Cell &cell){x = cell.x;y = cell.y;cell.x = 0;cell.y = 0;}Cell &operator +=(const Cell &cell){x += cell.x;y += cell.y;return *this;}Cell &operator +(const Cell &cell){x += cell.x;y += cell.y;return *this;}Cell &operator *(const Cell &cell){x *= cell.x;y *= cell.y;return *this;}Cell &operator ++(){x += 1;y += 1;return *this;}bool operator <(const Cell &cell) const{if (x == cell.x){return y < cell.y;}else{return x < cell.x;}}bool operator ==(const Cell &cell) const{return x == cell.x && y == cell.y;}
};std::ostream &operator<<(std::ostream &os, const Cell &cell)
{os << "{" << cell.x << "," << cell.y << "}";return os;
}std::istream &operator>>(std::istream &is, Cell &cell)
{is >> cell.x;is >> cell.y;return is;
}// 定义一个简单的迭代器适配器
template<typename _Iterator>
class move_iterator : public std::move_iterator<_Iterator>
{
public:// 使用基类的构造函数using std::move_iterator<_Iterator>::move_iterator;// 可以在此添加其他成员函数,如有需要
};template< class BDIter >
void alg(BDIter, BDIter, std::input_iterator_tag)
{//遗留输入迭代器std::cout << "alg() called for input iterator" << std::endl;
}template< class BDIter >
void alg(BDIter, BDIter, std::output_iterator_tag)
{//遗留输出迭代器std::cout << "alg() called for output iterator" << std::endl;
}template< class BDIter >
void alg(BDIter, BDIter, std::forward_iterator_tag)
{//遗留向前迭代器std::cout << "alg() called for forward iterator" << std::endl;
}template< class BDIter >
void alg(BDIter, BDIter, std::bidirectional_iterator_tag)
{//遗留双向迭代器std::cout << "alg() called for bidirectional iterator" << std::endl;
}template <class RAIter>
void alg(RAIter, RAIter, std::random_access_iterator_tag)
{//遗留随机访问迭代器std::cout << "alg() called for random-access iterator" << std::endl;
}template< class Iter >
void alg(Iter first, Iter last)
{alg(first, last,typename std::iterator_traits<Iter>::iterator_category());
}std::ostringstream &operator<<(std::ostringstream &os, const Cell &cell)
{os << "{" << std::to_string(cell.x) << "," << std::to_string(cell.y) << "}";return os;
}std::istringstream &operator>>(std::istringstream &is, Cell &cell)
{is >> cell.x;is >> cell.y;return is;
}int main()
{// 典型使用:输入流以一对迭代器表示std::istringstream istringstream1("Hello, world");std::vector<char> vector1((std::istreambuf_iterator<char>(istringstream1)),std::istreambuf_iterator<char>());std::cout << "vector1 has " << vector1.size() << " bytes. ";vector1.push_back('\0');std::cout << "it holds \"" << &vector1[0] << std::endl;// 单趟生态的演示std::istringstream istringstream2("abcdefg");std::istreambuf_iterator<char>istreambuf_iterator1(istringstream2), istreambuf_iterator2(istringstream2);std::cout << "istreambuf_iterator1 returns " << *istreambuf_iterator1 << std::endl;std::cout << "istreambuf_iterator2 returns " << *istreambuf_iterator2 << std::endl;++istreambuf_iterator1;std::cout << "after incrementing istreambuf_iterator1, but not istreambuf_iterator2" << std::endl;std::cout << "istreambuf_iterator1 returns " << *istreambuf_iterator1 << std::endl;std::cout << "istreambuf_iterator2 returns " << *istreambuf_iterator2 << std::endl;++istreambuf_iterator2; // 这使得 *i2 的表观值从 'a' 跳到 'c'std::cout << "after incrementing istreambuf_iterator2, but not istreambuf_iterator1" << std::endl;std::cout << "istreambuf_iterator1 returns " << *istreambuf_iterator1 << std::endl;std::cout << "istreambuf_iterator2 returns " << *istreambuf_iterator2 << std::endl;alg(istreambuf_iterator1, istreambuf_iterator1);return 0;
}
输出
vector1 has 12 bytes. it holds "Hello, world
istreambuf_iterator1 returns a
istreambuf_iterator2 returns a
after incrementing istreambuf_iterator1, but not istreambuf_iterator2
istreambuf_iterator1 returns b
istreambuf_iterator2 returns a
after incrementing istreambuf_iterator2, but not istreambuf_iterator1
istreambuf_iterator1 returns b
istreambuf_iterator2 returns c
alg() called for input iterator
