ivl 679
ivl/details/array/impl/specialization/member_class.hpp
00001 /* This file is part of the ivl C++ library <http://image.ntua.gr/ivl>.
00002    A C++ template library extending syntax towards mathematical notation.
00003 
00004    Copyright (C) 2012 Yannis Avrithis <iavr@image.ntua.gr>
00005    Copyright (C) 2012 Kimon Kontosis <kimonas@image.ntua.gr>
00006 
00007    ivl is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU Lesser General Public License 
00009    version 3 as published by the Free Software Foundation.
00010 
00011    Alternatively, you can redistribute it and/or modify it under the terms 
00012    of the GNU General Public License version 2 as published by the Free 
00013    Software Foundation.
00014 
00015    ivl is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00018    See the GNU General Public License for more details.
00019 
00020    You should have received a copy of the GNU General Public License 
00021    and a copy of the GNU Lesser General Public License along 
00022    with ivl. If not, see <http://www.gnu.org/licenses/>. */
00023 
00024 namespace array_details {
00025 
00026 template <class RESIZEABLE>
00027 struct member_array_resize_details { };
00028 
00029 template <class HAS_REF, class TP>
00030 struct member_tool
00031 {
00032         template<class T, class Y>
00033         static inline TP get_reference(T& x, Y& y) { return x; }
00034 };
00035 template <class TP>
00036 struct member_tool<types::t_false, TP>
00037 {
00038         template<class T, class Y>
00039         static inline TP get_reference(T& x, Y& y) { return TP(x, y); }
00040 };
00041 
00042 } /* namespace array_details */
00043 
00048 template <class T,
00049                  class A,
00050                  class DERIVED_INFO
00051              >
00052 class array<T, data::member<A, T, DERIVED_INFO> >
00053         :
00054         public array_common_base<
00055                 array<T, data::member<A, T, DERIVED_INFO> > >,
00056 
00057         public data::referer<typename types::derive<
00058                 array<T, data::member<A, T, DERIVED_INFO> > >::type>
00059 {
00060 
00061 private:
00062         typedef array_common_base<array<T,
00063                 data::member<A, T, DERIVED_INFO> > > common_base_class;
00064 
00065         typedef typename types::t_if<typename array::is_writeable,
00066                         typename types::best_iterator<A>::type,
00067                         typename A::const_iterator>::type a_best_iterator;
00068 
00069         typedef typename types::t_if<typename array::is_writeable,
00070                         typename types::best_reverse_iterator<A>::type,
00071                         typename A::const_reverse_iterator>::type a_best_reverse_iterator;
00072 
00073         typedef typename A::this_array_type a_t;
00074 
00075         typedef typename A::elem_type a_elem_t;
00076 
00077         typedef T a_elem_t::* m_type;
00078 
00079         // check if the source iterator gives reference or value
00080         typedef typename types::
00081                 is_ref<typename a_best_iterator::reference>::type has_src_ref;
00082 
00083         // TODO: should wrap the a_best_iterator::reference or do something clever, also should mind const
00084         typedef typename types::t_if<has_src_ref, T&, T>::type best_base_ref_type;
00085 
00086 protected:
00087         typedef typename array::has_random_access prv_has_random_access;
00088 
00089         typedef array_details::elem_func_tools<T,
00090                 prv_has_random_access::value> tool;
00091 
00092         //friend class tool::not_a_type; // allow disabled types only in our class
00093         class not_a_type {};
00094 
00095         A* a;
00096         m_type m;
00097 
00098 public:
00099         typedef array this_type;
00100 
00101         typedef this_type this_array_type;
00102 
00103         typedef this_type array_type;
00104 
00105         typedef T elem_type;
00106 
00107         typedef typename common_base_class::derived_type derived_type;
00108 
00109         typedef typename common_base_class::base_class base_class;
00110 
00112         typedef size_t size_type;
00113 
00115         typedef ptrdiff_t diff_type;
00116 
00117         using base_class::derived;
00118 
00119 
00120         //
00121 
00122         template <bool CONST>
00123         class iterator_type
00124         : public data::data_details::
00125                 rnd_iter_operator_expander<iterator_type<CONST>, T, CONST, best_base_ref_type>
00126         {
00127         private:
00128                 template <bool C> friend class iterator_type;
00129 
00130                 template <class X, class Y, bool C, class Z>
00131                 friend class data::data_details::rnd_iter_operator_expander;
00132 
00133                 template <class X, class Y, bool C, class Z>
00134                 friend class data::data_details::iter_operator_expander;
00135 
00136                 typedef typename types::apply_const<T, types::t_expr<CONST> >
00137                         ::type best_value_type;
00138 
00139                 // TODO: should wrap the a_best_iterator::reference or do something clever, also should mind const
00140                 typedef typename types::t_if<has_src_ref,
00141                         typename types::apply_const<T&, types::t_expr<CONST> >::type,
00142                         const internal::reference_face<const T, iterator_type<CONST> > >
00143                                 ::type best_ref_type;
00144 
00145                 // TODO: same as above
00146                 typedef typename types::t_if<has_src_ref,
00147                         typename types::apply_const<T*, types::t_expr<CONST> >::type,
00148                         const internal::pointer_face<const T> > 
00149                                 ::type best_ptr_type;
00150         
00151                 // this class is used to disable specific specialization members
00152                 class not_a_type { };
00153 
00154                 typedef typename types::t_if<types::t_expr<CONST>, not_a_type,
00155                         types::code_word<> >::type invalid_if_const;
00156 
00157                 typedef typename types::t_if<types::t_expr<CONST>,
00158                         typename A::const_iterator, a_best_iterator>::type a_iterator;
00159 
00160                 a_iterator a;
00161                 m_type m;
00162 
00163         protected:
00164                 inline typename types::apply_const<best_ref_type>::type base(
00165                         types::code_word<> ok = types::code_word<>()) const
00166                         { 
00167                                 return array_details::member_tool<has_src_ref,
00168                                         typename types::apply_const<best_ref_type>::type>::
00169                                                 get_reference(((*a).*m), *this); 
00170                         }
00171 //TODO!!!! make it random access only if b is random access
00172 // otherwise make it non-random access.
00173 // make it complain if a is non-random access.
00174                 inline best_ref_type base(
00175                         invalid_if_const disable = invalid_if_const())
00176                         { 
00177                                 return array_details::member_tool<has_src_ref,
00178                                         best_ref_type>::
00179                                                 get_reference(((*a).*m), *this); 
00180                         }
00181 
00182                 inline typename types::apply_const<best_ref_type>::type base(size_t j,
00183                         types::code_word<> ok = types::code_word<>()) const
00184                         { 
00185                                 return array_details::member_tool<has_src_ref,
00186                                         typename types::apply_const<best_ref_type>::type>::
00187                                                 get_reference((a[j].*m), *this); 
00188                         }
00189 
00190                 inline best_ref_type base(size_t j,
00191                         invalid_if_const disable = invalid_if_const())
00192                         { 
00193                                 return array_details::member_tool<has_src_ref,
00194                                         best_ref_type>::
00195                                                 get_reference((a[j].*m), *this); 
00196                         }
00197 
00198         public:
00199                 typedef iterator_type<CONST> this_type;
00200 
00201                 // iterator_traits
00202                 typedef std::random_access_iterator_tag iterator_category;
00203                 typedef T value_type;
00204                 typedef ptrdiff_t difference_type;
00205                 typedef best_ptr_type pointer;
00206                 typedef best_ref_type reference;
00207 
00208                 // constructors
00209                 iterator_type() { }
00210                 iterator_type(const this_type& it)
00211                 : a(it.a), m(it.m) { }
00212                 template <bool C>
00213                 iterator_type(const iterator_type<C>& it)
00214                 : a(it.a), m(it.m) { }
00215                 iterator_type(const a_iterator& a, const m_type& m)
00216                         : a(a), m(m) { }
00217 
00218                 // members
00219 
00220                 // increment-decrement
00221                 this_type& operator++() { ++a; return *this; }
00222                 this_type& operator--() { --a; return *this; }
00223 
00224                 this_type operator++(int) { this_type t(*this); ++(*this); return t; }
00225                 this_type operator--(int) { this_type t(*this); --(*this); return t; }
00226 
00227                 // random access.
00228 
00229                 // X can be either size_t or B::iter_bound_mover
00230                 template<class X>
00231                 this_type& operator +=(X j) { a += j; return *this; }
00232 
00233                 template<class X>
00234                 this_type& operator -=(X j) { a -= j; return *this; }
00235 
00236                 template<class X>
00237                 inline this_type operator +(X j) const
00238                 {
00239                         this_type tmp(*this);
00240                         tmp += j;
00241                         return tmp;
00242                 }
00243                 template<class X>
00244                 inline this_type operator -(X j) const
00245                 {
00246                         this_type tmp(*this);
00247                         tmp -= j;
00248                         return tmp;
00249                 }
00250 
00251                 // difference.
00252                 ptrdiff_t operator-(const this_type& it) const
00253                 {
00254                         return a - it.a;
00255                 }
00256 
00257                 //copy same type iterator
00258                 this_type& operator=(const this_type& it)
00259                 {
00260                         a = it.a; m = it.m;
00261                         return *this;
00262                 }
00263                 //copy relevant type iterator
00264                 template<bool C>
00265                 this_type& operator=(const iterator_type<C>& it)
00266                 {
00267                         a = it.a; m = it.m;
00268                         return *this;
00269                 }
00270 
00271                 bool operator==(const this_type& it) const { return (a == it.a); }
00272                 bool operator!=(const this_type& it) const { return (a != it.a); }
00273                 bool operator<(const this_type& it) const { return (a < it.a); }
00274                 bool operator<=(const this_type& it) const { return (a <= it.a); }
00275                 bool operator>(const this_type& it) const { return (a > it.a); }
00276                 bool operator>=(const this_type& it) const { return (a >= it.a); }
00277 
00278         };
00279 
00280         // typedefs for class iterators
00281         typedef typename types::t_if<typename array::is_writeable,
00282                 iterator_type<false>, not_a_type>::type iterator;
00283 
00284         typedef iterator_type<true> const_iterator;
00285 
00286         typedef typename types::t_if<types::t_eq<iterator, not_a_type>,
00287                 const_iterator, iterator>::type best_iterator;
00288 
00289         typedef typename best_iterator::reference best_reference;
00290         typedef best_reference reference;
00291         typedef typename const_iterator::reference const_reference;
00292 
00293         typedef std::reverse_iterator<iterator> reverse_iterator;
00294 
00295         typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00296 
00297         typedef typename data::iterator_extended_traits<a_best_iterator>
00298                 ::iter_border_walker iter_border_walker;
00299 
00300         best_iterator begin() { return best_iterator(a->begin(), m); }
00301         best_iterator end() { return best_iterator(a->end(), m); }
00302 
00303         const_iterator begin() const 
00304                 { return const_iterator(a->begin(), m); }
00305 
00306         const_iterator end() const
00307                 { return const_iterator(a->end(), m); }
00308 
00309         // reverse iterator defs
00310         reverse_iterator rbegin() { return reverse_iterator(end()); }
00311 
00312         reverse_iterator rend() { return reverse_iterator(begin()); }
00313 
00314         const_reverse_iterator rbegin() const
00315                 { return const_reverse_iterator(end()); }
00316 
00317         const_reverse_iterator rend() const
00318                 { return const_reverse_iterator(begin()); }
00319 
00320 
00321         using common_base_class::operator[];
00322 
00323         // todo: resolve when b has no random access
00324         typename best_iterator::reference operator[](size_t j)
00325         {
00326                 return (*a)[j].*m;
00327         }
00328         typename const_iterator::reference operator[](size_t j) const
00329         {
00330                 return (*a)[j].*m;
00331         }
00332 
00335         //TODO: explain this better.
00337         size_t length() const { return a->length(); }
00339         size_type size() const { return length(); }
00341         size_t numel() const { return length(); }
00343         void resize(size_t len)
00344         {
00345                 array_details::
00346                         member_array_resize_details<typename array::is_resizeable>
00347                         ::resize(m, a, len);
00348         }
00349 
00350         void resize(size_t len, const T& s) // with padding
00351         {
00352                 array_details::
00353                         member_array_resize_details<typename array::is_resizeable>
00354                         ::resize(m, static_cast<a_t*>(a), len, s);
00355         }
00356 
00358         void reshape(size_t len) { resize(len); }
00359         void reshape(size_t len, const T& s) { resize(len, s); }
00360 
00361         void clear() { resize(0); }
00362 
00363 
00364         iter_border_walker first_to_last() { return a->first_to_last(); }
00365         iter_border_walker begin_to_end() { return a->begin_to_end(); }
00366 
00367 
00368         void init(A& a0, m_type m0)
00369         {
00370                 a = &a0;
00371                 m = m0;
00372         }
00373 
00374         void init(const array& o)
00375         {
00376                 a = o.a;
00377                 m = o.m;
00378         }
00379 
00382 
00383         array(A& a, m_type m) : a(&a), m(m) { }
00384 
00386         array(const this_type& o) : a(o.a), m(o.m) {}
00387 
00392         array() {}
00393 
00395         array(size_t) {}
00396 
00398         template <class J, class D>
00399         array(size_t, const array<J, D>&) {}
00400 
00402         array(size_t, const T*) {}
00403 
00405         template<class J, class S>
00406         array(const array<J, S>& a) {}
00407 
00411 
00412         ~array() { }
00413 
00416         template <class D>
00417         bool overlap(const D& d) const
00418         {
00419                 return a->overlap(d);
00420         }
00421 
00422         // TODO: ensure correctness.
00423         template <class D>
00424         bool self_overlap(const D& d) const
00425         {
00426                 return d.overlap(*a);
00427         }
00428 
00435         using common_base_class::operator=;
00436 
00437         this_type& operator=(const this_type& a)
00438         {
00439                 common_base_class::operator=(a);
00440                 return *this;
00441         }
00442 
00446 };
00447 
00448 
00449 namespace array_details {
00450 
00451 template<>
00452 struct member_array_resize_details<types::t_false>
00453 {
00454         template <class T0, class E0, class A, class S>
00455         static inline
00456         bool resize(T0 E0::* pv, A* a, const S& l) { return false; }
00457 
00458         template <class T0, class E0, class A, class S, class T>
00459         static inline
00460         bool resize(T0 E0::* pv, A* a, const S& l, const T& t) { return false; }
00461 };
00462 
00463 template<>
00464 struct member_array_resize_details<types::t_true>
00465 {
00466         template <class T0, class E0, class A, class S>
00467         static inline
00468         bool resize(T0 E0::* pv, A* a, const S& l) { a->resize(l); return true; }
00469 
00470         template <class T0, class E0, class A, class S, class T>
00471         static inline
00472         bool resize(T0 E0::* pv, A* a, const S& l, const T& t) { 
00473                 E0 tv;
00474                 tv.*pv = t;
00475                 a->resize(l, tv); 
00476                 return true; 
00477         }
00478 };
00479 
00480 } /* namespace array_details */
00481 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations