This paper studies possible changes to the Containers Library to make broad use of noexcept. The paper addresses National Body comments CH 16 and GB 60.
Changes in this paper are restricted to chapter 23 (containers library).
All changes in this paper are relative to N3126
Function swap() on arrays may throw only if the corresponding member function from array may throw. It has been made conditionally noexcept.
Tuple interface functions for class array cannot throw as they return a reference to a position which is known to exist at compile-time.
Member function swap() cannot throw unless the member-wise swap throws an exception (23.3.1.6/2). Thus, it has been made conditionally noexcept.
Iterator functions (begin(), end() and so on) cannot throw in any case (23.2.1/11), because copying an iterator cannot throw.
Member function empty cannot throw. It depends on iterator comparison which cannot throw for library provided iterators. Member function max_size cannot throw as it just computes the size of the largest container.
Operator [] cannot throw as it simply de-references a pointer.
Member function at() has not been made noexcept as it may throw.
Member functions front() and back() have been made noexcept as they simply de-reference a pointer.
Member function data() simply gives access to the internal array returning a pointer and cannot throw
All constructors may throw as they are very likely to allocate memory. This is the case for all the member functions imlpying some insertion as assign(), resize(), shrink_to_fit, insert, push_front, and push_back.
All destructors have been made noexcept as they cannot throw per general rules in the library
Member function get_allocator may be made noexcept because any allocator satisfying allocator requirements cannot throw when copying and/or moving. This has been also applied to all iterator acces member functions.
Member function empty cannot throw. It depends on iterator comparison which cannot throw for library provided iterators. Member function max_size cannot throw as it just computes the size of the largest container.
For member function clear application of clause 23.2.1/11 follows that it must be made noexcept.
Function swap() has to consider several factors. First, it shall exchange values without invoking
any move, copy or swap on individual elements. Second, if
allocator_traits
Access through operator[] has been made noexcept.
For container adaptors most members cannot be made noexcept without providing a condition based on the user provided container. However some members have been made noexcept.
Conditionally noexcept members include move constructors, move assignment operators and swap().
Function swap() on associative containers if the corresponding container swap() member function may throw. It has been made conditionally noexcept.
For member functions, all the reasoning applied to sequence container has been applied here too, with the exception of member function swap(). This member function must be made here conditionally noexcept as it relies on swap() for key comparator.
? All standard containers will have their destructor's noexcept-specification deduced to noexcept(true).
namespace std { #include <initializer_list> ... template <class T, size_t N > void swap(array<T,N>& x, array<T,N>& y)noexcept(noexcept(x.swap(y))); template <class T> class tuple_size; template <size_t I, class T> class tuple_element; template <class T, size_t N> struct tuple_size<array<T, N> >; template <size_t I, class T, size_t N> struct tuple_element<I, array<T, N> >; template <size_t I, class T, size_t N> T& get(array<T, N>&) noexcept; template <size_t I, class T, size_t N> const T& get(const array<T, N>&) noexcept; }
namespace std { template <class T, size_t N > struct array { ... // No explicit construct/copy/destroy for aggregate type ... void swap(array& x) noexcept(noexcept(swap(elems[0], x.elems[0]))); // iterators: iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; // capacity: constexpr size_type size() noexcept; constexpr size_type max_size() noexcept; constexpr bool empty() noexcept; // element access: reference operator[](size_type n) noexcept; const_reference operator[](size_type n) const noexcept; const_reference at(size_type n) const; reference at(size_type n); reference front() noexcept; const_reference front() const noexcept; reference back() noexcept; const_reference back() const noexcept; T * data() noexcept; const T * data() const noexcept; }; }
template <class T, size_t N> void swap(array<T,N>& x, array<T,N>& y) noexcept(noexcept(x.swap(y)));
template <class T, size_t N> constexpr size_type array<T,N>::size() noexcept;
T *data() noexcept; const T *data() const noexcept;
void swap(array& y) noexcept(noexcept(swap(declval<T&>(), declval<T&>)));
? Member function swap() will have a noexcept-specification which is equivalent to noexcept(true).
template <size_t I, class T, size_t N> T& get(array<T, N>& a) noexcept;After p. 7
template <size_t I, class T, size_t N> const T& get(const array<T, N>& a) noexcept;
namespace std { template <class T, class Allocator = allocator<T> > class deque { public: ... allocator_type get_allocator() const noexcept; // iterators: iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; // 23.3.2.2 capacity: size_type size() const noexcept; size_type max_size() const noexcept; void resize(size_type sz); void resize(size_type sz, const T& c); void shrink_to_fit(); bool empty() const noexcept; // element access: reference operator[](size_type n) noexcept; const_reference operator[](size_type n) const noexcept; ... // 23.3.2.3 modifiers: ... void pop_front() noexcept; void pop_back() noexcept; ... void swap(deque<T,Allocator>&) noexcept; void clear() noexcept; }; ... // specialized algorithms: template <class T, class Allocator> void swap(deque<T,Allocator>& x, deque<T,Allocator>& y) noexcept; }
template <class T, class Allocator> void swap(deque<T,Allocator>& x, deque<T,Allocator>& y) noexcept;
namespace std { template <class T, class Allocator = allocator<T> > class forward_list { ... allocator_type get_allocator() const noexcept; ... // 23.3.3.2 iterators: iterator before_begin() noexcept; const_iterator before_begin() const noexcept; iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cbefore_begin() const noexcept; const_iterator cend() const noexcept; // capacity: bool empty() const noexcept; size_type max_size() const noexcept; ... // 23.3.3.4 modifiers: template <class... Args> void emplace_front(Args&&... args); void push_front(const T& x); void push_front(T&& x); void pop_front() noexcept; ... void swap(forward_list<T,Allocator>&) noexcept; void resize(size_type sz); void resize(size_type sz, value_type c); void clear() noexcept; ... }; ... // 23.3.3.6 specialized algorithms: template <class T, class Allocator> void swap(forward_list<T,Allocator>& x, forward_list<T,Allocator>& y) noexcept; }
iterator before_begin() noexcept; const_iterator before_begin() const noexcept; const_iterator cbefore_begin() const noexcept;
void pop_front() noexcept;After p. 27
void clear() noexcept;
template <class T, class Allocator> void swap(forward_list<T,Allocator>& x, forward_list<T,Allocator>& y) noexcept;
namespace std { template <class T, class Allocator = allocator<T> > class list { public: ... allocator_type get_allocator() const noexcept; // iterators: iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; // 23.3.4.2 capacity: bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; void resize(size_type sz); void resize(size_type sz, const T& c); ... // 23.3.4.3 modifiers: ... void swap(list<T,Allocator>&) noexcept; void clear() noexcept; ... }; ... // specialized algorithms: template <class T, class Allocator> void swap(list<T,Allocator>& x, list<T,Allocator>& y) noexcept; }
template <class T, class Allocator> void swap(list<T,Allocator>& x, list<T,Allocator>& y) noexcept;
namespace std { template <class T, class Allocator = allocator<T> > class vector { public: ... allocator_type get_allocator() const noexcept; // iterators: iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; // 23.4.1.2 capacity: size_type size() const noexcept; size_type max_size() const noexcept; void resize(size_type sz); void resize(size_type sz, const T& c); size_type capacity() const noexcept; bool empty() const noexcept; void reserve(size_type n); void shrink_to_fit(); // element access: reference operator[](size_type n) noexcept; const_reference operator[](size_type n) const noexcept; const_reference at(size_type n) const; reference at(size_type n); ... // 23.4.1.4 modifiers: ... void pop_back() noexcept; ... void swap(vector<T,Allocator>&) noexcept; void clear() noexcept; }; ... // specialized algorithms: template <class T, class Allocator> void swap(vector<T,Allocator>& x, vector<T,Allocator>& y) noexcept; }
size_type capacity() const noexcept;After p. 6
void swap(vector<T,Allocator>& x) noexcept;
template <class T, class Allocator> void swap(vector<T,Allocator>& x, vector<T,Allocator>& y) noexcept;
namespace std { template <class Allocator> class vector<bool, Allocator> { public: ... // bit reference: class reference { friend class vector; reference() noexcept; public: ~reference() noexcept; operator bool() const noexcept; reference& operator=(const bool x) noexcept; reference& operator=(const reference& x) noexcept; void flip() noexcept; // flips the bit }; ... allocator_type get_allocator() const noexcept; // iterators: iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; // capacity: size_type size() const noexcept; size_type max_size() const noexcept; void resize(size_type sz, bool c = false); size_type capacity() const noexcept; bool empty() const noexcept; void reserve(size_type n); void shrink_to_fit(); // element access: reference operator[](size_type n) noexcept; const_reference operator[](size_type n) const noexcept; const_reference at(size_type n) const; reference at(size_type n); ... // modifiers: ... void pop_back() noexcept; ... iterator erase(const_iterator position) noexcept; iterator erase(const_iterator first, const_iterator last) noexcept; void swap(vector<T,Allocator>&) noexcept; static void swap(reference x, reference y) noexcept; void flip() noexcept; // flips all bits void clear() noexcept; };After p. 4
void flip() noexcept;After p. 5
static void swap(reference x, reference y) noexcept;
namespace std { template <class T, class Container = deque<T> > class queue { public: ... explicit queue(Container&& = Container()) noexcept(see below); queue(queue&& q) noexcept(see below); ... template <class Alloc> queue(Container&&, const Alloc&) noexcept(see below); ... template <class Alloc> queue(queue&&, const Alloc&) noexcept(see below); queue& operator=(queue&& q) noexcept(see below); ... void swap(queue& q) noxcept(noexcept(c.swap(q.c))) { c.swap(q.c); } }; ... template <class T, class Container> void swap(queue<T, Container>& x, queue<T, Container>& y) noexcept(noexcept(x.swap(y))); ... }
explicit queue(Container&& cont = Container()) noexcept(see below);
Remarks: The expression inside noexcept is equivalent to:
is_nothrow_move_constructible<Container>::valueAfter p. 2
queue(queue&& q) noexcept(see below);
Remarks: The expression inside noexcept is equivalent to:
is_nothrow_constructible<Container, Container&&>::valueAfter p. 3
queue& operator=(queue&& q) noexcept(see below);
Remarks: The expression inside noexcept is equivalent to:
has_nothrow_move_assign<Container>::value
template <class Alloc> queue(container_type&& cont, const Alloc& a) noexcept(see below);
Remarks: The expression inside noexcept is equivalent to:
is_nothrow_constructible<Container, Container&&, const Alloc&>::valueAfter p. 5
template <class Alloc> queue(queue&& q, const Alloc& a) noexcept(see below);
Remarks: The expression inside noexcept is equivalent to:
is_nothrow_constructible<Container, Container&&, const Alloc&>::value
template <class T, class Container> void swap(queue<T, Container>& x, queue<T, Container>& y)noexcept(noexcept(x.swap(y)));
namespace std { template <class T, class Container = vector<T>, class Compare = less<typename Container::value_type> > class priority_queue { public: ... explicit priority_queue(const Compare& x = Compare(), Container&& = Container()) noexcept(see below); ... priority_queue(priority_queue&&) noexcept(see below); ... template <class Alloc> priority_queue(const Compare&, Container&&, const Alloc&) noexcept(see below); ... template <class Alloc> priority_queue(priority_queue&&, const Alloc&) noexcept(see below); priority_queue& operator=(priority_queue&&) noexcept(see below); ... void swap(priority_queue& q) noexcept( noexcept(c.swap(q.c)) && noexcept(comp.swap(q.comp))); }; // no equality is provided template <class T, class Container, class Compare> void swap(priority_queue<T, Container, Compare>& x, priority_queue<T, Container, Compare>& y) noexcept(noexcept(x.swap(y))); ... }
priority_queue(const Compare& x, const Container& y); explicit priority_queue(const Compare& x = Compare(), Container&& y = Container()) noexcept(see below);
Remarks: The expression inside noexcept in the second constructor is equivalent to:
is_nothrow_copy_constructible<Compare>::value && is_nothrow_move_constructible<Container>::value && noexcept(make_heap(y.begin(), y.end(), x))After p. 4
priority_queue(priority_queue&& q) noexcept(see below);
Remarks: The expression inside noexcept is equivalent to:
is_nothrow_move_constructible<Compare>::value && is_notrhow_move_constructible<Container>::valueAfter p. 5
priority_queue& operator=(priority_queue&& q) noexcept(see below);
Remarks: The expression inside noexcept is equivalent to:
is_nothrow_move_assignable<Compare>::value && is_notrhow_move_assignable<Container>::value
template <class Alloc> priority_queue(const Compare& compare, Container&& cont, const Alloc& a);
Remarks: The expression inside noexcept is equivalent to:
is_nothrow_constructible<Container, Container&&, const Alloc&>::value && is_nothrow_copy_constructible<Compare>::value
template <class T, class Container, Compare> void swap(priority_queue<T, Container, Compare>& x, priority_queue<T, Container, Compare>& y) noexcept(noexcept(x.swap(y)));
namespace std { template <class T, class Container = deque<T> > class stack { public: ... explicit stack(Container&& = Container()); stack(stack&&s) noexcept(see below); ... template <class Alloc> stack(Container&&, const Alloc&) noexcept(see below); ... template <class Alloc> stack(stack&&, const Alloc&) noexcept(see below); stack& operator=(stack&& s) noexcept(see below); ... void swap(stack& s) noexcept(noexcept(c.swap(s.c))) { c.swap(s.c); } }; ... template <class T, class Container, class Alloc> struct uses_allocator<stack<T, Container>, Alloc> : uses_allocator<Container, Alloc>::type { }; }
stack(stack&& s) noexcept(see below);
Remarks: The expression inside noexcept is equivalent to:
is_nothrow_move_constructible<Container>::valueAfter p. 1
stack& operator=(stack&& s) noexcept(see below);
Remarks: The expression inside noexcept is equivalent to:
is_nothrow_move_constructible<Container>::value
template <class Alloc> stack(container_type&& cont, const Alloc& a) noexcept(see below);
Remarks: The expression inside noexcept is equivalent to:
is_nothrow_constructible<Container, Container&&, const Alloc&>::valueAfter p. 5
template <class Alloc> stack(stack&& s, const Alloc& a) noexcept(see below);
Remarks: The expression inside noexcept is equivalent to:
is_nothrow_constructible<Container, Container&&, const Alloc&>::value
template <class T, class Container> void swap(stack<T, Container>& x, stack<T, Container>& y)noexcept(noexcept(x.swap(y)));
Header <map> synopsis
namespace std { ... template <class Key, class T, class Compare, class Allocator> void swap(map<Key,T,Compare,Allocator>& x, map<Key,T,Compare,Allocator>& y) noexcept(see below); ... template <class Key, class T, class Compare, class Allocator> void swap(multimap<Key,T,Compare,Allocator>& x, multimap<Key,T,Compare,Allocator>& y) noexcept(see below); }
Header <set> synopsis
namespace std { ... template <class Key, class Compare, class Allocator> void swap(set<Key,Compare,Allocator>& x, set<Key,Compare,Allocator>& y) noexcept(see below); ... template <class Key, class Compare, class Allocator> void swap(multiset<Key,Compare,Allocator>& x, multiset<Key,Compare,Allocator>& y) noexcept(see below); }
namespace std { template <class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T> > > class map { public: ... // 23.6.1.1 construct/copy/destroy: ... allocator_type get_allocator() const noexcept; // iterators: iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; // capacity: bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; ... // modifiers: ... void swap(map<Key,T,Compare,Allocator>& m) noexcept(noexcept(swap(declval<key_compare&>(), declval<key_compare&>()))); void clear() noexcept; ... }; ... // specialized algorithms: template <class Key, class T, class Compare, class Allocator> void swap(map<Key,T,Compare,Allocator>& x, map<Key,T,Compare,Allocator>& y) noexcept(noexcept(x.swap(y)));
template <class Key, class T, class Compare, class Allocator> void swap(map<Key,T,Compare,Allocator>& x, map<Key,T,Compare,Allocator>& y)noexcept(noexcept(x.swap(y)));
namespace std { template <class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T> > > class multimap { public: ... allocator_type get_allocator() const noexcept; // iterators: iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; // capacity: bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; ... // modifiers: ... void swap(multimap<Key,T,Compare,Allocator>&) noexcept(noexcept(swap(declval<key_compare&>(),declval<key_compare&>()))); void clear() noexcept; ... }; ... // specialized algorithms: template <class Key, class T, class Compare, class Allocator> void swap(multimap<Key,T,Compare,Allocator>& x, multimap<Key,T,Compare,Allocator>& y) noexcept(noexcept(x.swap(y))); }
template <class Key, class T, class Compare, class Allocator> void swap(multimap<Key,T,Compare,Allocator>& x, multimap<Key,T,Compare,Allocator>& y) noexcept(noexcept(x.swap(y)));
namespace std { template <class Key, class Compare = less<Key>, class Allocator = allocator<Key> > class set { public: ... allocator_type get_allocator() const noexcept; // iterators: iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; // capacity: bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // modifiers: ... void swap(set<Key,Compare,Allocator>&) noexcept(noexcept(swap(declval<key_compare&>(), declval<key_compare&>()))); void clear() noexcept; ... }; ... // specialized algorithms: template <class Key, class Compare, class Allocator> void swap(set<Key,Compare,Allocator>& x, set<Key,Compare,Allocator>& y) noexcept(noexcept(x.swap(y))); }
template <class Key, class Compare, class Allocator> void swap(set<Key,Compare,Allocator>& x, set<Key,Compare,Allocator>& y) noexcept(noexcept(x.swap(y)));
namespace std { template <class Key, class Compare = less<Key>, class Allocator = allocator<Key> > class multiset { public: ... allocator_type get_allocator() const noexcept; // iterators: iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin() const noexcept; reverse_iterator rend() noexcept; const_reverse_iterator rend() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; const_reverse_iterator crbegin() const noexcept; const_reverse_iterator crend() const noexcept; // capacity: bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // modifiers: ... void swap(multiset<Key,Compare,Allocator>&) noexcept(noexcept(swap(declval<key_compare&>(), declval<key_compare&>()))); void clear() noexcept; ... }; ... // specialized algorithms: template <class Key, class Compare, class Allocator> void swap(multiset<Key,Compare,Allocator>& x, multiset<Key,Compare,Allocator>& y) noexcept(noexcept(x.swap(y))); }
template <class Key, class Compare, class Allocator> void swap(multiset<Key,Compare,Allocator>& x, multiset<Key,Compare,Allocator>& y) noexcept(noexcept(x.swap(y)));
Header <unordered_map> synopsis
namespace std { ... template <class Key, class T, class Hash, class Pred, class Alloc> void swap(unordered_map<Key, T, Hash, Pred, Alloc>& x, unordered_map<Key, T, Hash, Pred, Alloc>& y) noexcept(noexcept(x.swap(y))); template <class Key, class T, class Hash, class Pred, class Alloc> void swap(unordered_multimap<Key, T, Hash, Pred, Alloc>& x, unordered_multimap<Key, T, Hash, Pred, Alloc>& y) noexcept(noexcept(x.swap(y))); } // namespace std
Header <unordered_set> synopsis
namespace std { ... template <class Key, class Hash, class Pred, class Alloc> void swap(unordered_set<Key, Hash, Pred, Alloc>& x, unordered_set<Key, Hash, Pred, Alloc>& y) noexcept(noexcept(x.swap(y))); template <class Key, class Hash, class Pred, class Alloc> void swap(unordered_multiset<Key, Hash, Pred, Alloc>& x, unordered_multiset<Key, Hash, Pred, Alloc>& y) noexcept(noexcept(x.swap(y))); ... } // namespace std
namespace std { template <class Key, class T, class Hash = hash<Key>, class Pred = std::equal_to<Key>, class Alloc = std::allocator<std::pair<const Key, T> > > class unordered_map { public: ... allocator_type get_allocator() const noexcept; // size and capacity bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // iterators iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; // modifiers ... void clear() noexcept; void swap(unordered_map&) noexcept( noexcept(swap(declval<hasher&>(),declval<hasher&>())) && noexcept(swap(declval<key_equal&>(), declval<key_equal&>()))); ... // bucket interface size_type bucket_count() const noexcept; size_type max_bucket_count() const noexcept; size_type bucket_size(size_type n) noexcept; size_type bucket(const key_type& k) const noexcept; local_iterator begin(size_type n) noexcept; const_local_iterator begin(size_type n) const noexcept; local_iterator end(size_type n) noexcept; const_local_iterator end(size_type n) const noexcept; const_local_iterator cbegin(size_type n) const noexcept; const_local_iterator cend(size_type n) const noexcept; // hash policy float load_factor() const noexcept; float max_load_factor() const noexcept; void max_load_factor(float z) noexcept; ... }; template <class Key, class T, class Hash, class Pred, class Alloc> void swap(unordered_map<Key, T, Hash, Pred, Alloc>& x, unordered_map<Key, T, Hash, Pred, Alloc>& y) noexcept(noexcept(x.swap(y))); }
template <class Key, class T, class Hash, class Pred, class Alloc> void swap(unordered_map<Key, T, Hash, Pred, Alloc>& x, unordered_map<Key, T, Hash, Pred, Alloc>& y) noexcept(noexcept(x.swap(y)));
namespace std { template <class Key, class T, class Hash = hash<Key>, class Pred = std::equal_to<Key>, class Alloc = std::allocator<std::pair<const Key, T> > > class unordered_multimap { public: ... allocator_type get_allocator() const noexcept; // size and capacity bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // iterators iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; // modifiers ... void clear() noexcept; void swap(unordered_multimap&)noexcept( noexcept(swap(declval<hasher&>(),declval<hasher&>())) && noexcept(swap(declval<key_equal&>(), declval<key_equal&>()))); ... // bucket interface size_type bucket_count() const noexcept; size_type max_bucket_count() const noexcept; size_type bucket_size(size_type n) noexcept; size_type bucket(const key_type& k) const noexcept; local_iterator begin(size_type n) noexcept; const_local_iterator begin(size_type n) const noexcept; local_iterator end(size_type n) noexcept; const_local_iterator end(size_type n) const noexcept; const_local_iterator cbegin(size_type n) const noexcept; const_local_iterator cend(size_type n) const noexcept; // hash policy float load_factor() const noexcept; float max_load_factor() const noexcept; void max_load_factor(float z) noexcept; ... }; template <class Key, class T, class Hash, class Pred, class Alloc> void swap(unordered_multimap<Key, T, Hash, Pred, Alloc>& x, unordered_multimap<Key, T, Hash, Pred, Alloc>& y) noexcept(noexcept(x.swap(y))); }
template <class Key, class T, class Hash, class Pred, class Alloc> void swap(unordered_multimap<Key, T, Hash, Pred, Alloc>& x, unordered_multimap<Key, T, Hash, Pred, Alloc>& y) noexcept(noexcept(x.swap(y)));
namespace std { template <class Key, class Hash = hash<Key>, class Pred = std::equal_to<Key>, class Alloc = std::allocator<Key> > class unordered_set { public: ... allocator_type get_allocator() const noexcept; // size and capacity bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // iterators iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; // modifiers ... void clear() noexcept; void swap(unordered_set&)noexcept( noexcept(swap(declval<hasher&>(),declval<hasher&>())) && noexcept(swap(declval<key_equal&>(), declval<key_equal&>()))); ... // bucket interface size_type bucket_count() const noexcept; size_type max_bucket_count() const noexcept; size_type bucket_size(size_type n) noexcept; size_type bucket(const key_type& k) const noexcept; local_iterator begin(size_type n) noexcept; const_local_iterator begin(size_type n) const noexcept; local_iterator end(size_type n) noexcept; const_local_iterator end(size_type n) const noexcept; const_local_iterator cbegin(size_type n) const noexcept; const_local_iterator cend(size_type n) const noexcept; // hash policy float load_factor() const noexcept; float max_load_factor() const noexcept; void max_load_factor(float z) noexcept; ... }; template <class Key, class T, class Hash, class Pred, class Alloc> void swap(unordered_set<Key, T, Hash, Pred, Alloc>& x, unordered_set<Key, T, Hash, Pred, Alloc>& y) noexcept(noexcept(x.swap(y))); }
template <class Key, class Hash, class Pred, class Alloc> void swap(unordered_set<Key, Hash, Pred, Alloc>& x, unordered_set<Key, Hash, Pred, Alloc>& y) noexcept(noexcept(x.swap(y)));
namespace std { template, class Pred = std::equal_to , class Alloc = std::allocator > class unordered_multiset { public: ... allocator_type get_allocator() const noexcept; // size and capacity bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; // iterators iterator begin() noexcept; const_iterator begin() const noexcept; iterator end() noexcept; const_iterator end() const noexcept; const_iterator cbegin() const noexcept; const_iterator cend() const noexcept; // modifiers ... void clear() noexcept; void swap(unordered_multiset&)noexcept( noexcept(swap(declval<hasher&>(),declval<hasher&>())) && noexcept(swap(declval<key_equal&>(), declval<key_equal&>()))); ... // bucket interface size_type bucket_count() const noexcept; size_type max_bucket_count() const noexcept; size_type bucket_size(size_type n) noexcept; size_type bucket(const key_type& k) const noexcept; local_iterator begin(size_type n) noexcept; const_local_iterator begin(size_type n) const noexcept; local_iterator end(size_type n) noexcept; const_local_iterator end(size_type n) const noexcept; const_local_iterator cbegin(size_type n) const noexcept; const_local_iterator cend(size_type n) const noexcept; // hash policy float load_factor() const noexcept; float max_load_factor() const noexcept; void max_load_factor(float z) noexcept; ... }; template <class Key, class T, class Hash, class Pred, class Alloc> void swap(unordered_multiset<Key, T, Hash, Pred, Alloc>& x, unordered_multiset<Key, T, Hash, Pred, Alloc>& y) noexcept(noexcept(x.swap(y))); }
template <class Key, class T, class Hash, class Pred, class Alloc> void swap(unordered_multiset<Key, T, Hash, Pred, Alloc>& x, unordered_multiset<Key, T, Hash, Pred, Alloc>& y) noexcept(noexcept(x.swap(y)));