繁体   English   中英

丢弃需要 output 迭代器的 function 的 output

[英]Discarding the output of a function that needs an output iterator

假设在 C++ 中有一个模板 function 做了一些有用的工作,但也通过 output 迭代器输出一系列值。 现在假设该值序列有时很有趣,但有时没有用。 Is there a ready-to-use iterator class in the STL that can be instantiated and passed to the function and will ignore any values the function tries to assign to the output iterator? 换句话说,将所有数据发送到 /dev/null?

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;的结果*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*返回任何数据:我们只使用迭代器本身。 请注意,模板化运算符=不会覆盖内置复制赋值运算符。 它仍然提供。

写一个并不难。

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;
};

我没有对此进行测试,可能还有一些重要的缺失,但我认为这是个主意。

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

但这并不理想。 无论你使用什么迭代器,仍然需要在operator *中为return返回创建一个value_type实例,即使它然后抛出它。

我基于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是编译时错误。 此外,对于std::iterator的各种模板参数,它使用void ,就像标准库中的输出迭代std::iterator一样。

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

更新答案 (2022)

对于 C++17,std::iterator 已弃用。 如果要避免警告,则必须在公共接口中声明类型:

  ///
  /// @brief Allows to discard the output of functions that requires an output iterator
  ///
  template<typename T>
  struct null_output_iterator
  {
    using iterator_category = std::forward_iterator_tag;
    using value_type = T;
    using difference_type = T;
    using pointer = T*;
    using reference = T&;
    ///
    /// @brief No-op assignment
    ///
    void operator=(T const&) {}
    ///
    /// @brief Can be pre-incremented
    ///
    null_output_iterator & operator++()
    {
      return *this;
    }
    ///
    /// @brief Can be post-incremented
    ///
    null_output_iterator operator++(int)
    {
      return *this;
    }
    ///
    /// @brief Can be dereferenced
    ///
    null_output_iterator & operator*()
    {
      return *this;
    }
  };

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM