2713. More missing allocator-extended constructors for unordered containers

Section: 23.5 [unord] Status: New Submitter: Billy Robert O'Neal III Opened: 2016-05-20 Last modified: 2022-07-16

Priority: 3

View all other issues in [unord].

View all issues with New status.

Discussion:

The resolution of LWG 2210 missed constructors accepting a range or initializer list and allocator.

Previous resolution [SUPERSEDED]:

This wording is relative to N4582.

  1. Add to the synopsis in 23.5.3.1 [unord.map.overview] p3:

    namespace std {
      template <class Key, class T,
        class Hash = hash<Key>,
        class Pred = std::equal_to<Key>,
        class Allocator = std::allocator<std::pair<const Key, T> > > {
      class unordered_map {
      public:
        […]
        unordered_map(size_type n, const hasher& hf, const allocator_type& a)
          : unordered_map(n, hf, key_equal(), a) { }
        template <class InputIterator>
          unordered_map(InputIterator f, InputIterator l, const allocator_type& a)
          : unordered_map(f, l, see below, hasher(), key_equal(), a) { }
        template <class InputIterator>
          unordered_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
          : unordered_map(f, l, n, hasher(), key_equal(), a) { }
        template <class InputIterator>
          unordered_map(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                const allocator_type& a)
          : unordered_map(f, l, n, hf, key_equal(), a) { }
        unordered_map(initializer_list<value_type> il, const allocator_type& a)
          : unordered_map(il, see below, hasher(), key_equal(), a) { }
        unordered_map(initializer_list<value_type> il, size_type n, const allocator_type& a)
          : unordered_map(il, n, hasher(), key_equal(), a) { }
        […]
      };
    }
    
  2. Add to the synopsis in 23.5.4.1 [unord.multimap.overview] p3:

    namespace std {
      template <class Key, class T,
        class Hash = hash<Key>,
        class Pred = std::equal_to<Key>,
        class Allocator = std::allocator<std::pair<const Key, T> > > {
      class unordered_multimap {
      public:
        […]
        unordered_multimap(size_type n, const hasher& hf, const allocator_type& a)
          : unordered_multimap(n, hf, key_equal(), a) { }
        template <class InputIterator>
          unordered_multimap(InputIterator f, InputIterator l, const allocator_type& a)
          : unordered_multimap(f, l, see below, hasher(), key_equal(), a) { }
        template <class InputIterator>
          unordered_multimap(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
          : unordered_multimap(f, l, n, hasher(), key_equal(), a) { }
        template <class InputIterator>
          unordered_multimap(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                const allocator_type& a)
          : unordered_multimap(f, l, n, hf, key_equal(), a) { }
        unordered_multimap(initializer_list<value_type> il, const allocator_type& a)
          : unordered_multimap(il, see below, hasher(), key_equal(), a) { }
        unordered_multimap(initializer_list<value_type> il, size_type n, const allocator_type& a)
          : unordered_multimap(il, n, hasher(), key_equal(), a) { }
        […]
      };
    }
    
  3. Add to the synopsis in 23.5.6.1 [unord.set.overview] p3:

    namespace std {
      template <class Key,
        class Hash = hash<Key>,
        class Pred = std::equal_to<Key>,
        class Allocator = std::allocator<Key> > {
      class unordered_set {
      public:
        […]
        unordered_set(size_type n, const hasher& hf, const allocator_type& a)
          : unordered_set(n, hf, key_equal(), a) { }
        template <class InputIterator>
          unordered_set(InputIterator f, InputIterator l, const allocator_type& a)
          : unordered_set(f, l, see below, hasher(), key_equal(), a) { }
        template <class InputIterator>
          unordered_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
          : unordered_set(f, l, n, hasher(), key_equal(), a) { }
        template <class InputIterator>
          unordered_set(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                const allocator_type& a)
          : unordered_set(f, l, n, hf, key_equal(), a) { }
        unordered_set(initializer_list<value_type> il, const allocator_type& a)
          : unordered_set(il, see below, hasher(), key_equal(), a) { }
        unordered_set(initializer_list<value_type> il, size_type n, const allocator_type& a)
          : unordered_set(il, n, hasher(), key_equal(), a) { }
        […]
      };
    }
    
  4. Add to the synopsis in 23.5.7.1 [unord.multiset.overview] p3:

    namespace std {
      template <class Key,
        class Hash = hash<Key>,
        class Pred = std::equal_to<Key>,
        class Allocator = std::allocator<Key> > {
      class unordered_multiset {
      public:
        […]
        unordered_multiset(size_type n, const hasher& hf, const allocator_type& a)
          : unordered_multiset(n, hf, key_equal(), a) { }
        template <class InputIterator>
          unordered_multiset(InputIterator f, InputIterator l, const allocator_type& a)
          : unordered_multiset(f, l, see below, hasher(), key_equal(), a) { }
        template <class InputIterator>
          unordered_multiset(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
          : unordered_multiset(f, l, n, hasher(), key_equal(), a) { }
        template <class InputIterator>
          unordered_multiset(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                const allocator_type& a)
          : unordered_multiset(f, l, n, hf, key_equal(), a) { }
        unordered_multiset(initializer_list<value_type> il, const allocator_type& a)
          : unordered_multiset(il, see below, hasher(), key_equal(), a) { }
        unordered_multiset(initializer_list<value_type> il, size_type n, const allocator_type& a)
          : unordered_multiset(il, n, hasher(), key_equal(), a) { }
        […]
      };
    }
    

[2016-06, Oulu — Daniel comments and provides new wording]

During the LWG discussion of this issue it has been observed, that the interpretation of the embedded see below is not really clear and that we should split declaration and definition of the new overloads, so that we have a place that allows us to specify what "see below" stands for. In addition, the new wording wraps the "see below" as "size_type(see below)" to clarify the provided expression type, similar as we did for the default constructor of unordered_map.

[Oulu, 2016-06]

Alisdair to review wording.

Previous resolution [SUPERSEDED]:

This wording is relative to N4594.

  1. Add to the synopsis in 23.5.3.1 [unord.map.overview] p3:

    namespace std {
      template <class Key, class T,
        class Hash = hash<Key>,
        class Pred = std::equal_to<Key>,
        class Allocator = std::allocator<std::pair<const Key, T> > > {
      class unordered_map {
      public:
        […]
        unordered_map(size_type n, const hasher& hf, const allocator_type& a)
          : unordered_map(n, hf, key_equal(), a) { }
        template <class InputIterator>
          unordered_map(InputIterator f, InputIterator l, const allocator_type& a);
        template <class InputIterator>
          unordered_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
          : unordered_map(f, l, n, hasher(), key_equal(), a) { }
        template <class InputIterator>
          unordered_map(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                const allocator_type& a)
          : unordered_map(f, l, n, hf, key_equal(), a) { }
        unordered_map(initializer_list<value_type> il, const allocator_type& a);
        unordered_map(initializer_list<value_type> il, size_type n, const allocator_type& a)
          : unordered_map(il, n, hasher(), key_equal(), a) { }
        […]
      };
    }
    
  2. Insert the following new prototype specification just after 23.5.3.2 [unord.map.cnstr] p2

    template <class InputIterator>
      unordered_map(InputIterator f, InputIterator l, const allocator_type& a)
        : unordered_map(f, l, size_type(see below), hasher(), key_equal(), a) { }
    
    unordered_map(initializer_list<value_type> il, const allocator_type& a)
      : unordered_map(il, size_type(see below), hasher(), key_equal(), a) { }
    

    -?- Remarks: The number of buckets is implementation-defined.

  3. Add to the synopsis in 23.5.4.1 [unord.multimap.overview] p3:

    namespace std {
      template <class Key, class T,
        class Hash = hash<Key>,
        class Pred = std::equal_to<Key>,
        class Allocator = std::allocator<std::pair<const Key, T> > > {
      class unordered_multimap {
      public:
        […]
        unordered_multimap(size_type n, const hasher& hf, const allocator_type& a)
          : unordered_multimap(n, hf, key_equal(), a) { }
        template <class InputIterator>
          unordered_multimap(InputIterator f, InputIterator l, const allocator_type& a);
        template <class InputIterator>
          unordered_multimap(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
          : unordered_multimap(f, l, n, hasher(), key_equal(), a) { }
        template <class InputIterator>
          unordered_multimap(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                const allocator_type& a)
          : unordered_multimap(f, l, n, hf, key_equal(), a) { }
        unordered_multimap(initializer_list<value_type> il, const allocator_type& a);
        unordered_multimap(initializer_list<value_type> il, size_type n, const allocator_type& a)
          : unordered_multimap(il, n, hasher(), key_equal(), a) { }
        […]
      };
    }
    
  4. Insert the following new prototype specification just after 23.5.4.2 [unord.multimap.cnstr] p2

    template <class InputIterator>
      unordered_multimap(InputIterator f, InputIterator l, const allocator_type& a)
        : unordered_multimap(f, l, size_type(see below), hasher(), key_equal(), a) { }
    
    unordered_multimap(initializer_list<value_type> il, const allocator_type& a)
      : unordered_multimap(il, size_type(see below), hasher(), key_equal(), a) { }
    

    -?- Remarks: The number of buckets is implementation-defined.

  5. Add to the synopsis in 23.5.6.1 [unord.set.overview] p3:

    namespace std {
      template <class Key,
        class Hash = hash<Key>,
        class Pred = std::equal_to<Key>,
        class Allocator = std::allocator<Key> > {
      class unordered_set {
      public:
        […]
        unordered_set(size_type n, const hasher& hf, const allocator_type& a)
          : unordered_set(n, hf, key_equal(), a) { }
        template <class InputIterator>
          unordered_set(InputIterator f, InputIterator l, const allocator_type& a);
        template <class InputIterator>
          unordered_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
          : unordered_set(f, l, n, hasher(), key_equal(), a) { }
        template <class InputIterator>
          unordered_set(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                const allocator_type& a)
          : unordered_set(f, l, n, hf, key_equal(), a) { }
        unordered_set(initializer_list<value_type> il, const allocator_type& a);
        unordered_set(initializer_list<value_type> il, size_type n, const allocator_type& a)
          : unordered_set(il, n, hasher(), key_equal(), a) { }
        […]
      };
    }
    
  6. Insert the following new prototype specification just after 23.5.6.2 [unord.set.cnstr] p2

    template <class InputIterator>
      unordered_set(InputIterator f, InputIterator l, const allocator_type& a)
        : unordered_set(f, l, size_type(see below), hasher(), key_equal(), a) { }
    
    unordered_set(initializer_list<value_type> il, const allocator_type& a)
      : unordered_set(il, size_type(see below), hasher(), key_equal(), a) { }
    

    -?- Remarks: The number of buckets is implementation-defined.

  7. Add to the synopsis in 23.5.7.1 [unord.multiset.overview] p3:

    namespace std {
      template <class Key,
        class Hash = hash<Key>,
        class Pred = std::equal_to<Key>,
        class Allocator = std::allocator<Key> > {
      class unordered_multiset {
      public:
        […]
        unordered_multiset(size_type n, const hasher& hf, const allocator_type& a)
          : unordered_multiset(n, hf, key_equal(), a) { }
        template <class InputIterator>
          unordered_multiset(InputIterator f, InputIterator l, const allocator_type& a);
        template <class InputIterator>
          unordered_multiset(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
          : unordered_multiset(f, l, n, hasher(), key_equal(), a) { }
        template <class InputIterator>
          unordered_multiset(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                const allocator_type& a)
          : unordered_multiset(f, l, n, hf, key_equal(), a) { }
        unordered_multiset(initializer_list<value_type> il, const allocator_type& a);
        unordered_multiset(initializer_list<value_type> il, size_type n, const allocator_type& a)
          : unordered_multiset(il, n, hasher(), key_equal(), a) { }
        […]
      };
    }
    
  8. Insert the following new prototype specification just after 23.5.7.2 [unord.multiset.cnstr] p2

    template <class InputIterator>
      unordered_multiset(InputIterator f, InputIterator l, const allocator_type& a)
        : unordered_multiset(f, l, size_type(see below), hasher(), key_equal(), a) { }
    
    unordered_multiset(initializer_list<value_type> il, const allocator_type& a)
      : unordered_multiset(il, size_type(see below), hasher(), key_equal(), a) { }
    

    -?- Remarks: The number of buckets is implementation-defined.

[2017-08-04, Daniel and Alisdair finetune wording]

We decided to improve the added Remarks: elements by changing from the previous form:

Remarks: The number of buckets is implementation-defined.

to the more elaborate form:

Remarks: The initial number of buckets supplied by the size_type argument is implementation-defined.

[2020-11-29; Reflector discussions]

It has been pointed out that this issue is related to LWG 1199, LWG 2210, and LWG 3506.

Previous resolution [SUPERSEDED]:

This resolution is relative to N4687.

  1. Add to the synopsis in 23.5.3.1 [unord.map.overview] p3:

    namespace std {
      template <class Key, class T,
        class Hash = hash<Key>,
        class Pred = std::equal_to<Key>,
        class Allocator = std::allocator<std::pair<const Key, T> > > {
      class unordered_map {
      public:
        […]
        unordered_map(size_type n, const hasher& hf, const allocator_type& a)
          : unordered_map(n, hf, key_equal(), a) { }
        template <class InputIterator>
          unordered_map(InputIterator f, InputIterator l, const allocator_type& a);
        template <class InputIterator>
          unordered_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
          : unordered_map(f, l, n, hasher(), key_equal(), a) { }
        template <class InputIterator>
          unordered_map(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                const allocator_type& a)
          : unordered_map(f, l, n, hf, key_equal(), a) { }
        unordered_map(initializer_list<value_type> il, const allocator_type& a);
        unordered_map(initializer_list<value_type> il, size_type n, const allocator_type& a)
          : unordered_map(il, n, hasher(), key_equal(), a) { }
        […]
      };
    }
    
  2. Insert the following new prototype specification just after 23.5.3.2 [unord.map.cnstr] p2

    template <class InputIterator>
      unordered_map(InputIterator f, InputIterator l, const allocator_type& a)
        : unordered_map(f, l, size_type(see below), hasher(), key_equal(), a) { }
    
    unordered_map(initializer_list<value_type> il, const allocator_type& a)
      : unordered_map(il, size_type(see below), hasher(), key_equal(), a) { }
    

    -?- Remarks: The initial number of buckets supplied by the size_type argument is implementation-defined.

  3. Add to the synopsis in 23.5.4.1 [unord.multimap.overview] p3:

    namespace std {
      template <class Key, class T,
        class Hash = hash<Key>,
        class Pred = std::equal_to<Key>,
        class Allocator = std::allocator<std::pair<const Key, T> > > {
      class unordered_multimap {
      public:
        […]
        unordered_multimap(size_type n, const hasher& hf, const allocator_type& a)
          : unordered_multimap(n, hf, key_equal(), a) { }
        template <class InputIterator>
          unordered_multimap(InputIterator f, InputIterator l, const allocator_type& a);
        template <class InputIterator>
          unordered_multimap(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
          : unordered_multimap(f, l, n, hasher(), key_equal(), a) { }
        template <class InputIterator>
          unordered_multimap(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                const allocator_type& a)
          : unordered_multimap(f, l, n, hf, key_equal(), a) { }
        unordered_multimap(initializer_list<value_type> il, const allocator_type& a);
        unordered_multimap(initializer_list<value_type> il, size_type n, const allocator_type& a)
          : unordered_multimap(il, n, hasher(), key_equal(), a) { }
        […]
      };
    }
    
  4. Insert the following new prototype specification just after 23.5.4.2 [unord.multimap.cnstr] p2

    template <class InputIterator>
      unordered_multimap(InputIterator f, InputIterator l, const allocator_type& a)
        : unordered_multimap(f, l, size_type(see below), hasher(), key_equal(), a) { }
    
    unordered_multimap(initializer_list<value_type> il, const allocator_type& a)
      : unordered_multimap(il, size_type(see below), hasher(), key_equal(), a) { }
    

    -?- Remarks: The initial number of buckets supplied by the size_type argument is implementation-defined.

  5. Add to the synopsis in 23.5.6.1 [unord.set.overview] p3:

    namespace std {
      template <class Key,
        class Hash = hash<Key>,
        class Pred = std::equal_to<Key>,
        class Allocator = std::allocator<Key> > {
      class unordered_set {
      public:
        […]
        unordered_set(size_type n, const hasher& hf, const allocator_type& a)
          : unordered_set(n, hf, key_equal(), a) { }
        template <class InputIterator>
          unordered_set(InputIterator f, InputIterator l, const allocator_type& a);
        template <class InputIterator>
          unordered_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
          : unordered_set(f, l, n, hasher(), key_equal(), a) { }
        template <class InputIterator>
          unordered_set(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                const allocator_type& a)
          : unordered_set(f, l, n, hf, key_equal(), a) { }
        unordered_set(initializer_list<value_type> il, const allocator_type& a);
        unordered_set(initializer_list<value_type> il, size_type n, const allocator_type& a)
          : unordered_set(il, n, hasher(), key_equal(), a) { }
        […]
      };
    }
    
  6. Insert the following new prototype specification just after 23.5.6.2 [unord.set.cnstr] p2

    template <class InputIterator>
      unordered_set(InputIterator f, InputIterator l, const allocator_type& a)
        : unordered_set(f, l, size_type(see below), hasher(), key_equal(), a) { }
    
    unordered_set(initializer_list<value_type> il, const allocator_type& a)
      : unordered_set(il, size_type(see below), hasher(), key_equal(), a) { }
    

    -?- Remarks: The initial number of buckets supplied by the size_type argument is implementation-defined.

  7. Add to the synopsis in 23.5.7.1 [unord.multiset.overview] p3:

    namespace std {
      template <class Key,
        class Hash = hash<Key>,
        class Pred = std::equal_to<Key>,
        class Allocator = std::allocator<Key> > {
      class unordered_multiset {
      public:
        […]
        unordered_multiset(size_type n, const hasher& hf, const allocator_type& a)
          : unordered_multiset(n, hf, key_equal(), a) { }
        template <class InputIterator>
          unordered_multiset(InputIterator f, InputIterator l, const allocator_type& a);
        template <class InputIterator>
          unordered_multiset(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
          : unordered_multiset(f, l, n, hasher(), key_equal(), a) { }
        template <class InputIterator>
          unordered_multiset(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                const allocator_type& a)
          : unordered_multiset(f, l, n, hf, key_equal(), a) { }
        unordered_multiset(initializer_list<value_type> il, const allocator_type& a);
        unordered_multiset(initializer_list<value_type> il, size_type n, const allocator_type& a)
          : unordered_multiset(il, n, hasher(), key_equal(), a) { }
        […]
      };
    }
    
  8. Insert the following new prototype specification just after 23.5.7.2 [unord.multiset.cnstr] p2

    template <class InputIterator>
      unordered_multiset(InputIterator f, InputIterator l, const allocator_type& a)
        : unordered_multiset(f, l, size_type(see below), hasher(), key_equal(), a) { }
    
    unordered_multiset(initializer_list<value_type> il, const allocator_type& a)
      : unordered_multiset(il, size_type(see below), hasher(), key_equal(), a) { }
    

    -?- Remarks: The initial number of buckets supplied by the size_type argument is implementation-defined.

[2022-07-10; Daniel comments]

It is has been noticed by Daniel Eiband on [std-discussion] that the following deduction guides for the following constructors of the set types std::unordered_set and std::unordered_multiset are missing:

unordered_set(InputIterator, InputIterator, Allocator);
unordered_set(initializer_list<T>, Allocator);

unordered_multiset(InputIterator, InputIterator, Allocator);
unordered_multiset(initializer_list<T>, Allocator);

Since this issue is adding these missing constructors it should also add the associated deduction guides. The proposed wording has been updated to this effect and also rebased to N4910.

Previous resolution [SUPERSEDED]:

This resolution is relative to N4910.

  1. Add to the synopsis in 23.5.3.1 [unord.map.overview] p3:

    namespace std {
      template<class Key, 
               class T,
               class Hash = hash<Key>,
               class Pred = equal_to<Key>,
               class Allocator = allocator<pair<const Key, T>>> {
      class unordered_map {
      public:
        […]
        unordered_map(size_type n, const hasher& hf, const allocator_type& a)
          : unordered_map(n, hf, key_equal(), a) { }
        template<class InputIterator>
          unordered_map(InputIterator f, InputIterator l, const allocator_type& a);
        template<class InputIterator>
          unordered_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
          : unordered_map(f, l, n, hasher(), key_equal(), a) { }
        template<class InputIterator>
          unordered_map(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                const allocator_type& a)
          : unordered_map(f, l, n, hf, key_equal(), a) { }
        […]
        unordered_map(initializer_list<value_type> il, const allocator_type& a);
        unordered_map(initializer_list<value_type> il, size_type n, const allocator_type& a)
          : unordered_map(il, n, hasher(), key_equal(), a) { }
        […]
      };
    }
    
  2. Insert the following new prototype specification just after 23.5.3.2 [unord.map.cnstr] p2

    template<class InputIterator>
      unordered_map(InputIterator f, InputIterator l, const allocator_type& a)
        : unordered_map(f, l, size_type(see below), hasher(), key_equal(), a) { }
    
    unordered_map(initializer_list<value_type> il, const allocator_type& a)
      : unordered_map(il, size_type(see below), hasher(), key_equal(), a) { }
    

    -?- Remarks: The initial number of buckets supplied by the size_type argument is implementation-defined.

  3. Add to the synopsis in 23.5.4.1 [unord.multimap.overview] p3:

    namespace std {
      template<class Key, 
               class T,
               class Hash = hash<Key>,
               class Pred = equal_to<Key>,
               class Allocator = allocator<pair<const Key, T>>> {
      class unordered_multimap {
      public:
        […]
        unordered_multimap(size_type n, const hasher& hf, const allocator_type& a)
          : unordered_multimap(n, hf, key_equal(), a) { }
        template<class InputIterator>
          unordered_multimap(InputIterator f, InputIterator l, const allocator_type& a);
        template<class InputIterator>
          unordered_multimap(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
          : unordered_multimap(f, l, n, hasher(), key_equal(), a) { }
        template<class InputIterator>
          unordered_multimap(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                const allocator_type& a)
          : unordered_multimap(f, l, n, hf, key_equal(), a) { }
        […]
        unordered_multimap(initializer_list<value_type> il, const allocator_type& a);
        unordered_multimap(initializer_list<value_type> il, size_type n, const allocator_type& a)
          : unordered_multimap(il, n, hasher(), key_equal(), a) { }
        […]
      };
    }
    
  4. Insert the following new prototype specification just after 23.5.4.2 [unord.multimap.cnstr] p2

    template<class InputIterator>
      unordered_multimap(InputIterator f, InputIterator l, const allocator_type& a)
        : unordered_multimap(f, l, size_type(see below), hasher(), key_equal(), a) { }
    
    unordered_multimap(initializer_list<value_type> il, const allocator_type& a)
      : unordered_multimap(il, size_type(see below), hasher(), key_equal(), a) { }
    

    -?- Remarks: The initial number of buckets supplied by the size_type argument is implementation-defined.

  5. Add to the synopsis in 23.5.6.1 [unord.set.overview] p3:

    namespace std {
      template<class Key,
               class Hash = hash<Key>,
               class Pred = equal_to<Key>,
               class Allocator = allocator<Key>> {
      class unordered_set {
      public:
        […]
        unordered_set(size_type n, const hasher& hf, const allocator_type& a)
          : unordered_set(n, hf, key_equal(), a) { }
        template<class InputIterator>
          unordered_set(InputIterator f, InputIterator l, const allocator_type& a);
        template<class InputIterator>
          unordered_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
          : unordered_set(f, l, n, hasher(), key_equal(), a) { }
        template<class InputIterator>
          unordered_set(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                const allocator_type& a)
          : unordered_set(f, l, n, hf, key_equal(), a) { }
        unordered_set(initializer_list<value_type> il, const allocator_type& a);
        unordered_set(initializer_list<value_type> il, size_type n, const allocator_type& a)
          : unordered_set(il, n, hasher(), key_equal(), a) { }
        […]
      };
      
      […]
      template<class T, class Allocator>
        unordered_set(initializer_list<T>, typename see below::size_type, Allocator)
          -> unordered_set<T, hash<T>, equal_to<T>, Allocator>;
    
      template<class T, class Hash, class Allocator>
        unordered_set(initializer_list<T>, typename see below::size_type, Hash, Allocator)
          -> unordered_set<T, Hash, equal_to<T>, Allocator>;
          
      template<class InputIterator, class Allocator>
        unordered_set(InputIterator, InputIterator, Allocator)
          -> unordered_set<iter-value-type<InputIterator>,
                           hash<iter-value-type<InputIterator>>,
                           equal_to<iter-value-type<InputIterator>>,                           
                           Allocator>;
    
      template<class T, class Allocator>
        unordered_set(initializer_list<T>, Allocator) 
          -> unordered_set<T, hash<T>, equal_to<T>, Allocator>;
    }
    
  6. Insert the following new prototype specification just after 23.5.6.2 [unord.set.cnstr] p2

    template<class InputIterator>
      unordered_set(InputIterator f, InputIterator l, const allocator_type& a)
        : unordered_set(f, l, size_type(see below), hasher(), key_equal(), a) { }
    
    unordered_set(initializer_list<value_type> il, const allocator_type& a)
      : unordered_set(il, size_type(see below), hasher(), key_equal(), a) { }
    

    -?- Remarks: The initial number of buckets supplied by the size_type argument is implementation-defined.

  7. Add to the synopsis in 23.5.7.1 [unord.multiset.overview] p3:

    namespace std {
      template<class Key,
               class Hash = hash<Key>,
               class Pred = equal_to<Key>,
               class Allocator = allocator<Key>> {
      class unordered_multiset {
      public:
        […]
        unordered_multiset(size_type n, const hasher& hf, const allocator_type& a)
          : unordered_multiset(n, hf, key_equal(), a) { }
        template<class InputIterator>
          unordered_multiset(InputIterator f, InputIterator l, const allocator_type& a);
        template<class InputIterator>
          unordered_multiset(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
          : unordered_multiset(f, l, n, hasher(), key_equal(), a) { }
        template<class InputIterator>
          unordered_multiset(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                const allocator_type& a)
          : unordered_multiset(f, l, n, hf, key_equal(), a) { }
        unordered_multiset(initializer_list<value_type> il, const allocator_type& a);
        unordered_multiset(initializer_list<value_type> il, size_type n, const allocator_type& a)
          : unordered_multiset(il, n, hasher(), key_equal(), a) { }
        […]
      };
      
      […]
      template<class T, class Allocator>
        unordered_multiset(initializer_list<T>, typename see below ::size_type, Allocator)
          -> unordered_multiset<T, hash<T>, equal_to<T>, Allocator>;
    
      template<class T, class Hash, class Allocator>
        unordered_multiset(initializer_list<T>, typename see below ::size_type, Hash, Allocator)
          -> unordered_multiset<T, Hash, equal_to<T>, Allocator>;
          
      template<class InputIterator, class Allocator>
        unordered_multiset(InputIterator, InputIterator, Allocator)
          -> unordered_multiset<iter-value-type<InputIterator>,
                                hash<iter-value-type<InputIterator>>,
                                equal_to<iter-value-type<InputIterator>>,                  
                                Allocator>;
    
      template<class T, class Allocator>
        unordered_multiset(initializer_list<T>, Allocator) 
          -> unordered_multiset<T, hash<T>, equal_to<T>, Allocator>;
    }
    
  8. Insert the following new prototype specification just after 23.5.7.2 [unord.multiset.cnstr] p2

    template<class InputIterator>
      unordered_multiset(InputIterator f, InputIterator l, const allocator_type& a)
        : unordered_multiset(f, l, size_type(see below), hasher(), key_equal(), a) { }
    
    unordered_multiset(initializer_list<value_type> il, const allocator_type& a)
      : unordered_multiset(il, size_type(see below), hasher(), key_equal(), a) { }
    

    -?- Remarks: The initial number of buckets supplied by the size_type argument is implementation-defined.

[2022-07-15; Casey comments]

P1206R7 added from_range_t constructors corresponding to existing iterator pair constructors for the standard containers. For consistency, this issue should add from_range_t constructors corresponding to each new iterator pair constructor.

[2022-07-16; Daniel comments and updates wording]

The new from_range_t constructors have been added for each added new iterator pair constructor. Note that the corresponding deduction guides already exist.

Proposed resolution:

This resolution is relative to N4910.

  1. Add to the synopsis in 23.5.3.1 [unord.map.overview] p3:

    namespace std {
      template<class Key, 
               class T,
               class Hash = hash<Key>,
               class Pred = equal_to<Key>,
               class Allocator = allocator<pair<const Key, T>>> {
      class unordered_map {
      public:
        […]
        unordered_map(size_type n, const hasher& hf, const allocator_type& a)
          : unordered_map(n, hf, key_equal(), a) { }
        template<class InputIterator>
          unordered_map(InputIterator f, InputIterator l, const allocator_type& a);
        template<class InputIterator>
          unordered_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
            : unordered_map(f, l, n, hasher(), key_equal(), a) { }
        template<class InputIterator>
          unordered_map(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                const allocator_type& a)
            : unordered_map(f, l, n, hf, key_equal(), a) { }
        template<container-compatible-range<value_type> R>
          unordered_map(from_range_t, R&& rg, const allocator_type& a);
        template<container-compatible-range<value_type> R>
          unordered_map(from_range_t, R&& rg, size_type n, const allocator_type& a)
            : unordered_map(from_range, std::forward<R>(rg), n, hasher(), key_equal(), a) { }
        template<container-compatible-range<value_type> R>
          unordered_map(from_range_t, R&& rg, size_type n, const hasher& hf, const allocator_type& a)
            : unordered_map(from_range, std::forward<R>(rg), n, hf, key_equal(), a) { }
        unordered_map(initializer_list<value_type> il, const allocator_type& a);
        unordered_map(initializer_list<value_type> il, size_type n, const allocator_type& a)
          : unordered_map(il, n, hasher(), key_equal(), a) { }
        […]
      };
    }
    
  2. Insert the following new prototype specification just after 23.5.3.2 [unord.map.cnstr] p2

    template<class InputIterator>
      unordered_map(InputIterator f, InputIterator l, const allocator_type& a)
        : unordered_map(f, l, size_type(see below), hasher(), key_equal(), a) { }
    
    template<container-compatible-range<value_type> R>
      unordered_map(from_range_t, R&& rg, const allocator_type& a)
        : unordered_map(from_range, std::forward<R>(rg), size_type(see below), hasher(), key_equal(), a) { }
          
    unordered_map(initializer_list<value_type> il, const allocator_type& a)
      : unordered_map(il, size_type(see below), hasher(), key_equal(), a) { }
    

    -?- Remarks: The initial number of buckets supplied by the size_type argument is implementation-defined.

  3. Add to the synopsis in 23.5.4.1 [unord.multimap.overview] p3:

    namespace std {
      template<class Key, 
               class T,
               class Hash = hash<Key>,
               class Pred = equal_to<Key>,
               class Allocator = allocator<pair<const Key, T>>> {
      class unordered_multimap {
      public:
        […]
        unordered_multimap(size_type n, const hasher& hf, const allocator_type& a)
          : unordered_multimap(n, hf, key_equal(), a) { }
        template<class InputIterator>
          unordered_multimap(InputIterator f, InputIterator l, const allocator_type& a);
        template<class InputIterator>
          unordered_multimap(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
            : unordered_multimap(f, l, n, hasher(), key_equal(), a) { }
        template<class InputIterator>
          unordered_multimap(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                const allocator_type& a)
            : unordered_multimap(f, l, n, hf, key_equal(), a) { }
        template<container-compatible-range<value_type> R>
          unordered_multimap(from_range_t, R&& rg, const allocator_type& a);
        template<container-compatible-range<value_type> R>
          unordered_multimap(from_range_t, R&& rg, size_type n, const allocator_type& a)
            : unordered_multimap(from_range, std::forward<R>(rg),
                                 n, hasher(), key_equal(), a) { }
        […]
        unordered_multimap(initializer_list<value_type> il, const allocator_type& a);
        unordered_multimap(initializer_list<value_type> il, size_type n, const allocator_type& a)
          : unordered_multimap(il, n, hasher(), key_equal(), a) { }
        […]
      };
    }
    
  4. Insert the following new prototype specification just after 23.5.4.2 [unord.multimap.cnstr] p2

    template<class InputIterator>
      unordered_multimap(InputIterator f, InputIterator l, const allocator_type& a)
        : unordered_multimap(f, l, size_type(see below), hasher(), key_equal(), a) { }
    
    template<container-compatible-range<value_type> R>
      unordered_multimap(from_range_t, R&& rg, const allocator_type& a)
        : unordered_multimap(from_range, std::forward<R>(rg), size_type(see below), hasher(), key_equal(), a) { }
    
    unordered_multimap(initializer_list<value_type> il, const allocator_type& a)
      : unordered_multimap(il, size_type(see below), hasher(), key_equal(), a) { }
    

    -?- Remarks: The initial number of buckets supplied by the size_type argument is implementation-defined.

  5. Add to the synopsis in 23.5.6.1 [unord.set.overview] p3:

    namespace std {
      template<class Key,
               class Hash = hash<Key>,
               class Pred = equal_to<Key>,
               class Allocator = allocator<Key>> {
      class unordered_set {
      public:
        […]
        unordered_set(size_type n, const hasher& hf, const allocator_type& a)
          : unordered_set(n, hf, key_equal(), a) { }
        template<class InputIterator>
          unordered_set(InputIterator f, InputIterator l, const allocator_type& a);
        template<class InputIterator>
          unordered_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
            : unordered_set(f, l, n, hasher(), key_equal(), a) { }
        template<class InputIterator>
          unordered_set(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                const allocator_type& a)
            : unordered_set(f, l, n, hf, key_equal(), a) { }
        unordered_set(initializer_list<value_type> il, const allocator_type& a);
        unordered_set(initializer_list<value_type> il, size_type n, const allocator_type& a)
          : unordered_set(il, n, hasher(), key_equal(), a) { }
        template<container-compatible-range<value_type> R>
          unordered_set(from_range_t, R&& rg, const allocator_type& a);
        template<container-compatible-range<value_type> R>
          unordered_set(from_range_t, R&& rg, size_type n, const allocator_type& a)
            : unordered_set(from_range, std::forward<R>(rg), n, hasher(), key_equal(), a) { }
        […]
      };
      
      […]
      template<class T, class Allocator>
        unordered_set(initializer_list<T>, typename see below::size_type, Allocator)
          -> unordered_set<T, hash<T>, equal_to<T>, Allocator>;
    
      template<class T, class Hash, class Allocator>
        unordered_set(initializer_list<T>, typename see below::size_type, Hash, Allocator)
          -> unordered_set<T, Hash, equal_to<T>, Allocator>;
          
      template<class InputIterator, class Allocator>
        unordered_set(InputIterator, InputIterator, Allocator)
          -> unordered_set<iter-value-type<InputIterator>,
                           hash<iter-value-type<InputIterator>>,
                           equal_to<iter-value-type<InputIterator>>,                           
                           Allocator>;
    
      template<class T, class Allocator>
        unordered_set(initializer_list<T>, Allocator) 
          -> unordered_set<T, hash<T>, equal_to<T>, Allocator>;
    }
    
  6. Insert the following new prototype specification just after 23.5.6.2 [unord.set.cnstr] p2

    template<class InputIterator>
      unordered_set(InputIterator f, InputIterator l, const allocator_type& a)
        : unordered_set(f, l, size_type(see below), hasher(), key_equal(), a) { }
    
    template<container-compatible-range<value_type> R>
      unordered_set(from_range_t, R&& rg, const allocator_type& a)
        : unordered_set(from_range, std::forward<R>(rg), size_type(see below), hasher(), key_equal(), a) { }
    
    unordered_set(initializer_list<value_type> il, const allocator_type& a)
      : unordered_set(il, size_type(see below), hasher(), key_equal(), a) { }
    

    -?- Remarks: The initial number of buckets supplied by the size_type argument is implementation-defined.

  7. Add to the synopsis in 23.5.7.1 [unord.multiset.overview] p3:

    namespace std {
      template<class Key,
               class Hash = hash<Key>,
               class Pred = equal_to<Key>,
               class Allocator = allocator<Key>> {
      class unordered_multiset {
      public:
        […]
        unordered_multiset(size_type n, const hasher& hf, const allocator_type& a)
          : unordered_multiset(n, hf, key_equal(), a) { }
        template<class InputIterator>
          unordered_multiset(InputIterator f, InputIterator l, const allocator_type& a);
        template<class InputIterator>
          unordered_multiset(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
          : unordered_multiset(f, l, n, hasher(), key_equal(), a) { }
        template<class InputIterator>
          unordered_multiset(InputIterator f, InputIterator l, size_type n, const hasher& hf,
                const allocator_type& a)
          : unordered_multiset(f, l, n, hf, key_equal(), a) { }
        template<container-compatible-range<value_type> R>
          unordered_multiset(from_range_t, R&& rg, const allocator_type& a);
        template<container-compatible-range<value_type> R>
          unordered_multiset(from_range_t, R&& rg, size_type n, const allocator_type& a)
            : unordered_multiset(from_range, std::forward<R>(rg),
                                 n, hasher(), key_equal(), a) { }
        […]
        unordered_multiset(initializer_list<value_type> il, const allocator_type& a);
        unordered_multiset(initializer_list<value_type> il, size_type n, const allocator_type& a)
          : unordered_multiset(il, n, hasher(), key_equal(), a) { }
        […]
      };
      
      […]
      template<class T, class Allocator>
        unordered_multiset(initializer_list<T>, typename see below ::size_type, Allocator)
          -> unordered_multiset<T, hash<T>, equal_to<T>, Allocator>;
    
      template<class T, class Hash, class Allocator>
        unordered_multiset(initializer_list<T>, typename see below ::size_type, Hash, Allocator)
          -> unordered_multiset<T, Hash, equal_to<T>, Allocator>;
          
      template<class InputIterator, class Allocator>
        unordered_multiset(InputIterator, InputIterator, Allocator)
          -> unordered_multiset<iter-value-type<InputIterator>,
                                hash<iter-value-type<InputIterator>>,
                                equal_to<iter-value-type<InputIterator>>,                  
                                Allocator>;
    
      template<class T, class Allocator>
        unordered_multiset(initializer_list<T>, Allocator) 
          -> unordered_multiset<T, hash<T>, equal_to<T>, Allocator>;
    }
    
  8. Insert the following new prototype specification just after 23.5.7.2 [unord.multiset.cnstr] p2

    template<class InputIterator>
      unordered_multiset(InputIterator f, InputIterator l, const allocator_type& a)
        : unordered_multiset(f, l, size_type(see below), hasher(), key_equal(), a) { }
    
    template<container-compatible-range<value_type> R>
      unordered_multiset(from_range_t, R&& rg, const allocator_type& a))
        : unordered_multiset(from_range, std::forward<R>(rg), size_type(see below), hasher(), key_equal(), a) { }
    
    unordered_multiset(initializer_list<value_type> il, const allocator_type& a)
      : unordered_multiset(il, size_type(see below), hasher(), key_equal(), a) { }
    

    -?- Remarks: The initial number of buckets supplied by the size_type argument is implementation-defined.