迭代器庫-流迭代器
?
迭代器庫提供了五種迭代器的定義,同時還提供了迭代器特征、適配器及相關的工具函數。
迭代器分類
迭代器共有五 (C++17 前)六 (C++17 起)種:遺留輸入迭代器 (LegacyInputIterator) 、遺留輸出迭代器 (LegacyOutputIterator) 、遺留向前迭代器 (LegacyForwardIterator) 、遺留雙向迭代器 (LegacyBidirectionalIterator) 、遺留隨機訪問迭代器 (LegacyRandomAccessIterator) ,及 遺留連續迭代器 (LegacyContiguousIterator) (C++17 起)。
迭代器的分類的依據并不是迭代器的類型,而是迭代器所支持的操作。換句話說,某個類型只要支持相應的操作,就可以作為迭代器使用。例如,完整對象類型指針支持所有遺留隨機訪問迭代器 (LegacyRandomAccessIterator) 要求的操作,于是任何需要遺留隨機訪問迭代器 (LegacyRandomAccessIterator) 的地方都可以使用指針。
迭代器的所有類別(除了遺留輸出迭代器 (LegacyOutputIterator) 和遺留連續迭代器 (LegacyContiguousIterator) )能組織到層級中,其中更強力的迭代器類別(如遺留隨機訪問迭代器 (LegacyRandomAccessIterator) )支持較不強力的類別(例如遺留輸入迭代器 (LegacyInputIterator) )的所有操作。若迭代器落入這些類別之一且亦滿足遺留輸出迭代器 (LegacyOutputIterator) 的要求,則稱之為可變 迭代器并且支持輸入還有輸出。稱非可變迭代器為常迭代器。
寫入 std::basic_streambuf 的輸出迭代器
std::ostreambuf_iterator
template< class CharT, class Traits = std::char_traits<CharT> > class ostreambuf_iterator : public std::iterator<std::output_iterator_tag, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?void, void, void, void> | (C++17 前) | |
template< class CharT, class Traits = std::char_traits<CharT> > | (C++17 起) |
std::ostreambuf_iterator
是單趟遺留輸出迭代器 (LegacyOutputIterator) ,寫入相繼元素到為之創建迭代器的 std::basic_streambuf 對象。實際寫操作在賦值給迭代器(無論是否解引用)時進行。自增 std::ostreambuf_iterator
是無操作。
典型實現中, std::ostreambuf_iterator
僅有的數據成員是指向關聯 std::basic_streambuf
的指針,和指示是否抵達文件尾條件的布爾標志。
成員類型
成員類型 | 定義 |
iterator_category | std::output_iterator_tag |
value_type | void |
difference_type | void |
pointer | void |
reference | void |
char_type | CharT |
traits_type | Traits |
streambuf_type | std::basic_streambuf<CharT, Traits> |
ostream_type | std::basic_ostream<CharT, Traits> |
要求通過從 std::iterator<std::output_iterator_tag, void, void, void, void> 繼承獲得成員類型 | (C++17 前) |
成員函數
(構造函數) | 構造新的 ostreambuf_iterator (公開成員函數) |
(析構函數) (隱式聲明) | 銷毀 ostreambuf_iterator (公開成員函數) |
operator= | 寫字符到關聯的輸出序列 (公開成員函數) |
operator* | 無操作 (公開成員函數) |
operator++operator++(int) | 無操作 (公開成員函數) |
failed | 測試是否輸出失敗 (公開成員函數) |
寫字符到關聯的輸出序列
std::ostreambuf_iterator<CharT,Traits>::operator=
ostreambuf_iterator& operator=( CharT c ); |
若 failed() 返回 false ,則用 pbuf->sputc(c) 插入 c
到關聯的輸出流緩沖,其中 pbuf
是 streambuf_type*
類型的私有成員。否則,不做任何事。
若調用 pbuf->sputc(c) 返回 Traits::eof ,則設置 failed() 標志為 true 。
參數
c | - | 要插入的字符 |
返回值
*this
無操作
std::ostreambuf_iterator<CharT,Traits>::operator*
ostreambuf_iterator& operator*(); |
不做任何事,提供此函數以滿足遺留輸出迭代器 (LegacyOutputIterator) 的要求。
它返回迭代器自身,這使得可以用諸如 *iter = value 的代碼輸出(插入)值到底層的流。
參數
(無)
返回值
*this
無操作
std::ostreambuf_iterator<CharT,Traits>::operator++
ostreambuf_iterator& operator++(); | ||
ostreambuf_iterator& operator++( int ); |
不做任何事。提供這些運算符以滿足遺留輸出迭代器 (LegacyOutputIterator) 的要求。它們使得表達式 *iter++=value 和 *++iter=value 可用于輸出(插入)值到底層的流。
參數
(無)
返回值
*this
測試是否輸出失敗
std::ostreambuf_iterator<CharT,Traits>::failed
bool failed() const throw(); | (C++11 前) | |
bool failed() const noexcept; | (C++11 起) |
若迭代器遇到文件尾條件,即若先前對 std::basic_streambuf::sputc (由 operator=
執行)的調用返回 Traits::eof ,則返回 true。
參數
(無)
返回值
若迭代器在輸出時已遇到文件尾條件則為 true ,否則為 false 。
調用示例
#include <iostream>
#include <sstream>
#include <iterator>
#include <fstream>
#include <numeric>
#include <algorithm>
#include <vector>
#include <time.h>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());
}int main()
{std::mt19937 g{std::random_device{}()};srand((unsigned)time(NULL));std::cout << std::boolalpha;std::string string = "This is an example";std::copy(string.cbegin(), string.cend(), std::ostreambuf_iterator<char>(std::cout));std::cout << std::endl;std::basic_filebuf<char> basic_filebuf;basic_filebuf.open("ostreambuf_iterator.txt", std::ios::out);std::ostreambuf_iterator<char> ostreambuf_iterator1(&basic_filebuf);std::ostreambuf_iterator<wchar_t> ostreambuf_iterator2(std::wcout);//寫字符到關聯的輸出序列//無操作*ostreambuf_iterator1 = 'a';std::copy(string.cbegin(), string.cend(), ostreambuf_iterator1);*ostreambuf_iterator2 = L'a';alg(ostreambuf_iterator1, ostreambuf_iterator1);//測試是否輸出失敗std::cout << "ostreambuf_iterator1.failed(): "<< ostreambuf_iterator1.failed() << std::endl;basic_filebuf.close();std::ostreambuf_iterator<char> ostreambuf_iterator3(&basic_filebuf);std::cout << "ostreambuf_iterator3.failed(): "<< ostreambuf_iterator3.failed() << std::endl;return 0;
}
輸出
This is an example
aalg() called for output iterator
ostreambuf_iterator1.failed(): false
ostreambuf_iterator3.failed(): false