Mirror reflection library - Rubber type-erasure utility 0.5.13
|
00001 00010 #ifndef RUBBER_RANGE_1103151301_HPP 00011 #define RUBBER_RANGE_1103151301_HPP 00012 00013 #include <rubber/config.hpp> 00014 #include <rubber/wrap.hpp> 00015 00016 #include <mirror/meta_prog/range.hpp> 00017 00018 #include <vector> 00019 #include <functional> 00020 00021 RUBBER_NAMESPACE_BEGIN 00022 00023 template <typename TypeErased> 00024 class range; 00025 00027 00032 struct iteration_info 00033 { 00035 bool is_first; 00037 bool is_last; 00038 }; 00039 00041 00046 template <typename TypeErased> 00047 class range 00048 { 00049 private: 00050 typedef typename aux::return_value<TypeErased>::type 00051 (*member_getter)(void); 00052 00053 const std::vector<member_getter>& getters; 00054 typename std::vector<member_getter>::const_iterator pos; 00055 public: 00056 range(const std::vector<member_getter>& _getters) 00057 : getters(_getters) 00058 , pos(getters.begin()) 00059 { } 00060 00062 inline bool empty(void) const 00063 { 00064 return getters.end() == pos; 00065 } 00066 00068 inline size_t size(void) const 00069 { 00070 return getters.end() - pos; 00071 } 00072 00073 #ifdef MIRROR_DOCUMENTATION_ONLY 00074 00075 TypeErased front(void) const; 00076 #else 00077 inline typename aux::return_value<TypeErased>::type front(void) const 00078 { 00079 assert(!empty()); 00080 return (*pos)(); 00081 } 00082 #endif 00083 00084 #ifdef MIRROR_DOCUMENTATION_ONLY 00085 00086 TypeErased at(size_t index) const; 00087 #else 00088 inline typename aux::return_value<TypeErased>::type at(size_t idx) const 00089 { 00090 assert(idx < size()); 00091 return (*(pos + idx))(); 00092 } 00093 #endif 00094 00096 inline void step_front(void) 00097 { 00098 assert(!empty()); 00099 ++pos; 00100 } 00101 00103 void for_each(const std::function<void(const TypeErased&)>& func) const 00104 { 00105 if(!empty()) 00106 { 00107 range tmp = *this; 00108 while(!tmp.empty()) 00109 { 00110 func(tmp.front()); 00111 tmp.step_front(); 00112 } 00113 } 00114 } 00115 00117 00121 void for_each_ii( 00122 const std::function< 00123 void(const TypeErased&, const iteration_info&) 00124 >& func 00125 ) const 00126 { 00127 if(!empty()) 00128 { 00129 auto tmp_pos = pos; 00130 auto tmp_get = *tmp_pos; 00131 ++tmp_pos; 00132 struct iteration_info iter_info = { 00133 true, 00134 tmp_pos == getters.end() 00135 }; 00136 func(tmp_get(), iter_info); 00137 iter_info.is_first = false; 00138 while(tmp_pos != getters.end()) 00139 { 00140 tmp_get = *tmp_pos; 00141 ++tmp_pos; 00142 iter_info.is_last = tmp_pos == getters.end(); 00143 func(tmp_get(), iter_info); 00144 } 00145 } 00146 } 00147 }; 00148 00149 template <class TypeErased> 00150 class range_holder 00151 { 00152 private: 00153 typedef typename aux::return_value<TypeErased>::type 00154 (*getter)(void); 00155 00156 std::vector<getter> _getters; 00157 00158 template <typename ... MetaObjects> 00159 static std::vector<getter> init_getters( 00160 mirror::mp::range<MetaObjects...> 00161 ) 00162 { 00163 return {&wrap_shaped<MetaObjects, TypeErased>...}; 00164 } 00165 public: 00166 template <template <class> class Getter, class MetaObject> 00167 range_holder(Getter<MetaObject>) 00168 : _getters( 00169 init_getters( 00170 typename mirror::mp::as_range< 00171 Getter<MetaObject> 00172 >::type() 00173 ) 00174 ) 00175 { } 00176 00177 range_holder(mirror::mp::empty_range) 00178 { } 00179 00180 range<TypeErased> all(void) const 00181 { 00182 return range<TypeErased>(_getters); 00183 } 00184 }; 00185 00186 RUBBER_NAMESPACE_END 00187 00188 #endif //include guard 00189