pair<Key, T>
, not pair<const Key, T>
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++20 Submitter: Ville Voutilainen Opened: 2017-10-08 Last modified: 2021-02-25
Priority: 2
View all other issues in [map.overview].
View all issues with C++20 status.
Discussion:
With the deduction guides as specified currently, code like this doesn't work:
map m{pair{1, 1}, {2, 2}, {3, 3}};
Same problem occurs with multimap
, unordered_map
and unordered_multimap
.
The problem is in deduction guides like
template<class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T>>> map(initializer_list<pair<const Key, T>>, Compare = Compare(), Allocator = Allocator()) -> map<Key, T, Compare, Allocator>;
The pair<const Key, T>
is not matched by a pair<int, int>
, because
int
can't match a const Key
. Dropping the const
from the parameter of the
deduction guide makes it work with no loss of functionality.
[2017-11-03, Zhihao Yuan comments]
The fix described here prevents
std::map m2{m0.begin(), m0.end()};
from falling back to direct-non-list-initialization. Treating a uniform initialization with >1 clauses
of the same un-cvref type as std::initializer_list
is the only consistent interpretation I found
so far.
[2017-11 Albuquerque Wednesday night issues processing]
Priority set to 2
[2018-08-23 Batavia Issues processing]
Status to Tentatively Ready
[2018-11, Adopted in San Diego]
Proposed resolution:
This wording is relative to N4687.
Change 23.4.3.1 [map.overview] p3, class template map
synopsis, as indicated:
[…] template<class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T>>> map(initializer_list<pair<constKey, T>>, Compare = Compare(), Allocator = Allocator()) -> map<Key, T, Compare, Allocator>; […] template<class Key, class T, class Allocator> map(initializer_list<pair<constKey, T>>, Allocator) -> map<Key, T, less<Key>, Allocator>; […]
Change 23.4.4.1 [multimap.overview] p3, class template multimap
synopsis, as indicated:
[…] template<class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T>>> multimap(initializer_list<pair<constKey, T>>, Compare = Compare(), Allocator = Allocator()) -> multimap<Key, T, Compare, Allocator>; […] template<class Key, class T, class Allocator> multimap(initializer_list<pair<constKey, T>>, Allocator) -> multimap<Key, T, less<Key>, Allocator>; […]
Change 23.5.3.1 [unord.map.overview] p3, class template unordered_map
synopsis, as indicated:
[…] template<class Key, class T, class Hash = hash<Key>, class Pred = equal_to<Key>, class Allocator = allocator<pair<const Key, T>>> unordered_map(initializer_list<pair<constKey, T>>, typename see below::size_type = see below, Hash = Hash(), Pred = Pred(), Allocator = Allocator()) -> unordered_map<Key, T, Hash, Pred, Allocator>; […] template<class Key, class T, typename Allocator> unordered_map(initializer_list<pair<constKey, T>>, typename see below::size_type, Allocator) -> unordered_map<Key, T, hash<Key>, equal_to<Key>, Allocator>; template<class Key, class T, typename Allocator> unordered_map(initializer_list<pair<constKey, T>>, Allocator) -> unordered_map<Key, T, hash<Key>, equal_to<Key>, Allocator>; template<class Key, class T, class Hash, class Allocator> unordered_map(initializer_list<pair<constKey, T>>, typename see below::size_type, Hash, Allocator) -> unordered_map<Key, T, Hash, equal_to<Key>, Allocator>; […]
Change 23.5.4.1 [unord.multimap.overview] p3, class template unordered_multimap
synopsis, as indicated:
[…] template<class Key, class T, class Hash = hash<Key>, class Pred = equal_to<Key>, class Allocator = allocator<pair<const Key, T>>> unordered_multimap(initializer_list<pair<constKey, T>>, typename see below::size_type = see below, Hash = Hash(), Pred = Pred(), Allocator = Allocator()) -> unordered_multimap<Key, T, Hash, Pred, Allocator>; […] template<class Key, class T, typename Allocator> unordered_multimap(initializer_list<pair<constKey, T>>, typename see below::size_type, Allocator) -> unordered_multimap<Key, T, hash<Key>, equal_to<Key>, Allocator>; template<class Key, class T, typename Allocator> unordered_multimap(initializer_list<pair<constKey, T>>, Allocator) -> unordered_multimap<Key, T, hash<Key>, equal_to<Key>, Allocator>; template<class Key, class T, class Hash, class Allocator> unordered_multimap(initializer_list<pair<constKey, T>>, typename see below::size_type, Hash, Allocator) -> unordered_multimap<Key, T, Hash, equal_to<Key>, Allocator>; […]