Issue 2210: Missing allocator-extended constructor for allocator-aware containers (original) (raw)


This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++14 status.

2210. Missing allocator-extended constructor for allocator-aware containers

Section: 23.3 [sequences], 23.4 [associative], 23.5 [unord] Status: C++14 Submitter: Jonathan Wakely Opened: 2012-11-01 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [sequences].

View all issues with C++14 status.

Discussion:

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

#include #include #include

using namespace std;

int main() { using list = forward_list; vector<list, scoped_allocator_adaptorlist::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 #include #include

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

int main() { int values[] = {0, 1, 2}; std::vector<std::set, A> v; v.emplace_back(std::begin(values), std::end(values)); }

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

[2013-04-18, Bristol]

Proposed resolution:

This wording is relative to N3485.

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

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

  2. Edit 23.3.5.2 [deque.cons]/2:

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

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

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

    namespace std {
    template <class T, class Allocator = allocator >
    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 elementsusing the specified allocator.

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

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

  6. Edit 23.3.11.2 [list.cons]/3:

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

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

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

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

  8. Edit 23.3.13.2 [vector.cons]/3:

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

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

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

    namespace std {
    template 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 23.4.3.1 [map.overview] p2:
namespace std {
template <class Key, class T, class Compare = less,
class Allocator = allocator<pair<const Key, T> > > {
class map {
public:
[…]
map(initializer_list,
const Compare& = Compare(),
const Allocator& = Allocator());
template
map(InputIterator first, InputIterator last, const Allocator& a)
: map(first, last, Compare(), a) { }
map(initializer_list il, const Allocator& a)
: map(il, Compare(), a) { }
~map();
[…]
};
} 11. Add to the synopsis in 23.4.4.1 [multimap.overview] p2:
namespace std {
template <class Key, class T, class Compare = less,
class Allocator = allocator<pair<const Key, T> > > {
class multimap {
public:
[…]
multimap(initializer_list,
const Compare& = Compare(),
const Allocator& = Allocator());
template
multimap(InputIterator first, InputIterator last, const Allocator& a)
: multimap(first, last, Compare(), a) { }
multimap(initializer_list il, const Allocator& a)
: multimap(il, Compare(), a) { }
~multimap();
[…]
};
} 12. Add to the synopsis in 23.4.6.1 [set.overview] p2:
namespace std {
template <class Key, class Compare = less,
class Allocator = allocator > {
class set {
public:
[…]
set(initializer_list,
const Compare& = Compare(),
const Allocator& = Allocator());
template
set(InputIterator first, InputIterator last, const Allocator& a)
: set(first, last, Compare(), a) { }
set(initializer_list il, const Allocator& a)
: set(il, Compare(), a) { }
~set();
[…]
};
} 13. Add to the synopsis in 23.4.7.1 [multiset.overview] p2:
namespace std {
template <class Key, class Compare = less,
class Allocator = allocator > {
class multiset {
public:
[…]
multiset(initializer_list,
const Compare& = Compare(),
const Allocator& = Allocator());
template
multiset(InputIterator first, InputIterator last, const Allocator& a)
: multiset(first, last, Compare(), a) { }
multiset(initializer_list il, const Allocator& a)
: multiset(il, Compare(), a) { }
~multiset();
[…]
};
} 14. Add to the synopsis in 23.5.3.1 [unord.map.overview] p3:
namespace std {
template <class Key, class T,
class Hash = hash,
class Pred = std::equal_to,
class Allocator = std::allocator<std::pair<const Key, T> > > {
class unordered_map {
public:
[…]
unordered_map(initializer_list,
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
unordered_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
: unordered_map(f, l, n, hasher(), key_equal(), a) { }
template
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 il, size_type n, const allocator_type& a)
: unordered_map(il, n, hasher(), key_equal(), a) { }
unordered_map(initializer_list 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 23.5.4.1 [unord.multimap.overview] p3:
namespace std {
template <class Key, class T,
class Hash = hash,
class Pred = std::equal_to,
class Allocator = std::allocator<std::pair<const Key, T> > > {
class unordered_multimap {
public:
[…]
unordered_multimap(initializer_list,
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
unordered_multimap(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
: unordered_multimap(f, l, n, hasher(), key_equal(), a) { }
template
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 il, size_type n, const allocator_type& a)
: unordered_multimap(il, n, hasher(), key_equal(), a) { }
unordered_multimap(initializer_list 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 23.5.6.1 [unord.set.overview] p3:
namespace std {
template <class Key,
class Hash = hash,
class Pred = std::equal_to,
class Allocator = std::allocator > {
class unordered_set {
public:
[…]
unordered_set(initializer_list,
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
unordered_set(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
: unordered_set(f, l, n, hasher(), key_equal(), a) { }
template
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 il, size_type n, const allocator_type& a)
: unordered_set(il, n, hasher(), key_equal(), a) { }
unordered_set(initializer_list 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 23.5.7.1 [unord.multiset.overview] p3:
namespace std {
template <class Key,
class Hash = hash,
class Pred = std::equal_to,
class Allocator = std::allocator > {
class unordered_multiset {
public:
[…]
unordered_multiset(initializer_list,
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
unordered_multiset(InputIterator f, InputIterator l, size_type n, const allocator_type& a)
: unordered_multiset(f, l, n, hasher(), key_equal(), a) { }
template
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 il, size_type n, const allocator_type& a)
: unordered_multiset(il, n, hasher(), key_equal(), a) { }
unordered_multiset(initializer_list il, size_type n, const hasher& hf,
const allocator_type& a)
: unordered_multiset(il, n, hf, key_equal(), a) { }
~unordered_multiset();
[…]
};
}