This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++14 status.
Section: 16.4.4.6 [allocator.requirements], 23.2 [container.requirements] Status: C++14 Submitter: Howard Hinnant Opened: 2013-06-25 Last modified: 2016-01-28
Priority: 1
View other active issues in [allocator.requirements].
View all other issues in [allocator.requirements].
View all issues with C++14 status.
Discussion:
This ancient issue 179(i) says one ought to be able to compare iterators with const_iterators
from any given container. I'm having trouble finding words that guarantee this in C++11. This impacts not only a
container's iterators, but also the allocator requirements in [llocator.requirements] surrounding
pointer, const_pointer, void_pointer and const_void_pointer. E.g. can one
compare a pointer with a const_pointer?
allocator::pointer and const_pointer are required to be random access iterators, one could
expect that the 179(i) guarantees apply for them as well.
[ Daniel comments: ]
The wording for 179(i) was part of several working drafts (e.g. also in N3092) over some time and suddenly got lost in N3242, presumably by accident. Whatever we decide for allocator pointers, I expect that we need to restore the 179(i) wording as part of the overall resolution:
Reinsert after 23.2 [container.requirements] p6:
-6-
-?- In the expressionsbegin()returns an iterator referring to the first element in the container.end()returns an iterator which is the past-the-end value for the container. If the container is empty, thenbegin() == end();i == j i != j i < j i <= j i >= j i > j i - jwhere
iandjdenote objects of a container'siteratortype, either or both may be replaced by an object of the container'sconst_iteratortype referring to the same element with no change in semantics.
[2014-02-13 Issaquah, Daniel comments and suggests wording]
First, I didn't originally move the seemingly lost wording to the resolution section because I wanted to ensure that the committee double-checks the reason of this loss.
Second, albeit restoring this wording will restore the comparability ofconst_iterator and iterator of
containers specified in Clause 23, but this alone would not imply that this guarantee automatically extends to
all other iterators, simply because there is no fundamental relation between a mutable iterator and a constant
iterator by itself. This relation only exists under specific conditions, for example for containers which provide two such
typedefs of that kind. Thus the wording restoration would not ensure that allocator pointer and
const_pointer would be comparable with each other. To realize that, we would need additional guarantees added
to the allocator requirements. In fact, it is crucial to separate these things, because allocators are not
restricted to be used within containers, they have their own legitimate use for other places as well (albeit containers
presumably belong to the most important use-cases), and this is also stated in the introduction of 16.4.4.6 [allocator.requirements],
where it says:
All of the string types (Clause 21), containers (Clause 23) (except array), string buffers and string streams (Clause 27), and
match_results(Clause 28) are parameterized in terms of allocators.
[2014-02-12 Issaquah meeting]
Move a Immediate.
Proposed resolution:
Insert after 16.4.4.6 [allocator.requirements] p4 as indicated:
-4- An allocator type
-?- LetXshall satisfy the requirements ofCopyConstructible(17.6.3.1). TheX::pointer,X::const_pointer,X::void_pointer, andX::const_void_pointertypes shall satisfy the requirements ofNullablePointer(17.6.3.3). No constructor, comparison operator, copy operation, move operation, or swap operation on these types shall exit via an exception.X::pointerandX::const_pointershall also satisfy the requirements for a random access iterator (24.2).x1andx2denote objects of (possibly different) typesX::void_pointer,X::const_void_pointer,X::pointer, orX::const_pointer. Then,x1andx2are equivalently-valued pointer values, if and only if bothx1andx2can be explicitly converted to the two corresponding objectspx1andpx2of typeX::const_pointer, using a sequence ofstatic_casts using only these four types, and the expressionpx1 == px2evaluates totrue.Drafting note: This wording uses the seemingly complicated route via
X::const_pointer, because these are (contrary toX::const_void_pointer) random access iterators and we can rely here for dereferenceable values on the fundamental pointee equivalence of 24.3.5.5 [forward.iterators] p6:If
aandbare both dereferenceable, thena == bif and only if*aand*bare bound to the same object.while for null pointer values we can rely on the special equality relation induced by 16.4.4.4 [nullablepointer.requirements].
-?- Let
w1andw2denote objects of typeX::void_pointer. Then for the expressionsw1 == w2 w1 != w2either or both objects may be replaced by an equivalently-valued object of type
-?- LetX::const_void_pointerwith no change in semantics.p1andp2denote objects of typeX::pointer. Then for the expressionsp1 == p2 p1 != p2 p1 < p2 p1 <= p2 p1 >= p2 p1 > p2 p1 - p2either or both objects may be replaced by an equivalently-valued object of type
X::const_pointerwith no change in semantics.
Reinsert after 23.2 [container.requirements] p6:
-6-
-?- In the expressionsbegin()returns an iterator referring to the first element in the container.end()returns an iterator which is the past-the-end value for the container. If the container is empty, thenbegin() == end();i == j i != j i < j i <= j i >= j i > j i - jwhere
iandjdenote objects of a container'siteratortype, either or both may be replaced by an object of the container'sconst_iteratortype referring to the same element with no change in semantics.