22

假设 C++ 中有一个模板函数,它做了一些有用的工作,但也通过输出迭代器输出一系列值。现在假设该值序列有时很有趣,但有时没有用。STL 中是否有现成的迭代器类可以实例化并传递给函数,并且会忽略函数试图分配给输出迭代器的任何值?换句话说,将所有数据发送到 /dev/null?

4

4 回答 4

24

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= 不会覆盖内置的复制赋值运算符。它仍然提供。

于 2008-12-03T01:15:41.430 回答
4

你有 Boost 可用吗?如果是这样,您可以使用function_output_iterator包装一个空函数。

但这并不理想。无论您使用什么迭代器,仍然需要创建 value_type 的实例以在 operator* 中返回,即使它随后将其丢弃。

于 2008-12-03T00:53:05.157 回答
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;
};

我没有对此进行测试,可能缺少一些重要的东西,但我认为这就是想法。

于 2008-12-03T00:56:31.577 回答
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; }
};

这类似于 Johannes 的答案,但没有任何模板operator=。我喜欢强打字;我想*it = wrong_type_thing成为一个编译时错误。这也void用于各种模板参数std::iterator,例如标准库中的输出迭代器。

这也类似于 Mark 的解决方案,但是 (a) 它正确地继承自std::iterator并且 (b) 它没有不需要的内部状态变量。

于 2017-06-07T18:00:56.717 回答