- 论坛徽章:
- 0
|
179. Comparison of const_iterators to iterators doesn't work
Section: 23.1 [lib.container.requirements] Status: WP Submitter: Judy Ward Date: 2 Jul 1998
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.1 [lib.container.requirements] paragraph 7:
In the expressions
i == j
i != j
i < j
i <= j
i >= j
i > j
i - j
Where 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. |
|