Mirror reflection library - Rubber type-erasure utility 0.5.13

rubber/range.hpp

Go to the documentation of this file.
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 

Copyright © 2006-2011 Matus Chochlik, University of Zilina, Zilina, Slovakia.
<matus.chochlik -at- fri.uniza.sk>
<chochlik -at -gmail.com>
Documentation generated on Fri Dec 16 2011 by Doxygen (version 1.7.3).
Important note: Although the 'boostified' version of Mirror uses the Boost C++ libraries Coding Guidelines and is implemented inside of the boost namespace, it IS NOT an officially reviewed and accepted Boost library. Mirror is being developed with the intention to be submitted for review for inclusion to the Boost C++ libraries.