Title
LWG 3025 broke previous valid code
Status
new
Section
[map.overview][multimap.overview] [unord.map.overview][unord.multimap.overview]
Submitter
Mike Spertus

Created on 2021-03-09.00:00:00 last changed 1 month ago

Messages

Date: 2021-04-20.20:40:18

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.

  1. (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.

    1. Modify [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>;
      […]
      
  2. (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.

    1. Modify [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>;           
      
      […]
      
Date: 2021-04-15.00:00:00

[ 2021-04-20; Reflector poll ]

Priority set to 3. Three preferences expressed for Option B, none for A.

Date: 2021-03-09.00:00:00

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]

History
Date User Action Args
2021-04-20 20:40:18adminsetmessages: + msg11773
2021-03-13 13:34:47adminsetmessages: + msg11741
2021-03-09 00:00:00admincreate