[Bug libstdc++/51823] reverse iterator instantiated with POD type returns uninitialized values + work around

redi at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Wed Jan 11 13:56:00 GMT 2012


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51823

--- Comment #3 from Jonathan Wakely <redi at gcc dot gnu.org> 2012-01-11 13:55:49 UTC ---
(In reply to comment #0)
> Headerfiles involved:
>  <iterator>

And <iostream>

> Consider an iterator class that implements the requirements of a
> forward_iterator.

Do you mean bidirectional iterator?  You can't reverse a forward iterator, and 
std::reverse_iterator requires that its template parameter meets the
requirements of a Bidirectional Iterator.
Your class doesn't implement those requirements, it doesn't have a
post-increment operator.

And as I said in my previous comment, the iterator requirements say operator*
returns the iterator's 'reference' type.  reverse_iterator::operator* then
returns the same thing because the 'reference' type is, in effect, defined as
"the type returned by operator*"

(Also, the name __traits is forbidden, names beginning with double-underscore
are reserved for the implementation)

> The 'work-around' forces the use of forwarding. I put it as comment in the
> minimum example. If I should have attached a separate source file with just the
> operator*()-line replaced, I wish to express my apologies in advance.

The preprocessor strips comments out, so the workaround isn't in the attached
file.


The first problem is that your class lies, saying its 'reference' type is a
reference, but then returning something different from operator*.  That causes
a reference to be bound to a temporary, as you'll see if you compile with
-Wsystem-headers to enable warnings for code in the standard library headers.

The second problem is how reverse_iterator::operator* is defined:

      reference
      operator*() const
      {
    _Iterator __tmp = current;
    return *--__tmp;
      }

This creates a temporary iterator, then returns a reference to its d_val
member. By the time that's written to std::cout the temporary has been
destroyed.

For a bidirectional iterator the expression *r-- is required to be valid, so
your type fails that requirement.

What you've written is not an iterator, it's a generator.  It doesn't meet the
iterator requirements, so can't be used with std::reverse_iterator and
std::copy and other templates that require iterators.



More information about the Gcc-bugs mailing list