Mirror reflection library 0.5.13

mirror/meta_enum.hpp

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

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.