Mirror reflection library - Rubber type-erasure utility 0.5.13
|
00001 00010 #ifndef RUBBER_RUBBER_1103151301_HPP 00011 #define RUBBER_RUBBER_1103151301_HPP 00012 00013 #include <rubber/config.hpp> 00014 #include <rubber/wrap.hpp> 00015 #include <rubber/range.hpp> 00016 #include <rubber/specifiers.hpp> 00017 #include <rubber/meta_objects.hpp> 00018 #include <puddle/auxiliary/fwd.hpp> 00019 00020 #include <functional> 00021 00040 00041 00044 RUBBER_NAMESPACE_BEGIN 00045 00046 template <class MirrorMetaObject> 00047 auto erase_type(void) -> 00048 decltype(wrap<MirrorMetaObject>()) 00049 { 00050 return wrap<MirrorMetaObject>(); 00051 } 00052 00053 template <class MirrorMetaObject> 00054 auto erase_type(const puddle::aux::meta_type<MirrorMetaObject>& mo) -> 00055 decltype(wrap<MirrorMetaObject>()) 00056 { 00057 return wrap<MirrorMetaObject>(); 00058 } 00059 00060 namespace aux { 00061 00062 template <typename ... Wrappers> 00063 class eraser_base; 00064 00065 template <> 00066 class eraser_base<> 00067 { 00068 public: 00069 template <typename MetaObject> 00070 void call(const MetaObject& mo) const 00071 { } 00072 }; 00073 00074 template <typename Wrapper, typename ... Wrappers> 00075 class eraser_base<Wrapper, Wrappers ...> 00076 { 00077 private: 00078 typedef std::function<void(const Wrapper&)> functor_type; 00079 functor_type functor; 00080 eraser_base<Wrappers...> base; 00081 00082 template <typename MetaObject> 00083 void do_call(const MetaObject& mo, std::false_type) const 00084 { 00085 base.call(mo); 00086 } 00087 00088 template <typename MetaObject> 00089 void do_call(const MetaObject& mo, std::true_type) const 00090 { 00091 functor(wrap_into<Wrapper>(mo)); 00092 } 00093 public: 00094 eraser_base( 00095 const functor_type& func, 00096 const std::function<void(const Wrappers&)>& ... fns 00097 ): functor(func) 00098 , base(fns ...) 00099 { } 00100 00101 template <typename MetaObject> 00102 void call(const MetaObject& mo) const 00103 { 00104 typename mirror::mp::is_a< 00105 MetaObject, 00106 typename tag_by_wrapper<Wrapper>::type 00107 >::type selector; 00108 do_call(mo, selector); 00109 } 00110 }; 00111 00112 } // namespace aux 00113 00114 template <typename ... Wrappers> 00115 class eraser 00116 { 00117 private: 00118 aux::eraser_base<Wrappers...> base; 00119 public: 00120 eraser(const std::function<void(const Wrappers&)>& ... fns) 00121 : base(fns...) 00122 { } 00123 00124 template <typename MetaObject> 00125 void operator()(MetaObject mo) const 00126 { 00127 base.call(mo); 00128 } 00129 }; 00130 00131 RUBBER_NAMESPACE_END 00132 00133 #endif //include guard 00134