流输出迭代器
题目描述
类比 std::ostream_iterator
,补全 OstreamIterator
类模板的定义。即向 OstreamIterator
所指向的内容写入时,将内容输出到流中。
关于输入
无
关于输出
见样例输出
注意事项
C++17 标准要求迭代器提供五个类型别名,而且可复制构造、可复制赋值。因此我们在预设代码中提供了这些声明。
但是,如果你尝试在迭代器中添加引用成员(如 std::ostream& os
),那么预置的复制赋值会被删除,从而在部分编译器/标准库实现中给出错误。(具体而言,引用成员无法如同复制构造那样复制赋值“重新绑定”,因此不提供预置复制赋值。)
对于这道题来说,使用指针成员是最标准的做法。
参考答案
#include <algorithm>
#include <iostream>
#include <vector>
#include <sstream>
#include <cassert>
template <typename T>
class OstreamIterator {
public:
// C++17 规定的迭代器必须定义的类型别名
// C++20 只需 value_type 和 difference_type
using value_type = T;
using reference = T&;
using pointer = T*;
using difference_type = std::ptrdiff_t;
using iterator_category = std::output_iterator_tag;
OstreamIterator(const OstreamIterator&) = default;
OstreamIterator& operator=(const OstreamIterator&) = default;
private:
std::ostream* os;
public:
OstreamIterator(std::ostream& os) : os{&os} {}
OstreamIterator& operator=(const T& val) {
*os << val;
return *this;
}
OstreamIterator& operator*() {
return *this;
}
OstreamIterator& operator++() {
return *this;
}
OstreamIterator& operator++(int) {
return *this;
}
};
int main() {
std::string strArr[]{"Creeper", "? ", "Aw", " ", "man"};
std::copy(std::begin(strArr), std::end(strArr), OstreamIterator<std::string>(std::cout));
// 输出到 std::string 的流
std::stringstream ss;
std::vector<int> intVec{1, 2, 3, 4, 5};
std::copy(intVec.begin(), intVec.end(), OstreamIterator<int>(ss));
assert(ss.str() == "12345");
}