Title
Map-like container deduction guides should use pair<Key, T>, not pair<const Key, T>
Status
c++20
Section
[map.overview][multimap.overview] [unord.map.overview][unord.multimap.overview]
Submitter
Ville Voutilainen

Created on 2017-10-08.00:00:00 last changed 46 months ago

Messages

Date: 2018-11-12.04:39:29

Proposed resolution:

This wording is relative to N4687.

  1. Change [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<const Key, T>>, Compare = Compare(), Allocator = Allocator())
        -> map<Key, T, Compare, Allocator>;
    […]
    template<class Key, class T, class Allocator>
      map(initializer_list<pair<const Key, T>>, Allocator) -> map<Key, T, less<Key>, Allocator>;
    […]
    
  2. Change [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<const Key, T>>, Compare = Compare(), Allocator = Allocator())
        -> multimap<Key, T, Compare, Allocator>;
    […]
    template<class Key, class T, class Allocator>
      multimap(initializer_list<pair<const Key, T>>, Allocator)
        -> multimap<Key, T, less<Key>, Allocator>;
    […]
    
  3. Change [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<const Key, 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<const Key, 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<const Key, 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<const Key, T>>, typename see below::size_type, Hash,
                    Allocator)
        -> unordered_map<Key, T, Hash, equal_to<Key>, Allocator>;
    […]
    
  4. Change [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<const Key, 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<const Key, 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<const Key, 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<const Key, T>>, typename see below::size_type,
                         Hash, Allocator)
        -> unordered_multimap<Key, T, Hash, equal_to<Key>, Allocator>;
    […]
    
Date: 2018-11-12.04:39:29

[ 2018-11, Adopted in San Diego ]

Date: 2018-08-23.00:00:00

[ 2018-08-23 Batavia Issues processing ]

Status to Tentatively Ready

Date: 2017-11-09.15:13:04

[ 2017-11 Albuquerque Wednesday night issues processing ]

Priority set to 2

Date: 2017-11-15.00:00:00

[ 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.

Date: 2017-10-08.00:00:00

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.

History
Date User Action Args
2021-02-25 10:48:01adminsetstatus: wp -> c++20
2018-11-12 04:39:29adminsetmessages: + msg10187
2018-11-12 04:39:29adminsetstatus: voting -> wp
2018-10-08 05:13:59adminsetstatus: ready -> voting
2018-08-24 13:31:33adminsetmessages: + msg10123
2018-08-24 13:31:33adminsetstatus: new -> ready
2017-11-09 15:13:04adminsetmessages: + msg9523
2017-11-03 19:09:18adminsetmessages: + msg9504
2017-10-15 13:57:32adminsetmessages: + msg9475
2017-10-08 00:00:00admincreate