假设 C++ 中有一个模板函数,它做了一些有用的工作,但也通过输出迭代器输出一系列值。现在假设该值序列有时很有趣,但有时没有用。STL 中是否有现成的迭代器类可以实例化并传递给函数,并且会忽略函数试图分配给输出迭代器的任何值?换句话说,将所有数据发送到 /dev/null?
4 回答
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*
:我们只使用迭代器本身。请注意,模板化的 operator= 不会覆盖内置的复制赋值运算符。它仍然提供。
你有 Boost 可用吗?如果是这样,您可以使用function_output_iterator包装一个空函数。
但这并不理想。无论您使用什么迭代器,仍然需要创建 value_type 的实例以在 operator* 中返回,即使它随后将其丢弃。
写一篇不难。
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;
};
我没有对此进行测试,可能缺少一些重要的东西,但我认为这就是想法。
我基于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; }
};
这类似于 Johannes 的答案,但没有任何模板operator=
。我喜欢强打字;我想*it = wrong_type_thing
成为一个编译时错误。这也void
用于各种模板参数std::iterator
,例如标准库中的输出迭代器。
这也类似于 Mark 的解决方案,但是 (a) 它正确地继承自std::iterator
并且 (b) 它没有不需要的内部状态变量。