Title
Missing allocator-extended constructor for allocator-aware containers
Status
c++14
Section
[sequences] [associative] [unord]
Submitter
Jonathan Wakely

Created on 2012-11-01.00:00:00 last changed 131 months ago

Messages

Date: 2013-04-18.22:58:13

Proposed resolution:

This wording is relative to N3485.

  1. Edit the synopsis in [deque.overview]/2:

    namespace std {
      template <class T, class Allocator = allocator<T> >
      class deque {
      public:
        […]
        explicit deque(const Allocator& = Allocator());
        explicit deque(size_type n, const Allocator& = Allocator());
        […]
      };
    }
    
  2. Edit [deque.cons]/2:

    explicit deque(size_type n, const Allocator& = Allocator());
    

    -3- Effects: Constructs a deque with n default-inserted elements using the specified allocator.

  3. Edit the synopsis in [forwardlist.overview]/3:

    namespace std {
      template <class T, class Allocator = allocator<T> >
      class forward_list {
      public:
        […]
        explicit forward_list(const Allocator& = Allocator());
        explicit forward_list(size_type n, const Allocator& = Allocator());
        […]
      };
    }
    
  4. Edit [forwardlist.cons]/3:

    explicit forward_list(size_type n, const Allocator& = Allocator());
    

    -3- Effects: Constructs a forward_list object with n default-inserted elements using the specified allocator.

  5. Edit the synopsis in [list.overview]/2:

    namespace std {
      template <class T, class Allocator = allocator<T> >
      class list {
      public:
        […]
        explicit list(const Allocator& = Allocator());
        explicit list(size_type n, const Allocator& = Allocator());
        […]
      };
    }
    
  6. Edit [list.cons]/3:

    explicit list(size_type n, const Allocator& = Allocator());
    

    -3- Effects: Constructs a list with n default-inserted elements using the specified allocator.

  7. Edit the synopsis in [vector.overview]/2:

    namespace std {
      template <class T, class Allocator = allocator<T> >
      class vector {
      public:
        […]
        explicit vector(const Allocator& = Allocator());
        explicit vector(size_type n, const Allocator& = Allocator());
        […]
      };
    }
    
  8. Edit [vector.cons]/3:

    explicit vector(size_type n, const Allocator& = Allocator());
    

    -3- Effects: Constructs a vector with n default-inserted elements using the specified allocator.

  9. Edit the synopsis in [vector.bool]/1:

    namespace std {
      template <class Allocator> class vector<bool, Allocator> {
      class vector {
      public:
        […]
        explicit vector(const Allocator& = Allocator());
        explicit vector(size_type n, const Allocator& = Allocator());
        explicit vector(size_type n, const bool& value = bool(),
                        const Allocator& = Allocator());
        […]
      };
    }
    
  10. Add to the synopsis in [map.overview] p2:

    namespace std {
      template <class Key, class T, class Compare = less<Key>,
        class Allocator = allocator<pair<const Key, T> > > {
      class map {
      public:
        […]
        map(initializer_list<value_type>,
          const Compare& = Compare(),
          const Allocator& = Allocator());
        template <class InputIterator>
        map(InputIterator first, InputIterator last, const Allocator& a)
          : map(first, last, Compare(), a) { }
        map(initializer_list<value_type> il, const Allocator& a)
          : map(il, Compare(), a) { }
        ~map();
        […]
      };
    }
    
  11. Add to the synopsis in [multimap.overview] p2:

    namespace std {
      template <class Key, class T, class Compare = less<Key>,
        class Allocator = allocator<pair<const Key, T> > > {
      class multimap {
      public:
        […]
        multimap(initializer_list<value_type>,
          const Compare& = Compare(),
          const Allocator& = Allocator());
        template <class InputIterator>
        multimap(InputIterator first, InputIterator last, const Allocator& a)
          : multimap(first, last, Compare(), a) { }
        multimap(initializer_list<value_type> il, const Allocator& a)
          : multimap(il, Compare(), a) { }
        ~multimap();
        […]
      };
    }
    
  12. Add to the synopsis in [set.overview] p2:

    namespace std {
      template <class Key, class Compare = less<Key>,
        class Allocator = allocator<Key> > {
      class set {
      public:
        […]
        set(initializer_list<value_type>,
          const Compare& = Compare(),
          const Allocator& = Allocator());
        template <class InputIterator>
        set(InputIterator first, InputIterator last, const Allocator& a)
          : set(first, last, Compare(), a) { }
        set(initializer_list<value_type> il, const Allocator& a)
          : set(il, Compare(), a) { }
        ~set();
        […]
      };
    }
    
  13. Add to the synopsis in [multiset.overview] p2:

    namespace std {
      template <class Key, class Compare = less<Key>,
        class Allocator = allocator<Key> > {
      class multiset {
      public:
        […]
        multiset(initializer_list<value_type>,
          const Compare& = Compare(),
          const Allocator& = Allocator());
        template <class InputIterator>
        multiset(InputIterator first, InputIterator last, const Allocator& a)
          : multiset(first, last, Compare(), a) { }
        multiset(initializer_list<value_type> il, const Allocator& a)
          : multiset(il, Compare(), a) { }
        ~multiset();
        […]
      };
    }
    
  14. Add to the synopsis in [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(initializer_list<value_type>,
          size_type = see below,
          const hasher& hf = hasher(),
          const key_equal& eql = key_equal(),
          const allocator_type& a = allocator_type());
        unordered_map(size_type n, const allocator_type& a)
          : unordered_map(n, hasher(), key_equal(), a) { }
        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, 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, size_type n, const allocator_type& a)
          : unordered_map(il, n, hasher(), key_equal(), a) { }
        unordered_map(initializer_list<value_type> il, size_type n, const hasher& hf, 
    	  const allocator_type& a)
          : unordered_map(il, n, hf, key_equal(), a) { }
        ~unordered_map();
        […]
      };
    }
    
  15. Add to the synopsis in [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(initializer_list<value_type>,
          size_type = see below,
          const hasher& hf = hasher(),
          const key_equal& eql = key_equal(),
          const allocator_type& a = allocator_type());
        unordered_multimap(size_type n, const allocator_type& a)
          : unordered_multimap(n, hasher(), key_equal(), a) { }
        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, 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, size_type n, const allocator_type& a)
          : unordered_multimap(il, n, hasher(), key_equal(), a) { }
        unordered_multimap(initializer_list<value_type> il, size_type n, const hasher& hf, 
    	  const allocator_type& a)
          : unordered_multimap(il, n, hf, key_equal(), a) { }
        ~unordered_multimap();
        […]
      };
    }
    
  16. Add to the synopsis in [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(initializer_list<value_type>,
          size_type = see below,
          const hasher& hf = hasher(),
          const key_equal& eql = key_equal(),
          const allocator_type& a = allocator_type());
        unordered_set(size_type n, const allocator_type& a)
          : unordered_set(n, hasher(), key_equal(), a) { }
        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, 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, size_type n, const allocator_type& a)
          : unordered_set(il, n, hasher(), key_equal(), a) { }
        unordered_set(initializer_list<value_type> il, size_type n, const hasher& hf, 
    	  const allocator_type& a)
          : unordered_set(il, n, hf, key_equal(), a) { }
        ~unordered_set();
        […]
      };
    }
    
  17. Add to the synopsis in [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(initializer_list<value_type>,
          size_type = see below,
          const hasher& hf = hasher(),
          const key_equal& eql = key_equal(),
          const allocator_type& a = allocator_type());
        unordered_multiset(size_type n, const allocator_type& a)
          : unordered_multiset(n, hasher(), key_equal(), a) { }
        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, 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, size_type n, const allocator_type& a)
          : unordered_multiset(il, n, hasher(), key_equal(), a) { }
        unordered_multiset(initializer_list<value_type> il, size_type n, const hasher& hf, 
    	  const allocator_type& a)
          : unordered_multiset(il, n, hf, key_equal(), a) { }
        ~unordered_multiset();
        […]
      };
    }
    
Date: 2013-04-15.00:00:00

[ 2013-04-18, Bristol ]

Date: 2013-03-15.00:00:00

[ 2013-03-15 Issues Teleconference ]

Moved to Review.

Jonathan: There are lots of places where this is missing.

Howard: We should ping Pablo, this might be a deliberate design decision.

Date: 2012-12-17.21:46:53

The forward_list(size_type) constructor has no allocator-extended equivalent, preventing the following code from compiling:

#include <forward_list>
#include <vector>
#include <scoped_allocator>

using namespace std;

int main()
{
  using list = forward_list<int>;
  vector<list, scoped_allocator_adaptor<list::allocator_type>> v;
  v.emplace_back(1u);
}

The very same problem exists for all allocator-aware sequence containers.

In addition it exists for associative containers. For example, it's possible to construct std::set<int>{0, 1, 2} but not std::set<int>{{0, 1, 2}, alloc}, and possible to construct std::set<int>{begin, end} but not std::set<int>{begin, end, alloc}.

This makes the following program fail when SCOPED is defined:

#include <set>
#include <vector>
#include <scoped_allocator>

#if SCOPED
using A = std::scoped_allocator_adaptor<std::allocator<int>>;
#else
using A = std::allocator<int>;
#endif

int main()
{
  int values[] = {0, 1, 2};
  std::vector<std::set<int>, A> v;
  v.emplace_back(std::begin(values), std::end(values));
}
History
Date User Action Args
2014-02-20 13:20:35adminsetstatus: wp -> c++14
2013-04-25 19:07:07adminsetstatus: voting -> wp
2013-04-19 21:44:50adminsetstatus: ready -> voting
2013-04-18 22:58:13adminsetmessages: + msg6462
2013-04-18 22:58:13adminsetstatus: review -> ready
2013-03-18 14:33:00adminsetmessages: + msg6425
2013-03-18 13:02:36adminsetstatus: new -> review
2012-11-01 22:07:51adminsetmessages: + msg6233
2012-11-01 00:00:00admincreate