pfr.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /*
  2. * Copyright (c) 2017-2023 zhllxt
  3. *
  4. * author : zhllxt
  5. * email : 37792738@qq.com
  6. *
  7. * Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. */
  10. #ifndef __ASIO2_EXTERNAL_PFR_HPP__
  11. #define __ASIO2_EXTERNAL_PFR_HPP__
  12. #include <asio2/external/config.hpp>
  13. #if !defined(ASIO2_HEADER_ONLY) && __has_include(<boost/core/type_name.hpp>)
  14. #include <boost/core/type_name.hpp>
  15. #else
  16. #include <asio2/bho/core/type_name.hpp>
  17. #endif
  18. #include <string>
  19. #include <unordered_map>
  20. #include <memory>
  21. #include <functional>
  22. #include <type_traits>
  23. #if !defined(ASIO2_HEADER_ONLY) && __has_include(<boost/pfr.hpp>)
  24. #include <boost/pfr.hpp>
  25. namespace pfr = ::boost::pfr;
  26. #else
  27. #include <asio2/bho/pfr.hpp>
  28. namespace pfr = ::bho::pfr;
  29. #endif
  30. #if !defined(ASIO2_HEADER_ONLY) && __has_include(<boost/pfr.hpp>)
  31. namespace boost::pfr
  32. #else
  33. namespace bho::pfr
  34. #endif
  35. {
  36. namespace detail
  37. {
  38. template<int N> struct refl_encode_counter : refl_encode_counter<N - 1> {};
  39. template<> struct refl_encode_counter<0> {};
  40. struct __refl_members_iterator_dummy__
  41. {
  42. template<typename ThisType, typename Func>
  43. static inline void for_each_field(ThisType&, Func&)
  44. {
  45. }
  46. template<typename Func>
  47. static inline void for_each_field_name(Func&)
  48. {
  49. }
  50. };
  51. }
  52. //---------------------------------------------------------------------------------------------
  53. // this code is refrenced from : https://zhuanlan.zhihu.com/p/320061875
  54. // this code has some unresolved problems.
  55. // eg:
  56. // struct actor : public dynamic_creator<actor, std::string, const char*>
  57. // create<actor>("abc", "xyz");
  58. // the create function will failed, beacuse the "abc" type is not equal to std::string, and the
  59. // "xyz" type is not equal to const char*
  60. // you must call the create function like this:
  61. // create<actor>(std::string("abc"), (const char*)"xyz");
  62. // This is terrible.
  63. // Is it possible to use serialization to solve this problem?
  64. //---------------------------------------------------------------------------------------------
  65. template<typename BaseT, typename... Args>
  66. class class_factory
  67. {
  68. private:
  69. class_factory() {}
  70. ~class_factory() {}
  71. public:
  72. static class_factory<BaseT, Args...>& instance()
  73. {
  74. static class_factory<BaseT, Args...> inst{};
  75. return inst;
  76. }
  77. bool regist(std::string name, std::function<BaseT*(Args&&... args)> fn)
  78. {
  79. if (!fn)
  80. return(false);
  81. return create_functions_.emplace(std::move(name), std::move(fn)).second;
  82. }
  83. BaseT* create(const std::string& name, Args&&... args)
  84. {
  85. auto iter = create_functions_.find(name);
  86. if (iter == create_functions_.end())
  87. {
  88. return (nullptr);
  89. }
  90. else
  91. {
  92. return ((iter->second)(std::forward<Args>(args)...));
  93. }
  94. }
  95. template<class Function>
  96. void for_each(Function&& callback) noexcept
  97. {
  98. for (const auto& [name, func] : create_functions_)
  99. {
  100. callback(name, func);
  101. }
  102. }
  103. std::function<BaseT* (Args&&...)>* find(const std::string& name)
  104. {
  105. auto it = create_functions_.find(name);
  106. return it == create_functions_.end() ? nullptr : std::addressof(it->second);
  107. }
  108. inline std::size_t size() const noexcept
  109. {
  110. return create_functions_.size();
  111. }
  112. inline bool empty() const noexcept
  113. {
  114. return create_functions_.empty();
  115. }
  116. private:
  117. std::unordered_map<std::string, std::function<BaseT*(Args&&...)>> create_functions_;
  118. };
  119. template<typename BaseT, typename T, typename ...Args>
  120. class base_dynamic_creator
  121. {
  122. public:
  123. struct registor
  124. {
  125. registor()
  126. {
  127. std::string name;
  128. #if !defined(ASIO2_HEADER_ONLY) && __has_include(<boost/core/type_name.hpp>)
  129. name = boost::core::type_name<T>();
  130. #else
  131. name = bho::core::type_name<T>();
  132. #endif
  133. class_factory<BaseT, Args...>::instance().regist(std::move(name), create);
  134. }
  135. inline void makesure_construct() const noexcept { };
  136. };
  137. explicit base_dynamic_creator() noexcept
  138. {
  139. registor_.makesure_construct();
  140. }
  141. virtual ~base_dynamic_creator() noexcept
  142. {
  143. registor_.makesure_construct();
  144. };
  145. private:
  146. static BaseT* create(Args&&... args)
  147. {
  148. return (new T(std::forward<Args>(args)...));
  149. }
  150. private:
  151. static inline registor registor_{};
  152. };
  153. template<typename BaseT, typename T, typename ...Args>
  154. using dynamic_creator = base_dynamic_creator<BaseT, T, Args...>;
  155. template<typename T, typename ...Args>
  156. class self_dynamic_creator
  157. {
  158. public:
  159. struct registor
  160. {
  161. registor()
  162. {
  163. std::string name;
  164. #if !defined(ASIO2_HEADER_ONLY) && __has_include(<boost/core/type_name.hpp>)
  165. name = boost::core::type_name<T>();
  166. #else
  167. name = bho::core::type_name<T>();
  168. #endif
  169. class_factory<T, Args...>::instance().regist(std::move(name), create);
  170. }
  171. inline void makesure_construct() const noexcept { };
  172. };
  173. explicit self_dynamic_creator() noexcept
  174. {
  175. registor_.makesure_construct();
  176. }
  177. virtual ~self_dynamic_creator() noexcept
  178. {
  179. registor_.makesure_construct();
  180. };
  181. private:
  182. static T* create(Args&&... args)
  183. {
  184. return (new T(std::forward<Args>(args)...));
  185. }
  186. private:
  187. static inline registor registor_{};
  188. };
  189. template<typename BaseT>
  190. class create_helper
  191. {
  192. public:
  193. // dont use Args&&... args
  194. // it will cause issue like this:
  195. // int i = 2;
  196. // create("dog", i);
  197. // the i will be parsed as int&
  198. template<typename ...Args>
  199. static inline BaseT* create(const std::string& name, Args... args)
  200. {
  201. return (class_factory<BaseT, Args...>::instance().create(
  202. name, std::move(args)...));
  203. }
  204. };
  205. template<typename BaseT>
  206. class create_helper<BaseT*>
  207. {
  208. public:
  209. template<typename ...Args>
  210. static inline BaseT* create(const std::string& name, Args... args)
  211. {
  212. return (class_factory<BaseT, Args...>::instance().create(
  213. name, std::move(args)...));
  214. }
  215. };
  216. template<typename BaseT>
  217. class create_helper<std::shared_ptr<BaseT>>
  218. {
  219. public:
  220. template<typename ...Args>
  221. static inline std::shared_ptr<BaseT> create(const std::string& name, Args... args)
  222. {
  223. return std::shared_ptr<BaseT>(class_factory<BaseT, Args...>::instance().create(
  224. name, std::move(args)...));
  225. }
  226. };
  227. template<typename BaseT>
  228. class create_helper<std::unique_ptr<BaseT>>
  229. {
  230. public:
  231. template<typename ...Args>
  232. static inline std::unique_ptr<BaseT> create(const std::string& name, Args... args)
  233. {
  234. return std::unique_ptr<BaseT>(class_factory<BaseT, Args...>::instance().create(
  235. name, std::move(args)...));
  236. }
  237. };
  238. }
  239. // this code is refrenced from :
  240. // https://github.com/yuanzhubi/reflect_struct
  241. // boost/typeof/dmc/typeof_impl.hpp
  242. #ifndef MAX_REFLECT_COUNT
  243. #define MAX_REFLECT_COUNT 480
  244. #endif
  245. #define BHO_REFLECT_INDEX(counter) \
  246. ((sizeof(*counter((pfr::detail::refl_encode_counter<MAX_REFLECT_COUNT>*)0)) - \
  247. sizeof(*counter((void*)0))) / sizeof(char)) \
  248. #define BHO_REFLECT_INCREASE(counter, index) \
  249. static constexpr std::size_t index = BHO_REFLECT_INDEX(counter); \
  250. static char (*counter(pfr::detail::refl_encode_counter< \
  251. sizeof(*counter((void*)0)) / sizeof(char) + index + 1>*)) \
  252. [sizeof(*counter((void*)0)) / sizeof(char) + index + 1]; \
  253. #define BHO_REFLECT_FIELD_INDEX(name) ASIO2_JOIN(__reflect_index_, name)
  254. #define F_FIELD_MEMBER_ITERATOR(type, name) \
  255. private: \
  256. BHO_REFLECT_INCREASE(__refl_field_counter__, BHO_REFLECT_FIELD_INDEX(name)) \
  257. template <typename T> \
  258. struct __refl_members_iterator__<T, BHO_REFLECT_FIELD_INDEX(name)> \
  259. { \
  260. typedef __refl_members_iterator__<T, BHO_REFLECT_FIELD_INDEX(name) + 1> next_type; \
  261. template<typename ThisType, typename Func> \
  262. static void for_each_field(ThisType& This, Func& func) noexcept \
  263. { \
  264. func(ASIO2_STRINGIZE(name), This.name); \
  265. next_type::for_each_field(This, func); \
  266. } \
  267. template<typename Func> \
  268. static void for_each_field_name(Func& func) noexcept \
  269. { \
  270. func(ASIO2_STRINGIZE(name)); \
  271. next_type::for_each_field_name(func); \
  272. } \
  273. } \
  274. #define F_BEGIN(Class) \
  275. private: \
  276. static char (*__refl_field_counter__(...))[1]; \
  277. template<typename T, int N = -1> struct __refl_members_iterator__ : \
  278. public pfr::detail::__refl_members_iterator_dummy__{}; \
  279. public: \
  280. template<typename Func> \
  281. void for_each_field(Func&& func) noexcept \
  282. { \
  283. decltype(auto) fun = std::forward<Func>(func); \
  284. __refl_members_iterator__<int, 0>::for_each_field(*this, fun); \
  285. } \
  286. template<typename Func> \
  287. static void for_each_field_name(Func&& func) noexcept \
  288. { \
  289. decltype(auto) fun = std::forward<Func>(func); \
  290. __refl_members_iterator__<int, 0>::for_each_field_name(fun); \
  291. } \
  292. inline static constexpr std::string_view get_class_name() noexcept \
  293. { \
  294. return ASIO2_STRINGIZE(Class); \
  295. } \
  296. template<typename T, int N> friend struct __refl_members_iterator__ \
  297. #define F_FIELD(type, name) \
  298. public: \
  299. type name{}; \
  300. F_FIELD_MEMBER_ITERATOR(type, name) \
  301. #define F_END() \
  302. public: \
  303. constexpr static std::size_t get_field_count() noexcept \
  304. { \
  305. constexpr std::size_t field_count = BHO_REFLECT_INDEX(__refl_field_counter__); \
  306. return field_count; \
  307. } \
  308. #endif