diff options
author | Boris Kolpackov <boris@codesynthesis.com> | 2013-02-05 15:50:06 +0200 |
---|---|---|
committer | Boris Kolpackov <boris@codesynthesis.com> | 2013-02-05 15:50:06 +0200 |
commit | 2b856f69d490f6cedffac03ecbed8fef318ecc43 (patch) | |
tree | 0876ef0d3539bb313a9dd66659e805e6980399aa /odb/vector.hxx | |
parent | 20daa3c4285c91dfcd35361f6550f80315e008a5 (diff) |
Add support for change-tracking containers
ODB now supports "smart" ordered containers. Such containers get extra
functions for updating and deleting individual elements. Based on this
functionality implement two change-tracking containers: odb::vector
(equivalent to std::vector) and QOdbList (equivalent to QList). New
tests: common/container/change-tracking and qt/common/container/change-
tracking.
Diffstat (limited to 'odb/vector.hxx')
-rw-r--r-- | odb/vector.hxx | 546 |
1 files changed, 546 insertions, 0 deletions
diff --git a/odb/vector.hxx b/odb/vector.hxx new file mode 100644 index 0000000..17f8653 --- /dev/null +++ b/odb/vector.hxx @@ -0,0 +1,546 @@ +// file : odb/vector.hxx +// copyright : Copyright (c) 2009-2012 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_VECTOR_HXX +#define ODB_VECTOR_HXX + +#include <odb/pre.hxx> +#include <odb/details/config.hxx> // ODB_CXX11 + +#include <vector> +#include <iterator> + +#ifdef ODB_CXX11 +# include <utility> // std::move, std::forward +# ifdef ODB_CXX11_INITIALIZER_LIST +# include <initializer_list> +# endif +#endif + +#include <odb/vector-impl.hxx> + +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 V, class I> + class vector_iterator; + + template <class T, class A = std::allocator<T> > + class vector: public vector_base + { + public: + typedef std::vector<T, A> 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<vector, base_iterator_type> 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; + typedef vector_iterator<vector, base_reverse_iterator_type> + reverse_iterator; + 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 <class I> + 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 <class I> + 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<T> il, const A& a = A()): v_ (il, a) {} + vector& operator=(std::initializer_list<T>); + void assign(std::initializer_list<T>); +#endif +#endif + + // iterators: (all /*noexcept*/) + // + iterator begin() {return iterator (this, v_.begin ());} + const_iterator begin() const {return v_.begin ();} + iterator end() {return iterator (this, v_.end ());} + const_iterator end() const {return v_.end ();} + reverse_iterator rbegin() {return reverse_iterator (this, v_.rbegin ());} + const_reverse_iterator rbegin() const {return v_.rbegin ();} + reverse_iterator rend() {return reverse_iterator (this, v_.rend ());} + 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 <class I> + 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 <class... Args> + void emplace_back(Args&&... args); + template <class... Args> + 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 <class T, class A> + inline bool operator==(const vector<T,A>& x, const vector<T,A>& y) + {return x.base () == y.base ();} + + template <class T, class A> + inline bool operator==(const vector<T,A>& x, const std::vector<T,A>& y) + {return x.base () == y;} + + template <class T, class A> + inline bool operator==(const std::vector<T,A>& x, const vector<T,A>& y) + {return x == y.base ();} + + template <class T, class A> + inline bool operator< (const vector<T,A>& x, const vector<T,A>& y) + {return x.base () < y.base ();} + + template <class T, class A> + inline bool operator<(const vector<T,A>& x, const std::vector<T,A>& y) + {return x.base () < y;} + + template <class T, class A> + inline bool operator<(const std::vector<T,A>& x, const vector<T,A>& y) + {return x < y.base ();} + + template <class T, class A> + inline bool operator!=(const vector<T,A>& x, const vector<T,A>& y) + {return x.base () != y.base ();} + + template <class T, class A> + inline bool operator!=(const vector<T,A>& x, const std::vector<T,A>& y) + {return x.base () != y;} + + template <class T, class A> + inline bool operator!=(const std::vector<T,A>& x, const vector<T,A>& y) + {return x != y.base ();} + + template <class T, class A> + inline bool operator> (const vector<T,A>& x, const vector<T,A>& y) + {return x.base () > y.base ();} + + template <class T, class A> + inline bool operator>=(const vector<T,A>& x, const vector<T,A>& y) + {return x.base () >= y.base ();} + + template <class T, class A> + inline bool operator>=(const vector<T,A>& x, const std::vector<T,A>& y) + {return x.base () >= y;} + + template <class T, class A> + inline bool operator>=(const std::vector<T,A>& x, const vector<T,A>& y) + {return x >= y.base ();} + + template <class T, class A> + inline bool operator<=(const vector<T,A>& x, const vector<T,A>& y) + {return x.base () <= y.base ();} + + template <class T, class A> + inline bool operator<=(const vector<T,A>& x, const std::vector<T,A>& y) + {return x.base () <= y;} + + template <class T, class A> + inline bool operator<=(const std::vector<T,A>& x, const vector<T,A>& y) + {return x <= y.base ();} + + template <class V, class I> + class vector_iterator + { + public: + typedef V vector_type; + typedef I base_iterator_type; + typedef typename vector_type::const_iterator const_iterator_type; + typedef std::iterator_traits<base_iterator_type> 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; + + 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. + // + reference modify () const; + reference modify (difference_type n) const; + + 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_; + }; + + template <class V, class J> + class vector_iterator<V, std::reverse_iterator<J> > + { + public: + typedef V vector_type; + typedef std::reverse_iterator<J> base_iterator_type; + typedef typename vector_type::const_reverse_iterator const_iterator_type; + typedef std::iterator_traits<base_iterator_type> 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; + reference modify (difference_type n) const; + + 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_; + }; + + // operator== + // + template <class V, class I> + inline bool + operator== (const vector_iterator<V, I>& x, const vector_iterator<V, I>& y) + {return x._base () == y._base ();} + + template <class V, class I> + inline bool + operator== (const vector_iterator<V, I>& x, + const typename vector_iterator<V, I>::const_iterator_type& y) + {return x._base () == y;} + + template <class V, class I> + inline bool + operator== (const typename vector_iterator<V, I>::const_iterator_type& x, + const vector_iterator<V, I>& y) + {return x == y._base ();} + + // operator< + // + template <class V, class I> + inline bool + operator< (const vector_iterator<V, I>& x, const vector_iterator<V, I>& y) + {return x._base () < y._base ();} + + template <class V, class I> + inline bool + operator< (const vector_iterator<V, I>& x, + const typename vector_iterator<V, I>::const_iterator_type& y) + {return x._base () < y;} + + template <class V, class I> + inline bool + operator< (const typename vector_iterator<V, I>::const_iterator_type& x, + const vector_iterator<V, I>& y) + {return x < y._base ();} + + // operator!= + // + template <class V, class I> + inline bool + operator!= (const vector_iterator<V, I>& x, const vector_iterator<V, I>& y) + {return x._base () != y._base ();} + + template <class V, class I> + inline bool + operator!= (const vector_iterator<V, I>& x, + const typename vector_iterator<V, I>::const_iterator_type& y) + {return x._base () != y;} + + template <class V, class I> + inline bool + operator!= (const typename vector_iterator<V, I>::const_iterator_type& x, + const vector_iterator<V, I>& y) + {return x != y._base ();} + + // operator> + // + template <class V, class I> + inline bool + operator> (const vector_iterator<V, I>& x, const vector_iterator<V, I>& y) + {return x._base () > y._base ();} + + template <class V, class I> + inline bool + operator> (const vector_iterator<V, I>& x, + const typename vector_iterator<V, I>::const_iterator_type& y) + {return x._base () > y;} + + template <class V, class I> + inline bool + operator> (const typename vector_iterator<V, I>::const_iterator_type& x, + const vector_iterator<V, I>& y) + {return x > y._base ();} + + // operator>= + // + template <class V, class I> + inline bool + operator>= (const vector_iterator<V, I>& x, const vector_iterator<V, I>& y) + {return x._base () >= y._base ();} + + template <class V, class I> + inline bool + operator>= (const vector_iterator<V, I>& x, + const typename vector_iterator<V, I>::const_iterator_type& y) + {return x._base () >= y;} + + template <class V, class I> + inline bool + operator>= (const typename vector_iterator<V, I>::const_iterator_type& x, + const vector_iterator<V, I>& y) + {return x >= y._base ();} + + // operator<= + // + template <class V, class I> + inline bool + operator<= (const vector_iterator<V, I>& x, const vector_iterator<V, I>& y) + {return x._base () <= y._base ();} + + template <class V, class I> + inline bool + operator<= (const vector_iterator<V, I>& x, + const typename vector_iterator<V, I>::const_iterator_type& y) + {return x._base () <= y;} + + template <class V, class I> + inline bool + operator<= (const typename vector_iterator<V, I>::const_iterator_type& x, + const vector_iterator<V, I>& y) + {return x <= y._base ();} + + // operator- + // + template <class V, class I> + inline typename vector_iterator<V, I>::difference_type + operator-(const vector_iterator<V, I>& x, const vector_iterator<V, I>& y) + {return x._base () - y._base ();} + + template <class V, class I> + inline typename vector_iterator<V, I>::difference_type + operator-(const vector_iterator<V, I>& x, + const typename vector_iterator<V, I>::const_iterator_type& y) + {return x._base () - y;} + + template <class V, class I> + inline typename vector_iterator<V, I>::difference_type + operator-(const typename vector_iterator<V, I>::const_iterator_type& x, + const vector_iterator<V, I>& y) + {return x - y._base ();} + + // operator+ + // + template <class V, class I> + inline vector_iterator<V, I> + operator+(typename vector_iterator<V, I>::difference_type n, + const vector_iterator<V, I>& x) + {return vector_iterator<V, I> (x.vector (), n + x._base ());} +} + +namespace std +{ + template <class T, class A> + inline void swap(odb::vector<T,A>& x, odb::vector<T,A>& y) {x.swap (y);} +} + +#include <odb/vector.ixx> + +#include <odb/vector-traits.hxx> + +#include <odb/post.hxx> + +#endif // ODB_VECTOR_HXX |