丢弃需要输出迭代器的函数的输出

时间:2008-12-03 00:43:04

标签: c++ stl iterator

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

4 个答案:

答案 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)它没有不需要的内部状态变量。