Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can iterators from different containers be (re)assigned?

Iterators from different containers cannot be compared (see for example here:https://stackoverflow.com/a/4664519/225186) (or more technically, it doesn't need to make sense.)

This raises another question, can iterator from different ranges be assigned to each other?

Container A = ...;
Container B = ...;
auto it1 = A.begin();
it1 = B.begin(); // it1 first belonged to A, does it1 need to belong to B later 

Is the last line required to work by the Iterator concept in some standard or in the accepted practices or in the upcoming std ranges?

Since equality and assigment are so intertwined, it seem that if equality (==) is not always well defined then assignment (=) doesn't need to be well defined either, and probably for similar underlying reasons.

The reason I ask is not purely academic, because a certain iterator implementation could have some "metadata" from the container, and that (depending on the implementation) may or may not be able to be reassigned or simply a waste to be reassigned. (For example a stride information that is unique to A and doesn't agree with that of B. Another example is when the iterator stores a reference to the original range.)

This could allow that when assignment is tried, a particular field (member) might be left untouched. One could make the assignment work in some cases, and that may produce less surprises, but it could also limit the implementations, and the question is would it be really necessary to define/allow the assignment between iterators of different origin (provenance)?


UPDATE 2021:

The linked documents read things like:

[...] the term the domain of == is used in the ordinary mathematical sense to denote the set of values over which == is (required to be) defined. This set can change over time. Each algorithm places additional requirements on the domain of == for the iterator values it uses. These requirements can be inferred from the uses that algorithm makes of == and !=.

So there is an implicit defined (by the algorithms) range of validity of == . Another way to formulate this question is if the same caveats for the domain of applicability of == can be applied, by simple use of logic, to =.

The underlying idea is that defining == in isolation of = or vise versa doesn't make sense. (and also because I found a motivating case).

like image 217
alfC Avatar asked Nov 06 '22 07:11

alfC


1 Answers

If you check out cppreference.com for the container you are interested you can find out the requirements for its iterators.

If we look at std::vector for example, its iterators are specified to be LegacyRandomAccessIterator. If you follow the hierarchy of definitions up from there to the base LegacyIterator you'll see that iterators are required to be CopyAssignable which means you must be able to assign one iterator to another of the same type.

All of the standard library containers use iterators derived from LegacyIterator, containers from other libraries or containers are free to ignore these requirements but it would be quite surprising to users if iterators weren't CopyAssignable and even more surprising if iterators were only not CopyAssignable between containers of the same type as that would potentially only be a runtime failure and not a compile time failure.

like image 134
Alan Birtles Avatar answered Nov 10 '22 01:11

Alan Birtles