假设在C ++中有一个模板函数可以完成一些有用的工作,但也可以通过输出迭代器输出一系列值。现在假设这个值序列有时很有趣,但在其他值上没有用。在STL中是否有一个可以实例化的迭代器类,它可以被实例化并传递给函数,并将忽略函数尝试分配给输出迭代器的任何值?换句话说,将所有数据发送到/ dev / null?
答案 0 :(得分:21)
STL不提供这样的迭代器。但你可以自己编写代码(测试代码):
struct null_output_iterator :
std::iterator< std::output_iterator_tag,
null_output_iterator > {
/* no-op assignment */
template<typename T>
void operator=(T const&) { }
null_output_iterator & operator++() {
return *this;
}
null_output_iterator operator++(int) {
return *this;
}
null_output_iterator & operator*() { return *this; }
};
operator*
的结果是使用自身不需要任何数据。 *it = x;
的结果未在输出迭代器要求中使用,因此我们可以给它一个void
的返回类型。
编辑:让我们来看看operator*
的工作原理。标准在 24.1.2 / 1 中说明输出迭代器的要求,在这两种情况下:
*it = t;
*it++ = t;
不使用这些表达式的结果。这就是使这项工作的原因:
null_output_iterator it;
*it; // returns a null_output_iterator& per definition of the `operator*`.
*it = some_value; // returns void per definition of the templated `operator=`.
现在我们不需要在operator*
中返回任何数据:我们只使用迭代器本身。请注意,模板化运算符=不会覆盖内置复制赋值运算符。它仍然提供。
答案 1 :(得分:4)
写一个并不难。
template<typename T>
class NullOutputIterator
{
public:
NullOutputIterator() {}
NullOutputIterator& operator++() { return *this; }
NullOutputIterator& operator++(int) { return *this; }
T& operator*() { return m; }
T* operator->() { return &m; }
private:
T m;
};
我没有对此进行过测试,可能还有一些重要的缺失,但我认为这是个主意。
答案 2 :(得分:3)
你有Boost可用吗?如果是这样,您可以使用function_output_iterator包装空函数。
但这并不理想。无论你使用什么迭代器,仍然需要在operator *中为return返回创建一个value_type实例,即使它然后抛出它。
答案 3 :(得分:1)
我以std::back_insert_iterator为基础,但没有容器:
#include <iterator>
template<typename T>
class NullOutputIter
: public std::iterator<std::output_iterator_tag,void,void,void,void>
{
public:
NullOutputIter &operator=(const T &) { return *this; }
NullOutputIter &operator*() { return *this; }
NullOutputIter &operator++() { return *this; }
NullOutputIter operator++(int) { return *this; }
};
这类似于约翰内斯的答案,但没有模板operator=
可以采取任何措施。我喜欢强烈的打字;我希望*it = wrong_type_thing
是编译时错误。这也使用void
作为std::iterator
的各种模板参数,就像标准库中的输出迭代器一样。
这也与Mark的解决方案类似,但是(a)它正确地从std::iterator
继承而且(b)它没有不需要的内部状态变量。