move_iterator
's conversions are more broken after P1207Section: 24.5.4.4 [move.iter.cons] Status: C++23 Submitter: Casey Carter Opened: 2019-08-23 Last modified: 2023-11-22
Priority: 2
View all other issues in [move.iter.cons].
View all issues with C++23 status.
Discussion:
The converting constructor and assignment operator specified in 24.5.4.4 [move.iter.cons] were technically broken before P1207:
24.5.4.4 [move.iter.cons] para 3 (and 5 for that matter) is an instance of LWG
3105; it should instead mandate that u.base()
is convertible to Iterator
.
24.5.4.4 [move.iter.cons] para 5 uses "is convertible" to guard an assignment operation instead of a conversion; it should instead mandate.
After applying P1207R4 "Movability of Single-pass Iterators",
u.base()
is not always well-formed, exacerbating the problem. These operations must ensure
that u.base()
is well-formed.
Let's burninate "Constructs a move_iterator
" while we're touching this subclause.
We'll also burninate "Iterator operations applied..." since the requirement it wants to impose is covered (and indeed must be covered) by the specifications of those other operations.
[2019-09-14 Priority set to 2 based on reflector discussion]
Previous resolution [SUPERSEDED]:This wording is relative to N4830.
Modify 24.5.4.4 [move.iter.cons] as indicated:
constexpr move_iterator();-1- Effects:
Constructs aValue-initializesmove_iterator
, vingcurrent
.Iterator operations applied to the resulting iterator have defined behavior if and only if the corresponding operations are defined on a value-initialized iterator of typeIterator
.constexpr explicit move_iterator(Iterator i);-2- Effects:
Constructs a move_iterator, iInitializesingcurrent
withstd::move(i)
.template<class U> constexpr move_iterator(const move_iterator<U>& u);-3- Mandates:
-4- Effects:is well-formed and convertible to
Uu.base()Iterator
.Constructs aInitializesmove_iterator
, iingcurrent
withu.base()
.template<class U> constexpr move_iterator& operator=(const move_iterator<U>& u);-5- Mandates:
-6- Effects: AssignsU
is convertible toIterator
u.base()
is well-formed andis_assignable_v<Iterator&, const U&>
istrue
.u.base()
tocurrent
.
[2020-02-14; Prague]
LWG Review. Some wording improvements have been made and lead to revised wording.
[2020-02-16; Prague]
Reviewed revised wording and moved to Ready for Varna.
[2020-07-17; superseded by 3435]
[2020-11-09 Approved In November virtual meeting. Status changed: Ready → WP.]
Proposed resolution:
This wording is relative to N4849.
Modify 24.5.4.4 [move.iter.cons] as indicated:
constexpr move_iterator();-1- Effects:
Constructs aValue-initializesmove_iterator
, vingcurrent
.Iterator operations applied to the resulting iterator have defined behavior if and only if the corresponding operations are defined on a value-initialized iterator of typeIterator
.constexpr explicit move_iterator(Iterator i);-2- Effects:
Constructs a move_iterator, iInitializesingcurrent
withstd::move(i)
.template<class U> constexpr move_iterator(const move_iterator<U>& u);-3- Mandates:
-4- Effects:is well-formed and convertible to
Uu.base()Iterator
.Constructs aInitializesmove_iterator
, iingcurrent
withu.base()
.template<class U> constexpr move_iterator& operator=(const move_iterator<U>& u);-5- Mandates:
-6- Effects: AssignsU
is convertible toIterator
u.base()
is well-formed andis_assignable_v<Iterator&, U>
istrue
.u.base()
tocurrent
.