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 #ifndef IVL_ARRAY_DETAILS_INDIRECT_ARRAY_HPP 00025 #define IVL_ARRAY_DETAILS_INDIRECT_ARRAY_HPP 00026 00027 namespace ivl { 00028 00029 template<class A, class B> class indirect_array; // fwd 00030 00031 namespace array_details { 00032 00033 // check if the array is already indirect 00034 template <class A, class D> 00035 struct indirect_ref_type_2 00036 { 00037 typedef A type; 00038 typedef types::term idref_type; 00039 }; 00040 00041 template <class A, class AR, class B, class D> 00042 struct indirect_ref_type_2<A, data::indirect<AR, B, D> > 00043 { 00044 // typedef typename types::apply_const<AR, 00045 // typename types::is_const<A>::type>::type type; 00046 typedef AR type; 00047 typedef types::term idref_type; 00048 }; 00049 00050 template <class A, class IS_ARRAY> 00051 struct indirect_ref_type_1 00052 { 00053 typedef A type; 00054 typedef types::term idref_type; 00055 }; 00056 00057 template <class A> 00058 struct indirect_ref_type_1<A, types::t_true> 00059 : public indirect_ref_type_2<A, typename A::data_type> 00060 { 00061 }; 00062 00063 template <class A> 00064 struct indirect_ref_type 00065 : public indirect_ref_type_1<A, typename 00066 types::is_ivl_array<A>::type> 00067 { 00068 }; 00069 00070 template <class A, class B, class BASE_PLAIN> 00071 struct rebase_indirect_1 00072 { 00073 typedef typename types::bare_type<B>::type b_t; 00074 00075 //typedef typename b_t::create_new n_t; 00076 typedef typename types::normal_type<b_t>::type n_t; 00077 00078 typedef typename types::change_elem_type<typename A::elem_type, n_t>::type t1; 00079 00080 typedef typename types::change_data_class_set<data::indirect<A, B>, t1>::type type; 00081 //typedef array<typename A::elem_type, data::indirect<A, B> > type; 00082 00083 typedef tuple<A&, const b_t&> data_init_arg; 00084 00085 static inline A& correct(A& a) { return a; } 00086 static inline const b_t& merge(A& a, const b_t& b) { return b; } 00087 }; 00088 00089 template <class A, class B> 00090 struct rebase_indirect_1<A, B, types::t_false> 00091 { 00092 // This is the case where indices need to be merged. 00093 00094 typedef typename types::bare_type<B>::type b_t; 00095 // B is either going to be an elem type or a mem type, 00096 // in our case a mem type. 00097 /* 00098 typedef typename types::t_if<types::is_ref<B>, 00099 typename types::create_similar<b_t>::type, B> 00100 ::type new_b_t; 00101 */ 00102 typedef typename types::create_similar<b_t>::type new_b_t; 00103 00104 00105 00106 typedef typename types::normal_type<b_t>::type n_t; 00107 typedef typename types::change_elem_type<typename A::elem_type, n_t>::type t1; 00108 typedef typename types::change_data_class_set<data::indirect<typename indirect_ref_type<A>::type, new_b_t>, t1>::type type; 00109 00110 //typedef indirect_array<typename indirect_ref_type<A>::type, new_b_t> type; 00111 00112 00113 00114 static inline 00115 typename indirect_ref_type<A>::type& correct(A& a) 00116 { 00117 return a.get_ref_1(); 00118 } 00119 // TODO: (more likely than below) 00120 // instead of elem- solution for merge, differentiate 00121 // indirect<indirect based on whether B is reference. 00122 // when B is stored, use the rebasing and merging approach. 00123 // when B is reference, do not rebase at all, use the original 00124 // data::indirect<data::indirect class that automatically inherits 00125 // and solves merging, even if slower. 00126 // The latter may have its own valid uses, e.g. the indices of 00127 // parent change and the child is dynamically affected. 00128 // 00129 // TODO: should be (in implementation and return type) 00130 // an elem func to avoid copy 00131 // something like idxmap(b, _[a.get_ref_2()]) 00132 // the _[] scalar conversion is to make the second arg scalar. 00133 // maybe when the B type is mem we need mem and when the B type 00134 // is reference we need that elem_func approach. 00135 typedef tuple<typename indirect_ref_type<A>::type&, new_b_t> data_init_arg; 00136 00137 static inline new_b_t merge(A& a, const b_t& b) 00138 { return a.merge_idx(b); } 00139 }; 00140 00141 template <class A, class B> 00142 struct rebase_indirect 00143 : public rebase_indirect_1<A, B, 00144 typename types::t_eq<A, typename indirect_ref_type<A>::type> 00145 ::type> 00146 { 00147 }; 00148 00149 } /* namespace array_details */ 00150 00151 template<class A, class B> 00152 class indirect_array 00153 //: public array<typename A::elem_type, data::indirect< 00154 // typename array_details::indirect_ref_type<A>::type, B> > 00155 : public array_details::rebase_indirect<A, B>::type 00156 { 00157 typedef typename array_details::indirect_ref_type<A>::type prv_ref_t; 00158 typedef typename array_details::rebase_indirect<A, B>::type prv_base; 00159 typedef typename array_details::rebase_indirect<A, B>::data_init_arg prv_arg; 00160 typedef typename types::bare_type<B>::type b_t; 00161 prv_base& get_prv_base() { return static_cast<prv_base&>(*this); } 00162 const prv_base& get_prv_base() const 00163 { return static_cast<const prv_base&>(*this); } 00164 typedef typename types::bare_type<B>::type prv_b; 00165 public: 00166 typedef indirect_array this_type; 00167 typedef typename this_type::array_type base_class; 00168 00169 base_class& base() { return static_cast<base_class&>(*this); } 00170 const base_class& base() const 00171 { return static_cast<const base_class&>(*this); } 00172 00173 // convert temporary object to non-const reference 00174 this_type& ref() { return *this; } 00175 00176 indirect_array() { } 00177 //indirect_array(const this_type& o) : base_class(o.base()) { } 00178 indirect_array(const this_type& o) : prv_base(o.get_prv_base()) { } 00179 00180 //indirect_array(const internal::tuple<prv_ref_t&, const B&>& t) 00181 // : base_class(t.v1, t.v2) { } 00182 00183 /* nd-spec 00184 template<class I> 00185 indirect_array(const internal::tuple<A&, const I&>& t) 00186 : prv_base(t.v2.size(), prv_arg(array_details::rebase_indirect<A, B> 00187 ::correct(t.v1), 00188 array_details::rebase_indirect<A, B> 00189 ::merge(t.v1, t.v2))) { } 00190 template<class SZ, class K> 00191 indirect_array(SZ sz, K t) 00192 : prv_base(t.v2.size(), prv_arg(array_details::rebase_indirect<A, B> 00193 ::correct(t.v1), 00194 array_details::rebase_indirect<A, B> 00195 ::merge(t.v1, t.v2))) { } 00196 00197 */ 00198 00199 00200 00201 template<class I> 00202 indirect_array(const internal::tuple<A&, I&>& t) 00203 : prv_base(t.v2.size(), prv_arg(array_details::rebase_indirect<A, B> 00204 ::correct(t.v1), 00205 array_details::rebase_indirect<A, B> 00206 ::merge(t.v1, t.v2))) { } 00207 00208 00209 /* old-spec works*/ 00210 /* 00211 template<class I> 00212 indirect_array(const internal::tuple<A&, const I&>& t) 00213 : prv_base(array_details::rebase_indirect<A, B> 00214 ::correct(t.v1), 00215 array_details::rebase_indirect<A, B> 00216 ::merge(t.v1, t.v2)) { } 00217 00218 indirect_array(A& a, const b_t& b) 00219 : prv_base(array_details::rebase_indirect<A, B> 00220 ::correct(a), 00221 array_details::rebase_indirect<A, B> 00222 ::merge(a, b)) { } 00223 */ 00224 00225 00226 00227 00228 //template<class P1, class P2> 00229 //template<class T, class I, class J> 00230 //indirect_array(const array<T, data::indirect<A, I, J> >& o) 00231 // : prv_base(o) { } 00232 00233 template<class T, class I> 00234 explicit indirect_array(array<T, I>& o) : prv_base(o.derived()) { } 00235 00236 template<class T, class I> 00237 explicit indirect_array(const array<T, I>& o) : prv_base(o.derived()) { } 00238 00239 00240 //indirect_array(A& a) 00241 // : prv_base(A, 00242 00243 00244 //using base_class::operator=; 00245 this_type& operator=(const this_type& o) 00246 { 00247 base_class::operator=(o); 00248 return *this; 00249 } 00250 template<class K> 00251 this_type& operator=(const K& o) 00252 { 00253 base_class::operator=(o); 00254 return *this; 00255 } 00256 }; 00257 00258 } /* namespace ivl */ 00259 00260 #endif // IVL_ARRAY_DETAILS_INDIRECT_ARRAY_HPP