Suppose there´s a template function in C++ that does some useful work but also outputs a sequence of values via an output iterator. Now suppose that the sequence of values sometimes is interesting, but at others is not useful. Is there a ready-to-use iterator class in the STL that can be instantiated and passed to the function and will ignore any value the function tries to assign to it? To put in another way, send all data to /dev/null?
5 Answers
The STL does not provide such an iterator. But you could code it yourself (tested that code):
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; }
};
It doesn't need any data by using itself as the result of operator*
. The result of *it = x;
is not used in the output iterator requirements, so we can give it a return type of void
.
Edit: Let's go into how this operator*
works. The Standard says in 24.1.2/1 about the requirements of an output iterator that in both these cases:
*it = t;
*it++ = t;
That the result of those expressions is not used. That's what makes this work:
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=`.
Now we don't need to have any data that we return in operator*
: We just use the iterator itself. Note that the templated operator= does not overwrite the builtin copy assignment operator. It's still provided.

- 23,859
- 5
- 60
- 99

- 496,577
- 130
- 894
- 1,212
-
Could you better explain the operator*? – David Reis Dec 03 '08 at 01:21
-
It's used in combination with the templated operator=. Tricky, I'd use a nested helper class dev_null. Also, I'd let operator++(int) return *this immediately. This version is inefficient. – MSalters Dec 03 '08 at 13:56
-
msalters, the operational semantics state a new object is returned :) – Johannes Schaub - litb Dec 03 '08 at 15:58
Do you have Boost available? If so you could use a function_output_iterator wrapping an empty function.
It's not ideal though. Whatever iterator you use will still need to create an instance of the value_type for return in operator*, even if it then throws it away.

- 4,475
- 1
- 26
- 23
It isn't hard to write one.
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;
};
I haven't tested this, and there's probably something important missing, but I think this is the idea.

- 299,747
- 42
- 398
- 622
-
1The idea is good, but I don´t think you need: T* operator->() { return &m; } And you should derive from stl::output_iterator With this implementation a copy of T is executed at each assignment through the out iterator. Is there anyway to avoid that? – David Reis Dec 03 '08 at 01:15
I based mine on std::back_insert_iterator, but without the container:
#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; }
};
This is similar to Johannes's answer, but without the template operator=
that takes whatever. I like strong typing; I want *it = wrong_type_thing
to be a compile-time error. Also this uses void
for the various template parameters to std::iterator
, like the output iterators in the standard library.
This is also similar to Mark's solution, but (a) it properly inherits from std::iterator
and (b) it does not have the unneeded internal state variable.

- 70,042
- 10
- 116
- 153
Updated answer (2022)
With C++17,std::iterator is deprecated. If you want to avoid a warning, you have to declare the types in the public interface:
///
/// @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;
}
};

- 850
- 6
- 18