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 N3242.
After discussion in Library Working Group of guidelines for applying noexcept to the standard library (N3248), this paper has been revised to apply noexcept accordingly to those guidelines
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))); ... }
namespace std { template <class T, size_t N > struct array { ... // No explicit construct/copy/destroy for aggregate type ... void swap(array&) noexcept(noexcept(swap(declval<T&>(), declval<T&>()))); // 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); const_reference operator[](size_type n) const; const_reference at(size_type n) const; reference at(size_type n); reference front(); const_reference front() const; reference back(); const_reference back() const; 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() shall have a noexcept-specification which is equivalent to noexcept(true).
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; ... void swap(deque<T,Allocator>&); void clear() 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; ... void swap(forward_list<T,Allocator>&); void resize(size_type sz); void resize(size_type sz, value_type c); void clear() noexcept; ... }; ... }
iterator before_begin() noexcept; const_iterator before_begin() const noexcept; const_iterator cbefore_begin() const noexcept;
void clear() 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>&); void clear() 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(); ... void swap(vector<T,Allocator>&); void clear() noexcept; }; ... // specialized algorithms: template <class T, class Allocator> void swap(vector<T,Allocator>& x, vector<T,Allocator>& y); }
size_type capacity() const noexcept;
namespace std { template <class Allocator> class vector<bool, Allocator> { public: ... // bit reference: class reference { friend class vector; reference() noexcept; public: ~reference(); 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(); ... // modifiers: ... void swap(vector<bool,Allocator>&); 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 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 clear() noexcept; ... }; ... }
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 clear() noexcept; ... }; ... }
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 clear() noexcept; ... }; ... }
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 clear() noexcept; ... }; ... }
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; ... // bucket interface size_type bucket_count() const noexcept; size_type max_bucket_count() const noexcept; ... // hash policy float load_factor() const noexcept; float max_load_factor() const noexcept; ... }; ... }
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; ... // bucket interface size_type bucket_count() const noexcept; size_type max_bucket_count() const noexcept; ... // hash policy float load_factor() const noexcept; float max_load_factor() const noexcept; ... }; ... }
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; ... // bucket interface size_type bucket_count() const noexcept; size_type max_bucket_count() const noexcept; ... // hash policy float load_factor() const noexcept; float max_load_factor() const noexcept; ... }; }
namespace std { template <class Key, class Hash = hash<Key>, class Pred = std::equal_to<Key>, class Alloc = std::allocator<Key> > 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; ... // bucket interface size_type bucket_count() const noexcept; size_type max_bucket_count() const noexcept; ... // hash policy float load_factor() const noexcept; float max_load_factor() const noexcept; ... }; ... }
... template <class T, classAllocatorContainer> void swap(queue<T, Container>& x, queue<T, Container>& y) noexcept(noexcept(x.swap(y))); 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))); ...
namespace std { template <class T, class Container = deque<T> > class queue { public: ... queue(queue&& q) noexcept(see below); ... queue& operator=(queue&& q) noexcept(see below); ... void swap(queue& q) noexcept(noexcept(swap(c,q.c))) { using std::swap; swap(c, q.c); } }; ... template <class T, class Container> void swap(queue<T, Container>& x, queue<T, Container>& y) noexcept(noexcept(x.swap(y))); ... }
queue(queue&& q) noexcept(see below);
Remarks: The expression inside noexcept is equivalent to:
is_nothrow_constructible<Container>::valueAfter p. 3
queue& operator=(queue&& q) noexcept(see below);
Remarks: The expression inside noexcept is equivalent to:
is_nothrow_move_assignable<Container>::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: ... priority_queue(priority_queue&&) noexcept(see below); ... priority_queue& operator=(priority_queue&&) noexcept(see below); ... void swap(priority_queue& q) noexcept( noexcept(swap(c, q.c)) && noexcept(swap(comp, q.comp))) { using std::swap; swap(c, q.c); swap(comp, 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(priority_queue&& q) noexcept(see below);
Remarks: The expression inside noexcept is equivalent to:
is_nothrow_move_constructible<Compare>::value && is_nothrow_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_nothrow_move_assignable<Container>::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)));
... template <class T, class Container> void swap(stack<T, Container>& x, stack<T, Container>& 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); ... stack& operator=(stack&& s) noexcept(see below); ... void swap(stack& s) noexcept(noexcept(swap(c, s.c))) { using std::swap; swap(c, 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_assignable<Container>::value
template <class T, class Container> void swap(stack<T, Container>& x, stack<T, Container>& y)noexcept(noexcept(x.swap(y)));