does output_iterator_tag imply non-terminating sequence?

In other words, can I assume that an output iterator (http://www.cplusplus.com/reference/iterator/OutputIterator/) can safely be written to without fear of bounds overruns?

(The iterator exists, AFAIK, to accommodate sink devices like ports and files and tapes.)


If that is so, then I can specialize an algorithm that writes a variable amount of data (all or nothing) to report error correctly for all iterator types except for output iterators, where no error can be assumed?

Is this correct?
Last edited on
Are you talking about the kinds of iterators returned from std::front_inserter, std::back_inserter, and std::inserter? I belive output iterators such as these can be considered as allowing you to write infinite data.
Last edited on
Yes. Thanks.

(Just wanted to make sure I wasn't making stuff up.)
Last edited on
> can I assume that an output iterator can safely be written to without fear of bounds overruns?

Yes, written to just one time.
Essentially, single pass, strictly alternating between dereference+assignment and increment:
deref-assign increment deref-assign increment deref-assign increment ...
Yes, exactly. My issue is the ability to identify whether the output sequence has sufficient length to receive the data to write, as half-written data is an error.
> My issue is the ability to identify whether the output sequence has sufficient length
> to receive the data to write, as half-written data is an error.

AFAIK, there is no good way to verify this, using a pure output only iterator alone, if all edge cases have to be covered. (An output iterator is a single pass iterator.)

For instance, writing through a std::back_insert_iterator<> may result in std::bad_alloc() being thrown, writing through a std::ostream_iterator<> may fail because the disk is full.
Right. So the specialization will verify when possible, otherwise it will write+advance until either the entire (1-6 character) sequence is written or something goes wrong -- where such error must be handled by the calling code (due to the calling code's choice of iterator).

This fixes everything to a simple specialized functor (about 10 lines of code) that will tell me whether or not it is okay to (try to) write N items to the output sequence or not.

But I'm starting to consider making a simple iterator wrapper to handle it better -- which will also help solve the begin/end issue with back inserters and the like. (Currently I have simply overloaded the equality+inequality operators to always return false/true -- a solution I'm not too keen on.)
In the fail-safe code, accept a destination range identified by a pair of mutable iterators? Something like:
1
2
3
4
5
6
7
template < typename INPUT_ITERATOR, typename MUTABLE_ITERATOR >
MUTABLE_ITERATOR copy_all_or_nothing( INPUT_ITERATOR srce_begin, INPUT_ITERATOR srce_end,
                                      MUTABLE_ITERATOR dest_begin, MUTABLE_ITERATOR dest_end )
{
    if( std::distance( srce_begin, srce_end ) > std::distance( dest_begin, dest_end ) ) return dest_begin ;
    else return std::copy( srce_begin, srce_end, dest_begin ) ;
}
Yes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    template <typename Iterator, typename Category>
    struct distance_ok
    {
      bool ok;
      distance_ok( Iterator first, Iterator last, std::ptrdiff_t n ): ok( n <= std::distance( first, last ) ) { }
      operator bool () const { return ok; }
    };
    
    template <typename Iterator>
    struct distance_ok <Iterator, std::output_iterator_tag> 
    {
      bool ok;
      distance_ok( Iterator first, Iterator last, std::ptrdiff_t n ): ok( true ) { }
      operator bool () const { return ok; }
    };

I may yet revise this design and move the subtraction to the creation of the writer object and only keep a ptrdiff_t count of remaining writes, which would turn into a simple comparison instead of a call to std::distance(). There is an additional addition required for every increment now as well, so the complexity constant remains the same, but it might result in a simpler design and more flexibility for the user.
Topic archived. No new replies allowed.