ivl 679
|
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