// file : odb/vector.hxx // copyright : Copyright (c) 2009-2019 Code Synthesis Tools CC // license : GNU GPL v2; see accompanying LICENSE file #ifndef ODB_VECTOR_HXX #define ODB_VECTOR_HXX #include #include // ODB_CXX11 #include #include #include // std::ptrdiff_t #ifdef ODB_CXX11 # include // std::move, std::forward # ifdef ODB_CXX11_INITIALIZER_LIST # include # endif #endif #include // Because both std::vector and odb::vector are called 'vector' (who // cares about namespace qualifications, right?), Sun CC complains // with a bogus "Ambiguous partial specialization" error. A really // hideous workaround for this bug is to to add a dummy third template // argument (with a default value). // #ifdef __SUNPRO_CC # define LIBODB_VECTOR_ARG_DEFAULT ,int = 0 # define LIBODB_VECTOR_ARG_DECL ,int DUMMY # define LIBODB_VECTOR_ARG_USE ,DUMMY #else # define LIBODB_VECTOR_ARG_DEFAULT # define LIBODB_VECTOR_ARG_DECL # define LIBODB_VECTOR_ARG_USE #endif namespace odb { // An std::vector-like container that keeps track of changes. // // Note that the style and order of definitions is as appears // in the standard. // template class vector_iterator; template LIBODB_VECTOR_ARG_DEFAULT> class vector: public vector_base { public: typedef std::vector base_vector_type; typedef typename base_vector_type::iterator base_iterator_type; typedef typename base_vector_type::reverse_iterator base_reverse_iterator_type; // types: // typedef typename base_vector_type::reference reference; typedef typename base_vector_type::const_reference const_reference; typedef vector_iterator iterator; typedef typename base_vector_type::const_iterator const_iterator; typedef typename base_vector_type::size_type size_type; typedef typename base_vector_type::difference_type difference_type; typedef T value_type; typedef A allocator_type; typedef typename base_vector_type::pointer pointer; typedef typename base_vector_type::const_pointer const_pointer; // No non-const reverse iterator support for Sun CC with non-standard STL. // #ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC typedef vector_iterator reverse_iterator; #endif typedef typename base_vector_type::const_reverse_iterator const_reverse_iterator; // construct/copy/destroy: // explicit vector(const A& a = A()): v_ (a) {} explicit vector(size_type n): v_ (n) {} // C++11 vector(size_type n, const T& v, const A& a = A()): v_ (n, v, a) {} template vector(I f, I l, const A& a = A()) : v_ (f, l, a) {} vector(const vector& x): vector_base (x), v_ (x.v_) {} // ~vector() {} vector& operator=(const vector&); template void assign(I f, I l); void assign(size_type n, const T& u); allocator_type get_allocator() const /*noexcept*/ {return v_.get_allocator ();} #ifdef ODB_CXX11 vector(vector&& x): vector_base (std::move (x)), v_ (std::move (x.v_)) {} vector(const vector& x, const A& a): vector_base (x), v_ (x.v_, a) {} vector(vector&& x, const A& a) : vector_base (std::move (x)), v_ (std::move (x.v_), a) {} vector& operator=(vector&&); #ifdef ODB_CXX11_INITIALIZER_LIST vector(std::initializer_list il, const A& a = A()): v_ (il, a) {} vector& operator=(std::initializer_list); void assign(std::initializer_list); #endif #endif // iterators: (all /*noexcept*/) // iterator begin() {return iterator (this, v_.begin ());} iterator end() {return iterator (this, v_.end ());} const_iterator begin() const {return v_.begin ();} const_iterator end() const {return v_.end ();} #ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC reverse_iterator rbegin() {return reverse_iterator (this, v_.rbegin ());} reverse_iterator rend() {return reverse_iterator (this, v_.rend ());} #endif const_reverse_iterator rbegin() const {return v_.rbegin ();} const_reverse_iterator rend() const {return v_.rend ();} // Return standard vector iterators. The begin() functions mark all // the elements as modified. // base_iterator_type mbegin (); base_iterator_type mend () {return v_.end ();} base_reverse_iterator_type mrbegin (); base_reverse_iterator_type mrend () {return v_.rend ();} #ifdef ODB_CXX11 const_iterator cbegin() const {return v_.cbegin ();} const_iterator cend() const {return v_.cend ();} const_reverse_iterator crbegin() const {return v_.crbegin ();} const_reverse_iterator crend() const {return v_.crend ();} #endif // capacity: // size_type size() const /*noexcept*/ {return v_.size ();} size_type max_size() const /*noexcept*/ {return v_.max_size ();} void resize(size_type); // C++11 void resize(size_type, const T&); size_type capacity() const /*noexcept*/ {return v_.capacity ();} bool empty() const /*noexcept*/ {return v_.empty ();} void reserve(size_type); #ifdef ODB_CXX11 void shrink_to_fit(); #endif // element access: // //reference operator[](size_type n); reference modify(size_type n); const_reference operator[](size_type n) const {return v_[n];} //reference at(size_type n); reference modify_at(size_type n); const_reference at(size_type n) const {return v_.at (n);} //reference front(); reference modify_front(); const_reference front() const {return v_.front ();} //reference back(); reference modify_back(); const_reference back() const {return v_.back ();} // data access: // #ifdef ODB_CXX11 //T* data() noexcept; T* modify_data() /*noexcept*/; const T* data() const /*noexcept*/ {return v_.data ();} #endif // modifiers: // void push_back(const T& x); void pop_back(); iterator insert(iterator position, const T& x); void insert(iterator position, size_type n, const T& x); template void insert(iterator position, I first, I last); iterator erase(iterator position); iterator erase(iterator first, iterator last); void swap(vector&); void clear() /*noexcept*/; #ifdef ODB_CXX11 // In C++11 all modifiers use const_iterator instead of iterator // to represent position. However, some standard libraries (notably // GCC's) still use iterator and so we will do that as well, for now. // void push_back(T&& x); iterator insert(iterator position, T&& x); #ifdef ODB_CXX11_VARIADIC_TEMPLATE template void emplace_back(Args&&... args); template iterator emplace(iterator position, Args&&... args); #endif #endif // Interfacing with the base vector. // vector (const base_vector_type& x): v_ (x) {} vector& operator= (const base_vector_type&); operator const base_vector_type& () const {return v_;} base_vector_type& base () {return v_;} const base_vector_type& base () const {return v_;} #ifdef ODB_CXX11 vector (base_vector_type&& x): v_ (std::move (x)) {} vector& operator= (base_vector_type&&); #endif // Change tracking (the rest comes from vector_base). // public: void _start () const {impl_.start (v_.size ());} private: base_vector_type v_; }; namespace core { using odb::vector; } template inline bool operator==(const vector& x, const vector& y) {return x.base () == y.base ();} template inline bool operator==(const vector& x, const std::vector& y) {return x.base () == y;} template inline bool operator==(const std::vector& x, const vector& y) {return x == y.base ();} template inline bool operator< (const vector& x, const vector& y) {return x.base () < y.base ();} template inline bool operator<(const vector& x, const std::vector& y) {return x.base () < y;} template inline bool operator<(const std::vector& x, const vector& y) {return x < y.base ();} template inline bool operator!=(const vector& x, const vector& y) {return x.base () != y.base ();} template inline bool operator!=(const vector& x, const std::vector& y) {return x.base () != y;} template inline bool operator!=(const std::vector& x, const vector& y) {return x != y.base ();} template inline bool operator> (const vector& x, const vector& y) {return x.base () > y.base ();} template inline bool operator>=(const vector& x, const vector& y) {return x.base () >= y.base ();} template inline bool operator>=(const vector& x, const std::vector& y) {return x.base () >= y;} template inline bool operator>=(const std::vector& x, const vector& y) {return x >= y.base ();} template inline bool operator<=(const vector& x, const vector& y) {return x.base () <= y.base ();} template inline bool operator<=(const vector& x, const std::vector& y) {return x.base () <= y;} template inline bool operator<=(const std::vector& x, const vector& y) {return x <= y.base ();} template class vector_iterator { public: typedef V vector_type; typedef I base_iterator_type; typedef typename vector_type::const_iterator const_iterator_type; // Sun CC with non-standard STL does not have iterator_traits. // #ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC typedef std::iterator_traits base_iterator_traits; typedef typename base_iterator_traits::value_type value_type; typedef typename base_iterator_traits::difference_type difference_type; typedef typename base_iterator_traits::pointer pointer; typedef typename base_iterator_traits::reference reference; typedef typename base_iterator_traits::iterator_category iterator_category; #else // Base iterator is just a pointer. // typedef typename vector_type::value_type value_type; typedef typename vector_type::pointer pointer; typedef typename vector_type::reference reference; typedef std::random_access_iterator_tag iterator_category; typedef std::ptrdiff_t difference_type; #endif typedef typename vector_type::size_type size_type; typedef typename vector_type::const_reference const_reference; typedef typename vector_type::const_pointer const_pointer; vector_iterator (): v_ (0), i_ () {} vector_iterator (vector_type* v, const base_iterator_type& i) : v_ (v), i_ (i) {} operator const_iterator_type () const {return i_;} base_iterator_type base () const {return i_;} vector_type* vector () const {return v_;} // Note: const_{reference,pointer}. // const_reference operator* () const {return *i_;} const_pointer operator-> () const {return i_.operator -> ();} const_reference operator[] (difference_type n) const {return i_[n];} // Modifiers. // // Buggy Sun CC cannot have them out of class. // reference modify () const { if (v_->_tracking ()) v_->_impl ().modify ( static_cast (i_ - v_->base ().begin ())); return *i_; } reference modify (difference_type n) const { if (v_->_tracking ()) v_->_impl ().modify ( static_cast (i_ - v_->base ().begin () + n)); return i_[n]; } vector_iterator& operator++ () {++i_; return *this;} vector_iterator operator++ (int) {return vector_iterator (v_, i_++);} vector_iterator& operator-- () {--i_; return *this;} vector_iterator operator-- (int) {return vector_iterator (v_, i_--);} vector_iterator operator+ (difference_type n) const {return vector_iterator (v_, i_ + n);} vector_iterator& operator+= (difference_type n) {i_ += n; return *this;} vector_iterator operator- (difference_type n) const {return vector_iterator (v_, i_ - n);} vector_iterator& operator-= (difference_type n) {i_ -= n; return *this;} // Implementation details. // public: base_iterator_type _base () const {return i_;} // Same as base (). private: vector_type* v_; base_iterator_type i_; }; #ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC template class vector_iterator > { public: typedef V vector_type; typedef std::reverse_iterator base_iterator_type; typedef typename vector_type::const_reverse_iterator const_iterator_type; typedef std::iterator_traits base_iterator_traits; typedef typename vector_type::iterator iterator_type; typedef typename base_iterator_traits::value_type value_type; typedef typename base_iterator_traits::difference_type difference_type; typedef typename base_iterator_traits::pointer pointer; typedef typename base_iterator_traits::reference reference; typedef typename base_iterator_traits::iterator_category iterator_category; typedef typename vector_type::size_type size_type; typedef typename vector_type::const_reference const_reference; typedef typename vector_type::const_pointer const_pointer; vector_iterator (): v_ (0), i_ () {} explicit vector_iterator (const iterator_type& i) : v_ (i.vector ()), i_ (i.base ()) {} vector_iterator (vector_type* v, const base_iterator_type& i) : v_ (v), i_ (i) {} operator const_iterator_type () const {return i_;} iterator_type base () const {return iterator_type (v_, i_.base ());} base_iterator_type rbase () const {return i_;} vector_type* vector () const {return v_;} // Note: const_{reference,pointer}. // const_reference operator* () const {return *i_;} const_pointer operator-> () const {return i_.operator -> ();} const_reference operator[] (difference_type n) const {return i_[n];} // Modifiers. // reference modify () const { if (v_->_tracking ()) v_->_impl ().modify ( static_cast (v_->base ().rend () - i_ - 1)); return *i_; } reference modify (difference_type n) const { if (v_->_tracking ()) // Note: going in the opposite direction. v_->_impl ().modify ( static_cast (v_->base ().rend () - i_ - 1 - n)); return i_[n]; } vector_iterator& operator++ () {++i_; return *this;} vector_iterator operator++ (int) {return vector_iterator (v_, i_++);} vector_iterator& operator-- () {--i_; return *this;} vector_iterator operator-- (int) {return vector_iterator (v_, i_--);} vector_iterator operator+ (difference_type n) const {return vector_iterator (v_, i_ + n);} vector_iterator& operator+= (difference_type n) {i_ += n; return *this;} vector_iterator operator- (difference_type n) const {return vector_iterator (v_, i_ - n);} vector_iterator& operator-= (difference_type n) {i_ -= n; return *this;} // Implementation details. // public: base_iterator_type _base () const {return i_;} // Same as rbase(). private: vector_type* v_; base_iterator_type i_; }; #endif // _RWSTD_NO_CLASS_PARTIAL_SPEC // operator== // template inline bool operator== (const vector_iterator& x, const vector_iterator& y) {return x._base () == y._base ();} template inline bool operator== (const vector_iterator& x, const typename vector_iterator::const_iterator_type& y) {return x._base () == y;} template inline bool operator== (const typename vector_iterator::const_iterator_type& x, const vector_iterator& y) {return x == y._base ();} // operator< // template inline bool operator< (const vector_iterator& x, const vector_iterator& y) {return x._base () < y._base ();} template inline bool operator< (const vector_iterator& x, const typename vector_iterator::const_iterator_type& y) {return x._base () < y;} template inline bool operator< (const typename vector_iterator::const_iterator_type& x, const vector_iterator& y) {return x < y._base ();} // operator!= // template inline bool operator!= (const vector_iterator& x, const vector_iterator& y) {return x._base () != y._base ();} template inline bool operator!= (const vector_iterator& x, const typename vector_iterator::const_iterator_type& y) {return x._base () != y;} template inline bool operator!= (const typename vector_iterator::const_iterator_type& x, const vector_iterator& y) {return x != y._base ();} // operator> // template inline bool operator> (const vector_iterator& x, const vector_iterator& y) {return x._base () > y._base ();} template inline bool operator> (const vector_iterator& x, const typename vector_iterator::const_iterator_type& y) {return x._base () > y;} template inline bool operator> (const typename vector_iterator::const_iterator_type& x, const vector_iterator& y) {return x > y._base ();} // operator>= // template inline bool operator>= (const vector_iterator& x, const vector_iterator& y) {return x._base () >= y._base ();} template inline bool operator>= (const vector_iterator& x, const typename vector_iterator::const_iterator_type& y) {return x._base () >= y;} template inline bool operator>= (const typename vector_iterator::const_iterator_type& x, const vector_iterator& y) {return x >= y._base ();} // operator<= // template inline bool operator<= (const vector_iterator& x, const vector_iterator& y) {return x._base () <= y._base ();} template inline bool operator<= (const vector_iterator& x, const typename vector_iterator::const_iterator_type& y) {return x._base () <= y;} template inline bool operator<= (const typename vector_iterator::const_iterator_type& x, const vector_iterator& y) {return x <= y._base ();} // operator- // template inline typename vector_iterator::difference_type operator-(const vector_iterator& x, const vector_iterator& y) {return x._base () - y._base ();} template inline typename vector_iterator::difference_type operator-(const vector_iterator& x, const typename vector_iterator::const_iterator_type& y) {return x._base () - y;} template inline typename vector_iterator::difference_type operator-(const typename vector_iterator::const_iterator_type& x, const vector_iterator& y) {return x - y._base ();} // operator+ // template inline vector_iterator operator+(typename vector_iterator::difference_type n, const vector_iterator& x) {return vector_iterator (x.vector (), n + x._base ());} } namespace std { template inline void swap(odb::vector& x, odb::vector& y) {x.swap (y);} } #include #include #include #endif // ODB_VECTOR_HXX