reflect.hpp 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. #pragma once
  2. #include <string>
  3. #include <unordered_map>
  4. template <typename Object>
  5. class reflection {
  6. private:
  7. template <typename T>
  8. using Field = T Object::*;
  9. public:
  10. reflection();
  11. template <typename T>
  12. static bool exists( std::string const & name ) {
  13. return s_reflector<T>.count( name );
  14. }
  15. template <typename T>
  16. static Field<T> get_pointer( std::string const & name ) {
  17. auto it = s_reflector<T>.find( name );
  18. if ( it == s_reflector<T>.end() ) { return nullptr; }
  19. return it->second;
  20. }
  21. template <typename T>
  22. static void bind( Field<T> field, std::string const & name, std::string const & /*discard*/ = "" ) {
  23. s_reflector<T>.reserve( s_reflector<T>.size() + 1 );
  24. s_reflector<T>.emplace( name, field );
  25. }
  26. private:
  27. template <typename T>
  28. static std::unordered_map<std::string, Field<T>> s_reflector;
  29. };
  30. #define REFLECT_MEMBER_PP_IMPL2( type, field, ... ) bind( &type::field, ##__VA_ARGS__, #field )
  31. #define REFLECT_MEMBER_PP_IMPL( type, field, ... ) REFLECT_MEMBER_PP_IMPL2( type, field, ##__VA_ARGS__ )
  32. #define UNWRAP( ... ) __VA_ARGS__
  33. #define REFLECT_MEMBER_PP2( data, elem ) REFLECT_MEMBER_PP_IMPL( data, UNWRAP elem )
  34. #define REFLECT_MEMBER_PP( r, data, elem ) REFLECT_MEMBER_PP2( data, elem );
  35. #include <boost/preprocessor/variadic/to_seq.hpp>
  36. #include <boost/preprocessor/seq/for_each.hpp>
  37. #define CONCAT2( A, B ) A##B
  38. #define CONCAT( A, B ) CONCAT2( A, B )
  39. #define CREATE_REFLECTION( type, ... ) \
  40. template <> reflection<type>::reflection() { \
  41. BOOST_PP_SEQ_FOR_EACH( REFLECT_MEMBER_PP, type, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__) ) \
  42. } \
  43. static reflection<type> CONCAT( reflector_, __LINE__ ) {}
  44. template <typename Object>
  45. template <typename T>
  46. std::unordered_map<std::string, T Object::*> reflection<Object>::s_reflector;