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 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 guarantees apply for them as well.
[ Daniel comments: ]
The wording for 179 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 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
i
andj
denote objects of a container'siterator
type, either or both may be replaced by an object of the container'sconst_iterator
type 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
-?- LetX
shall satisfy the requirements ofCopyConstructible
(17.6.3.1). TheX::pointer
,X::const_pointer
,X::void_pointer
, andX::const_void_pointer
types 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::pointer
andX::const_pointer
shall also satisfy the requirements for a random access iterator (24.2).x1
andx2
denote objects of (possibly different) typesX::void_pointer
,X::const_void_pointer
,X::pointer
, orX::const_pointer
. Then,x1
andx2
are equivalently-valued pointer values, if and only if bothx1
andx2
can be explicitly converted to the two corresponding objectspx1
andpx2
of typeX::const_pointer
, using a sequence ofstatic_cast
s using only these four types, and the expressionpx1 == px2
evaluates 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
a
andb
are both dereferenceable, thena == b
if and only if*a
and*b
are 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
w1
andw2
denote 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_pointer
with no change in semantics.p1
andp2
denote 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_pointer
with 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
i
andj
denote objects of a container'siterator
type, either or both may be replaced by an object of the container'sconst_iterator
type referring to the same element with no change in semantics.