...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
boost::container::stable_vector
// In header: <boost/container/stable_vector.hpp> template<typename T, typename Allocator = void> class stable_vector { public: // types typedef T value_type; typedef ::boost::container::allocator_traits< ValueAllocator >::pointer pointer; typedef ::boost::container::allocator_traits< ValueAllocator >::const_pointer const_pointer; typedef ::boost::container::allocator_traits< ValueAllocator >::reference reference; typedef ::boost::container::allocator_traits< ValueAllocator >::const_reference const_reference; typedef ::boost::container::allocator_traits< ValueAllocator >::size_type size_type; typedef ::boost::container::allocator_traits< ValueAllocator >::difference_type difference_type; typedef ValueAllocator allocator_type; typedef node_allocator_type stored_allocator_type; typedef implementation_defined iterator; typedef implementation_defined const_iterator; typedef implementation_defined reverse_iterator; typedef implementation_defined const_reverse_iterator; // construct/copy/destruct stable_vector() noexcept(dtl::is_nothrow_default_constructible< ValueAllocator >::value)); explicit stable_vector(const allocator_type &) noexcept; explicit stable_vector(size_type); stable_vector(size_type, default_init_t); explicit stable_vector(size_type, const allocator_type &); stable_vector(size_type, default_init_t, const allocator_type &); stable_vector(size_type, const T &, const allocator_type & = allocator_type()); template<typename InputIterator> stable_vector(InputIterator, InputIterator, const allocator_type & = allocator_type()); stable_vector(const stable_vector &); stable_vector(std::initializer_list< value_type >, const allocator_type & = allocator_type()); stable_vector(stable_vector &&) noexcept; stable_vector(const stable_vector &, const allocator_type &); stable_vector(stable_vector &&, const allocator_type &); stable_vector & operator=(const stable_vector &); stable_vector & operator=(stable_vector &&) noexcept(allocator_traits_type::propagate_on_container_move_assignment::value||allocator_traits_type::is_always_equal::value)); stable_vector & operator=(std::initializer_list< value_type >); ~stable_vector(); // public member functions void assign(size_type, const T &); template<typename InputIterator> void assign(InputIterator, InputIterator); void assign(std::initializer_list< value_type >); allocator_type get_allocator() const; const stored_allocator_type & get_stored_allocator() const noexcept; stored_allocator_type & get_stored_allocator() noexcept; 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; bool empty() const noexcept; size_type size() const noexcept; size_type max_size() const noexcept; void resize(size_type); void resize(size_type, default_init_t); void resize(size_type, const T &); size_type capacity() const noexcept; void reserve(size_type); void shrink_to_fit(); reference front() noexcept; const_reference front() const noexcept; reference back() noexcept; const_reference back() const noexcept; reference operator[](size_type) noexcept; const_reference operator[](size_type) const noexcept; iterator nth(size_type) noexcept; const_iterator nth(size_type) const noexcept; size_type index_of(iterator) noexcept; size_type index_of(const_iterator) const noexcept; reference at(size_type); const_reference at(size_type) const; template<class ... Args> reference emplace_back(Args &&...); template<class ... Args> iterator emplace(const_iterator, Args &&...); void push_back(const T &); void push_back(T &&); iterator insert(const_iterator, const T &); iterator insert(const_iterator, T &&); iterator insert(const_iterator, size_type, const T &); iterator insert(const_iterator, std::initializer_list< value_type >); template<typename InputIterator> iterator insert(const_iterator, InputIterator, InputIterator); void pop_back() noexcept; iterator erase(const_iterator) noexcept; iterator erase(const_iterator, const_iterator) noexcept; void swap(stable_vector &) noexcept(allocator_traits_type::propagate_on_container_swap::value||allocator_traits_type::is_always_equal::value)); void clear() noexcept; // friend functions friend bool operator==(const stable_vector &, const stable_vector &); friend bool operator!=(const stable_vector &, const stable_vector &); friend bool operator<(const stable_vector &, const stable_vector &); friend bool operator>(const stable_vector &, const stable_vector &); friend bool operator<=(const stable_vector &, const stable_vector &); friend bool operator>=(const stable_vector &, const stable_vector &); friend void swap(stable_vector &, stable_vector &) noexcept(noexcept(x.swap(y)))); };
Originally developed by Joaquin M. Lopez Munoz, stable_vector is a std::vector drop-in replacement implemented as a node container, offering iterator and reference stability.
Here are the details taken from the author's blog (Introducing stable_vector):
We present stable_vector, a fully STL-compliant stable container that provides most of the features of std::vector except element contiguity.
General properties: stable_vector satisfies all the requirements of a container, a reversible container and a sequence and provides all the optional operations present in std::vector. Like std::vector, iterators are random access. stable_vector does not provide element contiguity; in exchange for this absence, the container is stable, i.e. references and iterators to an element of a stable_vector remain valid as long as the element is not erased, and an iterator that has been assigned the return value of end() always remain valid until the destruction of the associated stable_vector.
Operation complexity: The big-O complexities of stable_vector operations match exactly those of std::vector. In general, insertion/deletion is constant time at the end of the sequence and linear elsewhere. Unlike std::vector, stable_vector does not internally perform any value_type destruction, copy or assignment operations other than those exactly corresponding to the insertion of new elements or deletion of stored elements, which can sometimes compensate in terms of performance for the extra burden of doing more pointer manipulation and an additional allocation per element.
Exception safety: As stable_vector does not internally copy elements around, some operations provide stronger exception safety guarantees than in std::vector.
typename T
The type of object that is stored in the stable_vector
typename Allocator = void
The allocator used for all internal memory management
stable_vector
public
construct/copy/destructstable_vector() noexcept(dtl::is_nothrow_default_constructible< ValueAllocator >::value));
Effects: Default constructs a stable_vector
.
Throws: If allocator_type's default constructor throws.
Complexity: Constant.
explicit stable_vector(const allocator_type & al) noexcept;
Effects: Constructs a stable_vector
taking the allocator as parameter.
Throws: Nothing
Complexity: Constant.
explicit stable_vector(size_type n);
Effects: Constructs a stable_vector
and inserts n value initialized values.
Throws: If allocator_type's default constructor throws or T's default or copy constructor throws.
Complexity: Linear to n.
stable_vector(size_type n, default_init_t);
Effects: Constructs a stable_vector
and inserts n default initialized values.
Throws: If allocator_type's default constructor throws or T's default or copy constructor throws.
Complexity: Linear to n.
Note: Non-standard extension
explicit stable_vector(size_type n, const allocator_type & a);
Effects: Constructs a stable_vector
that will use a copy of allocator a and inserts n value initialized values.
Throws: If allocator_type's default constructor throws or T's default or copy constructor throws.
Complexity: Linear to n.
stable_vector(size_type n, default_init_t, const allocator_type & a);
Effects: Constructs a stable_vector
that will use a copy of allocator a and inserts n default initialized values.
Throws: If allocator_type's default constructor throws or T's default or copy constructor throws.
Complexity: Linear to n.
Note: Non-standard extension
stable_vector(size_type n, const T & t, const allocator_type & al = allocator_type());
Effects: Constructs a stable_vector
that will use a copy of allocator a and inserts n copies of value.
Throws: If allocator_type's default constructor throws or T's default or copy constructor throws.
Complexity: Linear to n.
template<typename InputIterator> stable_vector(InputIterator first, InputIterator last, const allocator_type & al = allocator_type());
Effects: Constructs a stable_vector
that will use a copy of allocator a and inserts a copy of the range [first, last) in the stable_vector
.
Throws: If allocator_type's default constructor throws or T's constructor taking a dereferenced InIt throws.
Complexity: Linear to the range [first, last).
stable_vector(const stable_vector & x);
Effects: Copy constructs a stable_vector
.
Postcondition: x == *this.
Complexity: Linear to the elements x contains.
stable_vector(std::initializer_list< value_type > il, const allocator_type & l = allocator_type());
Effects: Constructs a stable_vector
that will use a copy of allocator a and inserts a copy of the range [il.begin(), il.last()) in the stable_vector
Throws: If allocator_type's default constructor throws or T's constructor taking a dereferenced initializer_list iterator throws.
Complexity: Linear to the range [il.begin(), il.end()).
stable_vector(stable_vector && x) noexcept;
Effects: Move constructor. Moves x's resources to *this.
Throws: If allocator_type's copy constructor throws.
Complexity: Constant.
stable_vector(const stable_vector & x, const allocator_type & a);
Effects: Copy constructs a stable_vector
using the specified allocator.
Postcondition: x == *this.
Complexity: Linear to the elements x contains.
stable_vector(stable_vector && x, const allocator_type & a);
Effects: Move constructor using the specified allocator. Moves x's resources to *this.
Throws: If allocator_type's copy constructor throws.
Complexity: Constant if a == x.get_allocator(), linear otherwise
stable_vector & operator=(const stable_vector & x);
Effects: Makes *this contain the same elements as x.
Postcondition: this->size() == x.size(). *this contains a copy of each of x's elements.
Throws: If memory allocation throws or T's copy constructor throws.
Complexity: Linear to the number of elements in x.
stable_vector & operator=(stable_vector && x) noexcept(allocator_traits_type::propagate_on_container_move_assignment::value||allocator_traits_type::is_always_equal::value));
Effects: Move assignment. All x's values are transferred to *this.
Postcondition: x.empty(). *this contains a the elements x had before the function.
Throws: If allocator_traits_type::propagate_on_container_move_assignment is false and (allocation throws or T's move constructor throws)
Complexity: Constant if allocator_traits_type:: propagate_on_container_move_assignment is true or this->get>allocator() == x.get_allocator(). Linear otherwise.
stable_vector & operator=(std::initializer_list< value_type > il);
Effects: Make *this container contains elements from il.
Complexity: Linear to the range [il.begin(), il.end()).
~stable_vector();
Effects: Destroys the stable_vector
. All stored values are destroyed and used memory is deallocated.
Throws: Nothing.
Complexity: Linear to the number of elements.
stable_vector
public member functionsvoid assign(size_type n, const T & t);
Effects: Assigns the n copies of val to *this.
Throws: If memory allocation throws or T's copy constructor throws.
Complexity: Linear to n.
template<typename InputIterator> void assign(InputIterator first, InputIterator last);
Effects: Assigns the the range [first, last) to *this.
Throws: If memory allocation throws or T's constructor from dereferencing InpIt throws.
Complexity: Linear to n.
void assign(std::initializer_list< value_type > il);
Effects: Assigns the the range [il.begin(), il.end()) to *this.
Throws: If memory allocation throws or T's constructor from dereferencing initializer_list iterator throws.
allocator_type get_allocator() const;
Effects: Returns a copy of the internal allocator.
Throws: If allocator's copy constructor throws.
Complexity: Constant.
const stored_allocator_type & get_stored_allocator() const noexcept;
Effects: Returns a reference to the internal allocator.
Throws: Nothing
Complexity: Constant.
Note: Non-standard extension.
stored_allocator_type & get_stored_allocator() noexcept;
Effects: Returns a reference to the internal allocator.
Throws: Nothing
Complexity: Constant.
Note: Non-standard extension.
iterator begin() noexcept;
Effects: Returns an iterator to the first element contained in the stable_vector
.
Throws: Nothing.
Complexity: Constant.
const_iterator begin() const noexcept;
Effects: Returns a const_iterator to the first element contained in the stable_vector
.
Throws: Nothing.
Complexity: Constant.
iterator end() noexcept;
Effects: Returns an iterator to the end of the stable_vector
.
Throws: Nothing.
Complexity: Constant.
const_iterator end() const noexcept;
Effects: Returns a const_iterator to the end of the stable_vector
.
Throws: Nothing.
Complexity: Constant.
reverse_iterator rbegin() noexcept;
Effects: Returns a reverse_iterator pointing to the beginning of the reversed stable_vector
.
Throws: Nothing.
Complexity: Constant.
const_reverse_iterator rbegin() const noexcept;
Effects: Returns a const_reverse_iterator pointing to the beginning of the reversed stable_vector
.
Throws: Nothing.
Complexity: Constant.
reverse_iterator rend() noexcept;
Effects: Returns a reverse_iterator pointing to the end of the reversed stable_vector
.
Throws: Nothing.
Complexity: Constant.
const_reverse_iterator rend() const noexcept;
Effects: Returns a const_reverse_iterator pointing to the end of the reversed stable_vector
.
Throws: Nothing.
Complexity: Constant.
const_iterator cbegin() const noexcept;
Effects: Returns a const_iterator to the first element contained in the stable_vector
.
Throws: Nothing.
Complexity: Constant.
const_iterator cend() const noexcept;
Effects: Returns a const_iterator to the end of the stable_vector
.
Throws: Nothing.
Complexity: Constant.
const_reverse_iterator crbegin() const noexcept;
Effects: Returns a const_reverse_iterator pointing to the beginning of the reversed stable_vector
.
Throws: Nothing.
Complexity: Constant.
const_reverse_iterator crend() const noexcept;
Effects: Returns a const_reverse_iterator pointing to the end of the reversed stable_vector
.
Throws: Nothing.
Complexity: Constant.
bool empty() const noexcept;
Effects: Returns true if the stable_vector
contains no elements.
Throws: Nothing.
Complexity: Constant.
size_type size() const noexcept;
Effects: Returns the number of the elements contained in the stable_vector
.
Throws: Nothing.
Complexity: Constant.
size_type max_size() const noexcept;
Effects: Returns the largest possible size of the stable_vector
.
Throws: Nothing.
Complexity: Constant.
void resize(size_type n);
Effects: Inserts or erases elements at the end such that the size becomes n. New elements are value initialized.
Throws: If memory allocation throws, or T's value initialization throws.
Complexity: Linear to the difference between size() and new_size.
void resize(size_type n, default_init_t);
Effects: Inserts or erases elements at the end such that the size becomes n. New elements are default initialized.
Throws: If memory allocation throws, or T's default initialization throws.
Complexity: Linear to the difference between size() and new_size.
Note: Non-standard extension
void resize(size_type n, const T & t);
Effects: Inserts or erases elements at the end such that the size becomes n. New elements are copy constructed from x.
Throws: If memory allocation throws, or T's copy constructor throws.
Complexity: Linear to the difference between size() and new_size.
size_type capacity() const noexcept;
Effects: Number of elements for which memory has been allocated. capacity() is always greater than or equal to size().
Throws: Nothing.
Complexity: Constant.
void reserve(size_type n);
Effects: If n is less than or equal to capacity(), this call has no effect. Otherwise, it is a request for allocation of additional memory. If the request is successful, then capacity() is greater than or equal to n; otherwise, capacity() is unchanged. In either case, size() is unchanged.
Throws: If memory allocation allocation throws.
void shrink_to_fit();
Effects: Tries to deallocate the excess of memory created with previous allocations. The size of the stable_vector
is unchanged
Throws: If memory allocation throws.
Complexity: Linear to size().
reference front() noexcept;
Requires: !empty()
Effects: Returns a reference to the first element of the container.
Throws: Nothing.
Complexity: Constant.
const_reference front() const noexcept;
Requires: !empty()
Effects: Returns a const reference to the first element of the container.
Throws: Nothing.
Complexity: Constant.
reference back() noexcept;
Requires: !empty()
Effects: Returns a reference to the last element of the container.
Throws: Nothing.
Complexity: Constant.
const_reference back() const noexcept;
Requires: !empty()
Effects: Returns a const reference to the last element of the container.
Throws: Nothing.
Complexity: Constant.
reference operator[](size_type n) noexcept;
Requires: size() > n.
Effects: Returns a reference to the nth element from the beginning of the container.
Throws: Nothing.
Complexity: Constant.
const_reference operator[](size_type n) const noexcept;
Requires: size() > n.
Effects: Returns a const reference to the nth element from the beginning of the container.
Throws: Nothing.
Complexity: Constant.
iterator nth(size_type n) noexcept;
Requires: size() >= n.
Effects: Returns an iterator to the nth element from the beginning of the container. Returns end() if n == size().
Throws: Nothing.
Complexity: Constant.
Note: Non-standard extension
const_iterator nth(size_type n) const noexcept;
Requires: size() >= n.
Effects: Returns a const_iterator to the nth element from the beginning of the container. Returns end() if n == size().
Throws: Nothing.
Complexity: Constant.
Note: Non-standard extension
size_type index_of(iterator p) noexcept;
Requires: begin() <= p <= end().
Effects: Returns the index of the element pointed by p and size() if p == end().
Throws: Nothing.
Complexity: Constant.
Note: Non-standard extension
size_type index_of(const_iterator p) const noexcept;
Requires: begin() <= p <= end().
Effects: Returns the index of the element pointed by p and size() if p == end().
Throws: Nothing.
Complexity: Constant.
Note: Non-standard extension
reference at(size_type n);
Requires: size() > n.
Effects: Returns a reference to the nth element from the beginning of the container.
Throws: range_error if n >= size()
Complexity: Constant.
const_reference at(size_type n) const;
Requires: size() > n.
Effects: Returns a const reference to the nth element from the beginning of the container.
Throws: range_error if n >= size()
Complexity: Constant.
template<class ... Args> reference emplace_back(Args &&... args);
Effects: Inserts an object of type T constructed with std::forward<Args>(args)... in the end of the stable_vector
.
Returns: A reference to the created object.
Throws: If memory allocation throws or the in-place constructor throws.
Complexity: Amortized constant time.
template<class ... Args> iterator emplace(const_iterator p, Args &&... args);
Requires: p must be a valid iterator of *this.
Effects: Inserts an object of type T constructed with std::forward<Args>(args)... before p
Throws: If memory allocation throws or the in-place constructor throws.
Complexity: If p is end(), amortized constant time Linear time otherwise.
void push_back(const T & x);
Effects: Inserts a copy of x at the end of the stable_vector
.
Throws: If memory allocation throws or T's copy constructor throws.
Complexity: Amortized constant time.
void push_back(T && x);
Effects: Constructs a new element in the end of the stable_vector
and moves the resources of x to this new element.
Throws: If memory allocation throws.
Complexity: Amortized constant time.
iterator insert(const_iterator p, const T & x);
Requires: p must be a valid iterator of *this.
Effects: Insert a copy of x before p.
Returns: An iterator to the inserted element.
Throws: If memory allocation throws or x's copy constructor throws.
Complexity: If p is end(), amortized constant time Linear time otherwise.
iterator insert(const_iterator p, T && x);
Requires: p must be a valid iterator of *this.
Effects: Insert a new element before p with x's resources.
Returns: an iterator to the inserted element.
Throws: If memory allocation throws.
Complexity: If p is end(), amortized constant time Linear time otherwise.
iterator insert(const_iterator p, size_type n, const T & t);
Requires: p must be a valid iterator of *this.
Effects: Insert n copies of x before p.
Returns: an iterator to the first inserted element or p if n is 0.
Throws: If memory allocation throws or T's copy constructor throws.
Complexity: Linear to n.
iterator insert(const_iterator p, std::initializer_list< value_type > il);Requires: p must be a valid iterator of *this.
Requires: p must be a valid iterator of *this.
Effects: Insert a copy of the [il.begin(), il.end()) range before p.
Returns: an iterator to the first inserted element or p if first == last.
Complexity: Linear to distance [il.begin(), il.end()).
template<typename InputIterator> iterator insert(const_iterator p, InputIterator first, InputIterator last);
Requires: pos must be a valid iterator of *this.
Effects: Insert a copy of the [first, last) range before p.
Returns: an iterator to the first inserted element or p if first == last.
Throws: If memory allocation throws, T's constructor from a dereferenced InpIt throws or T's copy constructor throws.
Complexity: Linear to distance [first, last).
void pop_back() noexcept;
Effects: Removes the last element from the stable_vector
.
Throws: Nothing.
Complexity: Constant time.
iterator erase(const_iterator p) noexcept;
Effects: Erases the element at p.
Throws: Nothing.
Complexity: Linear to the elements between p and the last element. Constant if p is the last element.
iterator erase(const_iterator first, const_iterator last) noexcept;
Effects: Erases the elements pointed by [first, last).
Throws: Nothing.
Complexity: Linear to the distance between first and last plus linear to the elements between p and the last element.
void swap(stable_vector & x) noexcept(allocator_traits_type::propagate_on_container_swap::value||allocator_traits_type::is_always_equal::value));
Effects: Swaps the contents of *this and x.
Throws: Nothing.
Complexity: Constant.
void clear() noexcept;
Effects: Erases all the elements of the stable_vector
.
Throws: Nothing.
Complexity: Linear to the number of elements in the stable_vector
.
stable_vector
friend functionsfriend bool operator==(const stable_vector & x, const stable_vector & y);
Effects: Returns true if x and y are equal
Complexity: Linear to the number of elements in the container.
friend bool operator!=(const stable_vector & x, const stable_vector & y);
Effects: Returns true if x and y are unequal
Complexity: Linear to the number of elements in the container.
friend bool operator<(const stable_vector & x, const stable_vector & y);
Effects: Returns true if x is less than y
Complexity: Linear to the number of elements in the container.
friend bool operator>(const stable_vector & x, const stable_vector & y);
Effects: Returns true if x is greater than y
Complexity: Linear to the number of elements in the container.
friend bool operator<=(const stable_vector & x, const stable_vector & y);
Effects: Returns true if x is equal or less than y
Complexity: Linear to the number of elements in the container.
friend bool operator>=(const stable_vector & x, const stable_vector & y);
Effects: Returns true if x is equal or greater than y
Complexity: Linear to the number of elements in the container.
friend void swap(stable_vector & x, stable_vector & y) noexcept(noexcept(x.swap(y))));
Effects: x.swap(y)
Complexity: Constant.