This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++23 status.
forward_list::merge
behavior unclear when passed *this
Section: 23.3.7.6 [forward.list.ops] Status: C++23 Submitter: Tim Song Opened: 2018-03-19 Last modified: 2023-11-22
Priority: 3
View all other issues in [forward.list.ops].
View all issues with C++23 status.
Discussion:
LWG 300(i) changed list::merge
to be a no-op when passed *this
, but there's
no equivalent rule for forward_list::merge
.
Presumably the forward_list
proposal predated the adoption of LWG 300's PR and was never updated
for the change. Everything in the discussion of that issue applies mutatis mutandis to the current
specification of forward_list::merge
.
[2018-06-18 after reflector discussion]
Priority set to 3
[2019-07-30 Tim provides updated PR]
Per the comments during issue prioritization, the new PR tries to synchronize the wording
between list::merge
and forward_list::merge
.
Previous resolution [SUPERSEDED]:
This wording is relative to N4727.
Edit [forwardlist.ops] as indicated:
void merge(forward_list& x); void merge(forward_list&& x); template<class Compare> void merge(forward_list& x, Compare comp); template<class Compare> void merge(forward_list&& x, Compare comp);-20- Requires:
-21- Effects: If*this
andx
are both sorted with respect to the comparatoroperator<
(for the first two overloads) orcomp
(for the last two overloads), andget_allocator() == x.get_allocator()
istrue
.addressof(x) == this
, does nothing. Otherwise, mMerges the two sorted ranges[begin(), end())
and[x.begin(), x.end())
. The result is a range that is sorted with respect to the comparatoroperator<
(for the first two overloads) orcomp
(for the last two overloads).x
is empty after the merge. If an exception is thrown other than by a comparison there are no effects. Pointers and references to the moved elements ofx
now refer to those same elements but as members of*this
. Iterators referring to the moved elements will continue to refer to their elements, but they now behave as iterators into*this
, not intox
. -22- Remarks: Stable (16.4.6.8 [algorithm.stable]). The behavior is undefined ifget_allocator() != x.get_allocator()
. -23- Complexity: At mostdistance(begin(), end()) + distance(x.begin(), x.end()) - 1
comparisons ifaddressof(x) != this
; otherwise, no comparisons are performed.
[2021-05-22 Tim syncs wording to the current working draft]
[2022-01-31; Reflector poll]
Set status to Tentatively Ready after six votes in favour during reflector poll.
[2022-02-10 Approved at February 2022 virtual plenary. Status changed: Tentatively Ready → WP.]
Proposed resolution:
This wording is relative to N4901.
Edit 23.3.7.6 [forward.list.ops] as indicated:
void merge(forward_list& x); void merge(forward_list&& x); template<class Compare> void merge(forward_list& x, Compare comp); template<class Compare> void merge(forward_list&& x, Compare comp);-?- Let
-24- Preconditions:comp
beless<>{}
for the first two overloads.*this
andx
are both sorted with respect to the comparatoroperator<
(for the first two overloads) orcomp
(for the last two overloads), andget_allocator() == x.get_allocator()
istrue
. -25- Effects: Ifaddressof(x) == this
, there are no effects. Otherwise, mMerges the two sorted ranges[begin(), end())
and[x.begin(), x.end())
. The result is a range that is sorted with respect to the comparatorcomp
.Pointers and references to the moved elements ofx
is empty after the merge. If an exception is thrown other than by a comparison there are no effects.x
now refer to those same elements but as members of*this
. Iterators referring to the moved elements will continue to refer to their elements, but they now behave as iterators into*this
, not intox
. -26- Complexity: At mostdistance(begin(), end()) + distance(x.begin(), x.end()) - 1
comparisons ifaddressof(x) != this
; otherwise, no comparisons are performed. -27- Remarks: Stable (16.4.6.8 [algorithm.stable]). Ifaddressof(x) != this
,x
is empty after the merge. No elements are copied by this operation. If an exception is thrown other than by a comparison there are no effects.
Edit 23.3.9.5 [list.ops] as indicated:
void merge(list& x); void merge(list&& x); template<class Compare> void merge(list& x, Compare comp); template<class Compare> void merge(list&& x, Compare comp);-?- Let
-26- Preconditions:comp
beless<>{}
for the first two overloads.Both the list and the argument list shall be*this
andx
are both sorted with respect to the comparatoroperator<
(for the first two overloads) orcomp
(for the last two overloads), andget_allocator() == x.get_allocator()
istrue
. -27- Effects: Ifaddressof(x) == this
,does nothing; othere are no effects. Otherwise, merges the two sorted ranges[begin(), end())
and[x.begin(), x.end())
. The result is a rangein which the elements will be sorted in non-decreasing order according to the ordering defined bythat is sorted with respect to the comparatorcomp
; that is, for every iteratori
, in the range other than the first, the conditioncomp(*i, *(i - 1))
will befalse
comp
. Pointers and references to the moved elements ofx
now refer to those same elements but as members of*this
. Iterators referring to the moved elements will continue to refer to their elements, but they now behave as iterators into*this
, not intox
. -28- Complexity: At mostsize() + x.size() - 1
applications ofcomparisons ifcomp
addressof(x) != this
; otherwise, noapplications ofcomparisons are performed.comp
If an exception is thrown other than by a comparison there are no effects.-29- Remarks: Stable (16.4.6.8 [algorithm.stable]). Ifaddressof(x) != this
,the range[x.begin(), x.end())
x
is empty after the merge. No elements are copied by this operation. If an exception is thrown other than by a comparison there are no effects.