Mirror reflection library 0.5.13
|
00001 00011 #ifndef MIRROR_META_CONTAINER_1104181551_HPP 00012 #define MIRROR_META_CONTAINER_1104181551_HPP 00013 00014 #include <mirror/mirror_fwd.hpp> 00015 #include <mirror/meta_object_tags.hpp> 00016 #include <mirror/cntnr_kind_tags.hpp> 00017 #include <mirror/cntnr_op_param_tags.hpp> 00018 #include <mirror/preprocessor.hpp> 00019 #include <mirror/auxiliary/scoped_named.hpp> 00020 #include <mirror/auxiliary/containers.hpp> 00021 #include <string> 00022 #include <type_traits> 00023 00024 MIRROR_NAMESPACE_BEGIN 00025 00026 namespace _container { 00027 00028 template <typename Container> 00029 struct _ 00030 { 00031 typedef std::integral_constant<int, 0> cntnr_count; 00032 typedef non_container_tag kind; 00033 }; 00034 00035 template <size_t Size> 00036 struct _array_base 00037 { 00038 static bool empty(const void*) 00039 { 00040 return Size == 0; 00041 } 00042 00043 static size_t size_hint(const void*) 00044 { 00045 return Size; 00046 } 00047 00048 typedef mirror::mp::empty_range inserters; 00049 typedef mirror::mp::empty_range erasers; 00050 }; 00051 00052 template <class ElementType, size_t Size> 00053 struct _<ElementType[Size]> 00054 { 00055 struct cntnr : _array_base<Size> 00056 { 00057 typedef ElementType elem_type; 00058 00059 typedef mirror::aux::meta_array_trav_fwd< 00060 ElementType, 00061 Size 00062 > default_traversal; 00063 00064 typedef mirror::mp::range< 00065 default_traversal 00066 // TODO: reverse traversal ? 00067 > traversals; 00068 00069 typedef mirror::mp::range< 00070 // TODO: begin/end/at/... ? 00071 > locators; 00072 }; 00073 static cntnr _cntnr(std::integral_constant<int, 0>); 00074 typedef std::integral_constant<int, 1> cntnr_count; 00075 typedef simple_container_tag kind; 00076 }; 00077 00078 } // namespace _container 00079 00080 template <class Container, typename IsSpecial, int Index> 00081 struct meta_container 00082 { 00083 private: 00084 typedef decltype( 00085 mirror::_container::_<Container>::_cntnr( 00086 std::integral_constant<int, Index>() 00087 ) 00088 ) _base_cntnr; 00089 00090 friend class default_traversal<meta_container>; 00091 friend class traversals<meta_container>; 00092 friend class locators<meta_container>; 00093 friend class inserters<meta_container>; 00094 friend class erasers<meta_container>; 00095 00096 // gets the scope for regular (class) containers 00097 static typename mirror::reflected<Container>::type 00098 _get_scope(std::false_type); 00099 00100 // scope for special container types (like arrays) 00101 static typename mirror::reflected<Container>::type::scope 00102 _get_scope(std::true_type); 00103 public: 00104 typedef typename mirror::reflected< 00105 typename _base_cntnr::elem_type 00106 >::type element_type; 00107 00108 typedef decltype(_get_scope(IsSpecial())) scope; 00109 00110 static bool empty(const Container& container) 00111 { 00112 return _base_cntnr::empty(container); 00113 } 00114 00115 static auto size_hint(const Container& container) -> 00116 decltype(_base_cntnr::size_hint(container)) 00117 { 00118 return _base_cntnr::size_hint(container); 00119 } 00120 00121 typedef typename _base_cntnr::default_traversal 00122 default_traversal; 00123 }; 00124 00125 template <class Container> 00126 struct container_kind<meta_type<Container> > 00127 { 00128 typedef typename mirror::_container::_< 00129 Container 00130 >::kind type; 00131 }; 00132 00133 template <class Container> 00134 struct container_kind<meta_class<Container> > 00135 : public container_kind<meta_type<Container> > 00136 { }; 00137 00138 template <class Container> 00139 struct container_kind<meta_enum<Container> > 00140 : public container_kind<meta_type<Container> > 00141 { }; 00142 00143 template <class Container> 00144 struct containers<meta_type<Container> > 00145 { 00146 typedef typename mirror::mp::apply_on_seq_pack< 00147 mirror::aux::cntnr_helper<Container>, 00148 typename mirror::_container::_<Container>::cntnr_count 00149 >::type type; 00150 }; 00151 00152 template <class Container> 00153 struct containers<meta_class<Container> > 00154 : public containers<meta_type<Container> > 00155 { }; 00156 00157 template <class Container> 00158 struct containers<meta_enum<Container> > 00159 { 00160 typedef mirror::mp::empty_range type; 00161 }; 00162 00163 template <class Container> 00164 struct all_containers<meta_class<Container> > 00165 { 00166 // TODO: inherited containers 00167 typedef typename mirror::mp::apply_on_seq_pack< 00168 mirror::aux::cntnr_helper<Container>, 00169 typename mirror::_container::_<Container>::cntnr_count 00170 >::type type; 00171 }; 00172 00173 template <class Container, class IsSpecial, int Index> 00174 struct default_traversal<meta_container<Container, IsSpecial, Index> > 00175 { 00176 typedef typename meta_container< 00177 Container, 00178 IsSpecial, 00179 Index 00180 >::_base_cntnr::default_traversal type; 00181 }; 00182 00183 template <class Container, class IsSpecial, int Index> 00184 struct traversals<meta_container<Container, IsSpecial, Index> > 00185 { 00186 typedef typename meta_container< 00187 Container, 00188 IsSpecial, 00189 Index 00190 >::_base_cntnr::traversals type; 00191 }; 00192 00193 template <class Container, class IsSpecial, int Index> 00194 struct locators<meta_container<Container, IsSpecial, Index> > 00195 { 00196 typedef typename meta_container< 00197 Container, 00198 IsSpecial, 00199 Index 00200 >::_base_cntnr::locators type; 00201 }; 00202 00203 template <class Container, class IsSpecial, int Index> 00204 struct inserters<meta_container<Container, IsSpecial, Index> > 00205 { 00206 typedef typename meta_container< 00207 Container, 00208 IsSpecial, 00209 Index 00210 >::_base_cntnr::inserters type; 00211 }; 00212 00213 template <class Container, class IsSpecial, int Index> 00214 struct erasers<meta_container<Container, IsSpecial, Index> > 00215 { 00216 typedef typename meta_container< 00217 Container, 00218 IsSpecial, 00219 Index 00220 >::_base_cntnr::erasers type; 00221 }; 00222 00223 // utilities 00224 00226 00234 struct element_traversal_info 00235 { 00236 #ifndef MIRROR_DOCUMNETATION_ONLY 00237 // Implementation details use the member functions instead 00238 int _elem_done; 00239 int _cntnr_idx; 00240 int _elem_idx; 00241 bool _first_cntnr; 00242 bool _last_cntnr; 00243 bool _first_elem; 00244 bool _last_elem; 00245 #endif 00246 00247 00252 const int elements_done(void) const 00253 { 00254 return _elem_done; 00255 } 00256 00258 00263 const int container_index(void) const 00264 { 00265 return _cntnr_idx; 00266 } 00267 00269 const bool first_container(void) const 00270 { 00271 return _first_cntnr; 00272 } 00273 00275 const bool last_container(void) const 00276 { 00277 return _last_cntnr; 00278 } 00279 00281 const int element_position(void) const 00282 { 00283 return _elem_idx; 00284 } 00285 00287 const bool first_in_container(void) const 00288 { 00289 return _first_elem; 00290 } 00291 00293 const bool last_in_container(void) const 00294 { 00295 return _last_elem; 00296 } 00297 }; 00298 00299 namespace aux { 00300 00301 template < 00302 typename Kind, 00303 typename Container, 00304 typename ElemFunctor, 00305 typename EmptyFunctor 00306 > 00307 struct trav_elems_hlpr 00308 { 00309 Kind& kind_tag; 00310 int& done; 00311 int& cntnr_idx; 00312 Container& cntnr; 00313 ElemFunctor& elem_func; 00314 EmptyFunctor& empty_func; 00315 00316 template <typename IterInfo> 00317 void operator()(IterInfo) const 00318 { 00319 typedef typename IterInfo::type meta_cntnr; 00320 if(meta_cntnr::empty(cntnr)) 00321 { 00322 element_traversal_info info = { 00323 done, 00324 cntnr_idx, 00325 -1, 00326 bool(IterInfo::is_first::value), 00327 bool(IterInfo::is_last::value), 00328 false, 00329 false 00330 }; 00331 empty_func(kind_tag, info); 00332 } 00333 else 00334 { 00335 auto tr = meta_cntnr:: 00336 default_traversal:: 00337 start(cntnr); 00338 int elem_idx = 0; 00339 while(!tr.done()) 00340 { 00341 auto loc = tr.front(); 00342 tr.step_front(); 00343 element_traversal_info info = { 00344 done, 00345 cntnr_idx, 00346 elem_idx, 00347 bool(IterInfo::is_first::value), 00348 bool(IterInfo::is_last::value), 00349 bool(elem_idx == 0), 00350 bool(tr.done()) 00351 }; 00352 elem_func(kind_tag, info, loc.get()); 00353 ++elem_idx; 00354 ++done; 00355 } 00356 } 00357 ++cntnr_idx; 00358 } 00359 }; 00360 00361 template < 00362 template <class> class Getter, 00363 class MetaType, 00364 typename Container, 00365 typename ElemFunctor, 00366 typename EmptyFunctor 00367 > int do_trav_elems( 00368 MetaType, 00369 Container& inst, 00370 ElemFunctor elem_func, 00371 EmptyFunctor empty_func 00372 ) 00373 { 00374 int done = 0, cntnr_idx = 0; 00375 typedef typename mirror::container_kind< 00376 MetaType 00377 >::type Kind; 00378 Kind kind; 00379 trav_elems_hlpr< 00380 Kind, 00381 Container, 00382 ElemFunctor, 00383 EmptyFunctor 00384 > hlpr = { 00385 kind, 00386 done, 00387 cntnr_idx, 00388 inst, 00389 elem_func, 00390 empty_func 00391 }; 00392 mirror::mp::for_each_ii< 00393 typename Getter<MetaType>::type 00394 >(hlpr); 00395 return done; 00396 } 00397 00398 } // namespace aux 00399 00400 template <typename Container, typename ElemFunctor, typename EmptyFunctor> 00401 int traverse_elements( 00402 meta_type<Container> mt, 00403 Container& inst, 00404 ElemFunctor elem_func, 00405 EmptyFunctor empty_func 00406 ) 00407 { 00408 return mirror::aux::do_trav_elems< 00409 mirror::containers 00410 >(mt, inst, elem_func, empty_func); 00411 } 00412 00413 template <typename Container, typename ElemFunctor, typename EmptyFunctor> 00414 int traverse_elements( 00415 meta_class<Container> mc, 00416 Container& inst, 00417 ElemFunctor elem_func, 00418 EmptyFunctor empty_func 00419 ) 00420 { 00421 return mirror::aux::do_trav_elems< 00422 mirror::all_containers 00423 >(mc, inst, elem_func, empty_func); 00424 } 00425 00426 MIRROR_NAMESPACE_END 00427 00428 #endif //include guard 00429