// Boost.Container varray // // Copyright (c) 2012-2014 Adam Wulkiewicz, Lodz, Poland. // Copyright (c) 2011-2013 Andrew Hundt. // // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_HPP #define BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_HPP // TODO - REMOVE/CHANGE #include #include #include #include #include #include #include #include #include #include // TODO - use std::reverse_iterator and std::iterator_traits // instead Boost.Iterator to remove dependency? // or boost/detail/iterator.hpp ? #include #include #include #include #include #include #include /*! \defgroup varray_non_member varray non-member functions */ namespace boost { namespace geometry { namespace index { namespace detail { namespace varray_detail { template struct varray_traits { typedef Value value_type; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; typedef Value * pointer; typedef const Value * const_pointer; typedef Value & reference; typedef const Value & const_reference; typedef boost::false_type use_memop_in_swap_and_move; typedef boost::false_type use_optimized_swap; typedef boost::false_type disable_trivial_init; }; template struct checker { typedef typename Varray::size_type size_type; typedef typename Varray::const_iterator const_iterator; static inline void check_capacity(Varray const& v, size_type s) { BOOST_GEOMETRY_INDEX_ASSERT(s <= v.capacity(), "size too big"); ::boost::ignore_unused_variable_warning(v); ::boost::ignore_unused_variable_warning(s); } static inline void throw_out_of_bounds(Varray const& v, size_type i) { //#ifndef BOOST_NO_EXCEPTIONS if ( v.size() <= i ) BOOST_THROW_EXCEPTION(std::out_of_range("index out of bounds")); //#else // BOOST_NO_EXCEPTIONS // BOOST_GEOMETRY_INDEX_ASSERT(i < v.size(), "index out of bounds"); //#endif // BOOST_NO_EXCEPTIONS ::boost::ignore_unused_variable_warning(v); ::boost::ignore_unused_variable_warning(i); } static inline void check_index(Varray const& v, size_type i) { BOOST_GEOMETRY_INDEX_ASSERT(i < v.size(), "index out of bounds"); ::boost::ignore_unused_variable_warning(v); ::boost::ignore_unused_variable_warning(i); } static inline void check_not_empty(Varray const& v) { BOOST_GEOMETRY_INDEX_ASSERT(!v.empty(), "the container is empty"); ::boost::ignore_unused_variable_warning(v); } static inline void check_iterator_end_neq(Varray const& v, const_iterator position) { BOOST_GEOMETRY_INDEX_ASSERT(v.begin() <= position && position < v.end(), "iterator out of bounds"); ::boost::ignore_unused_variable_warning(v); ::boost::ignore_unused_variable_warning(position); } static inline void check_iterator_end_eq(Varray const& v, const_iterator position) { BOOST_GEOMETRY_INDEX_ASSERT(v.begin() <= position && position <= v.end(), "iterator out of bounds"); ::boost::ignore_unused_variable_warning(v); ::boost::ignore_unused_variable_warning(position); } }; } // namespace varray_detail /*! \brief A variable-size array container with fixed capacity. varray is a sequence container like boost::container::vector with contiguous storage that can change in size, along with the static allocation, low overhead, and fixed capacity of boost::array. A varray is a sequence that supports random access to elements, constant time insertion and removal of elements at the end, and linear time insertion and removal of elements at the beginning or in the middle. The number of elements in a varray may vary dynamically up to a fixed capacity because elements are stored within the object itself similarly to an array. However, objects are initialized as they are inserted into varray unlike C arrays or std::array which must construct all elements on instantiation. The behavior of varray enables the use of statically allocated elements in cases with complex object lifetime requirements that would otherwise not be trivially possible. \par Error Handling Insertion beyond the capacity and out of bounds errors result in undefined behavior unless otherwise specified. In this respect if size() == capacity(), then varray::push_back() behaves like std::vector pop_front() if size() == empty(). The reason for this difference is because unlike vectors, varray does not perform allocation. \par Advanced Usage Error handling behavior can be modified to more closely match std::vector exception behavior when exceeding bounds by providing an alternate Strategy and varray_traits instantiation. \tparam Value The type of element that will be stored. \tparam Capacity The maximum number of elements varray can store, fixed at compile time. \tparam Strategy Defines the public typedefs and error handlers, implements StaticVectorStrategy and has some similarities to an Allocator. */ template class varray { typedef varray_detail::varray_traits vt; typedef varray_detail::checker errh; BOOST_MPL_ASSERT_MSG( ( boost::is_unsigned::value && sizeof(typename boost::uint_value_t::least) <= sizeof(typename vt::size_type) ), SIZE_TYPE_IS_TOO_SMALL_FOR_SPECIFIED_CAPACITY, (varray) ); typedef boost::aligned_storage< sizeof(Value[Capacity]), boost::alignment_of::value > aligned_storage_type; template friend class varray; BOOST_COPYABLE_AND_MOVABLE(varray) #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES public: template varray & operator=(varray & sv) { typedef varray other; this->operator=(static_cast &>(const_cast(sv))); return *this; } #endif public: //! @brief The type of elements stored in the container. typedef typename vt::value_type value_type; //! @brief The unsigned integral type used by the container. typedef typename vt::size_type size_type; //! @brief The pointers difference type. typedef typename vt::difference_type difference_type; //! @brief The pointer type. typedef typename vt::pointer pointer; //! @brief The const pointer type. typedef typename vt::const_pointer const_pointer; //! @brief The value reference type. typedef typename vt::reference reference; //! @brief The value const reference type. typedef typename vt::const_reference const_reference; //! @brief The iterator type. typedef pointer iterator; //! @brief The const iterator type. typedef const_pointer const_iterator; //! @brief The reverse iterator type. typedef boost::reverse_iterator reverse_iterator; //! @brief The const reverse iterator. typedef boost::reverse_iterator const_reverse_iterator; //! @brief Constructs an empty varray. //! //! @par Throws //! Nothing. //! //! @par Complexity //! Constant O(1). varray() : m_size(0) {} //! @pre count <= capacity() //! //! @brief Constructs a varray containing count default constructed Values. //! //! @param count The number of values which will be contained in the container. //! //! @par Throws //! If Value's default constructor throws. //! @internal //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default). //! @endinternal //! //! @par Complexity //! Linear O(N). explicit varray(size_type count) : m_size(0) { this->resize(count); // may throw } //! @pre count <= capacity() //! //! @brief Constructs a varray containing count copies of value. //! //! @param count The number of copies of a values that will be contained in the container. //! @param value The value which will be used to copy construct values. //! //! @par Throws //! If Value's copy constructor throws. //! @internal //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default). //! @endinternal //! //! @par Complexity //! Linear O(N). varray(size_type count, value_type const& value) : m_size(0) { this->resize(count, value); // may throw } //! @pre //! @li distance(first, last) <= capacity() //! @li Iterator must meet the \c ForwardTraversalIterator concept. //! //! @brief Constructs a varray containing copy of a range [first, last). //! //! @param first The iterator to the first element in range. //! @param last The iterator to the one after the last element in range. //! //! @par Throws //! If Value's constructor taking a dereferenced Iterator throws. //! @internal //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default). //! @endinternal //! //! @par Complexity //! Linear O(N). template varray(Iterator first, Iterator last) : m_size(0) { BOOST_CONCEPT_ASSERT((boost_concepts::ForwardTraversal)); // Make sure you passed a ForwardIterator this->assign(first, last); // may throw } //! @brief Constructs a copy of other varray. //! //! @param other The varray which content will be copied to this one. //! //! @par Throws //! If Value's copy constructor throws. //! //! @par Complexity //! Linear O(N). varray(varray const& other) : m_size(other.size()) { namespace sv = varray_detail; sv::uninitialized_copy(other.begin(), other.end(), this->begin()); // may throw } //! @pre other.size() <= capacity(). //! //! @brief Constructs a copy of other varray. //! //! @param other The varray which content will be copied to this one. //! //! @par Throws //! If Value's copy constructor throws. //! @internal //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default). //! @endinternal //! //! @par Complexity //! Linear O(N). template varray(varray const& other) : m_size(other.size()) { errh::check_capacity(*this, other.size()); // may throw namespace sv = varray_detail; sv::uninitialized_copy(other.begin(), other.end(), this->begin()); // may throw } //! @brief Copy assigns Values stored in the other varray to this one. //! //! @param other The varray which content will be copied to this one. //! //! @par Throws //! If Value's copy constructor or copy assignment throws. //! //! @par Complexity //! Linear O(N). varray & operator=(BOOST_COPY_ASSIGN_REF(varray) other) { this->assign(other.begin(), other.end()); // may throw return *this; } //! @pre other.size() <= capacity() //! //! @brief Copy assigns Values stored in the other varray to this one. //! //! @param other The varray which content will be copied to this one. //! //! @par Throws //! If Value's copy constructor or copy assignment throws. //! @internal //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default). //! @endinternal //! //! @par Complexity //! Linear O(N). template varray & operator=(BOOST_COPY_ASSIGN_REF_2_TEMPL_ARGS(varray, value_type, C) other) { this->assign(other.begin(), other.end()); // may throw return *this; } //! @brief Move constructor. Moves Values stored in the other varray to this one. //! //! @param other The varray which content will be moved to this one. //! //! @par Throws //! @li If \c boost::has_nothrow_move::value is \c true and Value's move constructor throws. //! @li If \c boost::has_nothrow_move::value is \c false and Value's copy constructor throws. //! @internal //! @li It throws only if \c use_memop_in_swap_and_move is \c false_type - default. //! @endinternal //! //! @par Complexity //! Linear O(N). varray(BOOST_RV_REF(varray) other) { typedef typename vt::use_memop_in_swap_and_move use_memop_in_swap_and_move; this->move_ctor_dispatch(other, use_memop_in_swap_and_move()); } //! @pre other.size() <= capacity() //! //! @brief Move constructor. Moves Values stored in the other varray to this one. //! //! @param other The varray which content will be moved to this one. //! //! @par Throws //! @li If \c boost::has_nothrow_move::value is \c true and Value's move constructor throws. //! @li If \c boost::has_nothrow_move::value is \c false and Value's copy constructor throws. //! @internal //! @li It throws only if \c use_memop_in_swap_and_move is false_type - default. //! @endinternal //! @internal //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default). //! @endinternal //! //! @par Complexity //! Linear O(N). template varray(BOOST_RV_REF_2_TEMPL_ARGS(varray, value_type, C) other) : m_size(other.m_size) { errh::check_capacity(*this, other.size()); // may throw typedef typename vt::use_memop_in_swap_and_move use_memop_in_swap_and_move; this->move_ctor_dispatch(other, use_memop_in_swap_and_move()); } //! @brief Move assignment. Moves Values stored in the other varray to this one. //! //! @param other The varray which content will be moved to this one. //! //! @par Throws //! @li If \c boost::has_nothrow_move::value is \c true and Value's move constructor or move assignment throws. //! @li If \c boost::has_nothrow_move::value is \c false and Value's copy constructor or copy assignment throws. //! @internal //! @li It throws only if \c use_memop_in_swap_and_move is \c false_type - default. //! @endinternal //! //! @par Complexity //! Linear O(N). varray & operator=(BOOST_RV_REF(varray) other) { if ( &other == this ) return *this; typedef typename vt::use_memop_in_swap_and_move use_memop_in_swap_and_move; this->move_assign_dispatch(other, use_memop_in_swap_and_move()); return *this; } //! @pre other.size() <= capacity() //! //! @brief Move assignment. Moves Values stored in the other varray to this one. //! //! @param other The varray which content will be moved to this one. //! //! @par Throws //! @li If \c boost::has_nothrow_move::value is \c true and Value's move constructor or move assignment throws. //! @li If \c boost::has_nothrow_move::value is \c false and Value's copy constructor or copy assignment throws. //! @internal //! @li It throws only if \c use_memop_in_swap_and_move is \c false_type - default. //! @endinternal //! @internal //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default). //! @endinternal //! //! @par Complexity //! Linear O(N). template varray & operator=(BOOST_RV_REF_2_TEMPL_ARGS(varray, value_type, C) other) { errh::check_capacity(*this, other.size()); // may throw typedef typename vt::use_memop_in_swap_and_move use_memop_in_swap_and_move; this->move_assign_dispatch(other, use_memop_in_swap_and_move()); return *this; } //! @brief Destructor. Destroys Values stored in this container. //! //! @par Throws //! Nothing //! //! @par Complexity //! Linear O(N). ~varray() { namespace sv = varray_detail; sv::destroy(this->begin(), this->end()); } //! @brief Swaps contents of the other varray and this one. //! //! @param other The varray which content will be swapped with this one's content. //! //! @par Throws //! @li If \c boost::has_nothrow_move::value is \c true and Value's move constructor or move assignment throws, //! @li If \c boost::has_nothrow_move::value is \c false and Value's copy constructor or copy assignment throws, //! @internal //! @li It throws only if \c use_memop_in_swap_and_move and \c use_optimized_swap are \c false_type - default. //! @endinternal //! //! @par Complexity //! Linear O(N). void swap(varray & other) { typedef typename vt::use_optimized_swap use_optimized_swap; this->swap_dispatch(other, use_optimized_swap()); } //! @pre other.size() <= capacity() && size() <= other.capacity() //! //! @brief Swaps contents of the other varray and this one. //! //! @param other The varray which content will be swapped with this one's content. //! //! @par Throws //! @li If \c boost::has_nothrow_move::value is \c true and Value's move constructor or move assignment throws, //! @li If \c boost::has_nothrow_move::value is \c false and Value's copy constructor or copy assignment throws, //! @internal //! @li It throws only if \c use_memop_in_swap_and_move and \c use_optimized_swap are \c false_type - default. //! @endinternal //! @internal //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default). //! @endinternal //! //! @par Complexity //! Linear O(N). template void swap(varray & other) { errh::check_capacity(*this, other.size()); errh::check_capacity(other, this->size()); typedef typename vt::use_optimized_swap use_optimized_swap; this->swap_dispatch(other, use_optimized_swap()); } //! @pre count <= capacity() //! //! @brief Inserts or erases elements at the end such that //! the size becomes count. New elements are default constructed. //! //! @param count The number of elements which will be stored in the container. //! //! @par Throws //! If Value's default constructor throws. //! @internal //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default). //! @endinternal //! //! @par Complexity //! Linear O(N). void resize(size_type count) { namespace sv = varray_detail; typedef typename vt::disable_trivial_init dti; if ( count < m_size ) { sv::destroy(this->begin() + count, this->end()); } else { errh::check_capacity(*this, count); // may throw sv::uninitialized_fill(this->end(), this->begin() + count, dti()); // may throw } m_size = count; // update end } //! @pre count <= capacity() //! //! @brief Inserts or erases elements at the end such that //! the size becomes count. New elements are copy constructed from value. //! //! @param count The number of elements which will be stored in the container. //! @param value The value used to copy construct the new element. //! //! @par Throws //! If Value's copy constructor throws. //! @internal //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default). //! @endinternal //! //! @par Complexity //! Linear O(N). void resize(size_type count, value_type const& value) { if ( count < m_size ) { namespace sv = varray_detail; sv::destroy(this->begin() + count, this->end()); } else { errh::check_capacity(*this, count); // may throw std::uninitialized_fill(this->end(), this->begin() + count, value); // may throw } m_size = count; // update end } //! @pre count <= capacity() //! //! @brief This call has no effect because the Capacity of this container is constant. //! //! @param count The number of elements which the container should be able to contain. //! //! @par Throws //! Nothing. //! @internal //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default). //! @endinternal //! //! @par Complexity //! Linear O(N). void reserve(size_type count) { errh::check_capacity(*this, count); // may throw } //! @pre size() < capacity() //! //! @brief Adds a copy of value at the end. //! //! @param value The value used to copy construct the new element. //! //! @par Throws //! If Value's copy constructor throws. //! @internal //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default). //! @endinternal //! //! @par Complexity //! Constant O(1). void push_back(value_type const& value) { typedef typename vt::disable_trivial_init dti; errh::check_capacity(*this, m_size + 1); // may throw namespace sv = varray_detail; sv::construct(dti(), this->end(), value); // may throw ++m_size; // update end } //! @pre size() < capacity() //! //! @brief Moves value to the end. //! //! @param value The value to move construct the new element. //! //! @par Throws //! If Value's move constructor throws. //! @internal //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default). //! @endinternal //! //! @par Complexity //! Constant O(1). void push_back(BOOST_RV_REF(value_type) value) { typedef typename vt::disable_trivial_init dti; errh::check_capacity(*this, m_size + 1); // may throw namespace sv = varray_detail; sv::construct(dti(), this->end(), ::boost::move(value)); // may throw ++m_size; // update end } //! @pre !empty() //! //! @brief Destroys last value and decreases the size. //! //! @par Throws //! Nothing by default. //! //! @par Complexity //! Constant O(1). void pop_back() { errh::check_not_empty(*this); namespace sv = varray_detail; sv::destroy(this->end() - 1); --m_size; // update end } //! @pre //! @li \c position must be a valid iterator of \c *this in range [begin(), end()]. //! @li size() < capacity() //! //! @brief Inserts a copy of element at position. //! //! @param position The position at which the new value will be inserted. //! @param value The value used to copy construct the new element. //! //! @par Throws //! @li If Value's copy constructor or copy assignment throws //! @li If Value's move constructor or move assignment throws. //! @internal //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default). //! @endinternal //! //! @par Complexity //! Constant or linear. iterator insert(iterator position, value_type const& value) { typedef typename vt::disable_trivial_init dti; namespace sv = varray_detail; errh::check_iterator_end_eq(*this, position); errh::check_capacity(*this, m_size + 1); // may throw if ( position == this->end() ) { sv::construct(dti(), position, value); // may throw ++m_size; // update end } else { // TODO - should move be used only if it's nonthrowing? value_type & r = *(this->end() - 1); sv::construct(dti(), this->end(), boost::move(r)); // may throw ++m_size; // update end sv::move_backward(position, this->end() - 2, this->end() - 1); // may throw sv::assign(position, value); // may throw } return position; } //! @pre //! @li \c position must be a valid iterator of \c *this in range [begin(), end()]. //! @li size() < capacity() //! //! @brief Inserts a move-constructed element at position. //! //! @param position The position at which the new value will be inserted. //! @param value The value used to move construct the new element. //! //! @par Throws //! If Value's move constructor or move assignment throws. //! @internal //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default). //! @endinternal //! //! @par Complexity //! Constant or linear. iterator insert(iterator position, BOOST_RV_REF(value_type) value) { typedef typename vt::disable_trivial_init dti; namespace sv = varray_detail; errh::check_iterator_end_eq(*this, position); errh::check_capacity(*this, m_size + 1); // may throw if ( position == this->end() ) { sv::construct(dti(), position, boost::move(value)); // may throw ++m_size; // update end } else { // TODO - should move be used only if it's nonthrowing? value_type & r = *(this->end() - 1); sv::construct(dti(), this->end(), boost::move(r)); // may throw ++m_size; // update end sv::move_backward(position, this->end() - 2, this->end() - 1); // may throw sv::assign(position, boost::move(value)); // may throw } return position; } //! @pre //! @li \c position must be a valid iterator of \c *this in range [begin(), end()]. //! @li size() + count <= capacity() //! //! @brief Inserts a count copies of value at position. //! //! @param position The position at which new elements will be inserted. //! @param count The number of new elements which will be inserted. //! @param value The value used to copy construct new elements. //! //! @par Throws //! @li If Value's copy constructor or copy assignment throws. //! @li If Value's move constructor or move assignment throws. //! @internal //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default). //! @endinternal //! //! @par Complexity //! Linear O(N). iterator insert(iterator position, size_type count, value_type const& value) { errh::check_iterator_end_eq(*this, position); errh::check_capacity(*this, m_size + count); // may throw if ( position == this->end() ) { std::uninitialized_fill(position, position + count, value); // may throw m_size += count; // update end } else { namespace sv = varray_detail; difference_type to_move = std::distance(position, this->end()); // TODO - should following lines check for exception and revert to the old size? if ( count < static_cast(to_move) ) { sv::uninitialized_move(this->end() - count, this->end(), this->end()); // may throw m_size += count; // update end sv::move_backward(position, position + to_move - count, this->end() - count); // may throw std::fill_n(position, count, value); // may throw } else { std::uninitialized_fill(this->end(), position + count, value); // may throw m_size += count - to_move; // update end sv::uninitialized_move(position, position + to_move, position + count); // may throw m_size += to_move; // update end std::fill_n(position, to_move, value); // may throw } } return position; } //! @pre //! @li \c position must be a valid iterator of \c *this in range [begin(), end()]. //! @li distance(first, last) <= capacity() //! @li \c Iterator must meet the \c ForwardTraversalIterator concept. //! //! @brief Inserts a copy of a range [first, last) at position. //! //! @param position The position at which new elements will be inserted. //! @param first The iterator to the first element of a range used to construct new elements. //! @param last The iterator to the one after the last element of a range used to construct new elements. //! //! @par Throws //! @li If Value's constructor and assignment taking a dereferenced \c Iterator. //! @li If Value's move constructor or move assignment throws. //! @internal //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default). //! @endinternal //! //! @par Complexity //! Linear O(N). template iterator insert(iterator position, Iterator first, Iterator last) { BOOST_CONCEPT_ASSERT((boost_concepts::ForwardTraversal)); // Make sure you passed a ForwardIterator typedef typename boost::iterator_traversal::type traversal; this->insert_dispatch(position, first, last, traversal()); return position; } //! @pre \c position must be a valid iterator of \c *this in range [begin(), end()) //! //! @brief Erases Value from position. //! //! @param position The position of the element which will be erased from the container. //! //! @par Throws //! If Value's move assignment throws. //! //! @par Complexity //! Linear O(N). iterator erase(iterator position) { namespace sv = varray_detail; errh::check_iterator_end_neq(*this, position); //TODO - add empty check? //errh::check_empty(*this); sv::move(position + 1, this->end(), position); // may throw sv::destroy(this->end() - 1); --m_size; return position; } //! @pre //! @li \c first and \c last must define a valid range //! @li iterators must be in range [begin(), end()] //! //! @brief Erases Values from a range [first, last). //! //! @param first The position of the first element of a range which will be erased from the container. //! @param last The position of the one after the last element of a range which will be erased from the container. //! //! @par Throws //! If Value's move assignment throws. //! //! @par Complexity //! Linear O(N). iterator erase(iterator first, iterator last) { namespace sv = varray_detail; errh::check_iterator_end_eq(*this, first); errh::check_iterator_end_eq(*this, last); difference_type n = std::distance(first, last); //TODO - add invalid range check? //BOOST_ASSERT_MSG(0 <= n, "invalid range"); //TODO - add this->size() check? //BOOST_ASSERT_MSG(n <= this->size(), "invalid range"); sv::move(last, this->end(), first); // may throw sv::destroy(this->end() - n, this->end()); m_size -= n; return first; } //! @pre distance(first, last) <= capacity() //! //! @brief Assigns a range [first, last) of Values to this container. //! //! @param first The iterator to the first element of a range used to construct new content of this container. //! @param last The iterator to the one after the last element of a range used to construct new content of this container. //! //! @par Throws //! If Value's copy constructor or copy assignment throws, //! //! @par Complexity //! Linear O(N). template void assign(Iterator first, Iterator last) { BOOST_CONCEPT_ASSERT((boost_concepts::ForwardTraversal)); // Make sure you passed a ForwardIterator typedef typename boost::iterator_traversal::type traversal; this->assign_dispatch(first, last, traversal()); // may throw } //! @pre count <= capacity() //! //! @brief Assigns a count copies of value to this container. //! //! @param count The new number of elements which will be container in the container. //! @param value The value which will be used to copy construct the new content. //! //! @par Throws //! If Value's copy constructor or copy assignment throws. //! //! @par Complexity //! Linear O(N). void assign(size_type count, value_type const& value) { if ( count < m_size ) { namespace sv = varray_detail; std::fill_n(this->begin(), count, value); // may throw sv::destroy(this->begin() + count, this->end()); } else { errh::check_capacity(*this, count); // may throw std::fill_n(this->begin(), m_size, value); // may throw std::uninitialized_fill(this->end(), this->begin() + count, value); // may throw } m_size = count; // update end } #if !defined(BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE) #if defined(BOOST_CONTAINER_PERFECT_FORWARDING) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED) //! @pre size() < capacity() //! //! @brief Inserts a Value constructed with //! \c std::forward(args)... in the end of the container. //! //! @param args The arguments of the constructor of the new element which will be created at the end of the container. //! //! @par Throws //! If in-place constructor throws or Value's move constructor throws. //! @internal //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default). //! @endinternal //! //! @par Complexity //! Constant O(1). template void emplace_back(BOOST_FWD_REF(Args) ...args) { typedef typename vt::disable_trivial_init dti; errh::check_capacity(*this, m_size + 1); // may throw namespace sv = varray_detail; sv::construct(dti(), this->end(), ::boost::forward(args)...); // may throw ++m_size; // update end } //! @pre //! @li \c position must be a valid iterator of \c *this in range [begin(), end()] //! @li size() < capacity() //! //! @brief Inserts a Value constructed with //! \c std::forward(args)... before position //! //! @param position The position at which new elements will be inserted. //! @param args The arguments of the constructor of the new element. //! //! @par Throws //! If in-place constructor throws or if Value's move constructor or move assignment throws. //! @internal //! @li If a throwing error handler is specified, throws when the capacity is exceeded. (not by default). //! @endinternal //! //! @par Complexity //! Constant or linear. template iterator emplace(iterator position, BOOST_FWD_REF(Args) ...args) { typedef typename vt::disable_trivial_init dti; namespace sv = varray_detail; errh::check_iterator_end_eq(*this, position); errh::check_capacity(*this, m_size + 1); // may throw if ( position == this->end() ) { sv::construct(dti(), position, ::boost::forward(args)...); // may throw ++m_size; // update end } else { // TODO - should following lines check for exception and revert to the old size? // TODO - should move be used only if it's nonthrowing? value_type & r = *(this->end() - 1); sv::construct(dti(), this->end(), boost::move(r)); // may throw ++m_size; // update end sv::move_backward(position, this->end() - 2, this->end() - 1); // may throw aligned_storage::value> temp_storage; value_type * val_p = static_cast(temp_storage.address()); sv::construct(dti(), val_p, ::boost::forward(args)...); // may throw sv::scoped_destructor d(val_p); sv::assign(position, ::boost::move(*val_p)); // may throw } return position; } #else // BOOST_CONTAINER_PERFECT_FORWARDING || BOOST_CONTAINER_DOXYGEN_INVOKED #define BOOST_PP_LOCAL_MACRO(n) \ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ void emplace_back(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ { \ typedef typename vt::disable_trivial_init dti; \ \ errh::check_capacity(*this, m_size + 1); /*may throw*/\ \ namespace sv = varray_detail; \ sv::construct(dti(), this->end() BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); /*may throw*/\ ++m_size; /*update end*/ \ } \ // #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) #include BOOST_PP_LOCAL_ITERATE() #define BOOST_PP_LOCAL_MACRO(n) \ BOOST_PP_EXPR_IF(n, template<) BOOST_PP_ENUM_PARAMS(n, class P) BOOST_PP_EXPR_IF(n, >) \ iterator emplace(iterator position BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \ { \ typedef typename vt::disable_trivial_init dti; \ namespace sv = varray_detail; \ \ errh::check_iterator_end_eq(*this, position); \ errh::check_capacity(*this, m_size + 1); /*may throw*/\ \ if ( position == this->end() ) \ { \ sv::construct(dti(), position BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); /*may throw*/\ ++m_size; /*update end*/ \ } \ else \ { \ /* TODO - should following lines check for exception and revert to the old size? */ \ /* TODO - should move be used only if it's nonthrowing? */ \ \ value_type & r = *(this->end() - 1); \ sv::construct(dti(), this->end(), boost::move(r)); /*may throw*/\ ++m_size; /*update end*/ \ sv::move_backward(position, this->end() - 2, this->end() - 1); /*may throw*/\ \ aligned_storage::value> temp_storage; \ value_type * val_p = static_cast(temp_storage.address()); \ sv::construct(dti(), val_p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) ); /*may throw*/\ sv::scoped_destructor d(val_p); \ sv::assign(position, ::boost::move(*val_p)); /*may throw*/\ } \ \ return position; \ } \ // #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS) #include BOOST_PP_LOCAL_ITERATE() #endif // BOOST_CONTAINER_PERFECT_FORWARDING || BOOST_CONTAINER_DOXYGEN_INVOKED #endif // !BOOST_CONTAINER_VARRAY_DISABLE_EMPLACE //! @brief Removes all elements from the container. //! //! @par Throws //! Nothing. //! //! @par Complexity //! Constant O(1). void clear() { namespace sv = varray_detail; sv::destroy(this->begin(), this->end()); m_size = 0; // update end } //! @pre i < size() //! //! @brief Returns reference to the i-th element. //! //! @param i The element's index. //! //! @return reference to the i-th element //! from the beginning of the container. //! //! @par Throws //! \c std::out_of_range exception by default. //! //! @par Complexity //! Constant O(1). reference at(size_type i) { errh::throw_out_of_bounds(*this, i); // may throw return *(this->begin() + i); } //! @pre i < size() //! //! @brief Returns const reference to the i-th element. //! //! @param i The element's index. //! //! @return const reference to the i-th element //! from the beginning of the container. //! //! @par Throws //! \c std::out_of_range exception by default. //! //! @par Complexity //! Constant O(1). const_reference at(size_type i) const { errh::throw_out_of_bounds(*this, i); // may throw return *(this->begin() + i); } //! @pre i < size() //! //! @brief Returns reference to the i-th element. //! //! @param i The element's index. //! //! @return reference to the i-th element //! from the beginning of the container. //! //! @par Throws //! Nothing by default. //! //! @par Complexity //! Constant O(1). reference operator[](size_type i) { // TODO: Remove bounds check? std::vector and std::array operator[] don't check. errh::check_index(*this, i); return *(this->begin() + i); } //! @pre i < size() //! //! @brief Returns const reference to the i-th element. //! //! @param i The element's index. //! //! @return const reference to the i-th element //! from the beginning of the container. //! //! @par Throws //! Nothing by default. //! //! @par Complexity //! Constant O(1). const_reference operator[](size_type i) const { errh::check_index(*this, i); return *(this->begin() + i); } //! @pre \c !empty() //! //! @brief Returns reference to the first element. //! //! @return reference to the first element //! from the beginning of the container. //! //! @par Throws //! Nothing by default. //! //! @par Complexity //! Constant O(1). reference front() { errh::check_not_empty(*this); return *(this->begin()); } //! @pre \c !empty() //! //! @brief Returns const reference to the first element. //! //! @return const reference to the first element //! from the beginning of the container. //! //! @par Throws //! Nothing by default. //! //! @par Complexity //! Constant O(1). const_reference front() const { errh::check_not_empty(*this); return *(this->begin()); } //! @pre \c !empty() //! //! @brief Returns reference to the last element. //! //! @return reference to the last element //! from the beginning of the container. //! //! @par Throws //! Nothing by default. //! //! @par Complexity //! Constant O(1). reference back() { errh::check_not_empty(*this); return *(this->end() - 1); } //! @pre \c !empty() //! //! @brief Returns const reference to the first element. //! //! @return const reference to the last element //! from the beginning of the container. //! //! @par Throws //! Nothing by default. //! //! @par Complexity //! Constant O(1). const_reference back() const { errh::check_not_empty(*this); return *(this->end() - 1); } //! @brief Pointer such that [data(), data() + size()) is a valid range. //! For a non-empty vector data() == &front(). //! //! @par Throws //! Nothing. //! //! @par Complexity //! Constant O(1). Value * data() { return boost::addressof(*(this->ptr())); } //! @brief Const pointer such that [data(), data() + size()) is a valid range. //! For a non-empty vector data() == &front(). //! //! @par Throws //! Nothing. //! //! @par Complexity //! Constant O(1). const Value * data() const { return boost::addressof(*(this->ptr())); } //! @brief Returns iterator to the first element. //! //! @return iterator to the first element contained in the vector. //! //! @par Throws //! Nothing. //! //! @par Complexity //! Constant O(1). iterator begin() { return this->ptr(); } //! @brief Returns const iterator to the first element. //! //! @return const_iterator to the first element contained in the vector. //! //! @par Throws //! Nothing. //! //! @par Complexity //! Constant O(1). const_iterator begin() const { return this->ptr(); } //! @brief Returns const iterator to the first element. //! //! @return const_iterator to the first element contained in the vector. //! //! @par Throws //! Nothing. //! //! @par Complexity //! Constant O(1). const_iterator cbegin() const { return this->ptr(); } //! @brief Returns iterator to the one after the last element. //! //! @return iterator pointing to the one after the last element contained in the vector. //! //! @par Throws //! Nothing. //! //! @par Complexity //! Constant O(1). iterator end() { return this->begin() + m_size; } //! @brief Returns const iterator to the one after the last element. //! //! @return const_iterator pointing to the one after the last element contained in the vector. //! //! @par Throws //! Nothing. //! //! @par Complexity //! Constant O(1). const_iterator end() const { return this->begin() + m_size; } //! @brief Returns const iterator to the one after the last element. //! //! @return const_iterator pointing to the one after the last element contained in the vector. //! //! @par Throws //! Nothing. //! //! @par Complexity //! Constant O(1). const_iterator cend() const { return this->cbegin() + m_size; } //! @brief Returns reverse iterator to the first element of the reversed container. //! //! @return reverse_iterator pointing to the beginning //! of the reversed varray. //! //! @par Throws //! Nothing. //! //! @par Complexity //! Constant O(1). reverse_iterator rbegin() { return reverse_iterator(this->end()); } //! @brief Returns const reverse iterator to the first element of the reversed container. //! //! @return const_reverse_iterator pointing to the beginning //! of the reversed varray. //! //! @par Throws //! Nothing. //! //! @par Complexity //! Constant O(1). const_reverse_iterator rbegin() const { return const_reverse_iterator(this->end()); } //! @brief Returns const reverse iterator to the first element of the reversed container. //! //! @return const_reverse_iterator pointing to the beginning //! of the reversed varray. //! //! @par Throws //! Nothing. //! //! @par Complexity //! Constant O(1). const_reverse_iterator crbegin() const { return const_reverse_iterator(this->end()); } //! @brief Returns reverse iterator to the one after the last element of the reversed container. //! //! @return reverse_iterator pointing to the one after the last element //! of the reversed varray. //! //! @par Throws //! Nothing. //! //! @par Complexity //! Constant O(1). reverse_iterator rend() { return reverse_iterator(this->begin()); } //! @brief Returns const reverse iterator to the one after the last element of the reversed container. //! //! @return const_reverse_iterator pointing to the one after the last element //! of the reversed varray. //! //! @par Throws //! Nothing. //! //! @par Complexity //! Constant O(1). const_reverse_iterator rend() const { return const_reverse_iterator(this->begin()); } //! @brief Returns const reverse iterator to the one after the last element of the reversed container. //! //! @return const_reverse_iterator pointing to the one after the last element //! of the reversed varray. //! //! @par Throws //! Nothing. //! //! @par Complexity //! Constant O(1). const_reverse_iterator crend() const { return const_reverse_iterator(this->begin()); } //! @brief Returns container's capacity. //! //! @return container's capacity. //! //! @par Throws //! Nothing. //! //! @par Complexity //! Constant O(1). static size_type capacity() { return Capacity; } //! @brief Returns container's capacity. //! //! @return container's capacity. //! //! @par Throws //! Nothing. //! //! @par Complexity //! Constant O(1). static size_type max_size() { return Capacity; } //! @brief Returns the number of stored elements. //! //! @return Number of elements contained in the container. //! //! @par Throws //! Nothing. //! //! @par Complexity //! Constant O(1). size_type size() const { return m_size; } //! @brief Queries if the container contains elements. //! //! @return true if the number of elements contained in the //! container is equal to 0. //! //! @par Throws //! Nothing. //! //! @par Complexity //! Constant O(1). bool empty() const { return 0 == m_size; } private: // @par Throws // Nothing. // @par Complexity // Linear O(N). template void move_ctor_dispatch(varray & other, boost::true_type /*use_memop*/) { ::memcpy(this->data(), other.data(), sizeof(Value) * other.m_size); m_size = other.m_size; } // @par Throws // @li If boost::has_nothrow_move::value is true and Value's move constructor throws // @li If boost::has_nothrow_move::value is false and Value's copy constructor throws. // @par Complexity // Linear O(N). template void move_ctor_dispatch(varray & other, boost::false_type /*use_memop*/) { namespace sv = varray_detail; sv::uninitialized_move_if_noexcept(other.begin(), other.end(), this->begin()); // may throw m_size = other.m_size; } // @par Throws // Nothing. // @par Complexity // Linear O(N). template void move_assign_dispatch(varray & other, boost::true_type /*use_memop*/) { this->clear(); ::memcpy(this->data(), other.data(), sizeof(Value) * other.m_size); std::swap(m_size, other.m_size); } // @par Throws // @li If boost::has_nothrow_move::value is true and Value's move constructor or move assignment throws // @li If boost::has_nothrow_move::value is false and Value's copy constructor or move assignment throws. // @par Complexity // Linear O(N). template void move_assign_dispatch(varray & other, boost::false_type /*use_memop*/) { namespace sv = varray_detail; if ( m_size <= static_cast(other.size()) ) { sv::move_if_noexcept(other.begin(), other.begin() + m_size, this->begin()); // may throw // TODO - perform uninitialized_copy first? sv::uninitialized_move_if_noexcept(other.begin() + m_size, other.end(), this->end()); // may throw } else { sv::move_if_noexcept(other.begin(), other.end(), this->begin()); // may throw sv::destroy(this->begin() + other.size(), this->end()); } m_size = other.size(); // update end } // @par Throws // Nothing. // @par Complexity // Linear O(N). template void swap_dispatch(varray & other, boost::true_type const& /*use_optimized_swap*/) { typedef typename boost::mpl::if_c< Capacity < C, aligned_storage_type, typename varray::aligned_storage_type >::type storage_type; storage_type temp; Value * temp_ptr = reinterpret_cast(temp.address()); ::memcpy(temp_ptr, this->data(), sizeof(Value) * this->size()); ::memcpy(this->data(), other.data(), sizeof(Value) * other.size()); ::memcpy(other.data(), temp_ptr, sizeof(Value) * this->size()); std::swap(m_size, other.m_size); } // @par Throws // If Value's move constructor or move assignment throws // but only if use_memop_in_swap_and_move is false_type - default. // @par Complexity // Linear O(N). template void swap_dispatch(varray & other, boost::false_type const& /*use_optimized_swap*/) { namespace sv = varray_detail; typedef typename vt::use_memop_in_swap_and_move use_memop_in_swap_and_move; if ( this->size() < other.size() ) swap_dispatch_impl(this->begin(), this->end(), other.begin(), other.end(), use_memop_in_swap_and_move()); // may throw else swap_dispatch_impl(other.begin(), other.end(), this->begin(), this->end(), use_memop_in_swap_and_move()); // may throw std::swap(m_size, other.m_size); } // @par Throws // Nothing. // @par Complexity // Linear O(N). void swap_dispatch_impl(iterator first_sm, iterator last_sm, iterator first_la, iterator last_la, boost::true_type const& /*use_memop*/) { //BOOST_ASSERT_MSG(std::distance(first_sm, last_sm) <= std::distance(first_la, last_la)); namespace sv = varray_detail; for (; first_sm != last_sm ; ++first_sm, ++first_la) { boost::aligned_storage< sizeof(value_type), boost::alignment_of::value > temp_storage; value_type * temp_ptr = reinterpret_cast(temp_storage.address()); ::memcpy(temp_ptr, boost::addressof(*first_sm), sizeof(value_type)); ::memcpy(boost::addressof(*first_sm), boost::addressof(*first_la), sizeof(value_type)); ::memcpy(boost::addressof(*first_la), temp_ptr, sizeof(value_type)); } ::memcpy(first_sm, first_la, sizeof(value_type) * std::distance(first_la, last_la)); } // @par Throws // If Value's move constructor or move assignment throws. // @par Complexity // Linear O(N). void swap_dispatch_impl(iterator first_sm, iterator last_sm, iterator first_la, iterator last_la, boost::false_type const& /*use_memop*/) { //BOOST_ASSERT_MSG(std::distance(first_sm, last_sm) <= std::distance(first_la, last_la)); namespace sv = varray_detail; for (; first_sm != last_sm ; ++first_sm, ++first_la) { //boost::swap(*first_sm, *first_la); // may throw value_type temp(boost::move(*first_sm)); // may throw *first_sm = boost::move(*first_la); // may throw *first_la = boost::move(temp); // may throw } sv::uninitialized_move(first_la, last_la, first_sm); // may throw sv::destroy(first_la, last_la); } // insert // @par Throws // If Value's move constructor, move assignment throws // or if Value's copy constructor or copy assignment throws. // @par Complexity // Linear O(N). template void insert_dispatch(iterator position, Iterator first, Iterator last, boost::random_access_traversal_tag const&) { BOOST_CONCEPT_ASSERT((boost_concepts::RandomAccessTraversal)); // Make sure you passed a RandomAccessIterator errh::check_iterator_end_eq(*this, position); typename boost::iterator_difference::type count = std::distance(first, last); errh::check_capacity(*this, m_size + count); // may throw if ( position == this->end() ) { namespace sv = varray_detail; sv::uninitialized_copy(first, last, position); // may throw m_size += count; // update end } else { this->insert_in_the_middle(position, first, last, count); // may throw } } // @par Throws // If Value's move constructor, move assignment throws // or if Value's copy constructor or copy assignment throws. // @par Complexity // Linear O(N). template void insert_dispatch(iterator position, Iterator first, Iterator last, Traversal const& /*not_random_access*/) { errh::check_iterator_end_eq(*this, position); if ( position == this->end() ) { namespace sv = varray_detail; std::ptrdiff_t d = std::distance(position, this->begin() + Capacity); std::size_t count = sv::uninitialized_copy_s(first, last, position, d); // may throw errh::check_capacity(*this, count <= static_cast(d) ? m_size + count : Capacity + 1); // may throw m_size += count; } else { typename boost::iterator_difference::type count = std::distance(first, last); errh::check_capacity(*this, m_size + count); // may throw this->insert_in_the_middle(position, first, last, count); // may throw } } // @par Throws // If Value's move constructor, move assignment throws // or if Value's copy constructor or copy assignment throws. // @par Complexity // Linear O(N). template void insert_in_the_middle(iterator position, Iterator first, Iterator last, difference_type count) { namespace sv = varray_detail; difference_type to_move = std::distance(position, this->end()); // TODO - should following lines check for exception and revert to the old size? if ( count < to_move ) { sv::uninitialized_move(this->end() - count, this->end(), this->end()); // may throw m_size += count; // update end sv::move_backward(position, position + to_move - count, this->end() - count); // may throw sv::copy(first, last, position); // may throw } else { Iterator middle_iter = first; std::advance(middle_iter, to_move); sv::uninitialized_copy(middle_iter, last, this->end()); // may throw m_size += count - to_move; // update end sv::uninitialized_move(position, position + to_move, position + count); // may throw m_size += to_move; // update end sv::copy(first, middle_iter, position); // may throw } } // assign // @par Throws // If Value's constructor or assignment taking dereferenced Iterator throws. // @par Complexity // Linear O(N). template void assign_dispatch(Iterator first, Iterator last, boost::random_access_traversal_tag const& /*not_random_access*/) { namespace sv = varray_detail; typename boost::iterator_difference::type s = std::distance(first, last); errh::check_capacity(*this, s); // may throw if ( m_size <= static_cast(s) ) { sv::copy(first, first + m_size, this->begin()); // may throw // TODO - perform uninitialized_copy first? sv::uninitialized_copy(first + m_size, last, this->end()); // may throw } else { sv::copy(first, last, this->begin()); // may throw sv::destroy(this->begin() + s, this->end()); } m_size = s; // update end } // @par Throws // If Value's constructor or assignment taking dereferenced Iterator throws. // @par Complexity // Linear O(N). template void assign_dispatch(Iterator first, Iterator last, Traversal const& /*not_random_access*/) { namespace sv = varray_detail; size_type s = 0; iterator it = this->begin(); for ( ; it != this->end() && first != last ; ++it, ++first, ++s ) *it = *first; // may throw sv::destroy(it, this->end()); std::ptrdiff_t d = std::distance(it, this->begin() + Capacity); std::size_t count = sv::uninitialized_copy_s(first, last, it, d); // may throw s += count; errh::check_capacity(*this, count <= static_cast(d) ? s : Capacity + 1); // may throw m_size = s; // update end } pointer ptr() { return pointer(static_cast(m_storage.address())); } const_pointer ptr() const { return const_pointer(static_cast(m_storage.address())); } size_type m_size; aligned_storage_type m_storage; }; #if !defined(BOOST_CONTAINER_DOXYGEN_INVOKED) template class varray { typedef varray_detail::varray_traits vt; typedef varray_detail::checker errh; public: typedef typename vt::value_type value_type; typedef typename vt::size_type size_type; typedef typename vt::difference_type difference_type; typedef typename vt::pointer pointer; typedef typename vt::const_pointer const_pointer; typedef typename vt::reference reference; typedef typename vt::const_reference const_reference; typedef pointer iterator; typedef const_pointer const_iterator; typedef boost::reverse_iterator reverse_iterator; typedef boost::reverse_iterator const_reverse_iterator; // nothrow varray() {} // strong explicit varray(size_type count) { errh::check_capacity(*this, count); // may throw } // strong varray(size_type count, value_type const&) { errh::check_capacity(*this, count); // may throw } // strong varray(varray const& /*other*/) { //errh::check_capacity(*this, count); } // strong template varray(varray const& other) { errh::check_capacity(*this, other.size()); // may throw } // strong template varray(Iterator first, Iterator last) { errh::check_capacity(*this, std::distance(first, last)); // may throw } // basic varray & operator=(varray const& /*other*/) { //errh::check_capacity(*this, other.size()); return *this; } // basic template varray & operator=(varray const& other) { errh::check_capacity(*this, other.size()); // may throw return *this; } // nothrow ~varray() {} // strong void resize(size_type count) { errh::check_capacity(*this, count); // may throw } // strong void resize(size_type count, value_type const&) { errh::check_capacity(*this, count); // may throw } // nothrow void reserve(size_type count) { errh::check_capacity(*this, count); // may throw } // strong void push_back(value_type const&) { errh::check_capacity(*this, 1); // may throw } // nothrow void pop_back() { errh::check_not_empty(*this); } // basic void insert(iterator position, value_type const&) { errh::check_iterator_end_eq(*this, position); errh::check_capacity(*this, 1); // may throw } // basic void insert(iterator position, size_type count, value_type const&) { errh::check_iterator_end_eq(*this, position); errh::check_capacity(*this, count); // may throw } // basic template void insert(iterator, Iterator first, Iterator last) { // TODO - add MPL_ASSERT, check if Iterator is really an iterator errh::check_capacity(*this, std::distance(first, last)); // may throw } // basic void erase(iterator position) { errh::check_iterator_end_neq(*this, position); } // basic void erase(iterator first, iterator last) { errh::check_iterator_end_eq(*this, first); errh::check_iterator_end_eq(*this, last); //BOOST_ASSERT_MSG(0 <= n, "invalid range"); } // basic template void assign(Iterator first, Iterator last) { // TODO - add MPL_ASSERT, check if Iterator is really an iterator errh::check_capacity(*this, std::distance(first, last)); // may throw } // basic void assign(size_type count, value_type const&) { errh::check_capacity(*this, count); // may throw } // nothrow void clear() {} // strong reference at(size_type i) { errh::throw_out_of_bounds(*this, i); // may throw return *(this->begin() + i); } // strong const_reference at(size_type i) const { errh::throw_out_of_bounds(*this, i); // may throw return *(this->begin() + i); } // nothrow reference operator[](size_type i) { errh::check_index(*this, i); return *(this->begin() + i); } // nothrow const_reference operator[](size_type i) const { errh::check_index(*this, i); return *(this->begin() + i); } // nothrow reference front() { errh::check_not_empty(*this); return *(this->begin()); } // nothrow const_reference front() const { errh::check_not_empty(*this); return *(this->begin()); } // nothrow reference back() { errh::check_not_empty(*this); return *(this->end() - 1); } // nothrow const_reference back() const { errh::check_not_empty(*this); return *(this->end() - 1); } // nothrow Value * data() { return boost::addressof(*(this->ptr())); } const Value * data() const { return boost::addressof(*(this->ptr())); } // nothrow iterator begin() { return this->ptr(); } const_iterator begin() const { return this->ptr(); } const_iterator cbegin() const { return this->ptr(); } iterator end() { return this->begin(); } const_iterator end() const { return this->begin(); } const_iterator cend() const { return this->cbegin(); } // nothrow reverse_iterator rbegin() { return reverse_iterator(this->end()); } const_reverse_iterator rbegin() const { return reverse_iterator(this->end()); } const_reverse_iterator crbegin() const { return reverse_iterator(this->end()); } reverse_iterator rend() { return reverse_iterator(this->begin()); } const_reverse_iterator rend() const { return reverse_iterator(this->begin()); } const_reverse_iterator crend() const { return reverse_iterator(this->begin()); } // nothrow size_type capacity() const { return 0; } size_type max_size() const { return 0; } size_type size() const { return 0; } bool empty() const { return true; } private: pointer ptr() { return pointer(reinterpret_cast(this)); } const_pointer ptr() const { return const_pointer(reinterpret_cast(this)); } }; #endif // !BOOST_CONTAINER_DOXYGEN_INVOKED //! @brief Checks if contents of two varrays are equal. //! //! @ingroup varray_non_member //! //! @param x The first varray. //! @param y The second varray. //! //! @return \c true if containers have the same size and elements in both containers are equal. //! //! @par Complexity //! Linear O(N). template bool operator== (varray const& x, varray const& y) { return x.size() == y.size() && std::equal(x.begin(), x.end(), y.begin()); } //! @brief Checks if contents of two varrays are not equal. //! //! @ingroup varray_non_member //! //! @param x The first varray. //! @param y The second varray. //! //! @return \c true if containers have different size or elements in both containers are not equal. //! //! @par Complexity //! Linear O(N). template bool operator!= (varray const& x, varray const& y) { return !(x==y); } //! @brief Lexicographically compares varrays. //! //! @ingroup varray_non_member //! //! @param x The first varray. //! @param y The second varray. //! //! @return \c true if x compares lexicographically less than y. //! //! @par Complexity //! Linear O(N). template bool operator< (varray const& x, varray const& y) { return std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()); } //! @brief Lexicographically compares varrays. //! //! @ingroup varray_non_member //! //! @param x The first varray. //! @param y The second varray. //! //! @return \c true if y compares lexicographically less than x. //! //! @par Complexity //! Linear O(N). template bool operator> (varray const& x, varray const& y) { return y bool operator<= (varray const& x, varray const& y) { return !(y bool operator>= (varray const& x, varray const& y) { return !(x inline void swap(varray & x, varray & y) { x.swap(y); } }}}} // namespace boost::geometry::index::detail // TODO - REMOVE/CHANGE #include #endif // BOOST_GEOMETRY_INDEX_DETAIL_VARRAY_HPP