Mirror reflection library 0.5.13
|
00001 00010 #ifndef MIRROR_META_ENUM_1101121701_HPP 00011 #define MIRROR_META_ENUM_1101121701_HPP 00012 00013 #include <mirror/meta_namespace.hpp> 00014 #include <mirror/meta_type.hpp> 00015 #include <mirror/specifier_tags.hpp> 00016 #include <mirror/auxiliary/enum_values.hpp> 00017 #include <mirror/meta_prog/range.hpp> 00018 #include <mirror/meta_prog/apply_on_seq_pack.hpp> 00019 #include <mirror/meta_prog/make_int_seq.hpp> 00020 #include <vector> 00021 00022 MIRROR_NAMESPACE_BEGIN 00023 00024 #define MIRROR_REG_GLOBAL_SCOPE_ENUM_BEGIN_CTS(NAME, SPELLED) \ 00025 MIRROR_REG_GLOBAL_SCOPE_TYPE_BASICS(enum, NAME, SPELLED) \ 00026 MIRROR_ADD_TO_GLOBAL_LIST( \ 00027 mirror::_namespace :: _, \ 00028 mirror::meta_enum< NAME > \ 00029 ) \ 00030 namespace _enum { \ 00031 template <> \ 00032 struct _< NAME > \ 00033 { \ 00034 typedef NAME _this_enum; \ 00035 typedef std::integral_constant<int, 0> 00036 00037 #ifdef MIRROR_DOCUMENTATION_ONLY 00038 00039 00046 #define MIRROR_REG_GLOBAL_SCOPE_ENUM_BEGIN(ENUM) 00047 #else 00048 #define MIRROR_REG_GLOBAL_SCOPE_ENUM_BEGIN(ENUM) \ 00049 MIRROR_REG_GLOBAL_SCOPE_ENUM_BEGIN_CTS(ENUM, ()) 00050 #endif 00051 00052 #define MIRROR_REG_ENUM_BEGIN_CTS(NAMESPACE, NAME, SPELLED) \ 00053 MIRROR_REG_TYPE_BASICS(enum, NAMESPACE, NAME, SPELLED) \ 00054 MIRROR_ADD_TO_GLOBAL_LIST( \ 00055 mirror::_namespace :: NAMESPACE :: _, \ 00056 mirror::meta_enum< :: NAMESPACE :: NAME > \ 00057 ) \ 00058 namespace _enum { \ 00059 template <> \ 00060 struct _< :: NAMESPACE :: NAME > \ 00061 { \ 00062 typedef :: NAMESPACE :: NAME _this_enum; \ 00063 typedef std::integral_constant<int, 0> 00064 00065 #ifdef MIRROR_DOCUMENTATION_ONLY 00066 00067 00075 #define MIRROR_REG_ENUM_BEGIN(NAMESPACE, ENUM) 00076 #else 00077 #define MIRROR_REG_ENUM_BEGIN(NAMESPACE, ENUM) \ 00078 MIRROR_REG_ENUM_BEGIN_CTS(NAMESPACE, ENUM, ()) 00079 #endif 00080 00081 #define MIRROR_REG_NESTED_ENUM_BEGIN_CTS(PARENT_CLASS, NAME, SPELLED) \ 00082 MIRROR_REG_NESTED_TYPE_BASICS(enum, PARENT_CLASS, NAME, SPELLED) \ 00083 namespace _enum { \ 00084 template <> \ 00085 struct _< :: PARENT_CLASS :: NAME > \ 00086 { \ 00087 typedef :: PARENT_CLASS :: NAME _this_enum; \ 00088 typedef std::integral_constant<int, 0> 00089 00090 #ifdef MIRROR_DOCUMENTATION_ONLY 00091 00092 00101 #define MIRROR_REG_NESTED_ENUM_BEGIN(PARENT_CLASS, ENUM) 00102 #else 00103 #define MIRROR_REG_NESTED_ENUM_BEGIN(PARENT_CLASS, ENUM) \ 00104 MIRROR_REG_NESTED_ENUM_BEGIN_CTS(PARENT_CLASS, ENUM, ()) 00105 #endif 00106 00107 #ifdef MIRROR_DOCUMENTATION_ONLY 00108 00109 00114 #define MIRROR_REG_ENUM_END 00115 #else 00116 #define MIRROR_REG_ENUM_END \ 00117 item_count; \ 00118 }; /* struct _enum::<...> */ \ 00119 } /* namespace _enum */ 00120 #endif 00121 00122 #define MIRROR_REG_ENUM_VALUE_CTS(ENUM_VALUE, SPELLED) \ 00123 item_ ## ENUM_VALUE; \ 00124 static std::integral_constant<_this_enum, _this_enum::ENUM_VALUE > \ 00125 item_val(item_ ## ENUM_VALUE); \ 00126 static inline _this_enum \ 00127 item_val_c(item_ ## ENUM_VALUE) \ 00128 { \ 00129 return _this_enum::ENUM_VALUE ;\ 00130 } \ 00131 static const char* item_name(item_ ## ENUM_VALUE) \ 00132 { \ 00133 return #ENUM_VALUE; \ 00134 } \ 00135 static size_t item_name_length(item_ ## ENUM_VALUE) \ 00136 { \ 00137 return sizeof(#ENUM_VALUE) - 1; \ 00138 } \ 00139 static typename mirror::cts::string< \ 00140 MIRROR_PP_EXPAND_ARGS SPELLED \ 00141 >::type item_ct_name(item_ ## ENUM_VALUE); \ 00142 typedef std::integral_constant<int, item_ ## ENUM_VALUE :: value + 1> 00143 00144 #ifdef MIRROR_DOCUMENTATION_ONLY 00145 00146 00151 #define MIRROR_REG_ENUM_VALUE(ENUM_VALUE) 00152 #else 00153 #define MIRROR_REG_ENUM_VALUE(ENUM_VALUE) \ 00154 MIRROR_REG_ENUM_VALUE_CTS(ENUM_VALUE, ()) 00155 #endif 00156 00157 template <class Enum> 00158 struct meta_enum 00159 : public meta_type<Enum> 00160 { 00161 public: 00162 typedef typename mirror::_enum::_<Enum>::item_count size; 00163 00164 template <int I> 00165 static Enum value(std::integral_constant<int, I> index) 00166 { 00167 return mirror::_enum::_<Enum>::item_val_c(index); 00168 } 00169 00170 template <int I> 00171 static std::string value_name(std::integral_constant<int, I> index) 00172 { 00173 return std::string( 00174 mirror::_enum::_<Enum>::item_name(index), 00175 mirror::_enum::_<Enum>::item_name_length(index) 00176 ); 00177 } 00178 private: 00179 template <typename ... Idx> 00180 static std::vector<Enum> cache_values(mp::range<Idx ...>) 00181 { 00182 return {mirror::_enum::_<Enum>::item_val_c(Idx())...}; 00183 } 00184 00185 template <typename ... Idx> 00186 static std::vector<const char*> cache_names(mp::range<Idx ...>) 00187 { 00188 return {mirror::_enum::_<Enum>::item_name(Idx())...}; 00189 } 00190 00191 static const std::vector<Enum>& _value_cache(void) 00192 { 00193 typename mp::make_index_seq<size>::type indices; 00194 static auto cache = cache_values(indices); 00195 return cache; 00196 } 00197 public: 00198 00199 //NOTE: this is an implementation detail, do not use in client code 00200 static const std::vector<const char*>& _name_cache(void) 00201 { 00202 typename mp::make_index_seq<size>::type indices; 00203 static auto cache = cache_names(indices); 00204 return cache; 00205 } 00206 00207 static Enum value(int index) 00208 { 00209 assert(index >= 0); 00210 assert(index < size::value); 00211 return _value_cache()[index]; 00212 } 00213 00214 static std::string value_name(int index) 00215 { 00216 assert(index >= 0); 00217 assert(index < size::value); 00218 return _name_cache()[index]; 00219 } 00220 00221 static std::string name_by_value(Enum x) 00222 { 00223 for(int i=0; i!= size::value; ++i) 00224 if(value(i) == x) 00225 return value_name(i); 00226 return std::string(); 00227 } 00228 00229 static Enum value_by_name(const std::string& x) 00230 { 00231 for(int i=0; i!= size::value; ++i) 00232 if(value_name(i) == x) 00233 return value(i); 00234 return Enum(); 00235 } 00236 00237 static bool has_value_name(const std::string& x) 00238 { 00239 for(int i=0; i!= size::value; ++i) 00240 if(value_name(i) == x) 00241 return true; 00242 return false; 00243 } 00244 }; 00245 00246 template <class Enum, int Index> 00247 struct meta_enum_value 00248 { 00249 public: 00250 typedef std::integral_constant<int, Index> position; 00251 typedef meta_enum<Enum> scope; 00252 00253 private: 00254 template <typename Local> 00255 static std::string make_name(Local local) 00256 { 00257 // get the full or local name of the scope 00258 std::string result( 00259 Local::value ? 00260 scope::local_name() : 00261 scope::full_name() 00262 ); 00263 // append the separating double colon 00264 result.append("::"); 00265 // and append the base name of this member variable 00266 result.append(base_name()); 00267 // return the result 00268 return result; 00269 } 00270 public: 00271 typedef decltype(mirror::_enum::_<Enum>::item_ct_name(position())) 00272 static_name; 00273 00274 // returns the base name of the member variable 00275 static std::string base_name(void) 00276 { 00277 return std::string( 00278 mirror::_enum::_<Enum>::item_name(position()), 00279 mirror::_enum::_<Enum>::item_name_length(position()) 00280 ); 00281 } 00282 00283 // returns the full name (including the full nested name qualifier) 00284 static std::string full_name(void) 00285 { 00286 return make_name(std::false_type()); 00287 } 00288 00289 // returns the local name (including partial nested name qualifier) 00290 static std::string local_name(void) 00291 { 00292 return make_name(std::true_type()); 00293 } 00294 00295 typedef decltype(mirror::_enum::_<Enum>::item_val(position())) value; 00296 }; 00297 00298 template <class Enum> 00299 struct enum_values<meta_enum<Enum> > 00300 { 00301 typedef typename mp::apply_on_seq_pack< 00302 mirror::aux::enum_val_helper<Enum>, 00303 typename mirror::_enum::_<Enum>::item_count 00304 >::type type; 00305 }; 00306 00307 template <typename Enum> 00308 struct members<meta_enum<Enum> > 00309 { 00310 typedef typename enum_values<meta_enum<Enum> >::type type; 00311 }; 00312 00313 template <class Class> 00314 struct constructors<meta_enum<Class> > 00315 : constructors<meta_type<Class> > 00316 { }; 00317 00318 00319 #ifdef MIRROR_DOCUMENTATION_ONLY 00320 00321 00334 #define MIRRORED_ENUM(FULL_ENUM_NAME) mirror::MetaEnum 00335 #else 00336 #define MIRRORED_ENUM(FULL_ENUM_NAME) \ 00337 mirror::meta_enum< FULL_ENUM_NAME > 00338 #endif 00339 00340 MIRROR_NAMESPACE_END 00341 00342 #endif //include guard 00343