Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

const to non-const iterator comparisons, are they valid [duplicate]

Tags:

c++

c++11

I have two iterators into a container, one const and one non-const. Is there an issue with comparing them to see if they both refer to the same object in the container? This is a general C++11 iterator question:

Can a const and non-const iterator be legitimately compared to see if they both refer to the same object, independent of the type of container (i.e., they are both iterators that are guaranteed to refer to objects in the same container or that container's end(), but one is const and the other is not)?

For example, consider the following code:

some_c++11_container container;

// Populate container
...

some_c++11_container::iterator iObject1=container.begin();
some_c++11_container::const_iterator ciObject2=container.cbegin();

// Some operations that move iObject1 and ciObject2 around the container
...

if (ciObject2==iObject1) // Is this comparison allowed by the C++11 standard?
  ...; //Perform some action contingent on the equality of the two iterators
like image 792
Michael Goldshteyn Avatar asked Jun 03 '13 15:06

Michael Goldshteyn


4 Answers

Yes, this will work like you expect.

The Standard guarantees that for any container type, some_container::iterator can be implicitly converted to some_container::const_iterator.

The first table in 23.2.1 [container.requirements.general], after defining X as a container type which contains objects of type T, has:

Expression: X::iterator

Return type: iterator type whose value type is T

Note: any iterator category that meets the forward iterator requirements. convertible to X::const_iterator.


Expression: X::const_iterator

Return type: constant iterator type whose value type is T

Note: any iterator category that meets the forward iterator requirements.

(These aren't really expressions, and are types, rather than having "return types", but that's how they're squeezed into the table that is mostly expressions.)

So when you have ciObject2==iObject1, the compiler notices that the best operator== is ciObject2==some_container::const_iterator(iObject1). And operator== on two const_iterator tells you if they refer to the same element.

(I don't see anything explicitly saying that the result of this conversion refers to the same object as the original iterator. I guess that's just understood.)

like image 128
aschepler Avatar answered Nov 16 '22 05:11

aschepler


From §24.2.3/1

A class or pointer type X satisfies the requirements of an input iterator for the value type T if X satisfies the Iterator (24.2.2) and EqualityComparable (Table 17) requirements ...

Thus input iterators are required to be EqualityComparable.

All standard library container iterators must satisfy forward iterator requirements (§23.2.1 - Table 96). Since those requirements are a superset of input iterator requirements, it follows these iterators must satisfy the EqualityComparable concept.

Also, from §23.2.1 - Table 96, X::iterator is required to be convertible to X::const_iterator.

Adding the two together answers your question that it is indeed required by the standard that comparing a Container::const_iterator to a Container::iterator is well-defined (as long as both are valid iterators pointing to the same container).

like image 34
Praetorian Avatar answered Nov 16 '22 06:11

Praetorian


I don't think it is possible for there to be an issue comparing them. If you have a const iterator when you check for it being the end the iterator end() returns is not const.

like image 1
aaronman Avatar answered Nov 16 '22 05:11

aaronman


IIRC iterator implicitly converts to const_iterator. And the result must point to the same position.

If so the mixed compare will do the conversion then compare the now compatible const_iterators.

like image 1
Balog Pal Avatar answered Nov 16 '22 06:11

Balog Pal