Section: 23.2 [container.requirements] Status: CD1 Submitter: Judy Ward Opened: 1998-07-02 Last modified: 2016-01-28
Priority: Not Prioritized
View all other issues in [container.requirements].
View all issues with CD1 status.
Discussion:
Currently the following will not compile on two well-known standard library implementations:
#include <set> using namespace std; void f(const set<int> &s) { set<int>::iterator i; if (i==s.end()); // s.end() returns a const_iterator }
The reason this doesn't compile is because operator== was implemented as a member function of the nested classes set:iterator and set::const_iterator, and there is no conversion from const_iterator to iterator. Surprisingly, (s.end() == i) does work, though, because of the conversion from iterator to const_iterator.
I don't see a requirement anywhere in the standard that this must work. Should there be one? If so, I think the requirement would need to be added to the tables in section 24.1.1. I'm not sure about the wording. If this requirement existed in the standard, I would think that implementors would have to make the comparison operators non-member functions.
This issues was also raised on comp.std.c++ by Darin Adler. The example given was:
bool check_equal(std::deque<int>::iterator i, std::deque<int>::const_iterator ci) { return i == ci; }
Comment from John Potter:
In case nobody has noticed, accepting it will break reverse_iterator.
The fix is to make the comparison operators templated on two types.
template <class Iterator1, class Iterator2> bool operator== (reverse_iterator<Iterator1> const& x, reverse_iterator<Iterator2> const& y);Obviously: return x.base() == y.base();
Currently, no reverse_iterator to const_reverse_iterator compares are valid.
BTW, I think the issue is in support of bad code. Compares should be between two iterators of the same type. All std::algorithms require the begin and end iterators to be of the same type.
Proposed resolution:
Insert this paragraph after 23.2 [container.requirements] paragraph 7:
In the expressions
i == j i != j i < j i <= j i >= j i > j i - jWhere i and j denote objects of a container's iterator type, either or both may be replaced by an object of the container's const_iterator type referring to the same element with no change in semantics.
[post-Toronto: Judy supplied a proposed resolution saying that
iterator
and const_iterator
could be freely mixed in
iterator comparison and difference operations.]
[Redmond: Dave and Howard supplied a new proposed resolution which explicitly listed expressions; there was concern that the previous proposed resolution was too informal.]
Rationale:
The LWG believes it is clear that the above wording applies only to
the nested types X::iterator
and X::const_iterator
,
where X
is a container. There is no requirement that
X::reverse_iterator
and X::const_reverse_iterator
can be mixed. If mixing them is considered important, that's a
separate issue. (Issue 280.)