[英]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)它没有不需要的内部状态变量。
对于 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.