This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++17 status.
CopyConstructible
requirement in set constructorsSection: 23.4.6.2 [set.cons] Status: C++17 Submitter: Jens Maurer Opened: 2011-08-20 Last modified: 2017-07-30
Priority: 3
View all issues with C++17 status.
Discussion:
23.4.6.2 [set.cons] paragraph 4 says:
Requires: If the iterator's dereference operator returns an lvalue or a non-const rvalue, then
Key
shall beCopyConstructible
.
I'm confused why a "non-const rvalue" for the return value of the iterator
would require CopyConstructible
; isn't that exactly the situation
when you'd want to apply the move constructor?
multimap
seems better in that regard
([multimap.cons] paragraph 3):
Requires: If the iterator's dereference operator returns an lvalue or a const rvalue
pair<key_type, mapped_type>
, then bothkey_type
and mapped_type shall beCopyConstructible
.
Obviously, if I have a const rvalue, I can't apply the move constructor (which will likely attempt modify its argument).
Dave Abrahams: I think you are right. Proposed resolution: drop "non-" from 23.4.6.2 [set.cons] paragraph 3.[2012, Kona]
The wording is in this area will be affected by Pablo's paper being adopted at this meeting. Wait for that paper to be applied before visiting this issue - deliberately leave in New status until the next meeting.
Proposed resolution from Kona 2012:
This wording is relative to the FDIS.
Change 23.4.6.2 [set.cons] p3 as follows:
template <class InputIterator> set(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator());-3- Effects: Constructs an empty set using the specified comparison object and allocator, and inserts elements from the range [
-4- Requires: If the iterator's dereference operator returns an lvalue or afirst,last
).non-const rvalue, thenKey
shall beCopyConstructible
. -5- Complexity: Linear inN
if the range [first,last
) is already sorted usingcomp
and otherwiseN logN
, whereN
islast - first
.
[2014-05-18, Daniel comments]
According to Pablo, the current P/R correctly incorporates the changes from his paper (which was adopted in Kona)
[2014-06-10, STL comments and suggests better wording]
N1858 was voted into WP N2284 but was "(reworded)", introducing the "non-const" damage.
N1858 wanted to add this for map:Requires: Does not require
CopyConstructible
of eitherkey_type
ormapped_type
if the dereferencedInputIterator
returns a non-const rvaluepair<key_type, mapped_type>
. OtherwiseCopyConstructible
is required for bothkey_type
andmapped_type
.
And this for set:
Requires:
Key
must beCopyConstructible
only if the dereferencedInputIterator
returns an lvalue or const rvalue.
(And similarly for multi.)
This was reworded to N2284 23.3.1.1 [map.cons]/3 and N2284 23.3.3.1 [set.cons]/4, and it slightly changed over the years into N3936 23.4.4.2 [map.cons]/3 and N3936 23.4.6.2 [set.cons]/4. In 2005/2007, this was the best known way to say "hey, we should try to move this stuff", as the fine-grained element requirements were taking shape. Then in 2010, N3173 was voted into WP N3225, adding the definition ofEmplaceConstructible
and modifying the container requirements tables to make the range constructors require
EmplaceConstructible
.
After looking at this history and double-checking our implementation (where map
/set
range construction goes through
emplacement, with absolutely no special-casing for map
's pairs), I am convinced that N3173 superseded N1858 here.
(Range-insert()
and the unordered containers are unaffected.)
Previous resolution [SUPERSEDED]:
This wording is relative to the N3936.
Change 23.4.6.2 [set.cons] p4 as follows:
template <class InputIterator> set(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator());-3- Effects: Constructs an empty
-4- Requires: If the iterator's indirection operator returns an lvalue or aset
using the specified comparison object and allocator, and inserts elements from the range [first,last
).non-const rvalue, thenKey
shall beCopyInsertible
into*this
. -5- Complexity: Linear inN
if the range [first,last
) is already sorted usingcomp
and otherwiseN logN
, whereN
islast - first
.
[2015-02 Cologne]
GR: Do requirements supersede rather than compose [container requirements and per-function requirements]? AM: Yes, they supersede.
AM: This looks good. Ready? Agreement.Proposed resolution:
This wording is relative to the N4296.
Remove 23.4.3.2 [map.cons] p3:
template <class InputIterator> map(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator());[…]
-3- Requires: If the iterator's indirection operator returns an lvalue or aconst
rvaluepair<key_type, mapped_type>
, then bothkey_type
andmapped_type
shall beCopyInsertible
into*this
.
Remove 23.4.4.2 [multimap.cons] p3:
template <class InputIterator> multimap(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator());[…]
-3- Requires: If the iterator's indirection operator returns an lvalue or aconst
rvaluepair<key_type, mapped_type>
, then bothkey_type
andmapped_type
shall beCopyInsertible
into*this
.
Remove 23.4.6.2 [set.cons] p4:
template <class InputIterator> set(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator());[…]
-4- Requires: If the iterator's indirection operator returns an lvalue or a non-const
rvalue, thenKey
shall beCopyInsertible
into*this
.
Remove 23.4.7.2 [multiset.cons] p3:
template <class InputIterator> multiset(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator());[…]
-3- Requires: If the iterator's indirection operator returns an lvalue or aconst
rvalue, thenKey
shall beCopyInsertible
into*this
.