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: New Submitter: Mike Spertus Opened: 2021-03-09 Last modified: 2021-04-20
Priority: 3
View all other issues in [map.overview].
View all issues with New status.
Discussion:
The resolution for LWG 3025 enabled code like the following to be accepted:
map m1{{pair{1, 2}, {3, 4}}, less<int>()};
but breaks code that had been previously working like the following
using value_type = pair<const int, int>; map m2{{value_type{1, 2}, {3, 4}}, less<int>()};
as shown on godbolt.
[Acknowledgment to Tim Song and Arthur O'Dwyer for independently pointing out this case on the LWG mailing list][2021-04-20; Reflector poll]
Priority set to 3. Three preferences expressed for Option B, none for A.
Proposed resolution:
This wording is relative to N4878.
We present two partial wording options for
std::map
, denoted by (A) and (B) below. If the committee accepts one of them, we will complete them to all key-value containers.
(A) Wording option 1: In this option, we restore the deduction guide that was removed in LWG 3025 while maintaining the one that was added, demonstrates this working.
Modify 23.4.3.1 [map.overview] as indicated:
[…] template<class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T>>> map(initializer_list<pair<Key, T>>, Compare = Compare(), Allocator = Allocator()) -> map<Key, T, Compare, Allocator>; 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>; template<class InputIterator, class Allocator> map(InputIterator, InputIterator, Allocator) -> map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, less<iter-key-type<InputIterator>>, Allocator>; template<class Key, class T, class Allocator> map(initializer_list<pair<Key, T>>, Allocator) -> map<Key, T, less<Key>, Allocator>; template<class Key, class T, class Allocator> map(initializer_list<pair<const Key, T>>, Allocator) -> map<Key, T, less<Key>, Allocator>; […]
(B) Wording option 2: This one follows Tim Song's suggestion:
"It seems that the cleanest fix is to 1) disallow the initializer_list<value_type>
constructors from being
used for CTAD, and 2) change the guides to use remove_const_t<Key>
." This change has been tested locally
with g++ similar to the above godbolt.
Modify 23.4.3.1 [map.overview] as indicated:
[…] // types using key_type = Key; using mapped_type = T; using value_type = type_identity_t<pair<const Key, T>>; […] template<class Key, class T, class Compare = less<remove_const_t<Key>>, class Allocator = allocator<pair<const Key, T>>> map(initializer_list<pair<Key, T>>, Compare = Compare(), Allocator = Allocator()) -> map<remove_const_t<Key>, T, Compare, Allocator>; template<class InputIterator, class Allocator> map(InputIterator, InputIterator, Allocator) -> map<iter-key-type<InputIterator>, iter-mapped-type<InputIterator>, less<iter-key-type<InputIterator>>, Allocator>; template<class Key, class T, class Allocator> map(initializer_list<pair<Key, T>>, Allocator) -> map<remove_const_t<Key>, T, less<remove_const_t<Key>>, Allocator>; […]