2 // Copyright (c) 2000-2010
3 // Joerg Walter, Mathias Koch, David Bellot
4 // Copyright (c) 2014, Athanasios Iliopoulos
6 // Distributed under the Boost Software License, Version 1.0. (See
7 // accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
10 // The authors gratefully acknowledge the support of
11 // GeNeSys mbH & Co. KG in producing this work.
13 // And we acknowledge the support from all contributors.
15 /// \file vector.hpp Definition for the class vector and its derivative
17 #ifndef _BOOST_UBLAS_VECTOR_
18 #define _BOOST_UBLAS_VECTOR_
20 #include <boost/config.hpp>
21 #include <boost/numeric/ublas/storage.hpp>
22 #include <boost/numeric/ublas/vector_expression.hpp>
23 #include <boost/numeric/ublas/detail/vector_assign.hpp>
24 #include <boost/serialization/collection_size_type.hpp>
25 #include <boost/serialization/nvp.hpp>
27 #ifdef BOOST_UBLAS_CPP_GE_2011
29 #include <initializer_list>
30 #if defined(BOOST_MSVC) // For std::forward in fixed_vector
35 // Iterators based on ideas of Jeremy Siek
37 namespace boost { namespace numeric { namespace ublas {
39 /** \brief A dense vector of values of type \c T.
41 * For a \f$n\f$-dimensional vector \f$v\f$ and \f$0\leq i < n\f$ every element \f$v_i\f$ is mapped
42 * to the \f$i\f$-th element of the container. A storage type \c A can be specified which defaults to \c unbounded_array.
43 * Elements are constructed by \c A, which need not initialise their value.
45 * \tparam T type of the objects stored in the vector (like int, double, complex,...)
46 * \tparam A The type of the storage array of the vector. Default is \c unbounded_array<T>. \c <bounded_array<T> and \c std::vector<T> can also be used
48 template<class T, class A>
50 public vector_container<vector<T, A> > {
52 typedef vector<T, A> self_type;
54 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
55 using vector_container<self_type>::operator ();
58 typedef typename A::size_type size_type;
59 typedef typename A::difference_type difference_type;
61 typedef typename type_traits<T>::const_reference const_reference;
64 typedef const T *const_pointer;
66 typedef const vector_reference<const self_type> const_closure_type;
67 typedef vector_reference<self_type> closure_type;
68 typedef self_type vector_temporary_type;
69 typedef dense_tag storage_category;
71 // Construction and destruction
73 /// \brief Constructor of a vector
74 /// By default it is empty, i.e. \c size()==0.
77 vector_container<self_type> (),
80 /// \brief Constructor of a vector with a predefined size
81 /// By default, its elements are initialized to 0.
82 /// \param size initial size of the vector
83 explicit BOOST_UBLAS_INLINE
84 vector (size_type size):
85 vector_container<self_type> (),
89 /// \brief Constructor of a vector by copying from another container
90 /// This type has the generic name \c array_typ within the vector definition.
91 /// \param size initial size of the vector \bug this value is not used
92 /// \param data container of type \c A
93 /// \todo remove this definition because \c size is not used
95 vector (size_type /*size*/, const array_type &data):
96 vector_container<self_type> (),
99 /// \brief Constructor of a vector by copying from another container
100 /// This type has the generic name \c array_typ within the vector definition.
101 /// \param data container of type \c A
103 vector (const array_type &data):
104 vector_container<self_type> (),
107 /// \brief Constructor of a vector with a predefined size and a unique initial value
108 /// \param size of the vector
109 /// \param init value to assign to each element of the vector
111 vector (size_type size, const value_type &init):
112 vector_container<self_type> (),
113 data_ (size, init) {}
115 /// \brief Copy-constructor of a vector
116 /// \param v is the vector to be duplicated
118 vector (const vector &v):
119 vector_container<self_type> (),
122 /// \brief Copy-constructor of a vector from a vector_expression
123 /// Depending on the vector_expression, this constructor can have the cost of the computations
124 /// of the expression (trivial to say it, but it is to take into account in your complexity calculations).
125 /// \param ae the vector_expression which values will be duplicated into the vector
128 vector (const vector_expression<AE> &ae):
129 vector_container<self_type> (),
130 data_ (ae ().size ()) {
131 vector_assign<scalar_assign> (*this, ae);
134 // -----------------------
135 // Random Access Container
136 // -----------------------
138 /// \brief Return the maximum size of the data container.
139 /// Return the upper bound (maximum size) on the data container. Depending on the container, it can be bigger than the current size of the vector.
141 size_type max_size () const {
142 return data_.max_size ();
145 /// \brief Return true if the vector is empty (\c size==0)
146 /// \return \c true if empty, \c false otherwise
148 bool empty () const {
149 return data_.size () == 0;
156 /// \brief Return the size of the vector
158 size_type size () const {
159 return data_.size ();
166 /// \brief Return a \c const reference to the container. Useful to access data directly for specific type of container.
168 const array_type &data () const {
172 /// \brief Return a reference to the container. Useful to speed-up write operations to the data in very specific case.
174 array_type &data () {
182 /// \brief Resize the vector
183 /// Resize the vector to a new size. If \c preserve is true, data are copied otherwise data are lost. If the new size is bigger, the remaining values are filled in with the initial value (0 by default) in the case of \c unbounded_array, which is the container by default. If the new size is smaller, last values are lost. This behaviour can be different if you explicitely specify another type of container.
184 /// \param size new size of the vector
185 /// \param preserve if true, keep values
187 void resize (size_type size, bool preserve = true) {
189 data ().resize (size, typename A::value_type ());
191 data ().resize (size);
198 /// \brief Return a pointer to the element \f$i\f$
199 /// \param i index of the element
200 // XXX this semantic is not the one expected by the name of this method
202 pointer find_element (size_type i) {
203 return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i));
206 /// \brief Return a const pointer to the element \f$i\f$
207 /// \param i index of the element
208 // XXX this semantic is not the one expected by the name of this method
210 const_pointer find_element (size_type i) const {
211 return & (data () [i]);
218 /// \brief Return a const reference to the element \f$i\f$
219 /// Return a const reference to the element \f$i\f$. With some compilers, this notation will be faster than \c[i]
220 /// \param i index of the element
222 const_reference operator () (size_type i) const {
226 /// \brief Return a reference to the element \f$i\f$
227 /// Return a reference to the element \f$i\f$. With some compilers, this notation will be faster than \c[i]
228 /// \param i index of the element
230 reference operator () (size_type i) {
234 /// \brief Return a const reference to the element \f$i\f$
235 /// \param i index of the element
237 const_reference operator [] (size_type i) const {
241 /// \brief Return a reference to the element \f$i\f$
242 /// \param i index of the element
244 reference operator [] (size_type i) {
248 // ------------------
249 // Element assignment
250 // ------------------
252 /// \brief Set element \f$i\f$ to the value \c t
253 /// \param i index of the element
254 /// \param t reference to the value to be set
255 // XXX semantic of this is to insert a new element and therefore size=size+1 ?
257 reference insert_element (size_type i, const_reference t) {
258 return (data () [i] = t);
261 /// \brief Set element \f$i\f$ to the \e zero value
262 /// \param i index of the element
264 void erase_element (size_type i) {
265 data () [i] = value_type/*zero*/();
272 /// \brief Clear the vector, i.e. set all values to the \c zero value.
275 std::fill (data ().begin (), data ().end (), value_type/*zero*/());
279 #ifdef BOOST_UBLAS_MOVE_SEMANTICS
281 /// \brief Assign a full vector (\e RHS-vector) to the current vector (\e LHS-vector)
282 /// \param v is the source vector
283 /// \return a reference to a vector (i.e. the destination vector)
284 /*! @note "pass by value" the key idea to enable move semantics */
286 vector &operator = (vector v) {
291 /// \brief Assign a full vector (\e RHS-vector) to the current vector (\e LHS-vector)
292 /// \param v is the source vector
293 /// \return a reference to a vector (i.e. the destination vector)
295 vector &operator = (const vector &v) {
301 /// \brief Assign a full vector (\e RHS-vector) to the current vector (\e LHS-vector)
302 /// Assign a full vector (\e RHS-vector) to the current vector (\e LHS-vector). This method does not create any temporary.
303 /// \param v is the source vector container
304 /// \return a reference to a vector (i.e. the destination vector)
305 template<class C> // Container assignment without temporary
307 vector &operator = (const vector_container<C> &v) {
308 resize (v ().size (), false);
313 /// \brief Assign a full vector (\e RHS-vector) to the current vector (\e LHS-vector)
314 /// \param v is the source vector
315 /// \return a reference to a vector (i.e. the destination vector)
317 vector &assign_temporary (vector &v) {
322 /// \brief Assign the result of a vector_expression to the vector
323 /// Assign the result of a vector_expression to the vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
324 /// \tparam AE is the type of the vector_expression
325 /// \param ae is a const reference to the vector_expression
326 /// \return a reference to the resulting vector
329 vector &operator = (const vector_expression<AE> &ae) {
330 self_type temporary (ae);
331 return assign_temporary (temporary);
334 /// \brief Assign the result of a vector_expression to the vector
335 /// Assign the result of a vector_expression to the vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
336 /// \tparam AE is the type of the vector_expression
337 /// \param ae is a const reference to the vector_expression
338 /// \return a reference to the resulting vector
341 vector &assign (const vector_expression<AE> &ae) {
342 vector_assign<scalar_assign> (*this, ae);
346 // -------------------
347 // Computed assignment
348 // -------------------
350 /// \brief Assign the sum of the vector and a vector_expression to the vector
351 /// Assign the sum of the vector and a vector_expression to the vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
352 /// A temporary is created for the computations.
353 /// \tparam AE is the type of the vector_expression
354 /// \param ae is a const reference to the vector_expression
355 /// \return a reference to the resulting vector
358 vector &operator += (const vector_expression<AE> &ae) {
359 self_type temporary (*this + ae);
360 return assign_temporary (temporary);
363 /// \brief Assign the sum of the vector and a vector_expression to the vector
364 /// Assign the sum of the vector and a vector_expression to the vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
365 /// No temporary is created. Computations are done and stored directly into the resulting vector.
366 /// \tparam AE is the type of the vector_expression
367 /// \param ae is a const reference to the vector_expression
368 /// \return a reference to the resulting vector
369 template<class C> // Container assignment without temporary
371 vector &operator += (const vector_container<C> &v) {
376 /// \brief Assign the sum of the vector and a vector_expression to the vector
377 /// Assign the sum of the vector and a vector_expression to the vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
378 /// No temporary is created. Computations are done and stored directly into the resulting vector.
379 /// \tparam AE is the type of the vector_expression
380 /// \param ae is a const reference to the vector_expression
381 /// \return a reference to the resulting vector
384 vector &plus_assign (const vector_expression<AE> &ae) {
385 vector_assign<scalar_plus_assign> (*this, ae);
389 /// \brief Assign the difference of the vector and a vector_expression to the vector
390 /// Assign the difference of the vector and a vector_expression to the vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
391 /// A temporary is created for the computations.
392 /// \tparam AE is the type of the vector_expression
393 /// \param ae is a const reference to the vector_expression
396 vector &operator -= (const vector_expression<AE> &ae) {
397 self_type temporary (*this - ae);
398 return assign_temporary (temporary);
401 /// \brief Assign the difference of the vector and a vector_expression to the vector
402 /// Assign the difference of the vector and a vector_expression to the vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
403 /// No temporary is created. Computations are done and stored directly into the resulting vector.
404 /// \tparam AE is the type of the vector_expression
405 /// \param ae is a const reference to the vector_expression
406 /// \return a reference to the resulting vector
407 template<class C> // Container assignment without temporary
409 vector &operator -= (const vector_container<C> &v) {
414 /// \brief Assign the difference of the vector and a vector_expression to the vector
415 /// Assign the difference of the vector and a vector_expression to the vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
416 /// No temporary is created. Computations are done and stored directly into the resulting vector.
417 /// \tparam AE is the type of the vector_expression
418 /// \param ae is a const reference to the vector_expression
419 /// \return a reference to the resulting vector
422 vector &minus_assign (const vector_expression<AE> &ae) {
423 vector_assign<scalar_minus_assign> (*this, ae);
427 /// \brief Assign the product of the vector and a scalar to the vector
428 /// Assign the product of the vector and a scalar to the vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
429 /// No temporary is created. Computations are done and stored directly into the resulting vector.
430 /// \tparam AE is the type of the vector_expression
431 /// \param at is a const reference to the scalar
432 /// \return a reference to the resulting vector
435 vector &operator *= (const AT &at) {
436 vector_assign_scalar<scalar_multiplies_assign> (*this, at);
440 /// \brief Assign the division of the vector by a scalar to the vector
441 /// Assign the division of the vector by a scalar to the vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
442 /// No temporary is created. Computations are done and stored directly into the resulting vector.
443 /// \tparam AE is the type of the vector_expression
444 /// \param at is a const reference to the scalar
445 /// \return a reference to the resulting vector
448 vector &operator /= (const AT &at) {
449 vector_assign_scalar<scalar_divides_assign> (*this, at);
457 /// \brief Swap the content of the vector with another vector
458 /// \param v is the vector to be swapped with
460 void swap (vector &v) {
462 data ().swap (v.data ());
466 /// \brief Swap the content of two vectors
467 /// \param v1 is the first vector. It takes values from v2
468 /// \param v2 is the second vector It takes values from v1
470 friend void swap (vector &v1, vector &v2) {
476 // Use the storage array iterator
477 typedef typename A::const_iterator const_subiterator_type;
478 typedef typename A::iterator subiterator_type;
481 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
482 typedef indexed_iterator<self_type, dense_random_access_iterator_tag> iterator;
483 typedef indexed_const_iterator<self_type, dense_random_access_iterator_tag> const_iterator;
485 class const_iterator;
493 /// \brief Return a const iterator to the element \e i
494 /// \param i index of the element
496 const_iterator find (size_type i) const {
497 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
498 return const_iterator (*this, data ().begin () + i);
500 return const_iterator (*this, i);
504 /// \brief Return an iterator to the element \e i
505 /// \param i index of the element
507 iterator find (size_type i) {
508 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
509 return iterator (*this, data ().begin () + i);
511 return iterator (*this, i);
515 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
516 class const_iterator:
517 public container_const_reference<vector>,
518 public random_access_iterator_base<dense_random_access_iterator_tag,
519 const_iterator, value_type, difference_type> {
521 typedef typename vector::difference_type difference_type;
522 typedef typename vector::value_type value_type;
523 typedef typename vector::const_reference reference;
524 typedef const typename vector::pointer pointer;
526 // ----------------------------
527 // Construction and destruction
528 // ----------------------------
533 container_const_reference<self_type> (), it_ () {}
535 const_iterator (const self_type &v, const const_subiterator_type &it):
536 container_const_reference<self_type> (v), it_ (it) {}
538 const_iterator (const typename self_type::iterator &it): // ISSUE vector:: stops VC8 using std::iterator here
539 container_const_reference<self_type> (it ()), it_ (it.it_) {}
545 /// \brief Increment by 1 the position of the iterator
546 /// \return a reference to the const iterator
548 const_iterator &operator ++ () {
553 /// \brief Decrement by 1 the position of the iterator
554 /// \return a reference to the const iterator
556 const_iterator &operator -- () {
561 /// \brief Increment by \e n the position of the iterator
562 /// \return a reference to the const iterator
564 const_iterator &operator += (difference_type n) {
569 /// \brief Decrement by \e n the position of the iterator
570 /// \return a reference to the const iterator
572 const_iterator &operator -= (difference_type n) {
577 /// \brief Return the different in number of positions between 2 iterators
579 difference_type operator - (const const_iterator &it) const {
580 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
584 /// \brief Dereference an iterator
585 /// Dereference an iterator: a bounds' check is done before returning the value. A bad_index() expection is returned if out of bounds.
586 /// \return a const reference to the value pointed by the iterator
588 const_reference operator * () const {
589 BOOST_UBLAS_CHECK (it_ >= (*this) ().begin ().it_ && it_ < (*this) ().end ().it_, bad_index ());
593 /// \brief Dereference an iterator at the n-th forward value
594 /// Dereference an iterator at the n-th forward value, that is the value pointed by iterator+n.
595 /// A bounds' check is done before returning the value. A bad_index() expection is returned if out of bounds.
596 /// \return a const reference
598 const_reference operator [] (difference_type n) const {
603 /// \brief return the index of the element referenced by the iterator
605 size_type index () const {
606 BOOST_UBLAS_CHECK (it_ >= (*this) ().begin ().it_ && it_ < (*this) ().end ().it_, bad_index ());
607 return it_ - (*this) ().begin ().it_;
612 /// \brief assign the value of an iterator to the iterator
613 const_iterator &operator = (const const_iterator &it) {
614 container_const_reference<self_type>::assign (&it ());
620 /// \brief compare the value of two itetarors
621 /// \return true if they reference the same element
623 bool operator == (const const_iterator &it) const {
624 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
625 return it_ == it.it_;
629 /// \brief compare the value of two iterators
630 /// \return return true if the left-hand-side iterator refers to a value placed before the right-hand-side iterator
632 bool operator < (const const_iterator &it) const {
633 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
638 const_subiterator_type it_;
640 friend class iterator;
644 /// \brief return an iterator on the first element of the vector
646 const_iterator begin () const {
650 /// \brief return an iterator on the first element of the vector
652 const_iterator cbegin () const {
656 /// \brief return an iterator after the last element of the vector
658 const_iterator end () const {
659 return find (data_.size ());
662 /// \brief return an iterator after the last element of the vector
664 const_iterator cend () const {
668 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
670 public container_reference<vector>,
671 public random_access_iterator_base<dense_random_access_iterator_tag,
672 iterator, value_type, difference_type> {
674 typedef typename vector::difference_type difference_type;
675 typedef typename vector::value_type value_type;
676 typedef typename vector::reference reference;
677 typedef typename vector::pointer pointer;
680 // Construction and destruction
683 container_reference<self_type> (), it_ () {}
685 iterator (self_type &v, const subiterator_type &it):
686 container_reference<self_type> (v), it_ (it) {}
690 iterator &operator ++ () {
695 iterator &operator -- () {
700 iterator &operator += (difference_type n) {
705 iterator &operator -= (difference_type n) {
710 difference_type operator - (const iterator &it) const {
711 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
717 reference operator * () const {
718 BOOST_UBLAS_CHECK (it_ >= (*this) ().begin ().it_ && it_ < (*this) ().end ().it_ , bad_index ());
722 reference operator [] (difference_type n) const {
728 size_type index () const {
729 BOOST_UBLAS_CHECK (it_ >= (*this) ().begin ().it_ && it_ < (*this) ().end ().it_ , bad_index ());
730 return it_ - (*this) ().begin ().it_;
735 iterator &operator = (const iterator &it) {
736 container_reference<self_type>::assign (&it ());
743 bool operator == (const iterator &it) const {
744 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
745 return it_ == it.it_;
748 bool operator < (const iterator &it) const {
749 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
754 subiterator_type it_;
756 friend class const_iterator;
760 /// \brief Return an iterator on the first element of the vector
766 /// \brief Return an iterator at the end of the vector
769 return find (data_.size ());
773 typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
774 typedef reverse_iterator_base<iterator> reverse_iterator;
776 /// \brief Return a const reverse iterator before the first element of the reversed vector (i.e. end() of normal vector)
778 const_reverse_iterator rbegin () const {
779 return const_reverse_iterator (end ());
782 /// \brief Return a const reverse iterator before the first element of the reversed vector (i.e. end() of normal vector)
784 const_reverse_iterator crbegin () const {
788 /// \brief Return a const reverse iterator on the end of the reverse vector (i.e. first element of the normal vector)
790 const_reverse_iterator rend () const {
791 return const_reverse_iterator (begin ());
794 /// \brief Return a const reverse iterator on the end of the reverse vector (i.e. first element of the normal vector)
796 const_reverse_iterator crend () const {
800 /// \brief Return a const reverse iterator before the first element of the reversed vector (i.e. end() of normal vector)
802 reverse_iterator rbegin () {
803 return reverse_iterator (end ());
806 /// \brief Return a const reverse iterator on the end of the reverse vector (i.e. first element of the normal vector)
808 reverse_iterator rend () {
809 return reverse_iterator (begin ());
816 /// Serialize a vector into and archive as defined in Boost
817 /// \param ar Archive object. Can be a flat file, an XML file or any other stream
818 /// \param file_version Optional file version (not yet used)
819 template<class Archive>
820 void serialize(Archive & ar, const unsigned int /* file_version */){
821 ar & serialization::make_nvp("data",data_);
829 #ifdef BOOST_UBLAS_CPP_GE_2011
830 /** \brief A dense vector of values of type \c T.
832 * For a \f$n\f$-dimensional vector \f$v\f$ and \f$0\leq i < n\f$ every element \f$v_i\f$ is mapped
833 * to the \f$i\f$-th element of the container. A storage type \c A can be specified which defaults to \c std::array.
834 * Elements are constructed by \c A, which need not initialise their value.
836 * \tparam T type of the objects stored in the vector (like int, double, complex,...)
837 * \tparam A The type of the storage array of the vector. Default is \c std::array<T>.
839 template<class T, std::size_t N, class A>
841 public vector_container<fixed_vector<T, N, A> > {
843 typedef fixed_vector<T, N, A> self_type;
845 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
846 using vector_container<self_type>::operator ();
849 typedef typename A::size_type size_type;
850 typedef typename A::difference_type difference_type;
851 typedef T value_type;
852 typedef typename type_traits<T>::const_reference const_reference;
853 typedef T &reference;
855 typedef const T *const_pointer;
856 typedef A array_type;
857 typedef const vector_reference<const self_type> const_closure_type;
858 typedef vector_reference<self_type> closure_type;
859 typedef self_type vector_temporary_type;
860 typedef dense_tag storage_category;
862 // Construction and destruction
864 /// \brief Constructor of a fixed_vector
867 vector_container<self_type> (),
870 /// \brief Constructor of a fixed_vector by copying from another container
871 /// This type uses the generic name \c array_type within the vector definition.
872 /// \param data container of type \c A
874 fixed_vector (const array_type &data):
875 vector_container<self_type> (),
878 /// \brief Constructor of a fixed_vector with a unique initial value
879 /// \param init value to assign to each element of the vector
881 fixed_vector (const value_type &init):
882 vector_container<self_type> (),
887 /// \brief Copy-constructor of a fixed_vector
888 /// \param v is the fixed_vector to be duplicated
890 fixed_vector (const fixed_vector &v):
891 vector_container<self_type> (),
894 /// \brief Copy-constructor of a vector from a vector_expression
895 /// Depending on the vector_expression, this constructor can have the cost of the computations
896 /// of the expression (trivial to say it, but take it must be taken into account in your complexity calculations).
897 /// \param ae the vector_expression which values will be duplicated into the vector
900 fixed_vector (const vector_expression<AE> &ae):
901 vector_container<self_type> (),
903 vector_assign<scalar_assign> (*this, ae);
906 /// \brief Construct a fixed_vector from a list of values
907 /// This constructor enables initialization by using any of:
908 /// fixed_vector<double, 3> v = { 1, 2, 3 } or fixed_vector<double,3> v( {1, 2, 3} ) or fixed_vector<double,3> v( 1, 2, 3 )
909 #if defined(BOOST_MSVC)
910 // This may or may not work. Maybe use this for all instead only for MSVC
911 template <typename... U>
912 fixed_vector(U&&... values) :
913 vector_container<self_type> (),
914 data_{{ std::forward<U>(values)... }} {}
916 template <typename... Types>
917 fixed_vector(value_type v0, Types... vrest) :
918 vector_container<self_type> (),
919 data_{ { v0, vrest... } } {}
922 // -----------------------
923 // Random Access Container
924 // -----------------------
926 /// \brief Return the maximum size of the data container.
927 /// Return the upper bound (maximum size) on the data container. Depending on the container, it can be bigger than the current size of the vector.
929 size_type max_size () const {
930 return data_.max_size ();
933 /// \brief Return true if the vector is empty (\c size==0)
934 /// \return \c true if empty, \c false otherwise
936 const bool &empty () const {
937 return data_.empty();
944 /// \brief Return the size of the vector
946 BOOST_CONSTEXPR size_type size () const{ // should have a const after C++14
947 return data_.size ();
954 /// \brief Return a \c const reference to the container. Useful to access data directly for specific type of container.
956 const array_type &data () const {
960 /// \brief Return a reference to the container. Useful to speed-up write operations to the data in very specific case.
962 array_type &data () {
970 /// \brief Return a pointer to the element \f$i\f$
971 /// \param i index of the element
972 // XXX this semantic is not the one expected by the name of this method
974 pointer find_element (size_type i) {
975 return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i));
978 /// \brief Return a const pointer to the element \f$i\f$
979 /// \param i index of the element
980 // XXX this semantic is not the one expected by the name of this method
982 const_pointer find_element (size_type i) const {
983 BOOST_UBLAS_CHECK (i < data_.size(), bad_index() ); // Since std:array doesn't check for bounds
984 return & (data () [i]);
991 /// \brief Return a const reference to the element \f$i\f$
992 /// Return a const reference to the element \f$i\f$. With some compilers, this notation will be faster than \c[i]
993 /// \param i index of the element
995 const_reference operator () (size_type i) const {
996 BOOST_UBLAS_CHECK (i < data_.size(), bad_index() );
1000 /// \brief Return a reference to the element \f$i\f$
1001 /// Return a reference to the element \f$i\f$. With some compilers, this notation will be faster than \c[i]
1002 /// \param i index of the element
1004 reference operator () (size_type i) {
1005 BOOST_UBLAS_CHECK (i < data_.size(), bad_index() );
1009 /// \brief Return a const reference to the element \f$i\f$
1010 /// \param i index of the element
1012 const_reference operator [] (size_type i) const {
1013 BOOST_UBLAS_CHECK (i < data_.size(), bad_index() );
1017 /// \brief Return a reference to the element \f$i\f$
1018 /// \param i index of the element
1020 reference operator [] (size_type i) {
1021 BOOST_UBLAS_CHECK (i < data_.size(), bad_index() );
1025 // ------------------
1026 // Element assignment
1027 // ------------------
1029 /// \brief Set element \f$i\f$ to the value \c t
1030 /// \param i index of the element
1031 /// \param t reference to the value to be set
1032 // XXX semantic of this is to insert a new element and therefore size=size+1 ?
1034 reference insert_element (size_type i, const_reference t) {
1035 BOOST_UBLAS_CHECK (i < data_.size(), bad_index ());
1036 return (data () [i] = t);
1039 /// \brief Set element \f$i\f$ to the \e zero value
1040 /// \param i index of the element
1042 void erase_element (size_type i) {
1043 BOOST_UBLAS_CHECK (i < data_.size(), bad_index ());
1044 data () [i] = value_type/*zero*/();
1051 /// \brief Clear the vector, i.e. set all values to the \c zero value.
1054 std::fill (data ().begin (), data ().end (), value_type/*zero*/());
1058 #ifdef BOOST_UBLAS_MOVE_SEMANTICS
1060 /// \brief Assign a full fixed_vector (\e RHS-vector) to the current fixed_vector (\e LHS-vector)
1061 /// \param v is the source vector
1062 /// \return a reference to a fixed_vector (i.e. the destination vector)
1063 /*! @note "pass by value" the key idea to enable move semantics */
1065 fixed_vector &operator = (fixed_vector v) {
1066 assign_temporary(v);
1070 /// \brief Assign a full fixed_vector (\e RHS-vector) to the current fixed_vector (\e LHS-vector)
1071 /// \param v is the source fixed_vector
1072 /// \return a reference to a fixed_vector (i.e. the destination vector)
1074 fixed_vector &operator = (const fixed_vector &v) {
1075 data () = v.data ();
1080 /// \brief Assign a full vector (\e RHS-vector) to the current fixed_vector (\e LHS-vector)
1081 /// Assign a full vector (\e RHS-vector) to the current fixed_vector (\e LHS-vector). This method does not create any temporary.
1082 /// \param v is the source vector container
1083 /// \return a reference to a vector (i.e. the destination vector)
1084 template<class C> // Container assignment without temporary
1086 fixed_vector &operator = (const vector_container<C> &v) {
1091 /// \brief Assign a full fixed_vector (\e RHS-vector) to the current fixed_vector (\e LHS-vector)
1092 /// \param v is the source fixed_vector
1093 /// \return a reference to a fixed_vector (i.e. the destination fixed_vector)
1095 fixed_vector &assign_temporary (fixed_vector &v) {
1100 /// \brief Assign the result of a vector_expression to the fixed_vector
1101 /// Assign the result of a vector_expression to the vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
1102 /// \tparam AE is the type of the vector_expression
1103 /// \param ae is a const reference to the vector_expression
1104 /// \return a reference to the resulting fixed_vector
1107 fixed_vector &operator = (const vector_expression<AE> &ae) {
1108 self_type temporary (ae);
1109 return assign_temporary (temporary);
1112 /// \brief Assign the result of a vector_expression to the fixed_vector
1113 /// Assign the result of a vector_expression to the vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
1114 /// \tparam AE is the type of the vector_expression
1115 /// \param ae is a const reference to the vector_expression
1116 /// \return a reference to the resulting fixed_vector
1119 fixed_vector &assign (const vector_expression<AE> &ae) {
1120 vector_assign<scalar_assign> (*this, ae);
1124 // -------------------
1125 // Computed assignment
1126 // -------------------
1128 /// \brief Assign the sum of the fixed_vector and a vector_expression to the fixed_vector
1129 /// Assign the sum of the fixed_vector and a vector_expression to the fixed_vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
1130 /// A temporary is created for the computations.
1131 /// \tparam AE is the type of the vector_expression
1132 /// \param ae is a const reference to the vector_expression
1133 /// \return a reference to the resulting fixed_vector
1136 fixed_vector &operator += (const vector_expression<AE> &ae) {
1137 self_type temporary (*this + ae);
1138 return assign_temporary (temporary);
1141 /// \brief Assign the sum of the fixed_vector and a vector_expression to the fixed_vector
1142 /// Assign the sum of the fixed_vector and a vector_expression to the fixed_vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
1143 /// No temporary is created. Computations are done and stored directly into the resulting vector.
1144 /// \tparam AE is the type of the vector_expression
1145 /// \param ae is a const reference to the vector_expression
1146 /// \return a reference to the resulting vector
1147 template<class C> // Container assignment without temporary
1149 fixed_vector &operator += (const vector_container<C> &v) {
1154 /// \brief Assign the sum of the fixed_vector and a vector_expression to the fixed_vector
1155 /// Assign the sum of the fixed_vector and a vector_expression to the fixed_vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
1156 /// No temporary is created. Computations are done and stored directly into the resulting fixed_vector.
1157 /// \tparam AE is the type of the vector_expression
1158 /// \param ae is a const reference to the vector_expression
1159 /// \return a reference to the resulting vector
1162 fixed_vector &plus_assign (const vector_expression<AE> &ae) {
1163 vector_assign<scalar_plus_assign> (*this, ae);
1167 /// \brief Assign the difference of the fixed_vector and a vector_expression to the fixed_vector
1168 /// Assign the difference of the fixed_vector and a vector_expression to the fixed_vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
1169 /// A temporary is created for the computations.
1170 /// \tparam AE is the type of the vector_expression
1171 /// \param ae is a const reference to the vector_expression
1174 fixed_vector &operator -= (const vector_expression<AE> &ae) {
1175 self_type temporary (*this - ae);
1176 return assign_temporary (temporary);
1179 /// \brief Assign the difference of the fixed_vector and a vector_expression to the fixed_vector
1180 /// Assign the difference of the fixed_vector and a vector_expression to the fixed_vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
1181 /// No temporary is created. Computations are done and stored directly into the resulting fixed_vector.
1182 /// \tparam AE is the type of the vector_expression
1183 /// \param ae is a const reference to the vector_expression
1184 /// \return a reference to the resulting vector
1185 template<class C> // Container assignment without temporary
1187 fixed_vector &operator -= (const vector_container<C> &v) {
1192 /// \brief Assign the difference of the fixed_vector and a vector_expression to the fixed_vector
1193 /// Assign the difference of the fixed_vector and a vector_expression to the fixed_vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
1194 /// No temporary is created. Computations are done and stored directly into the resulting fixed_vector.
1195 /// \tparam AE is the type of the vector_expression
1196 /// \param ae is a const reference to the vector_expression
1197 /// \return a reference to the resulting fixed_vector
1200 fixed_vector &minus_assign (const vector_expression<AE> &ae) {
1201 vector_assign<scalar_minus_assign> (*this, ae);
1205 /// \brief Assign the product of the fixed_vector and a scalar to the fixed_vector
1206 /// Assign the product of the fixed_vector and a scalar to the fixed_vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
1207 /// No temporary is created. Computations are done and stored directly into the resulting fixed_vector.
1208 /// \tparam AE is the type of the vector_expression
1209 /// \param at is a const reference to the scalar
1210 /// \return a reference to the resulting fixed_vector
1213 fixed_vector &operator *= (const AT &at) {
1214 vector_assign_scalar<scalar_multiplies_assign> (*this, at);
1218 /// \brief Assign the division of the fixed_vector by a scalar to the fixed_vector
1219 /// Assign the division of the fixed_vector by a scalar to the vector. This is lazy-compiled and will be optimized out by the compiler on any type of expression.
1220 /// No temporary is created. Computations are done and stored directly into the resulting vector.
1221 /// \tparam AE is the type of the vector_expression
1222 /// \param at is a const reference to the scalar
1223 /// \return a reference to the resulting fixed_vector
1226 fixed_vector &operator /= (const AT &at) {
1227 vector_assign_scalar<scalar_divides_assign> (*this, at);
1235 /// \brief Swap the content of the fixed_vector with another vector
1236 /// \param v is the fixed_vector to be swapped with
1238 void swap (fixed_vector &v) {
1240 data ().swap (v.data ());
1244 /// \brief Swap the content of two fixed_vectors
1245 /// \param v1 is the first fixed_vector. It takes values from v2
1246 /// \param v2 is the second fixed_vector It takes values from v1
1248 friend void swap (fixed_vector &v1, fixed_vector &v2) {
1254 // Use the storage array iterator
1255 typedef typename A::const_iterator const_subiterator_type;
1256 typedef typename A::iterator subiterator_type;
1259 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
1260 typedef indexed_iterator<self_type, dense_random_access_iterator_tag> iterator;
1261 typedef indexed_const_iterator<self_type, dense_random_access_iterator_tag> const_iterator;
1263 class const_iterator;
1271 /// \brief Return a const iterator to the element \e i
1272 /// \param i index of the element
1274 const_iterator find (size_type i) const {
1275 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1276 return const_iterator (*this, data ().begin () + i);
1278 return const_iterator (*this, i);
1282 /// \brief Return an iterator to the element \e i
1283 /// \param i index of the element
1285 iterator find (size_type i) {
1286 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1287 return iterator (*this, data ().begin () + i);
1289 return iterator (*this, i);
1293 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1294 class const_iterator:
1295 public container_const_reference<fixed_vector>,
1296 public random_access_iterator_base<dense_random_access_iterator_tag,
1297 const_iterator, value_type, difference_type> {
1299 typedef typename fixed_vector::difference_type difference_type;
1300 typedef typename fixed_vector::value_type value_type;
1301 typedef typename fixed_vector::const_reference reference;
1302 typedef const typename fixed_vector::pointer pointer;
1304 // ----------------------------
1305 // Construction and destruction
1306 // ----------------------------
1311 container_const_reference<self_type> (), it_ () {}
1313 const_iterator (const self_type &v, const const_subiterator_type &it):
1314 container_const_reference<self_type> (v), it_ (it) {}
1316 const_iterator (const typename self_type::iterator &it): // ISSUE vector:: stops VC8 using std::iterator here
1317 container_const_reference<self_type> (it ()), it_ (it.it_) {}
1323 /// \brief Increment by 1 the position of the iterator
1324 /// \return a reference to the const iterator
1326 const_iterator &operator ++ () {
1331 /// \brief Decrement by 1 the position of the iterator
1332 /// \return a reference to the const iterator
1334 const_iterator &operator -- () {
1339 /// \brief Increment by \e n the position of the iterator
1340 /// \return a reference to the const iterator
1342 const_iterator &operator += (difference_type n) {
1347 /// \brief Decrement by \e n the position of the iterator
1348 /// \return a reference to the const iterator
1350 const_iterator &operator -= (difference_type n) {
1355 /// \brief Return the different in number of positions between 2 iterators
1357 difference_type operator - (const const_iterator &it) const {
1358 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1359 return it_ - it.it_;
1362 /// \brief Dereference an iterator
1363 /// Dereference an iterator: a bounds' check is done before returning the value. A bad_index() expection is returned if out of bounds.
1364 /// \return a const reference to the value pointed by the iterator
1366 const_reference operator * () const {
1367 BOOST_UBLAS_CHECK (it_ >= (*this) ().begin ().it_ && it_ < (*this) ().end ().it_, bad_index ());
1371 /// \brief Dereference an iterator at the n-th forward value
1372 /// Dereference an iterator at the n-th forward value, that is the value pointed by iterator+n.
1373 /// A bounds' check is done before returning the value. A bad_index() expection is returned if out of bounds.
1374 /// \return a const reference
1376 const_reference operator [] (difference_type n) const {
1381 /// \brief return the index of the element referenced by the iterator
1383 size_type index () const {
1384 BOOST_UBLAS_CHECK (it_ >= (*this) ().begin ().it_ && it_ < (*this) ().end ().it_, bad_index ());
1385 return it_ - (*this) ().begin ().it_;
1390 /// \brief assign the value of an iterator to the iterator
1391 const_iterator &operator = (const const_iterator &it) {
1392 container_const_reference<self_type>::assign (&it ());
1398 /// \brief compare the value of two itetarors
1399 /// \return true if they reference the same element
1401 bool operator == (const const_iterator &it) const {
1402 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1403 return it_ == it.it_;
1407 /// \brief compare the value of two iterators
1408 /// \return return true if the left-hand-side iterator refers to a value placed before the right-hand-side iterator
1410 bool operator < (const const_iterator &it) const {
1411 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1412 return it_ < it.it_;
1416 const_subiterator_type it_;
1418 friend class iterator;
1422 /// \brief return an iterator on the first element of the fixed_vector
1424 const_iterator begin () const {
1428 /// \brief return an iterator on the first element of the fixed_vector
1430 const_iterator cbegin () const {
1434 /// \brief return an iterator after the last element of the fixed_vector
1436 const_iterator end () const {
1437 return find (data_.size ());
1440 /// \brief return an iterator after the last element of the fixed_vector
1442 const_iterator cend () const {
1446 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
1448 public container_reference<fixed_vector>,
1449 public random_access_iterator_base<dense_random_access_iterator_tag,
1450 iterator, value_type, difference_type> {
1452 typedef typename fixed_vector::difference_type difference_type;
1453 typedef typename fixed_vector::value_type value_type;
1454 typedef typename fixed_vector::reference reference;
1455 typedef typename fixed_vector::pointer pointer;
1458 // Construction and destruction
1461 container_reference<self_type> (), it_ () {}
1463 iterator (self_type &v, const subiterator_type &it):
1464 container_reference<self_type> (v), it_ (it) {}
1468 iterator &operator ++ () {
1473 iterator &operator -- () {
1478 iterator &operator += (difference_type n) {
1483 iterator &operator -= (difference_type n) {
1488 difference_type operator - (const iterator &it) const {
1489 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1490 return it_ - it.it_;
1495 reference operator * () const {
1496 BOOST_UBLAS_CHECK (it_ >= (*this) ().begin ().it_ && it_ < (*this) ().end ().it_ , bad_index ());
1500 reference operator [] (difference_type n) const {
1506 size_type index () const {
1507 BOOST_UBLAS_CHECK (it_ >= (*this) ().begin ().it_ && it_ < (*this) ().end ().it_ , bad_index ());
1508 return it_ - (*this) ().begin ().it_;
1513 iterator &operator = (const iterator &it) {
1514 container_reference<self_type>::assign (&it ());
1521 bool operator == (const iterator &it) const {
1522 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1523 return it_ == it.it_;
1526 bool operator < (const iterator &it) const {
1527 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1528 return it_ < it.it_;
1532 subiterator_type it_;
1534 friend class const_iterator;
1538 /// \brief Return an iterator on the first element of the fixed_vector
1544 /// \brief Return an iterator at the end of the fixed_vector
1547 return find (data_.size ());
1551 typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
1552 typedef reverse_iterator_base<iterator> reverse_iterator;
1554 /// \brief Return a const reverse iterator before the first element of the reversed fixed_vector (i.e. end() of normal fixed_vector)
1556 const_reverse_iterator rbegin () const {
1557 return const_reverse_iterator (end ());
1560 /// \brief Return a const reverse iterator before the first element of the reversed fixed_vector (i.e. end() of normal fixed_vector)
1562 const_reverse_iterator crbegin () const {
1566 /// \brief Return a const reverse iterator on the end of the reverse fixed_vector (i.e. first element of the normal fixed_vector)
1568 const_reverse_iterator rend () const {
1569 return const_reverse_iterator (begin ());
1572 /// \brief Return a const reverse iterator on the end of the reverse fixed_vector (i.e. first element of the normal fixed_vector)
1574 const_reverse_iterator crend () const {
1578 /// \brief Return a const reverse iterator before the first element of the reversed fixed_vector (i.e. end() of normal fixed_vector)
1580 reverse_iterator rbegin () {
1581 return reverse_iterator (end ());
1584 /// \brief Return a const reverse iterator on the end of the reverse fixed_vector (i.e. first element of the normal fixed_vector)
1586 reverse_iterator rend () {
1587 return reverse_iterator (begin ());
1594 /// Serialize a fixed_vector into and archive as defined in Boost
1595 /// \param ar Archive object. Can be a flat file, an XML file or any other stream
1596 /// \param file_version Optional file version (not yet used)
1597 template<class Archive>
1598 void serialize(Archive & ar, const unsigned int /* file_version */){
1599 ar & serialization::make_nvp("data",data_);
1606 #endif // BOOST_UBLAS_CPP_GE_2011
1608 // --------------------
1609 // Bounded vector class
1610 // --------------------
1612 /// \brief a dense vector of values of type \c T, of variable size but with maximum \f$N\f$.
1613 /// A dense vector of values of type \c T, of variable size but with maximum \f$N\f$. The default constructor
1614 /// creates the vector with size \f$N\f$. Elements are constructed by the storage type \c bounded_array, which \b need \b not \b initialise their value.
1615 template<class T, std::size_t N>
1616 class bounded_vector:
1617 public vector<T, bounded_array<T, N> > {
1619 typedef vector<T, bounded_array<T, N> > vector_type;
1621 typedef typename vector_type::size_type size_type;
1622 static const size_type max_size = N;
1624 // Construction and destruction
1629 bounded_vector (size_type size):
1630 vector_type (size) {}
1632 bounded_vector (const bounded_vector &v):
1634 template<class A2> // Allow vector<T,bounded_array<N> construction
1636 bounded_vector (const vector<T, A2> &v):
1640 bounded_vector (const vector_expression<AE> &ae):
1643 ~bounded_vector () {}
1646 #ifdef BOOST_UBLAS_MOVE_SEMANTICS
1648 /*! @note "pass by value" the key idea to enable move semantics */
1650 bounded_vector &operator = (bounded_vector v) {
1651 vector_type::operator = (v);
1656 bounded_vector &operator = (const bounded_vector &v) {
1657 vector_type::operator = (v);
1661 template<class A2> // Generic vector assignment
1663 bounded_vector &operator = (const vector<T, A2> &v) {
1664 vector_type::operator = (v);
1667 template<class C> // Container assignment without temporary
1669 bounded_vector &operator = (const vector_container<C> &v) {
1670 vector_type::operator = (v);
1675 bounded_vector &operator = (const vector_expression<AE> &ae) {
1676 vector_type::operator = (ae);
1683 // -----------------
1684 // Zero vector class
1685 // -----------------
1687 /// \brief A zero vector of type \c T and a given \c size
1688 /// A zero vector of type \c T and a given \c size. This is a virtual vector in the sense that no memory is allocated
1689 /// for storing the zero values: it still acts like any other vector. However assigning values to it will not change the zero
1690 /// vector into a normal vector. It must first be assigned to another normal vector by any suitable means. Its memory footprint is constant.
1691 template<class T, class ALLOC>
1693 public vector_container<zero_vector<T, ALLOC> > {
1695 typedef const T *const_pointer;
1696 typedef zero_vector<T, ALLOC> self_type;
1698 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1699 using vector_container<self_type>::operator ();
1701 typedef typename ALLOC::size_type size_type;
1702 typedef typename ALLOC::difference_type difference_type;
1703 typedef T value_type;
1704 typedef const T &const_reference;
1705 typedef T &reference;
1706 typedef const vector_reference<const self_type> const_closure_type;
1707 typedef vector_reference<self_type> closure_type;
1708 typedef sparse_tag storage_category;
1710 // Construction and destruction
1713 vector_container<self_type> (),
1715 explicit BOOST_UBLAS_INLINE
1716 zero_vector (size_type size):
1717 vector_container<self_type> (),
1720 zero_vector (const zero_vector &v):
1721 vector_container<self_type> (),
1726 size_type size () const {
1732 void resize (size_type size, bool /*preserve*/ = true) {
1738 const_pointer find_element (size_type /*i*/) const {
1744 const_reference operator () (size_type /* i */) const {
1749 const_reference operator [] (size_type i) const {
1755 zero_vector &operator = (const zero_vector &v) {
1760 zero_vector &assign_temporary (zero_vector &v) {
1767 void swap (zero_vector &v) {
1769 std::swap (size_, v.size_);
1773 friend void swap (zero_vector &v1, zero_vector &v2) {
1779 class const_iterator;
1783 const_iterator find (size_type /*i*/) const {
1784 return const_iterator (*this);
1787 class const_iterator:
1788 public container_const_reference<zero_vector>,
1789 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
1790 const_iterator, value_type> {
1792 typedef typename zero_vector::difference_type difference_type;
1793 typedef typename zero_vector::value_type value_type;
1794 typedef typename zero_vector::const_reference reference;
1795 typedef typename zero_vector::const_pointer pointer;
1797 // Construction and destruction
1800 container_const_reference<self_type> () {}
1802 const_iterator (const self_type &v):
1803 container_const_reference<self_type> (v) {}
1807 const_iterator &operator ++ () {
1808 BOOST_UBLAS_CHECK_FALSE (bad_index ());
1812 const_iterator &operator -- () {
1813 BOOST_UBLAS_CHECK_FALSE (bad_index ());
1819 const_reference operator * () const {
1820 BOOST_UBLAS_CHECK_FALSE (bad_index ());
1821 return zero_; // arbitary return value
1826 size_type index () const {
1827 BOOST_UBLAS_CHECK_FALSE (bad_index ());
1828 return 0; // arbitary return value
1833 const_iterator &operator = (const const_iterator &it) {
1834 container_const_reference<self_type>::assign (&it ());
1840 bool operator == (const const_iterator &it) const {
1841 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
1842 detail::ignore_unused_variable_warning(it);
1847 typedef const_iterator iterator;
1850 const_iterator begin () const {
1851 return const_iterator (*this);
1854 const_iterator cbegin () const {
1858 const_iterator end () const {
1859 return const_iterator (*this);
1862 const_iterator cend () const {
1867 typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
1870 const_reverse_iterator rbegin () const {
1871 return const_reverse_iterator (end ());
1874 const_reverse_iterator crbegin () const {
1878 const_reverse_iterator rend () const {
1879 return const_reverse_iterator (begin ());
1882 const_reverse_iterator crend () const {
1887 template<class Archive>
1888 void serialize(Archive & ar, const unsigned int /* file_version */){
1889 serialization::collection_size_type s (size_);
1890 ar & serialization::make_nvp("size",s);
1891 if (Archive::is_loading::value) {
1898 typedef const value_type const_value_type;
1899 static const_value_type zero_;
1902 template<class T, class ALLOC>
1903 typename zero_vector<T, ALLOC>::const_value_type zero_vector<T, ALLOC>::zero_ = T(/*zero*/);
1906 // Unit vector class
1907 /// \brief unit_vector represents a canonical unit vector
1908 /// unit_vector represents a canonical unit vector. The \e k-th unit vector of dimension \f$n\f$ holds 0 for every value \f$u_i\f$ s.t. \f$i \neq k\f$ and 1 when \f$i=k\f$.
1909 /// At construction, the value \e k is given after the dimension of the vector.
1910 /// \tparam T is the type of elements in the vector. They must be 0 and 1 assignable in order for the vector to have its unit-vector semantic.
1911 /// \tparam ALLOC a specific allocator can be specified if needed. Most of the time this parameter is omited.
1912 template<class T, class ALLOC>
1914 public vector_container<unit_vector<T, ALLOC> > {
1916 typedef const T *const_pointer;
1917 typedef unit_vector<T, ALLOC> self_type;
1919 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
1920 using vector_container<self_type>::operator ();
1922 typedef typename ALLOC::size_type size_type;
1923 typedef typename ALLOC::difference_type difference_type;
1924 typedef T value_type;
1925 typedef const T &const_reference;
1926 typedef T &reference;
1927 typedef const vector_reference<const self_type> const_closure_type;
1928 typedef vector_reference<self_type> closure_type;
1929 typedef sparse_tag storage_category;
1931 // Construction and destruction
1932 /// \brief Simple constructor with dimension and index 0
1935 vector_container<self_type> (),
1936 size_ (0), index_ (0) {}
1938 /// \brief Constructor of unit_vector
1939 /// \param size is the dimension of the vector
1940 /// \param index is the order of the vector
1942 explicit unit_vector (size_type size, size_type index = 0):
1943 vector_container<self_type> (),
1944 size_ (size), index_ (index) {}
1946 /// \brief Copy-constructor
1948 unit_vector (const unit_vector &v):
1949 vector_container<self_type> (),
1950 size_ (v.size_), index_ (v.index_) {}
1955 /// \brief Return the size (dimension) of the vector
1957 size_type size () const {
1961 /// \brief Return the order of the unit vector
1963 size_type index () const {
1970 /// \brief Resize the vector. The values are preserved by default (i.e. the index does not change)
1971 /// \param size is the new size of the vector
1973 void resize (size_type size, bool /*preserve*/ = true) {
1980 /// \brief Return a const pointer to the element of index i
1982 const_pointer find_element (size_type i) const {
1991 const_reference operator () (size_type i) const {
1999 const_reference operator [] (size_type i) const {
2005 unit_vector &operator = (const unit_vector &v) {
2011 unit_vector &assign_temporary (unit_vector &v) {
2018 void swap (unit_vector &v) {
2020 std::swap (size_, v.size_);
2021 std::swap (index_, v.index_);
2025 friend void swap (unit_vector &v1, unit_vector &v2) {
2031 // Use bool to indicate begin (one_ as value)
2032 typedef bool const_subiterator_type;
2034 class const_iterator;
2038 const_iterator find (size_type i) const {
2039 return const_iterator (*this, i <= index_);
2042 class const_iterator:
2043 public container_const_reference<unit_vector>,
2044 public bidirectional_iterator_base<sparse_bidirectional_iterator_tag,
2045 const_iterator, value_type> {
2047 typedef typename unit_vector::difference_type difference_type;
2048 typedef typename unit_vector::value_type value_type;
2049 typedef typename unit_vector::const_reference reference;
2050 typedef typename unit_vector::const_pointer pointer;
2052 // Construction and destruction
2055 container_const_reference<unit_vector> (), it_ () {}
2057 const_iterator (const unit_vector &v, const const_subiterator_type &it):
2058 container_const_reference<unit_vector> (v), it_ (it) {}
2062 const_iterator &operator ++ () {
2063 BOOST_UBLAS_CHECK (it_, bad_index ());
2068 const_iterator &operator -- () {
2069 BOOST_UBLAS_CHECK (!it_, bad_index ());
2076 const_reference operator * () const {
2077 BOOST_UBLAS_CHECK (it_, bad_index ());
2083 size_type index () const {
2084 BOOST_UBLAS_CHECK (it_, bad_index ());
2085 return (*this) ().index_;
2090 const_iterator &operator = (const const_iterator &it) {
2091 container_const_reference<unit_vector>::assign (&it ());
2098 bool operator == (const const_iterator &it) const {
2099 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2100 return it_ == it.it_;
2104 const_subiterator_type it_;
2107 typedef const_iterator iterator;
2110 const_iterator begin () const {
2111 return const_iterator (*this, true);
2114 const_iterator cbegin () const {
2118 const_iterator end () const {
2119 return const_iterator (*this, false);
2122 const_iterator cend () const {
2127 typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
2130 const_reverse_iterator rbegin () const {
2131 return const_reverse_iterator (end ());
2134 const_reverse_iterator crbegin () const {
2138 const_reverse_iterator rend () const {
2139 return const_reverse_iterator (begin ());
2142 const_reverse_iterator crend () const {
2147 template<class Archive>
2148 void serialize(Archive & ar, const unsigned int /* file_version */){
2149 serialization::collection_size_type s (size_);
2150 ar & serialization::make_nvp("size",s);
2151 if (Archive::is_loading::value) {
2154 ar & serialization::make_nvp("index", index_);
2160 typedef const value_type const_value_type;
2161 static const_value_type zero_;
2162 static const_value_type one_;
2165 template<class T, class ALLOC>
2166 typename unit_vector<T, ALLOC>::const_value_type unit_vector<T, ALLOC>::zero_ = T(/*zero*/);
2167 template<class T, class ALLOC>
2168 typename unit_vector<T, ALLOC>::const_value_type unit_vector<T, ALLOC>::one_ (1); // ISSUE: need 'one'-traits here
2170 /// \brief A scalar (i.e. unique value) vector of type \c T and a given \c size
2171 /// A scalar (i.e. unique value) vector of type \c T and a given \c size. This is a virtual vector in the sense that no memory is allocated
2172 /// for storing the unique value more than once: it still acts like any other vector. However assigning a new value will change all the value at once.
2173 /// vector into a normal vector. It must first be assigned to another normal vector by any suitable means. Its memory footprint is constant.
2174 /// \tparam T type of the objects stored in the vector: it can be anything even if most of the time, scalar types will be used like \c double or \c int. Complex types can be used, or even classes like boost::interval.
2175 template<class T, class ALLOC>
2176 class scalar_vector:
2177 public vector_container<scalar_vector<T, ALLOC> > {
2179 typedef const T *const_pointer;
2180 typedef scalar_vector<T, ALLOC> self_type;
2182 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
2183 using vector_container<self_type>::operator ();
2185 typedef typename ALLOC::size_type size_type;
2186 typedef typename ALLOC::difference_type difference_type;
2187 typedef T value_type;
2188 typedef const T &const_reference;
2189 typedef T &reference;
2190 typedef const vector_reference<const self_type> const_closure_type;
2191 typedef vector_reference<self_type> closure_type;
2192 typedef dense_tag storage_category;
2194 // Construction and destruction
2197 vector_container<self_type> (),
2198 size_ (0), value_ () {}
2200 explicit scalar_vector (size_type size, const value_type &value = value_type(1)):
2201 vector_container<self_type> (),
2202 size_ (size), value_ (value) {}
2204 scalar_vector (const scalar_vector &v):
2205 vector_container<self_type> (),
2206 size_ (v.size_), value_ (v.value_) {}
2210 size_type size () const {
2216 void resize (size_type size, bool /*preserve*/ = true) {
2222 const_pointer find_element (size_type /*i*/) const {
2228 const_reference operator () (size_type /*i*/) const {
2233 const_reference operator [] (size_type /*i*/) const {
2239 scalar_vector &operator = (const scalar_vector &v) {
2245 scalar_vector &assign_temporary (scalar_vector &v) {
2252 void swap (scalar_vector &v) {
2254 std::swap (size_, v.size_);
2255 std::swap (value_, v.value_);
2259 friend void swap (scalar_vector &v1, scalar_vector &v2) {
2266 typedef size_type const_subiterator_type;
2269 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2270 typedef indexed_const_iterator<self_type, dense_random_access_iterator_tag> iterator;
2271 typedef indexed_const_iterator<self_type, dense_random_access_iterator_tag> const_iterator;
2273 class const_iterator;
2278 const_iterator find (size_type i) const {
2279 return const_iterator (*this, i);
2282 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2283 class const_iterator:
2284 public container_const_reference<scalar_vector>,
2285 public random_access_iterator_base<dense_random_access_iterator_tag,
2286 const_iterator, value_type> {
2288 typedef typename scalar_vector::difference_type difference_type;
2289 typedef typename scalar_vector::value_type value_type;
2290 typedef typename scalar_vector::const_reference reference;
2291 typedef typename scalar_vector::const_pointer pointer;
2293 // Construction and destruction
2296 container_const_reference<scalar_vector> (), it_ () {}
2298 const_iterator (const scalar_vector &v, const const_subiterator_type &it):
2299 container_const_reference<scalar_vector> (v), it_ (it) {}
2303 const_iterator &operator ++ () {
2308 const_iterator &operator -- () {
2313 const_iterator &operator += (difference_type n) {
2318 const_iterator &operator -= (difference_type n) {
2323 difference_type operator - (const const_iterator &it) const {
2324 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2325 return it_ - it.it_;
2330 const_reference operator * () const {
2331 BOOST_UBLAS_CHECK (it_ < (*this) ().size (), bad_index ());
2332 return (*this) () (index ());
2335 const_reference operator [] (difference_type n) const {
2336 return *(*this + n);
2341 size_type index () const {
2342 BOOST_UBLAS_CHECK (it_ < (*this) ().size (), bad_index ());
2348 const_iterator &operator = (const const_iterator &it) {
2349 container_const_reference<scalar_vector>::assign (&it ());
2356 bool operator == (const const_iterator &it) const {
2357 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2358 return it_ == it.it_;
2361 bool operator < (const const_iterator &it) const {
2362 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2363 return it_ < it.it_;
2367 const_subiterator_type it_;
2370 typedef const_iterator iterator;
2374 const_iterator begin () const {
2378 const_iterator cbegin () const {
2382 const_iterator end () const {
2383 return find (size_);
2386 const_iterator cend () const {
2391 typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
2394 const_reverse_iterator rbegin () const {
2395 return const_reverse_iterator (end ());
2398 const_reverse_iterator crbegin () const {
2402 const_reverse_iterator rend () const {
2403 return const_reverse_iterator (begin ());
2406 const_reverse_iterator crend () const {
2411 template<class Archive>
2412 void serialize(Archive & ar, const unsigned int /* file_version */){
2413 serialization::collection_size_type s (size_);
2414 ar & serialization::make_nvp("size",s);
2415 if (Archive::is_loading::value) {
2418 ar & serialization::make_nvp("value", value_);
2426 // ------------------------
2427 // Array based vector class
2428 // ------------------------
2430 /// \brief A dense vector of values of type \c T with the given \c size. The data is stored as an ordinary C++ array \c T \c data_[M]
2431 template<class T, std::size_t N>
2433 public vector_container<c_vector<T, N> > {
2435 typedef c_vector<T, N> self_type;
2437 #ifdef BOOST_UBLAS_ENABLE_PROXY_SHORTCUTS
2438 using vector_container<self_type>::operator ();
2440 typedef std::size_t size_type;
2441 typedef std::ptrdiff_t difference_type;
2442 typedef T value_type;
2443 typedef const T &const_reference;
2444 typedef T &reference;
2445 typedef value_type array_type[N];
2447 typedef const T *const_pointer;
2448 typedef const vector_reference<const self_type> const_closure_type;
2449 typedef vector_reference<self_type> closure_type;
2450 typedef self_type vector_temporary_type;
2451 typedef dense_tag storage_category;
2453 // Construction and destruction
2456 size_ (N) /* , data_ () */ {}
2457 explicit BOOST_UBLAS_INLINE
2458 c_vector (size_type size):
2459 size_ (size) /* , data_ () */ {
2461 bad_size ().raise ();
2464 c_vector (const c_vector &v):
2465 size_ (v.size_) /* , data_ () */ {
2467 bad_size ().raise ();
2472 c_vector (const vector_expression<AE> &ae):
2473 size_ (ae ().size ()) /* , data_ () */ {
2475 bad_size ().raise ();
2476 vector_assign<scalar_assign> (*this, ae);
2481 size_type size () const {
2485 const_pointer data () const {
2495 void resize (size_type size, bool /*preserve*/ = true) {
2497 bad_size ().raise ();
2503 pointer find_element (size_type i) {
2504 return const_cast<pointer> (const_cast<const self_type&>(*this).find_element (i));
2507 const_pointer find_element (size_type i) const {
2513 const_reference operator () (size_type i) const {
2514 BOOST_UBLAS_CHECK (i < size_, bad_index ());
2518 reference operator () (size_type i) {
2519 BOOST_UBLAS_CHECK (i < size_, bad_index ());
2524 const_reference operator [] (size_type i) const {
2528 reference operator [] (size_type i) {
2532 // Element assignment
2534 reference insert_element (size_type i, const_reference t) {
2535 BOOST_UBLAS_CHECK (i < size_, bad_index ());
2536 return (data_ [i] = t);
2539 void erase_element (size_type i) {
2540 BOOST_UBLAS_CHECK (i < size_, bad_index ());
2541 data_ [i] = value_type/*zero*/();
2547 std::fill (data_, data_ + size_, value_type/*zero*/());
2551 #ifdef BOOST_UBLAS_MOVE_SEMANTICS
2553 /*! @note "pass by value" the key idea to enable move semantics */
2555 c_vector &operator = (c_vector v) {
2556 assign_temporary(v);
2561 c_vector &operator = (const c_vector &v) {
2563 std::copy (v.data_, v.data_ + v.size_, data_);
2567 template<class C> // Container assignment without temporary
2569 c_vector &operator = (const vector_container<C> &v) {
2570 resize (v ().size (), false);
2575 c_vector &assign_temporary (c_vector &v) {
2581 c_vector &operator = (const vector_expression<AE> &ae) {
2582 self_type temporary (ae);
2583 return assign_temporary (temporary);
2587 c_vector &assign (const vector_expression<AE> &ae) {
2588 vector_assign<scalar_assign> (*this, ae);
2592 // Computed assignment
2595 c_vector &operator += (const vector_expression<AE> &ae) {
2596 self_type temporary (*this + ae);
2597 return assign_temporary (temporary);
2599 template<class C> // Container assignment without temporary
2601 c_vector &operator += (const vector_container<C> &v) {
2607 c_vector &plus_assign (const vector_expression<AE> &ae) {
2608 vector_assign<scalar_plus_assign> ( *this, ae);
2613 c_vector &operator -= (const vector_expression<AE> &ae) {
2614 self_type temporary (*this - ae);
2615 return assign_temporary (temporary);
2617 template<class C> // Container assignment without temporary
2619 c_vector &operator -= (const vector_container<C> &v) {
2625 c_vector &minus_assign (const vector_expression<AE> &ae) {
2626 vector_assign<scalar_minus_assign> (*this, ae);
2631 c_vector &operator *= (const AT &at) {
2632 vector_assign_scalar<scalar_multiplies_assign> (*this, at);
2637 c_vector &operator /= (const AT &at) {
2638 vector_assign_scalar<scalar_divides_assign> (*this, at);
2644 void swap (c_vector &v) {
2646 BOOST_UBLAS_CHECK (size_ == v.size_, bad_size ());
2647 std::swap (size_, v.size_);
2648 std::swap_ranges (data_, data_ + size_, v.data_);
2652 friend void swap (c_vector &v1, c_vector &v2) {
2658 // Use pointers for iterator
2659 typedef const_pointer const_subiterator_type;
2660 typedef pointer subiterator_type;
2663 #ifdef BOOST_UBLAS_USE_INDEXED_ITERATOR
2664 typedef indexed_iterator<self_type, dense_random_access_iterator_tag> iterator;
2665 typedef indexed_const_iterator<self_type, dense_random_access_iterator_tag> const_iterator;
2667 class const_iterator;
2673 const_iterator find (size_type i) const {
2674 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2675 return const_iterator (*this, &data_ [i]);
2677 return const_iterator (*this, i);
2681 iterator find (size_type i) {
2682 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2683 return iterator (*this, &data_ [i]);
2685 return iterator (*this, i);
2689 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2690 class const_iterator:
2691 public container_const_reference<c_vector>,
2692 public random_access_iterator_base<dense_random_access_iterator_tag,
2693 const_iterator, value_type> {
2695 typedef typename c_vector::difference_type difference_type;
2696 typedef typename c_vector::value_type value_type;
2697 typedef typename c_vector::const_reference reference;
2698 typedef typename c_vector::const_pointer pointer;
2700 // Construction and destruction
2703 container_const_reference<self_type> (), it_ () {}
2705 const_iterator (const self_type &v, const const_subiterator_type &it):
2706 container_const_reference<self_type> (v), it_ (it) {}
2708 const_iterator (const typename self_type::iterator &it): // ISSUE self_type:: stops VC8 using std::iterator here
2709 container_const_reference<self_type> (it ()), it_ (it.it_) {}
2713 const_iterator &operator ++ () {
2718 const_iterator &operator -- () {
2723 const_iterator &operator += (difference_type n) {
2728 const_iterator &operator -= (difference_type n) {
2733 difference_type operator - (const const_iterator &it) const {
2734 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2735 return it_ - it.it_;
2740 const_reference operator * () const {
2741 BOOST_UBLAS_CHECK (it_ >= (*this) ().begin ().it_ && it_ < (*this) ().end ().it_, bad_index ());
2745 const_reference operator [] (difference_type n) const {
2751 size_type index () const {
2752 BOOST_UBLAS_CHECK (it_ >= (*this) ().begin ().it_ && it_ < (*this) ().end ().it_, bad_index ());
2753 const self_type &v = (*this) ();
2754 return it_ - v.begin ().it_;
2759 const_iterator &operator = (const const_iterator &it) {
2760 container_const_reference<self_type>::assign (&it ());
2767 bool operator == (const const_iterator &it) const {
2768 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2769 return it_ == it.it_;
2772 bool operator < (const const_iterator &it) const {
2773 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2774 return it_ < it.it_;
2778 const_subiterator_type it_;
2780 friend class iterator;
2785 const_iterator begin () const {
2789 const_iterator cbegin () const {
2793 const_iterator end () const {
2794 return find (size_);
2797 const_iterator cend () const {
2801 #ifndef BOOST_UBLAS_USE_INDEXED_ITERATOR
2803 public container_reference<c_vector>,
2804 public random_access_iterator_base<dense_random_access_iterator_tag,
2805 iterator, value_type> {
2807 typedef typename c_vector::difference_type difference_type;
2808 typedef typename c_vector::value_type value_type;
2809 typedef typename c_vector::reference reference;
2810 typedef typename c_vector::pointer pointer;
2812 // Construction and destruction
2815 container_reference<self_type> (), it_ () {}
2817 iterator (self_type &v, const subiterator_type &it):
2818 container_reference<self_type> (v), it_ (it) {}
2822 iterator &operator ++ () {
2827 iterator &operator -- () {
2832 iterator &operator += (difference_type n) {
2837 iterator &operator -= (difference_type n) {
2842 difference_type operator - (const iterator &it) const {
2843 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2844 return it_ - it.it_;
2849 reference operator * () const {
2850 BOOST_UBLAS_CHECK (it_ >= (*this) ().begin ().it_ && it_ < (*this) ().end ().it_, bad_index ());
2854 reference operator [] (difference_type n) const {
2860 size_type index () const {
2861 BOOST_UBLAS_CHECK (it_ >= (*this) ().begin ().it_ && it_ < (*this) ().end ().it_, bad_index ());
2862 // EDG won't allow const self_type it doesn't allow friend access to it_
2863 self_type &v = (*this) ();
2864 return it_ - v.begin ().it_;
2869 iterator &operator = (const iterator &it) {
2870 container_reference<self_type>::assign (&it ());
2877 bool operator == (const iterator &it) const {
2878 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2879 return it_ == it.it_;
2882 bool operator < (const iterator &it) const {
2883 BOOST_UBLAS_CHECK (&(*this) () == &it (), external_logic ());
2884 return it_ < it.it_;
2888 subiterator_type it_;
2890 friend class const_iterator;
2900 return find (size_);
2904 typedef reverse_iterator_base<const_iterator> const_reverse_iterator;
2905 typedef reverse_iterator_base<iterator> reverse_iterator;
2908 const_reverse_iterator rbegin () const {
2909 return const_reverse_iterator (end ());
2912 const_reverse_iterator crbegin () const {
2916 const_reverse_iterator rend () const {
2917 return const_reverse_iterator (begin ());
2920 const_reverse_iterator crend () const {
2924 reverse_iterator rbegin () {
2925 return reverse_iterator (end ());
2928 reverse_iterator rend () {
2929 return reverse_iterator (begin ());
2933 template<class Archive>
2934 void serialize(Archive & ar, const unsigned int /* file_version */){
2935 serialization::collection_size_type s (size_);
2936 ar & serialization::make_nvp("size",s);
2938 // copy the value back if loading
2939 if (Archive::is_loading::value) {
2940 if (s > N) bad_size("too large size in bounded_vector::load()\n").raise();
2943 // ISSUE: this writes the full array
2944 ar & serialization::make_nvp("data",data_);