Section: 23.4.3.1 [map.overview], 23.4.4.1 [multimap.overview], 23.5.3.1 [unord.map.overview], 23.5.4.1 [unord.multimap.overview] Status: C++17 Submitter: Geoffrey Romer Opened: 2014-01-08 Last modified: 2017-10-13
Priority: 2
View all other issues in [map.overview].
View all issues with C++17 status.
Discussion:
The rvalue-reference insert()
members of map
, multimap
, unordered_map
, and
unordered_multimap
are specified as function templates, where the rvalue-reference parameter type
depends on the template parameter.
As a consequence, these overloads cannot be invoked via braced-initializer syntax (e.g. my_map.insert({key, value})
),
because the template argument cannot be deduced from a braced-init-list. Such calls instead resolve to the
const lvalue reference overload, which forces a non-elidable copy of the argument, despite the fact that the
argument is an rvalue, and so should be eligible for moving and copy elision.
value_type&&
overload for each affected
member template. Simply declaring these members in the class synopses should be sufficient; their semantics are
already dictated by the container concepts (c.f. the corresponding lvalue-reference overloads, which have no
additional discussion beyond being listed in the synopsis).
[2014-02-13 Issaquah]
AJM: Is this not better solved by emplace
?
Nico: emplace
was a mistake, it breaks a uniform pattern designed into the STL.
Hence, this fix is important, it should be the preferred way to do this.
JonW: emplace
is still more efficient, as this form must make a non-elidable copy.
GeoffR: Also, cannot move from a const
key, must always make a copy.
Poll for adopting the proposed wording:
SF: 1 WF: 4 N: 4 WA: 1 SA: 0Move to Ready, pending implementation experience.
Proposed resolution:
This wording is relative to N3797.
Change 23.4.3.1 [map.overview], class template map
synopsis, as indicated:
[…] pair<iterator, bool> insert(const value_type& x); pair<iterator, bool> insert(value_type&& x); template <class P> pair<iterator, bool> insert(P&& x); iterator insert(const_iterator position, const value_type& x); iterator insert(const_iterator position, value_type&& x); template <class P> iterator insert(const_iterator position, P&&); […]
Change 23.4.4.1 [multimap.overview], class template multimap
synopsis, as indicated:
[…] iterator insert(const value_type& x); iterator insert(value_type&& x); template <class P> iterator insert(P&& x); iterator insert(const_iterator position, const value_type& x); iterator insert(const_iterator position, value_type&& x); template <class P> iterator insert(const_iterator position, P&& x); […]
Change 23.5.3.1 [unord.map.overview], class template unordered_map
synopsis, as indicated:
[…] pair<iterator, bool> insert(const value_type& obj); pair<iterator, bool> insert(value_type&& obj); template <class P> pair<iterator, bool> insert(P&& obj); iterator insert(const_iterator hint, const value_type& obj); iterator insert(const_iterator hint, value_type&& obj); template <class P> iterator insert(const_iterator hint, P&& obj); […]
Change 23.5.4.1 [unord.multimap.overview], class template unordered_multimap
synopsis, as indicated:
[…] iterator insert(const value_type& obj); iterator insert(value_type&& obj); template <class P> iterator insert(P&& obj); iterator insert(const_iterator hint, const value_type& obj); iterator insert(const_iterator hint, value_type&& obj); template <class P> iterator insert(const_iterator hint, P&& obj); […]