meta.hpp 75 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995
  1. #ifndef ENTT_META_META_HPP
  2. #define ENTT_META_META_HPP
  3. #include <cstddef>
  4. #include <iterator>
  5. #include <memory>
  6. #include <type_traits>
  7. #include <utility>
  8. #include "../config/config.h"
  9. #include "../core/any.hpp"
  10. #include "../core/fwd.hpp"
  11. #include "../core/iterator.hpp"
  12. #include "../core/type_info.hpp"
  13. #include "../core/type_traits.hpp"
  14. #include "../core/utility.hpp"
  15. #include "../locator/locator.hpp"
  16. #include "adl_pointer.hpp"
  17. #include "context.hpp"
  18. #include "fwd.hpp"
  19. #include "node.hpp"
  20. #include "range.hpp"
  21. #include "type_traits.hpp"
  22. namespace entt {
  23. class meta_any;
  24. class meta_type;
  25. /*! @brief Proxy object for sequence containers. */
  26. class meta_sequence_container {
  27. class meta_iterator;
  28. public:
  29. /*! @brief Unsigned integer type. */
  30. using size_type = std::size_t;
  31. /*! @brief Meta iterator type. */
  32. using iterator = meta_iterator;
  33. /*! @brief Default constructor. */
  34. meta_sequence_container() noexcept
  35. : meta_sequence_container{locator<meta_ctx>::value_or()} {}
  36. /**
  37. * @brief Context aware constructor.
  38. * @param area The context from which to search for meta types.
  39. */
  40. meta_sequence_container(const meta_ctx &area) noexcept
  41. : ctx{&area} {}
  42. /**
  43. * @brief Rebinds a proxy object to a sequence container type.
  44. * @tparam Type Type of container to wrap.
  45. * @param instance The container to wrap.
  46. */
  47. template<typename Type>
  48. void rebind(Type &instance) noexcept {
  49. value_type_node = &internal::resolve<typename Type::value_type>;
  50. const_reference_node = &internal::resolve<std::remove_const_t<std::remove_reference_t<typename Type::const_reference>>>;
  51. size_fn = meta_sequence_container_traits<std::remove_const_t<Type>>::size;
  52. clear_fn = meta_sequence_container_traits<std::remove_const_t<Type>>::clear;
  53. reserve_fn = meta_sequence_container_traits<std::remove_const_t<Type>>::reserve;
  54. resize_fn = meta_sequence_container_traits<std::remove_const_t<Type>>::resize;
  55. begin_fn = meta_sequence_container_traits<std::remove_const_t<Type>>::begin;
  56. end_fn = meta_sequence_container_traits<std::remove_const_t<Type>>::end;
  57. insert_fn = meta_sequence_container_traits<std::remove_const_t<Type>>::insert;
  58. erase_fn = meta_sequence_container_traits<std::remove_const_t<Type>>::erase;
  59. const_only = std::is_const_v<Type>;
  60. data = &instance;
  61. }
  62. [[nodiscard]] inline meta_type value_type() const noexcept;
  63. [[nodiscard]] inline size_type size() const noexcept;
  64. inline bool resize(const size_type);
  65. inline bool clear();
  66. inline bool reserve(const size_type);
  67. [[nodiscard]] inline iterator begin();
  68. [[nodiscard]] inline iterator end();
  69. inline iterator insert(iterator, meta_any);
  70. inline iterator erase(iterator);
  71. [[nodiscard]] inline meta_any operator[](const size_type);
  72. [[nodiscard]] inline explicit operator bool() const noexcept;
  73. private:
  74. const meta_ctx *ctx{};
  75. internal::meta_type_node (*value_type_node)(const internal::meta_context &){};
  76. internal::meta_type_node (*const_reference_node)(const internal::meta_context &){};
  77. size_type (*size_fn)(const void *){};
  78. bool (*clear_fn)(void *){};
  79. bool (*reserve_fn)(void *, const size_type){};
  80. bool (*resize_fn)(void *, const size_type){};
  81. iterator (*begin_fn)(const meta_ctx &, void *, const void *){};
  82. iterator (*end_fn)(const meta_ctx &, void *, const void *){};
  83. iterator (*insert_fn)(const meta_ctx &, void *, const void *, const void *, const iterator &){};
  84. iterator (*erase_fn)(const meta_ctx &, void *, const iterator &){};
  85. const void *data{};
  86. bool const_only{};
  87. };
  88. /*! @brief Proxy object for associative containers. */
  89. class meta_associative_container {
  90. class meta_iterator;
  91. public:
  92. /*! @brief Unsigned integer type. */
  93. using size_type = std::size_t;
  94. /*! @brief Meta iterator type. */
  95. using iterator = meta_iterator;
  96. /*! @brief Default constructor. */
  97. meta_associative_container() noexcept
  98. : meta_associative_container{locator<meta_ctx>::value_or()} {}
  99. /**
  100. * @brief Context aware constructor.
  101. * @param area The context from which to search for meta types.
  102. */
  103. meta_associative_container(const meta_ctx &area) noexcept
  104. : ctx{&area} {}
  105. /**
  106. * @brief Rebinds a proxy object to an associative container type.
  107. * @tparam Type Type of container to wrap.
  108. * @param instance The container to wrap.
  109. */
  110. template<typename Type>
  111. void rebind(Type &instance) noexcept {
  112. key_type_node = &internal::resolve<typename Type::key_type>;
  113. value_type_node = &internal::resolve<typename Type::value_type>;
  114. if constexpr(!meta_associative_container_traits<std::remove_const_t<Type>>::key_only) {
  115. mapped_type_node = &internal::resolve<typename Type::mapped_type>;
  116. }
  117. size_fn = &meta_associative_container_traits<std::remove_const_t<Type>>::size;
  118. clear_fn = &meta_associative_container_traits<std::remove_const_t<Type>>::clear;
  119. reserve_fn = &meta_associative_container_traits<std::remove_const_t<Type>>::reserve;
  120. begin_fn = &meta_associative_container_traits<std::remove_const_t<Type>>::begin;
  121. end_fn = &meta_associative_container_traits<std::remove_const_t<Type>>::end;
  122. insert_fn = &meta_associative_container_traits<std::remove_const_t<Type>>::insert;
  123. erase_fn = &meta_associative_container_traits<std::remove_const_t<Type>>::erase;
  124. find_fn = &meta_associative_container_traits<std::remove_const_t<Type>>::find;
  125. const_only = std::is_const_v<Type>;
  126. data = &instance;
  127. }
  128. [[nodiscard]] inline bool key_only() const noexcept;
  129. [[nodiscard]] inline meta_type key_type() const noexcept;
  130. [[nodiscard]] inline meta_type mapped_type() const noexcept;
  131. [[nodiscard]] inline meta_type value_type() const noexcept;
  132. [[nodiscard]] inline size_type size() const noexcept;
  133. inline bool clear();
  134. inline bool reserve(const size_type);
  135. [[nodiscard]] inline iterator begin();
  136. [[nodiscard]] inline iterator end();
  137. inline bool insert(meta_any, meta_any);
  138. inline size_type erase(meta_any);
  139. [[nodiscard]] inline iterator find(meta_any);
  140. [[nodiscard]] inline explicit operator bool() const noexcept;
  141. private:
  142. const meta_ctx *ctx{};
  143. internal::meta_type_node (*key_type_node)(const internal::meta_context &){};
  144. internal::meta_type_node (*mapped_type_node)(const internal::meta_context &){};
  145. internal::meta_type_node (*value_type_node)(const internal::meta_context &){};
  146. size_type (*size_fn)(const void *){};
  147. bool (*clear_fn)(void *){};
  148. bool (*reserve_fn)(void *, const size_type){};
  149. iterator (*begin_fn)(const meta_ctx &, void *, const void *){};
  150. iterator (*end_fn)(const meta_ctx &, void *, const void *){};
  151. bool (*insert_fn)(void *, const void *, const void *){};
  152. size_type (*erase_fn)(void *, const void *){};
  153. iterator (*find_fn)(const meta_ctx &, void *, const void *, const void *){};
  154. const void *data{};
  155. bool const_only{};
  156. };
  157. /*! @brief Possible modes of a meta any object. */
  158. using meta_any_policy = any_policy;
  159. /*! @brief Opaque wrapper for values of any type. */
  160. class meta_any {
  161. using vtable_type = void(const internal::meta_traits op, const bool, const void *, void *);
  162. template<typename Type>
  163. static std::enable_if_t<std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, Type>> basic_vtable([[maybe_unused]] const internal::meta_traits req, [[maybe_unused]] const bool const_only, [[maybe_unused]] const void *value, [[maybe_unused]] void *other) {
  164. if constexpr(is_meta_pointer_like_v<Type>) {
  165. if(req == internal::meta_traits::is_meta_pointer_like) {
  166. if constexpr(std::is_function_v<typename std::pointer_traits<Type>::element_type>) {
  167. static_cast<meta_any *>(other)->emplace<Type>(*static_cast<const Type *>(value));
  168. } else if constexpr(!std::is_void_v<std::remove_const_t<typename std::pointer_traits<Type>::element_type>>) {
  169. using in_place_type = decltype(adl_meta_pointer_like<Type>::dereference(*static_cast<const Type *>(value)));
  170. if constexpr(std::is_constructible_v<bool, Type>) {
  171. if(const auto &pointer_like = *static_cast<const Type *>(value); pointer_like) {
  172. static_cast<meta_any *>(other)->emplace<in_place_type>(adl_meta_pointer_like<Type>::dereference(pointer_like));
  173. }
  174. } else {
  175. static_cast<meta_any *>(other)->emplace<in_place_type>(adl_meta_pointer_like<Type>::dereference(*static_cast<const Type *>(value)));
  176. }
  177. }
  178. }
  179. }
  180. if constexpr(is_complete_v<meta_sequence_container_traits<Type>>) {
  181. if(req == internal::meta_traits::is_meta_sequence_container) {
  182. const_only ? static_cast<meta_sequence_container *>(other)->rebind(*static_cast<const Type *>(value)) : static_cast<meta_sequence_container *>(other)->rebind(*static_cast<Type *>(const_cast<void *>(value)));
  183. }
  184. }
  185. if constexpr(is_complete_v<meta_associative_container_traits<Type>>) {
  186. if(req == internal::meta_traits::is_meta_associative_container) {
  187. const_only ? static_cast<meta_associative_container *>(other)->rebind(*static_cast<const Type *>(value)) : static_cast<meta_associative_container *>(other)->rebind(*static_cast<Type *>(const_cast<void *>(value)));
  188. }
  189. }
  190. }
  191. void release() {
  192. if(node.dtor.dtor && (storage.policy() == any_policy::owner)) {
  193. node.dtor.dtor(storage.data());
  194. }
  195. }
  196. meta_any(const meta_ctx &area, const meta_any &other, any ref) noexcept
  197. : storage{std::move(ref)},
  198. ctx{&area},
  199. node{storage ? other.node : internal::meta_type_node{}},
  200. vtable{storage ? other.vtable : &basic_vtable<void>} {}
  201. public:
  202. /*! Default constructor. */
  203. meta_any() noexcept
  204. : meta_any{meta_ctx_arg, locator<meta_ctx>::value_or()} {}
  205. /**
  206. * @brief Context aware constructor.
  207. * @param area The context from which to search for meta types.
  208. */
  209. meta_any(meta_ctx_arg_t, const meta_ctx &area) noexcept
  210. : storage{},
  211. ctx{&area},
  212. node{},
  213. vtable{&basic_vtable<void>} {}
  214. /**
  215. * @brief Constructs a wrapper by directly initializing the new object.
  216. * @tparam Type Type of object to use to initialize the wrapper.
  217. * @tparam Args Types of arguments to use to construct the new instance.
  218. * @param args Parameters to use to construct the instance.
  219. */
  220. template<typename Type, typename... Args>
  221. explicit meta_any(std::in_place_type_t<Type>, Args &&...args)
  222. : meta_any{locator<meta_ctx>::value_or(), std::in_place_type<Type>, std::forward<Args>(args)...} {}
  223. /**
  224. * @brief Constructs a wrapper by directly initializing the new object.
  225. * @tparam Type Type of object to use to initialize the wrapper.
  226. * @tparam Args Types of arguments to use to construct the new instance.
  227. * @param area The context from which to search for meta types.
  228. * @param args Parameters to use to construct the instance.
  229. */
  230. template<typename Type, typename... Args>
  231. explicit meta_any(const meta_ctx &area, std::in_place_type_t<Type>, Args &&...args)
  232. : storage{std::in_place_type<Type>, std::forward<Args>(args)...},
  233. ctx{&area},
  234. node{internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx))},
  235. vtable{&basic_vtable<std::remove_cv_t<std::remove_reference_t<Type>>>} {}
  236. /**
  237. * @brief Constructs a wrapper from a given value.
  238. * @tparam Type Type of object to use to initialize the wrapper.
  239. * @param value An instance of an object to use to initialize the wrapper.
  240. */
  241. template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
  242. meta_any(Type &&value)
  243. : meta_any{locator<meta_ctx>::value_or(), std::forward<Type>(value)} {}
  244. /**
  245. * @brief Constructs a wrapper from a given value.
  246. * @tparam Type Type of object to use to initialize the wrapper.
  247. * @param area The context from which to search for meta types.
  248. * @param value An instance of an object to use to initialize the wrapper.
  249. */
  250. template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>>
  251. meta_any(const meta_ctx &area, Type &&value)
  252. : meta_any{area, std::in_place_type<std::decay_t<Type>>, std::forward<Type>(value)} {}
  253. /**
  254. * @brief Context aware copy constructor.
  255. * @param area The context from which to search for meta types.
  256. * @param other The instance to copy from.
  257. */
  258. meta_any(const meta_ctx &area, const meta_any &other)
  259. : meta_any{other} {
  260. ctx = &area;
  261. node = node.resolve ? node.resolve(internal::meta_context::from(*ctx)) : node;
  262. }
  263. /**
  264. * @brief Context aware move constructor.
  265. * @param area The context from which to search for meta types.
  266. * @param other The instance to move from.
  267. */
  268. meta_any(const meta_ctx &area, meta_any &&other)
  269. : meta_any{std::move(other)} {
  270. ctx = &area;
  271. node = node.resolve ? node.resolve(internal::meta_context::from(*ctx)) : node;
  272. }
  273. /**
  274. * @brief Copy constructor.
  275. * @param other The instance to copy from.
  276. */
  277. meta_any(const meta_any &other) = default;
  278. /**
  279. * @brief Move constructor.
  280. * @param other The instance to move from.
  281. */
  282. meta_any(meta_any &&other) noexcept
  283. : storage{std::move(other.storage)},
  284. ctx{other.ctx},
  285. node{std::exchange(other.node, internal::meta_type_node{})},
  286. vtable{std::exchange(other.vtable, &basic_vtable<void>)} {}
  287. /*! @brief Frees the internal storage, whatever it means. */
  288. ~meta_any() {
  289. release();
  290. }
  291. /**
  292. * @brief Copy assignment operator.
  293. * @param other The instance to copy from.
  294. * @return This meta any object.
  295. */
  296. meta_any &operator=(const meta_any &other) {
  297. release();
  298. storage = other.storage;
  299. ctx = other.ctx;
  300. node = other.node;
  301. vtable = other.vtable;
  302. return *this;
  303. }
  304. /**
  305. * @brief Move assignment operator.
  306. * @param other The instance to move from.
  307. * @return This meta any object.
  308. */
  309. meta_any &operator=(meta_any &&other) noexcept {
  310. release();
  311. storage = std::move(other.storage);
  312. ctx = other.ctx;
  313. node = std::exchange(other.node, internal::meta_type_node{});
  314. vtable = std::exchange(other.vtable, &basic_vtable<void>);
  315. return *this;
  316. }
  317. /**
  318. * @brief Value assignment operator.
  319. * @tparam Type Type of object to use to initialize the wrapper.
  320. * @param value An instance of an object to use to initialize the wrapper.
  321. * @return This meta any object.
  322. */
  323. template<typename Type>
  324. std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>, meta_any &>
  325. operator=(Type &&value) {
  326. emplace<std::decay_t<Type>>(std::forward<Type>(value));
  327. return *this;
  328. }
  329. /*! @copydoc any::type */
  330. [[nodiscard]] inline meta_type type() const noexcept;
  331. /*! @copydoc any::data */
  332. [[nodiscard]] const void *data() const noexcept {
  333. return storage.data();
  334. }
  335. /*! @copydoc any::data */
  336. [[nodiscard]] void *data() noexcept {
  337. return storage.data();
  338. }
  339. /**
  340. * @brief Invokes the underlying function, if possible.
  341. * @tparam Args Types of arguments to use to invoke the function.
  342. * @param id Unique identifier.
  343. * @param args Parameters to use to invoke the function.
  344. * @return A wrapper containing the returned value, if any.
  345. */
  346. template<typename... Args>
  347. meta_any invoke(const id_type id, Args &&...args) const;
  348. /*! @copydoc invoke */
  349. template<typename... Args>
  350. meta_any invoke(const id_type id, Args &&...args);
  351. /**
  352. * @brief Sets the value of a given variable.
  353. * @tparam Type Type of value to assign.
  354. * @param id Unique identifier.
  355. * @param value Parameter to use to set the underlying variable.
  356. * @return True in case of success, false otherwise.
  357. */
  358. template<typename Type>
  359. bool set(const id_type id, Type &&value);
  360. /**
  361. * @brief Gets the value of a given variable.
  362. * @param id Unique identifier.
  363. * @return A wrapper containing the value of the underlying variable.
  364. */
  365. [[nodiscard]] meta_any get(const id_type id) const;
  366. /*! @copydoc get */
  367. [[nodiscard]] meta_any get(const id_type id);
  368. /**
  369. * @brief Tries to cast an instance to a given type.
  370. * @tparam Type Type to which to cast the instance.
  371. * @return A (possibly null) pointer to the contained instance.
  372. */
  373. template<typename Type>
  374. [[nodiscard]] const Type *try_cast() const {
  375. const auto other = internal::resolve<std::remove_cv_t<Type>>(internal::meta_context::from(*ctx));
  376. return static_cast<const Type *>(internal::try_cast(internal::meta_context::from(*ctx), node, other, data()));
  377. }
  378. /*! @copydoc try_cast */
  379. template<typename Type>
  380. [[nodiscard]] Type *try_cast() {
  381. if constexpr(std::is_const_v<Type>) {
  382. return std::as_const(*this).try_cast<std::remove_const_t<Type>>();
  383. } else {
  384. const auto other = internal::resolve<std::remove_cv_t<Type>>(internal::meta_context::from(*ctx));
  385. return static_cast<Type *>(const_cast<void *>(internal::try_cast(internal::meta_context::from(*ctx), node, other, data())));
  386. }
  387. }
  388. /**
  389. * @brief Tries to cast an instance to a given type.
  390. * @tparam Type Type to which to cast the instance.
  391. * @return A reference to the contained instance.
  392. */
  393. template<typename Type>
  394. [[nodiscard]] Type cast() const {
  395. auto *const instance = try_cast<std::remove_reference_t<Type>>();
  396. ENTT_ASSERT(instance, "Invalid instance");
  397. return static_cast<Type>(*instance);
  398. }
  399. /*! @copydoc cast */
  400. template<typename Type>
  401. [[nodiscard]] Type cast() {
  402. // forces const on non-reference types to make them work also with wrappers for const references
  403. auto *const instance = try_cast<std::remove_reference_t<const Type>>();
  404. ENTT_ASSERT(instance, "Invalid instance");
  405. return static_cast<Type>(*instance);
  406. }
  407. /**
  408. * @brief Converts an object in such a way that a given cast becomes viable.
  409. * @param type Meta type to which the cast is requested.
  410. * @return A valid meta any object if there exists a viable conversion, an
  411. * invalid one otherwise.
  412. */
  413. [[nodiscard]] meta_any allow_cast(const meta_type &type) const;
  414. /**
  415. * @brief Converts an object in such a way that a given cast becomes viable.
  416. * @param type Meta type to which the cast is requested.
  417. * @return True if there exists a viable conversion, false otherwise.
  418. */
  419. [[nodiscard]] bool allow_cast(const meta_type &type) {
  420. if(auto other = std::as_const(*this).allow_cast(type); other) {
  421. if((other.storage.policy() == any_policy::owner)) {
  422. std::swap(*this, other);
  423. }
  424. return true;
  425. }
  426. return false;
  427. }
  428. /**
  429. * @brief Converts an object in such a way that a given cast becomes viable.
  430. * @tparam Type Type to which the cast is requested.
  431. * @return A valid meta any object if there exists a viable conversion, an
  432. * invalid one otherwise.
  433. */
  434. template<typename Type>
  435. [[nodiscard]] meta_any allow_cast() const {
  436. if constexpr(std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>) {
  437. return meta_any{meta_ctx_arg, *ctx};
  438. } else {
  439. auto other = internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx));
  440. return allow_cast(meta_type{*ctx, other});
  441. }
  442. }
  443. /**
  444. * @brief Converts an object in such a way that a given cast becomes viable.
  445. * @tparam Type Type to which the cast is requested.
  446. * @return True if there exists a viable conversion, false otherwise.
  447. */
  448. template<typename Type>
  449. [[nodiscard]] bool allow_cast() {
  450. auto other = internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx));
  451. return allow_cast(meta_type{*ctx, other}) && (!(std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>) || storage.data() != nullptr);
  452. }
  453. /*! @copydoc any::emplace */
  454. template<typename Type, typename... Args>
  455. void emplace(Args &&...args) {
  456. release();
  457. storage.emplace<Type>(std::forward<Args>(args)...);
  458. node = internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx));
  459. vtable = &basic_vtable<std::remove_cv_t<std::remove_reference_t<Type>>>;
  460. }
  461. /*! @copydoc any::assign */
  462. bool assign(const meta_any &other);
  463. /*! @copydoc any::assign */
  464. bool assign(meta_any &&other);
  465. /*! @copydoc any::reset */
  466. void reset() {
  467. release();
  468. storage.reset();
  469. node = {};
  470. vtable = &basic_vtable<void>;
  471. }
  472. /**
  473. * @brief Returns a sequence container proxy.
  474. * @return A sequence container proxy for the underlying object.
  475. */
  476. [[nodiscard]] meta_sequence_container as_sequence_container() noexcept {
  477. meta_sequence_container proxy{*ctx};
  478. vtable(internal::meta_traits::is_meta_sequence_container, policy() == meta_any_policy::cref, std::as_const(*this).data(), &proxy);
  479. return proxy;
  480. }
  481. /*! @copydoc as_sequence_container */
  482. [[nodiscard]] meta_sequence_container as_sequence_container() const noexcept {
  483. meta_sequence_container proxy{*ctx};
  484. vtable(internal::meta_traits::is_meta_sequence_container, true, data(), &proxy);
  485. return proxy;
  486. }
  487. /**
  488. * @brief Returns an associative container proxy.
  489. * @return An associative container proxy for the underlying object.
  490. */
  491. [[nodiscard]] meta_associative_container as_associative_container() noexcept {
  492. meta_associative_container proxy{*ctx};
  493. vtable(internal::meta_traits::is_meta_associative_container, policy() == meta_any_policy::cref, std::as_const(*this).data(), &proxy);
  494. return proxy;
  495. }
  496. /*! @copydoc as_associative_container */
  497. [[nodiscard]] meta_associative_container as_associative_container() const noexcept {
  498. meta_associative_container proxy{*ctx};
  499. vtable(internal::meta_traits::is_meta_associative_container, true, data(), &proxy);
  500. return proxy;
  501. }
  502. /**
  503. * @brief Indirection operator for dereferencing opaque objects.
  504. * @return A wrapper that shares a reference to an unmanaged object if the
  505. * wrapped element is dereferenceable, an invalid meta any otherwise.
  506. */
  507. [[nodiscard]] meta_any operator*() const noexcept {
  508. meta_any ret{meta_ctx_arg, *ctx};
  509. vtable(internal::meta_traits::is_meta_pointer_like, true, storage.data(), &ret);
  510. return ret;
  511. }
  512. /**
  513. * @brief Returns false if a wrapper is invalid, true otherwise.
  514. * @return False if the wrapper is invalid, true otherwise.
  515. */
  516. [[nodiscard]] explicit operator bool() const noexcept {
  517. return !(node.info == nullptr);
  518. }
  519. /*! @copydoc any::operator== */
  520. [[nodiscard]] bool operator==(const meta_any &other) const noexcept {
  521. return (ctx == other.ctx) && ((!node.info && !other.node.info) || (node.info && other.node.info && *node.info == *other.node.info && storage == other.storage));
  522. }
  523. /*! @copydoc any::operator!= */
  524. [[nodiscard]] bool operator!=(const meta_any &other) const noexcept {
  525. return !(*this == other);
  526. }
  527. /*! @copydoc any::as_ref */
  528. [[nodiscard]] meta_any as_ref() noexcept {
  529. return meta_any{*ctx, *this, storage.as_ref()};
  530. }
  531. /*! @copydoc any::as_ref */
  532. [[nodiscard]] meta_any as_ref() const noexcept {
  533. return meta_any{*ctx, *this, storage.as_ref()};
  534. }
  535. /*! @copydoc any::owner */
  536. [[deprecated("use policy() and meta_any_policy instead")]] [[nodiscard]] bool owner() const noexcept {
  537. return (storage.policy() == any_policy::owner);
  538. }
  539. /**
  540. * @brief Returns the current mode of a meta any object.
  541. * @return The current mode of the meta any object.
  542. */
  543. [[nodiscard]] meta_any_policy policy() const noexcept {
  544. return storage.policy();
  545. }
  546. private:
  547. any storage;
  548. const meta_ctx *ctx;
  549. internal::meta_type_node node;
  550. vtable_type *vtable;
  551. };
  552. /**
  553. * @brief Forwards its argument and avoids copies for lvalue references.
  554. * @tparam Type Type of argument to use to construct the new instance.
  555. * @param value Parameter to use to construct the instance.
  556. * @param ctx The context from which to search for meta types.
  557. * @return A properly initialized and not necessarily owning wrapper.
  558. */
  559. template<typename Type>
  560. [[nodiscard]] meta_any forward_as_meta(const meta_ctx &ctx, Type &&value) {
  561. return meta_any{ctx, std::in_place_type<Type &&>, std::forward<Type>(value)};
  562. }
  563. /**
  564. * @brief Forwards its argument and avoids copies for lvalue references.
  565. * @tparam Type Type of argument to use to construct the new instance.
  566. * @param value Parameter to use to construct the instance.
  567. * @return A properly initialized and not necessarily owning wrapper.
  568. */
  569. template<typename Type>
  570. [[nodiscard]] meta_any forward_as_meta(Type &&value) {
  571. return forward_as_meta(locator<meta_ctx>::value_or(), std::forward<Type>(value));
  572. }
  573. /**
  574. * @brief Opaque pointers to instances of any type.
  575. *
  576. * A handle doesn't perform copies and isn't responsible for the contained
  577. * object. It doesn't prolong the lifetime of the pointed instance.
  578. */
  579. struct meta_handle {
  580. /*! Default constructor. */
  581. meta_handle() noexcept
  582. : meta_handle{meta_ctx_arg, locator<meta_ctx>::value_or()} {}
  583. /**
  584. * @brief Context aware constructor.
  585. * @param area The context from which to search for meta types.
  586. */
  587. meta_handle(meta_ctx_arg_t, const meta_ctx &area) noexcept
  588. : any{meta_ctx_arg, area} {}
  589. /**
  590. * @brief Creates a handle that points to an unmanaged object.
  591. * @param value An instance of an object to use to initialize the handle.
  592. */
  593. meta_handle(meta_any &value) noexcept
  594. : any{value.as_ref()} {}
  595. /**
  596. * @brief Creates a handle that points to an unmanaged object.
  597. * @param value An instance of an object to use to initialize the handle.
  598. */
  599. meta_handle(const meta_any &value) noexcept
  600. : any{value.as_ref()} {}
  601. /**
  602. * @brief Creates a handle that points to an unmanaged object.
  603. * @tparam Type Type of object to use to initialize the handle.
  604. * @param ctx The context from which to search for meta types.
  605. * @param value An instance of an object to use to initialize the handle.
  606. */
  607. template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_handle>>>
  608. meta_handle(const meta_ctx &ctx, Type &value) noexcept
  609. : any{ctx, std::in_place_type<Type &>, value} {}
  610. /**
  611. * @brief Creates a handle that points to an unmanaged object.
  612. * @tparam Type Type of object to use to initialize the handle.
  613. * @param value An instance of an object to use to initialize the handle.
  614. */
  615. template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_handle>>>
  616. meta_handle(Type &value) noexcept
  617. : meta_handle{locator<meta_ctx>::value_or(), value} {}
  618. /**
  619. * @brief Context aware copy constructor.
  620. * @param area The context from which to search for meta types.
  621. * @param other The instance to copy from.
  622. */
  623. meta_handle(const meta_ctx &area, const meta_handle &other)
  624. : any{area, other.any} {}
  625. /**
  626. * @brief Context aware move constructor.
  627. * @param area The context from which to search for meta types.
  628. * @param other The instance to move from.
  629. */
  630. meta_handle(const meta_ctx &area, meta_handle &&other)
  631. : any{area, std::move(other.any)} {}
  632. /*! @brief Default copy constructor, deleted on purpose. */
  633. meta_handle(const meta_handle &) = delete;
  634. /*! @brief Default move constructor. */
  635. meta_handle(meta_handle &&) = default;
  636. /**
  637. * @brief Default copy assignment operator, deleted on purpose.
  638. * @return This meta handle.
  639. */
  640. meta_handle &operator=(const meta_handle &) = delete;
  641. /**
  642. * @brief Default move assignment operator.
  643. * @return This meta handle.
  644. */
  645. meta_handle &operator=(meta_handle &&) = default;
  646. /**
  647. * @brief Returns false if a handle is invalid, true otherwise.
  648. * @return False if the handle is invalid, true otherwise.
  649. */
  650. [[nodiscard]] explicit operator bool() const noexcept {
  651. return static_cast<bool>(any);
  652. }
  653. /*! @copydoc meta_any::operator== */
  654. [[nodiscard]] bool operator==(const meta_handle &other) const noexcept {
  655. return (any == other.any);
  656. }
  657. /*! @copydoc meta_any::operator!= */
  658. [[nodiscard]] bool operator!=(const meta_handle &other) const noexcept {
  659. return !(*this == other);
  660. }
  661. /**
  662. * @brief Access operator for accessing the contained opaque object.
  663. * @return A wrapper that shares a reference to an unmanaged object.
  664. */
  665. [[nodiscard]] meta_any *operator->() {
  666. return &any;
  667. }
  668. /*! @copydoc operator-> */
  669. [[nodiscard]] const meta_any *operator->() const {
  670. return &any;
  671. }
  672. private:
  673. meta_any any;
  674. };
  675. /*! @brief Opaque wrapper for properties of any type. */
  676. struct meta_prop {
  677. /*! @brief Default constructor. */
  678. meta_prop() noexcept
  679. : node{},
  680. ctx{} {}
  681. /**
  682. * @brief Context aware constructor for meta objects.
  683. * @param area The context from which to search for meta types.
  684. * @param curr The underlying node with which to construct the instance.
  685. */
  686. meta_prop(const meta_ctx &area, const internal::meta_prop_node &curr) noexcept
  687. : node{&curr},
  688. ctx{&area} {}
  689. /**
  690. * @brief Returns the stored value by const reference.
  691. * @return A wrapper containing the value stored with the property.
  692. */
  693. [[nodiscard]] meta_any value() const {
  694. return node->value ? node->type(internal::meta_context::from(*ctx)).from_void(*ctx, nullptr, node->value.get()) : meta_any{meta_ctx_arg, *ctx};
  695. }
  696. /**
  697. * @brief Returns the stored value by reference.
  698. * @return A wrapper containing the value stored with the property.
  699. */
  700. [[nodiscard]] meta_any value() {
  701. return node->value ? node->type(internal::meta_context::from(*ctx)).from_void(*ctx, node->value.get(), nullptr) : meta_any{meta_ctx_arg, *ctx};
  702. }
  703. /**
  704. * @brief Returns true if an object is valid, false otherwise.
  705. * @return True if the object is valid, false otherwise.
  706. */
  707. [[nodiscard]] explicit operator bool() const noexcept {
  708. return (node != nullptr);
  709. }
  710. /**
  711. * @brief Checks if two objects refer to the same type.
  712. * @param other The object with which to compare.
  713. * @return True if the objects refer to the same type, false otherwise.
  714. */
  715. [[nodiscard]] bool operator==(const meta_prop &other) const noexcept {
  716. return (ctx == other.ctx && node == other.node);
  717. }
  718. private:
  719. const internal::meta_prop_node *node;
  720. const meta_ctx *ctx;
  721. };
  722. /**
  723. * @brief Checks if two objects refer to the same type.
  724. * @param lhs An object, either valid or not.
  725. * @param rhs An object, either valid or not.
  726. * @return False if the objects refer to the same node, true otherwise.
  727. */
  728. [[nodiscard]] inline bool operator!=(const meta_prop &lhs, const meta_prop &rhs) noexcept {
  729. return !(lhs == rhs);
  730. }
  731. /*! @brief Opaque wrapper for data members. */
  732. struct meta_data {
  733. /*! @brief Unsigned integer type. */
  734. using size_type = typename internal::meta_data_node::size_type;
  735. /*! @brief Default constructor. */
  736. meta_data() noexcept
  737. : node{},
  738. ctx{} {}
  739. /**
  740. * @brief Context aware constructor for meta objects.
  741. * @param area The context from which to search for meta types.
  742. * @param curr The underlying node with which to construct the instance.
  743. */
  744. meta_data(const meta_ctx &area, const internal::meta_data_node &curr) noexcept
  745. : node{&curr},
  746. ctx{&area} {}
  747. /**
  748. * @brief Returns the number of setters available.
  749. * @return The number of setters available.
  750. */
  751. [[nodiscard]] size_type arity() const noexcept {
  752. return node->arity;
  753. }
  754. /**
  755. * @brief Indicates whether a data member is constant or not.
  756. * @return True if the data member is constant, false otherwise.
  757. */
  758. [[nodiscard]] bool is_const() const noexcept {
  759. return static_cast<bool>(node->traits & internal::meta_traits::is_const);
  760. }
  761. /**
  762. * @brief Indicates whether a data member is static or not.
  763. * @return True if the data member is static, false otherwise.
  764. */
  765. [[nodiscard]] bool is_static() const noexcept {
  766. return static_cast<bool>(node->traits & internal::meta_traits::is_static);
  767. }
  768. /*! @copydoc meta_any::type */
  769. [[nodiscard]] inline meta_type type() const noexcept;
  770. /**
  771. * @brief Sets the value of a given variable.
  772. * @tparam Type Type of value to assign.
  773. * @param instance An opaque instance of the underlying type.
  774. * @param value Parameter to use to set the underlying variable.
  775. * @return True in case of success, false otherwise.
  776. */
  777. template<typename Type>
  778. bool set(meta_handle instance, Type &&value) const {
  779. return node->set && node->set(meta_handle{*ctx, std::move(instance)}, meta_any{*ctx, std::forward<Type>(value)});
  780. }
  781. /**
  782. * @brief Gets the value of a given variable.
  783. * @param instance An opaque instance of the underlying type.
  784. * @return A wrapper containing the value of the underlying variable.
  785. */
  786. [[nodiscard]] meta_any get(meta_handle instance) const {
  787. return node->get(*ctx, meta_handle{*ctx, std::move(instance)});
  788. }
  789. /**
  790. * @brief Returns the type accepted by the i-th setter.
  791. * @param index Index of the setter of which to return the accepted type.
  792. * @return The type accepted by the i-th setter.
  793. */
  794. [[nodiscard]] inline meta_type arg(const size_type index) const noexcept;
  795. /**
  796. * @brief Returns a range to visit registered meta properties.
  797. * @return An iterable range to visit registered meta properties.
  798. */
  799. [[nodiscard]] meta_range<meta_prop, typename decltype(internal::meta_data_node::prop)::const_iterator> prop() const noexcept {
  800. return {{*ctx, node->prop.cbegin()}, {*ctx, node->prop.cend()}};
  801. }
  802. /**
  803. * @brief Lookup utility for meta properties.
  804. * @param key The key to use to search for a property.
  805. * @return The registered meta property for the given key, if any.
  806. */
  807. [[nodiscard]] meta_prop prop(const id_type key) const {
  808. const auto it = node->prop.find(key);
  809. return it != node->prop.cend() ? meta_prop{*ctx, it->second} : meta_prop{};
  810. }
  811. /**
  812. * @brief Returns true if an object is valid, false otherwise.
  813. * @return True if the object is valid, false otherwise.
  814. */
  815. [[nodiscard]] explicit operator bool() const noexcept {
  816. return (node != nullptr);
  817. }
  818. /*! @copydoc meta_prop::operator== */
  819. [[nodiscard]] bool operator==(const meta_data &other) const noexcept {
  820. return (ctx == other.ctx && node == other.node);
  821. }
  822. private:
  823. const internal::meta_data_node *node;
  824. const meta_ctx *ctx;
  825. };
  826. /**
  827. * @brief Checks if two objects refer to the same type.
  828. * @param lhs An object, either valid or not.
  829. * @param rhs An object, either valid or not.
  830. * @return False if the objects refer to the same node, true otherwise.
  831. */
  832. [[nodiscard]] inline bool operator!=(const meta_data &lhs, const meta_data &rhs) noexcept {
  833. return !(lhs == rhs);
  834. }
  835. /*! @brief Opaque wrapper for member functions. */
  836. struct meta_func {
  837. /*! @brief Unsigned integer type. */
  838. using size_type = typename internal::meta_func_node::size_type;
  839. /*! @brief Default constructor. */
  840. meta_func() noexcept
  841. : node{},
  842. ctx{} {}
  843. /**
  844. * @brief Context aware constructor for meta objects.
  845. * @param area The context from which to search for meta types.
  846. * @param curr The underlying node with which to construct the instance.
  847. */
  848. meta_func(const meta_ctx &area, const internal::meta_func_node &curr) noexcept
  849. : node{&curr},
  850. ctx{&area} {}
  851. /**
  852. * @brief Returns the number of arguments accepted by a member function.
  853. * @return The number of arguments accepted by the member function.
  854. */
  855. [[nodiscard]] size_type arity() const noexcept {
  856. return node->arity;
  857. }
  858. /**
  859. * @brief Indicates whether a member function is constant or not.
  860. * @return True if the member function is constant, false otherwise.
  861. */
  862. [[nodiscard]] bool is_const() const noexcept {
  863. return static_cast<bool>(node->traits & internal::meta_traits::is_const);
  864. }
  865. /**
  866. * @brief Indicates whether a member function is static or not.
  867. * @return True if the member function is static, false otherwise.
  868. */
  869. [[nodiscard]] bool is_static() const noexcept {
  870. return static_cast<bool>(node->traits & internal::meta_traits::is_static);
  871. }
  872. /**
  873. * @brief Returns the return type of a member function.
  874. * @return The return type of the member function.
  875. */
  876. [[nodiscard]] inline meta_type ret() const noexcept;
  877. /**
  878. * @brief Returns the type of the i-th argument of a member function.
  879. * @param index Index of the argument of which to return the type.
  880. * @return The type of the i-th argument of a member function.
  881. */
  882. [[nodiscard]] inline meta_type arg(const size_type index) const noexcept;
  883. /**
  884. * @brief Invokes the underlying function, if possible.
  885. *
  886. * @warning
  887. * The context of the arguments is **never** changed.
  888. *
  889. * @param instance An opaque instance of the underlying type.
  890. * @param args Parameters to use to invoke the function.
  891. * @param sz Number of parameters to use to invoke the function.
  892. * @return A wrapper containing the returned value, if any.
  893. */
  894. meta_any invoke(meta_handle instance, meta_any *const args, const size_type sz) const {
  895. return sz == arity() ? node->invoke(*ctx, meta_handle{*ctx, std::move(instance)}, args) : meta_any{meta_ctx_arg, *ctx};
  896. }
  897. /**
  898. * @copybrief invoke
  899. * @tparam Args Types of arguments to use to invoke the function.
  900. * @param instance An opaque instance of the underlying type.
  901. * @param args Parameters to use to invoke the function.
  902. * @return A wrapper containing the returned value, if any.
  903. */
  904. template<typename... Args>
  905. meta_any invoke(meta_handle instance, Args &&...args) const {
  906. meta_any arguments[sizeof...(Args) + !sizeof...(Args)]{{*ctx, std::forward<Args>(args)}...};
  907. return invoke(std::move(instance), arguments, sizeof...(Args));
  908. }
  909. /*! @copydoc meta_data::prop */
  910. [[nodiscard]] meta_range<meta_prop, typename decltype(internal::meta_func_node::prop)::const_iterator> prop() const noexcept {
  911. return {{*ctx, node->prop.cbegin()}, {*ctx, node->prop.cend()}};
  912. }
  913. /**
  914. * @brief Lookup utility for meta properties.
  915. * @param key The key to use to search for a property.
  916. * @return The registered meta property for the given key, if any.
  917. */
  918. [[nodiscard]] meta_prop prop(const id_type key) const {
  919. const auto it = node->prop.find(key);
  920. return it != node->prop.cend() ? meta_prop{*ctx, it->second} : meta_prop{};
  921. }
  922. /**
  923. * @brief Returns the next overload of a given function, if any.
  924. * @return The next overload of the given function, if any.
  925. */
  926. [[nodiscard]] meta_func next() const {
  927. return node->next ? meta_func{*ctx, *node->next} : meta_func{};
  928. }
  929. /**
  930. * @brief Returns true if an object is valid, false otherwise.
  931. * @return True if the object is valid, false otherwise.
  932. */
  933. [[nodiscard]] explicit operator bool() const noexcept {
  934. return (node != nullptr);
  935. }
  936. /*! @copydoc meta_prop::operator== */
  937. [[nodiscard]] bool operator==(const meta_func &other) const noexcept {
  938. return (ctx == other.ctx && node == other.node);
  939. }
  940. private:
  941. const internal::meta_func_node *node;
  942. const meta_ctx *ctx;
  943. };
  944. /**
  945. * @brief Checks if two objects refer to the same type.
  946. * @param lhs An object, either valid or not.
  947. * @param rhs An object, either valid or not.
  948. * @return False if the objects refer to the same node, true otherwise.
  949. */
  950. [[nodiscard]] inline bool operator!=(const meta_func &lhs, const meta_func &rhs) noexcept {
  951. return !(lhs == rhs);
  952. }
  953. /*! @brief Opaque wrapper for types. */
  954. class meta_type {
  955. template<typename Func>
  956. [[nodiscard]] auto lookup(meta_any *const args, const typename internal::meta_type_node::size_type sz, [[maybe_unused]] bool constness, Func next) const {
  957. decltype(next()) candidate = nullptr;
  958. size_type same{};
  959. bool ambiguous{};
  960. for(auto curr = next(); curr; curr = next()) {
  961. if constexpr(std::is_same_v<std::decay_t<decltype(*curr)>, internal::meta_func_node>) {
  962. if(constness && !static_cast<bool>(curr->traits & internal::meta_traits::is_const)) {
  963. continue;
  964. }
  965. }
  966. if(curr->arity == sz) {
  967. size_type match{};
  968. size_type pos{};
  969. for(; pos < sz && args[pos]; ++pos) {
  970. const auto other = curr->arg(*ctx, pos);
  971. const auto type = args[pos].type();
  972. if(const auto &info = other.info(); info == type.info()) {
  973. ++match;
  974. } else if(!((type.node.details && (type.node.details->base.contains(info.hash()) || type.node.details->conv.contains(info.hash()))) || (type.node.conversion_helper && other.node.conversion_helper))) {
  975. break;
  976. }
  977. }
  978. if(pos == sz) {
  979. if(!candidate || match > same) {
  980. candidate = curr;
  981. same = match;
  982. ambiguous = false;
  983. } else if(match == same) {
  984. if constexpr(std::is_same_v<std::decay_t<decltype(*curr)>, internal::meta_func_node>) {
  985. if(static_cast<bool>(curr->traits & internal::meta_traits::is_const) != static_cast<bool>(candidate->traits & internal::meta_traits::is_const)) {
  986. candidate = static_cast<bool>(candidate->traits & internal::meta_traits::is_const) ? curr : candidate;
  987. ambiguous = false;
  988. continue;
  989. }
  990. }
  991. ambiguous = true;
  992. }
  993. }
  994. }
  995. }
  996. return ambiguous ? nullptr : candidate;
  997. }
  998. public:
  999. /*! @brief Unsigned integer type. */
  1000. using size_type = typename internal::meta_type_node::size_type;
  1001. /*! @brief Default constructor. */
  1002. meta_type() noexcept
  1003. : node{},
  1004. ctx{} {}
  1005. /**
  1006. * @brief Context aware constructor for meta objects.
  1007. * @param area The context from which to search for meta types.
  1008. * @param curr The underlying node with which to construct the instance.
  1009. */
  1010. meta_type(const meta_ctx &area, const internal::meta_type_node &curr) noexcept
  1011. : node{curr},
  1012. ctx{&area} {}
  1013. /**
  1014. * @brief Context aware constructor for meta objects.
  1015. * @param area The context from which to search for meta types.
  1016. * @param curr The underlying node with which to construct the instance.
  1017. */
  1018. meta_type(const meta_ctx &area, const internal::meta_base_node &curr) noexcept
  1019. : meta_type{area, curr.type(internal::meta_context::from(area))} {}
  1020. /**
  1021. * @brief Returns the type info object of the underlying type.
  1022. * @return The type info object of the underlying type.
  1023. */
  1024. [[nodiscard]] const type_info &info() const noexcept {
  1025. return *node.info;
  1026. }
  1027. /**
  1028. * @brief Returns the identifier assigned to a type.
  1029. * @return The identifier assigned to the type.
  1030. */
  1031. [[nodiscard]] id_type id() const noexcept {
  1032. return node.id;
  1033. }
  1034. /**
  1035. * @brief Returns the size of the underlying type if known.
  1036. * @return The size of the underlying type if known, 0 otherwise.
  1037. */
  1038. [[nodiscard]] size_type size_of() const noexcept {
  1039. return node.size_of;
  1040. }
  1041. /**
  1042. * @brief Checks whether a type refers to an arithmetic type or not.
  1043. * @return True if the underlying type is an arithmetic type, false
  1044. * otherwise.
  1045. */
  1046. [[nodiscard]] bool is_arithmetic() const noexcept {
  1047. return static_cast<bool>(node.traits & internal::meta_traits::is_arithmetic);
  1048. }
  1049. /**
  1050. * @brief Checks whether a type refers to an integral type or not.
  1051. * @return True if the underlying type is an integral type, false otherwise.
  1052. */
  1053. [[nodiscard]] bool is_integral() const noexcept {
  1054. return static_cast<bool>(node.traits & internal::meta_traits::is_integral);
  1055. }
  1056. /**
  1057. * @brief Checks whether a type refers to a signed type or not.
  1058. * @return True if the underlying type is a signed type, false otherwise.
  1059. */
  1060. [[nodiscard]] bool is_signed() const noexcept {
  1061. return static_cast<bool>(node.traits & internal::meta_traits::is_signed);
  1062. }
  1063. /**
  1064. * @brief Checks whether a type refers to an array type or not.
  1065. * @return True if the underlying type is an array type, false otherwise.
  1066. */
  1067. [[nodiscard]] bool is_array() const noexcept {
  1068. return static_cast<bool>(node.traits & internal::meta_traits::is_array);
  1069. }
  1070. /**
  1071. * @brief Checks whether a type refers to an enum or not.
  1072. * @return True if the underlying type is an enum, false otherwise.
  1073. */
  1074. [[nodiscard]] bool is_enum() const noexcept {
  1075. return static_cast<bool>(node.traits & internal::meta_traits::is_enum);
  1076. }
  1077. /**
  1078. * @brief Checks whether a type refers to a class or not.
  1079. * @return True if the underlying type is a class, false otherwise.
  1080. */
  1081. [[nodiscard]] bool is_class() const noexcept {
  1082. return static_cast<bool>(node.traits & internal::meta_traits::is_class);
  1083. }
  1084. /**
  1085. * @brief Checks whether a type refers to a pointer or not.
  1086. * @return True if the underlying type is a pointer, false otherwise.
  1087. */
  1088. [[nodiscard]] bool is_pointer() const noexcept {
  1089. return node.info && (node.info->hash() != remove_pointer().info().hash());
  1090. }
  1091. /**
  1092. * @brief Provides the type for which the pointer is defined.
  1093. * @return The type for which the pointer is defined or this type if it
  1094. * doesn't refer to a pointer type.
  1095. */
  1096. [[nodiscard]] meta_type remove_pointer() const noexcept {
  1097. return {*ctx, node.remove_pointer(internal::meta_context::from(*ctx))};
  1098. }
  1099. /**
  1100. * @brief Checks whether a type is a pointer-like type or not.
  1101. * @return True if the underlying type is pointer-like, false otherwise.
  1102. */
  1103. [[nodiscard]] bool is_pointer_like() const noexcept {
  1104. return static_cast<bool>(node.traits & internal::meta_traits::is_meta_pointer_like);
  1105. }
  1106. /**
  1107. * @brief Checks whether a type refers to a sequence container or not.
  1108. * @return True if the type is a sequence container, false otherwise.
  1109. */
  1110. [[nodiscard]] bool is_sequence_container() const noexcept {
  1111. return static_cast<bool>(node.traits & internal::meta_traits::is_meta_sequence_container);
  1112. }
  1113. /**
  1114. * @brief Checks whether a type refers to an associative container or not.
  1115. * @return True if the type is an associative container, false otherwise.
  1116. */
  1117. [[nodiscard]] bool is_associative_container() const noexcept {
  1118. return static_cast<bool>(node.traits & internal::meta_traits::is_meta_associative_container);
  1119. }
  1120. /**
  1121. * @brief Checks whether a type refers to a recognized class template
  1122. * specialization or not.
  1123. * @return True if the type is a recognized class template specialization,
  1124. * false otherwise.
  1125. */
  1126. [[nodiscard]] bool is_template_specialization() const noexcept {
  1127. return (node.templ.arity != 0u);
  1128. }
  1129. /**
  1130. * @brief Returns the number of template arguments.
  1131. * @return The number of template arguments.
  1132. */
  1133. [[nodiscard]] size_type template_arity() const noexcept {
  1134. return node.templ.arity;
  1135. }
  1136. /**
  1137. * @brief Returns a tag for the class template of the underlying type.
  1138. * @return The tag for the class template of the underlying type.
  1139. */
  1140. [[nodiscard]] inline meta_type template_type() const noexcept {
  1141. return node.templ.type ? meta_type{*ctx, node.templ.type(internal::meta_context::from(*ctx))} : meta_type{};
  1142. }
  1143. /**
  1144. * @brief Returns the type of the i-th template argument of a type.
  1145. * @param index Index of the template argument of which to return the type.
  1146. * @return The type of the i-th template argument of a type.
  1147. */
  1148. [[nodiscard]] inline meta_type template_arg(const size_type index) const noexcept {
  1149. return index < template_arity() ? meta_type{*ctx, node.templ.arg(internal::meta_context::from(*ctx), index)} : meta_type{};
  1150. }
  1151. /**
  1152. * @brief Checks if a type supports direct casting to another type.
  1153. * @param other The meta type to test for.
  1154. * @return True if direct casting is allowed, false otherwise.
  1155. */
  1156. [[nodiscard]] bool can_cast(const meta_type &other) const noexcept {
  1157. // casting this is UB in all cases but we aren't going to use the resulting pointer, so...
  1158. return (internal::try_cast(internal::meta_context::from(*ctx), node, other.node, this) != nullptr);
  1159. }
  1160. /**
  1161. * @brief Checks if a type supports conversion it to another type.
  1162. * @param other The meta type to test for.
  1163. * @return True if the conversion is allowed, false otherwise.
  1164. */
  1165. [[nodiscard]] bool can_convert(const meta_type &other) const noexcept {
  1166. return (internal::try_convert(internal::meta_context::from(*ctx), node, other.info(), other.is_arithmetic() || other.is_enum(), nullptr, [](const void *, auto &&...args) { return ((static_cast<void>(args), 1) + ... + 0u); }) != 0u);
  1167. }
  1168. /**
  1169. * @brief Returns a range to visit registered top-level base meta types.
  1170. * @return An iterable range to visit registered top-level base meta types.
  1171. */
  1172. [[nodiscard]] meta_range<meta_type, typename decltype(internal::meta_type_descriptor::base)::const_iterator> base() const noexcept {
  1173. using range_type = meta_range<meta_type, typename decltype(internal::meta_type_descriptor::base)::const_iterator>;
  1174. return node.details ? range_type{{*ctx, node.details->base.cbegin()}, {*ctx, node.details->base.cend()}} : range_type{};
  1175. }
  1176. /**
  1177. * @brief Returns a range to visit registered top-level meta data.
  1178. * @return An iterable range to visit registered top-level meta data.
  1179. */
  1180. [[nodiscard]] meta_range<meta_data, typename decltype(internal::meta_type_descriptor::data)::const_iterator> data() const noexcept {
  1181. using range_type = meta_range<meta_data, typename decltype(internal::meta_type_descriptor::data)::const_iterator>;
  1182. return node.details ? range_type{{*ctx, node.details->data.cbegin()}, {*ctx, node.details->data.cend()}} : range_type{};
  1183. }
  1184. /**
  1185. * @brief Lookup utility for meta data (bases are also visited).
  1186. * @param id Unique identifier.
  1187. * @return The registered meta data for the given identifier, if any.
  1188. */
  1189. [[nodiscard]] meta_data data(const id_type id) const {
  1190. const auto *elem = internal::look_for<&internal::meta_type_descriptor::data>(internal::meta_context::from(*ctx), node, id);
  1191. return elem ? meta_data{*ctx, *elem} : meta_data{};
  1192. }
  1193. /**
  1194. * @brief Returns a range to visit registered top-level functions.
  1195. * @return An iterable range to visit registered top-level functions.
  1196. */
  1197. [[nodiscard]] meta_range<meta_func, typename decltype(internal::meta_type_descriptor::func)::const_iterator> func() const noexcept {
  1198. using return_type = meta_range<meta_func, typename decltype(internal::meta_type_descriptor::func)::const_iterator>;
  1199. return node.details ? return_type{{*ctx, node.details->func.cbegin()}, {*ctx, node.details->func.cend()}} : return_type{};
  1200. }
  1201. /**
  1202. * @brief Lookup utility for meta functions (bases are also visited).
  1203. *
  1204. * In case of overloaded functions, a random one is returned.
  1205. *
  1206. * @param id Unique identifier.
  1207. * @return The registered meta function for the given identifier, if any.
  1208. */
  1209. [[nodiscard]] meta_func func(const id_type id) const {
  1210. const auto *elem = internal::look_for<&internal::meta_type_descriptor::func>(internal::meta_context::from(*ctx), node, id);
  1211. return elem ? meta_func{*ctx, *elem} : meta_func{};
  1212. }
  1213. /**
  1214. * @brief Creates an instance of the underlying type, if possible.
  1215. *
  1216. * @warning
  1217. * The context of the arguments is **never** changed.
  1218. *
  1219. * @param args Parameters to use to construct the instance.
  1220. * @param sz Number of parameters to use to construct the instance.
  1221. * @return A wrapper containing the new instance, if any.
  1222. */
  1223. [[nodiscard]] meta_any construct(meta_any *const args, const size_type sz) const {
  1224. if(node.details) {
  1225. if(const auto *candidate = lookup(args, sz, false, [first = node.details->ctor.cbegin(), last = node.details->ctor.cend()]() mutable { return first == last ? nullptr : &(first++)->second; }); candidate) {
  1226. return candidate->invoke(*ctx, args);
  1227. }
  1228. }
  1229. if(sz == 0u && node.default_constructor) {
  1230. return node.default_constructor(*ctx);
  1231. }
  1232. return meta_any{meta_ctx_arg, *ctx};
  1233. }
  1234. /**
  1235. * @copybrief construct
  1236. * @tparam Args Types of arguments to use to construct the instance.
  1237. * @param args Parameters to use to construct the instance.
  1238. * @return A wrapper containing the new instance, if any.
  1239. */
  1240. template<typename... Args>
  1241. [[nodiscard]] meta_any construct(Args &&...args) const {
  1242. meta_any arguments[sizeof...(Args) + !sizeof...(Args)]{{*ctx, std::forward<Args>(args)}...};
  1243. return construct(arguments, sizeof...(Args));
  1244. }
  1245. /**
  1246. * @brief Wraps an opaque element of the underlying type.
  1247. * @param element A valid pointer to an element of the underlying type.
  1248. * @return A wrapper that references the given instance.
  1249. */
  1250. [[nodiscard]] meta_any from_void(void *element) const {
  1251. return (element && node.from_void) ? node.from_void(*ctx, element, nullptr) : meta_any{meta_ctx_arg, *ctx};
  1252. }
  1253. /*! @copydoc from_void */
  1254. [[nodiscard]] meta_any from_void(const void *element) const {
  1255. return (element && node.from_void) ? node.from_void(*ctx, nullptr, element) : meta_any{meta_ctx_arg, *ctx};
  1256. }
  1257. /**
  1258. * @brief Invokes a function given an identifier, if possible.
  1259. *
  1260. * @warning
  1261. * The context of the arguments is **never** changed.
  1262. *
  1263. * @param id Unique identifier.
  1264. * @param instance An opaque instance of the underlying type.
  1265. * @param args Parameters to use to invoke the function.
  1266. * @param sz Number of parameters to use to invoke the function.
  1267. * @return A wrapper containing the returned value, if any.
  1268. */
  1269. meta_any invoke(const id_type id, meta_handle instance, meta_any *const args, const size_type sz) const {
  1270. if(node.details) {
  1271. if(auto it = node.details->func.find(id); it != node.details->func.cend()) {
  1272. if(const auto *candidate = lookup(args, sz, instance && (instance->data() == nullptr), [curr = &it->second]() mutable { return curr ? std::exchange(curr, curr->next.get()) : nullptr; }); candidate) {
  1273. return candidate->invoke(*ctx, meta_handle{*ctx, std::move(instance)}, args);
  1274. }
  1275. }
  1276. }
  1277. for(auto &&curr: base()) {
  1278. if(auto elem = curr.second.invoke(id, *instance.operator->(), args, sz); elem) {
  1279. return elem;
  1280. }
  1281. }
  1282. return meta_any{meta_ctx_arg, *ctx};
  1283. }
  1284. /**
  1285. * @copybrief invoke
  1286. * @param id Unique identifier.
  1287. * @tparam Args Types of arguments to use to invoke the function.
  1288. * @param instance An opaque instance of the underlying type.
  1289. * @param args Parameters to use to invoke the function.
  1290. * @return A wrapper containing the returned value, if any.
  1291. */
  1292. template<typename... Args>
  1293. meta_any invoke(const id_type id, meta_handle instance, Args &&...args) const {
  1294. meta_any arguments[sizeof...(Args) + !sizeof...(Args)]{{*ctx, std::forward<Args>(args)}...};
  1295. return invoke(id, std::move(instance), arguments, sizeof...(Args));
  1296. }
  1297. /**
  1298. * @brief Sets the value of a given variable.
  1299. * @tparam Type Type of value to assign.
  1300. * @param id Unique identifier.
  1301. * @param instance An opaque instance of the underlying type.
  1302. * @param value Parameter to use to set the underlying variable.
  1303. * @return True in case of success, false otherwise.
  1304. */
  1305. template<typename Type>
  1306. bool set(const id_type id, meta_handle instance, Type &&value) const {
  1307. const auto candidate = data(id);
  1308. return candidate && candidate.set(std::move(instance), std::forward<Type>(value));
  1309. }
  1310. /**
  1311. * @brief Gets the value of a given variable.
  1312. * @param id Unique identifier.
  1313. * @param instance An opaque instance of the underlying type.
  1314. * @return A wrapper containing the value of the underlying variable.
  1315. */
  1316. [[nodiscard]] meta_any get(const id_type id, meta_handle instance) const {
  1317. const auto candidate = data(id);
  1318. return candidate ? candidate.get(std::move(instance)) : meta_any{meta_ctx_arg, *ctx};
  1319. }
  1320. /**
  1321. * @brief Returns a range to visit registered top-level meta properties.
  1322. * @return An iterable range to visit registered top-level meta properties.
  1323. */
  1324. [[nodiscard]] meta_range<meta_prop, typename decltype(internal::meta_type_descriptor::prop)::const_iterator> prop() const noexcept {
  1325. using range_type = meta_range<meta_prop, typename decltype(internal::meta_type_descriptor::prop)::const_iterator>;
  1326. return node.details ? range_type{{*ctx, node.details->prop.cbegin()}, {*ctx, node.details->prop.cend()}} : range_type{};
  1327. }
  1328. /**
  1329. * @brief Lookup utility for meta properties (bases are also visited).
  1330. * @param key The key to use to search for a property.
  1331. * @return The registered meta property for the given key, if any.
  1332. */
  1333. [[nodiscard]] meta_prop prop(const id_type key) const {
  1334. const auto *elem = internal::look_for<&internal::meta_type_descriptor::prop>(internal::meta_context::from(*ctx), node, key);
  1335. return elem ? meta_prop{*ctx, *elem} : meta_prop{};
  1336. }
  1337. /**
  1338. * @brief Returns true if an object is valid, false otherwise.
  1339. * @return True if the object is valid, false otherwise.
  1340. */
  1341. [[nodiscard]] explicit operator bool() const noexcept {
  1342. return !(ctx == nullptr);
  1343. }
  1344. /*! @copydoc meta_prop::operator== */
  1345. [[nodiscard]] bool operator==(const meta_type &other) const noexcept {
  1346. return (ctx == other.ctx) && ((!node.info && !other.node.info) || (node.info && other.node.info && *node.info == *other.node.info));
  1347. }
  1348. private:
  1349. internal::meta_type_node node;
  1350. const meta_ctx *ctx;
  1351. };
  1352. /**
  1353. * @brief Checks if two objects refer to the same type.
  1354. * @param lhs An object, either valid or not.
  1355. * @param rhs An object, either valid or not.
  1356. * @return False if the objects refer to the same node, true otherwise.
  1357. */
  1358. [[nodiscard]] inline bool operator!=(const meta_type &lhs, const meta_type &rhs) noexcept {
  1359. return !(lhs == rhs);
  1360. }
  1361. [[nodiscard]] inline meta_type meta_any::type() const noexcept {
  1362. return node.info ? meta_type{*ctx, node} : meta_type{};
  1363. }
  1364. template<typename... Args>
  1365. meta_any meta_any::invoke(const id_type id, Args &&...args) const {
  1366. return type().invoke(id, *this, std::forward<Args>(args)...);
  1367. }
  1368. template<typename... Args>
  1369. meta_any meta_any::invoke(const id_type id, Args &&...args) {
  1370. return type().invoke(id, *this, std::forward<Args>(args)...);
  1371. }
  1372. template<typename Type>
  1373. bool meta_any::set(const id_type id, Type &&value) {
  1374. return type().set(id, *this, std::forward<Type>(value));
  1375. }
  1376. [[nodiscard]] inline meta_any meta_any::get(const id_type id) const {
  1377. return type().get(id, *this);
  1378. }
  1379. [[nodiscard]] inline meta_any meta_any::get(const id_type id) {
  1380. return type().get(id, *this);
  1381. }
  1382. [[nodiscard]] inline meta_any meta_any::allow_cast(const meta_type &type) const {
  1383. return internal::try_convert(internal::meta_context::from(*ctx), node, type.info(), type.is_arithmetic() || type.is_enum(), data(), [this, &type]([[maybe_unused]] const void *instance, auto &&...args) {
  1384. if constexpr((std::is_same_v<std::remove_const_t<std::remove_reference_t<decltype(args)>>, internal::meta_type_node> || ...)) {
  1385. return (args.from_void(*ctx, nullptr, instance), ...);
  1386. } else if constexpr((std::is_same_v<std::remove_const_t<std::remove_reference_t<decltype(args)>>, internal::meta_conv_node> || ...)) {
  1387. return (args.conv(*ctx, instance), ...);
  1388. } else if constexpr((std::is_same_v<std::remove_const_t<std::remove_reference_t<decltype(args)>>, decltype(internal::meta_type_node::conversion_helper)> || ...)) {
  1389. // exploits the fact that arithmetic types and enums are also default constructible
  1390. auto other = type.construct();
  1391. const auto value = (args(nullptr, instance), ...);
  1392. other.node.conversion_helper(other.data(), &value);
  1393. return other;
  1394. } else {
  1395. // forwards to force a compile-time error in case of available arguments
  1396. return meta_any{meta_ctx_arg, *ctx, std::forward<decltype(args)>(args)...};
  1397. }
  1398. });
  1399. }
  1400. inline bool meta_any::assign(const meta_any &other) {
  1401. auto value = other.allow_cast({*ctx, node});
  1402. return value && storage.assign(value.storage);
  1403. }
  1404. inline bool meta_any::assign(meta_any &&other) {
  1405. if(*node.info == *other.node.info) {
  1406. return storage.assign(std::move(other.storage));
  1407. }
  1408. return assign(std::as_const(other));
  1409. }
  1410. [[nodiscard]] inline meta_type meta_data::type() const noexcept {
  1411. return meta_type{*ctx, node->type(internal::meta_context::from(*ctx))};
  1412. }
  1413. [[nodiscard]] inline meta_type meta_data::arg(const size_type index) const noexcept {
  1414. return index < arity() ? node->arg(*ctx, index) : meta_type{};
  1415. }
  1416. [[nodiscard]] inline meta_type meta_func::ret() const noexcept {
  1417. return meta_type{*ctx, node->ret(internal::meta_context::from(*ctx))};
  1418. }
  1419. [[nodiscard]] inline meta_type meta_func::arg(const size_type index) const noexcept {
  1420. return index < arity() ? node->arg(*ctx, index) : meta_type{};
  1421. }
  1422. /**
  1423. * @cond TURN_OFF_DOXYGEN
  1424. * Internal details not to be documented.
  1425. */
  1426. class meta_sequence_container::meta_iterator final {
  1427. using vtable_type = void(const void *, const std::ptrdiff_t, meta_any *);
  1428. template<typename It>
  1429. static void basic_vtable(const void *value, const std::ptrdiff_t offset, meta_any *other) {
  1430. const auto &it = *static_cast<const It *>(value);
  1431. other ? other->emplace<decltype(*it)>(*it) : std::advance(const_cast<It &>(it), offset);
  1432. }
  1433. public:
  1434. using difference_type = std::ptrdiff_t;
  1435. using value_type = meta_any;
  1436. using pointer = input_iterator_pointer<value_type>;
  1437. using reference = value_type;
  1438. using iterator_category = std::input_iterator_tag;
  1439. using iterator_concept = std::bidirectional_iterator_tag;
  1440. meta_iterator() noexcept
  1441. : meta_iterator{locator<meta_ctx>::value_or()} {}
  1442. meta_iterator(const meta_ctx &area) noexcept
  1443. : ctx{&area} {}
  1444. template<typename It>
  1445. meta_iterator(const meta_ctx &area, It iter) noexcept
  1446. : ctx{&area},
  1447. vtable{&basic_vtable<It>},
  1448. handle{iter} {}
  1449. meta_iterator &operator++() noexcept {
  1450. vtable(handle.data(), 1, nullptr);
  1451. return *this;
  1452. }
  1453. meta_iterator operator++(int value) noexcept {
  1454. meta_iterator orig = *this;
  1455. vtable(handle.data(), ++value, nullptr);
  1456. return orig;
  1457. }
  1458. meta_iterator &operator--() noexcept {
  1459. vtable(handle.data(), -1, nullptr);
  1460. return *this;
  1461. }
  1462. meta_iterator operator--(int value) noexcept {
  1463. meta_iterator orig = *this;
  1464. vtable(handle.data(), --value, nullptr);
  1465. return orig;
  1466. }
  1467. [[nodiscard]] reference operator*() const {
  1468. reference other{meta_ctx_arg, *ctx};
  1469. vtable(handle.data(), 0, &other);
  1470. return other;
  1471. }
  1472. [[nodiscard]] pointer operator->() const {
  1473. return operator*();
  1474. }
  1475. [[nodiscard]] explicit operator bool() const noexcept {
  1476. return static_cast<bool>(handle);
  1477. }
  1478. [[nodiscard]] bool operator==(const meta_iterator &other) const noexcept {
  1479. return handle == other.handle;
  1480. }
  1481. [[nodiscard]] bool operator!=(const meta_iterator &other) const noexcept {
  1482. return !(*this == other);
  1483. }
  1484. [[nodiscard]] const any &base() const noexcept {
  1485. return handle;
  1486. }
  1487. private:
  1488. const meta_ctx *ctx{};
  1489. vtable_type *vtable{};
  1490. any handle{};
  1491. };
  1492. class meta_associative_container::meta_iterator final {
  1493. using vtable_type = void(const void *, std::pair<meta_any, meta_any> *);
  1494. template<bool KeyOnly, typename It>
  1495. static void basic_vtable(const void *value, std::pair<meta_any, meta_any> *other) {
  1496. if(const auto &it = *static_cast<const It *>(value); other) {
  1497. if constexpr(KeyOnly) {
  1498. other->first.emplace<decltype(*it)>(*it);
  1499. } else {
  1500. other->first.emplace<decltype((it->first))>(it->first);
  1501. other->second.emplace<decltype((it->second))>(it->second);
  1502. }
  1503. } else {
  1504. ++const_cast<It &>(it);
  1505. }
  1506. }
  1507. public:
  1508. using difference_type = std::ptrdiff_t;
  1509. using value_type = std::pair<meta_any, meta_any>;
  1510. using pointer = input_iterator_pointer<value_type>;
  1511. using reference = value_type;
  1512. using iterator_category = std::input_iterator_tag;
  1513. using iterator_concept = std::forward_iterator_tag;
  1514. meta_iterator() noexcept
  1515. : meta_iterator{locator<meta_ctx>::value_or()} {}
  1516. meta_iterator(const meta_ctx &area) noexcept
  1517. : ctx{&area} {}
  1518. template<bool KeyOnly, typename It>
  1519. meta_iterator(const meta_ctx &area, std::bool_constant<KeyOnly>, It iter) noexcept
  1520. : ctx{&area},
  1521. vtable{&basic_vtable<KeyOnly, It>},
  1522. handle{iter} {}
  1523. meta_iterator &operator++() noexcept {
  1524. vtable(handle.data(), nullptr);
  1525. return *this;
  1526. }
  1527. meta_iterator operator++(int) noexcept {
  1528. meta_iterator orig = *this;
  1529. vtable(handle.data(), nullptr);
  1530. return orig;
  1531. }
  1532. [[nodiscard]] reference operator*() const {
  1533. reference other{{meta_ctx_arg, *ctx}, {meta_ctx_arg, *ctx}};
  1534. vtable(handle.data(), &other);
  1535. return other;
  1536. }
  1537. [[nodiscard]] pointer operator->() const {
  1538. return operator*();
  1539. }
  1540. [[nodiscard]] explicit operator bool() const noexcept {
  1541. return static_cast<bool>(handle);
  1542. }
  1543. [[nodiscard]] bool operator==(const meta_iterator &other) const noexcept {
  1544. return handle == other.handle;
  1545. }
  1546. [[nodiscard]] bool operator!=(const meta_iterator &other) const noexcept {
  1547. return !(*this == other);
  1548. }
  1549. private:
  1550. const meta_ctx *ctx{};
  1551. vtable_type *vtable{};
  1552. any handle{};
  1553. };
  1554. /**
  1555. * Internal details not to be documented.
  1556. * @endcond
  1557. */
  1558. /**
  1559. * @brief Returns the meta value type of a container.
  1560. * @return The meta value type of the container.
  1561. */
  1562. [[nodiscard]] inline meta_type meta_sequence_container::value_type() const noexcept {
  1563. return value_type_node ? meta_type{*ctx, value_type_node(internal::meta_context::from(*ctx))} : meta_type{};
  1564. }
  1565. /**
  1566. * @brief Returns the size of a container.
  1567. * @return The size of the container.
  1568. */
  1569. [[nodiscard]] inline meta_sequence_container::size_type meta_sequence_container::size() const noexcept {
  1570. return size_fn(data);
  1571. }
  1572. /**
  1573. * @brief Resizes a container to contain a given number of elements.
  1574. * @param sz The new size of the container.
  1575. * @return True in case of success, false otherwise.
  1576. */
  1577. inline bool meta_sequence_container::resize(const size_type sz) {
  1578. return !const_only && resize_fn(const_cast<void *>(data), sz);
  1579. }
  1580. /**
  1581. * @brief Clears the content of a container.
  1582. * @return True in case of success, false otherwise.
  1583. */
  1584. inline bool meta_sequence_container::clear() {
  1585. return !const_only && clear_fn(const_cast<void *>(data));
  1586. }
  1587. /**
  1588. * @brief Reserves storage for at least the given number of elements.
  1589. * @param sz The new capacity of the container.
  1590. * @return True in case of success, false otherwise.
  1591. */
  1592. inline bool meta_sequence_container::reserve(const size_type sz) {
  1593. return !const_only && reserve_fn(const_cast<void *>(data), sz);
  1594. }
  1595. /**
  1596. * @brief Returns an iterator to the first element of a container.
  1597. * @return An iterator to the first element of the container.
  1598. */
  1599. [[nodiscard]] inline meta_sequence_container::iterator meta_sequence_container::begin() {
  1600. return begin_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data);
  1601. }
  1602. /**
  1603. * @brief Returns an iterator that is past the last element of a container.
  1604. * @return An iterator that is past the last element of the container.
  1605. */
  1606. [[nodiscard]] inline meta_sequence_container::iterator meta_sequence_container::end() {
  1607. return end_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data);
  1608. }
  1609. /**
  1610. * @brief Inserts an element at a specified location of a container.
  1611. * @param it Iterator before which the element will be inserted.
  1612. * @param value Element value to insert.
  1613. * @return A possibly invalid iterator to the inserted element.
  1614. */
  1615. inline meta_sequence_container::iterator meta_sequence_container::insert(iterator it, meta_any value) {
  1616. // this abomination is necessary because only on macos value_type and const_reference are different types for std::vector<bool>
  1617. if(const auto vtype = value_type_node(internal::meta_context::from(*ctx)); !const_only && (value.allow_cast({*ctx, vtype}) || value.allow_cast({*ctx, const_reference_node(internal::meta_context::from(*ctx))}))) {
  1618. const bool is_value_type = (value.type().info() == *vtype.info);
  1619. return insert_fn(*ctx, const_cast<void *>(data), is_value_type ? std::as_const(value).data() : nullptr, is_value_type ? nullptr : std::as_const(value).data(), it);
  1620. }
  1621. return iterator{*ctx};
  1622. }
  1623. /**
  1624. * @brief Removes a given element from a container.
  1625. * @param it Iterator to the element to remove.
  1626. * @return A possibly invalid iterator following the last removed element.
  1627. */
  1628. inline meta_sequence_container::iterator meta_sequence_container::erase(iterator it) {
  1629. return const_only ? iterator{*ctx} : erase_fn(*ctx, const_cast<void *>(data), it);
  1630. }
  1631. /**
  1632. * @brief Returns a reference to the element at a given location of a container
  1633. * (no bounds checking is performed).
  1634. * @param pos The position of the element to return.
  1635. * @return A reference to the requested element properly wrapped.
  1636. */
  1637. [[nodiscard]] inline meta_any meta_sequence_container::operator[](const size_type pos) {
  1638. auto it = begin();
  1639. it.operator++(static_cast<int>(pos) - 1);
  1640. return *it;
  1641. }
  1642. /**
  1643. * @brief Returns false if a proxy is invalid, true otherwise.
  1644. * @return False if the proxy is invalid, true otherwise.
  1645. */
  1646. [[nodiscard]] inline meta_sequence_container::operator bool() const noexcept {
  1647. return (data != nullptr);
  1648. }
  1649. /**
  1650. * @brief Returns true if a container is also key-only, false otherwise.
  1651. * @return True if the associative container is also key-only, false otherwise.
  1652. */
  1653. [[deprecated("use mapped_type() instead")]] [[nodiscard]] inline bool meta_associative_container::key_only() const noexcept {
  1654. return (mapped_type_node == nullptr);
  1655. }
  1656. /**
  1657. * @brief Returns the meta key type of a container.
  1658. * @return The meta key type of the a container.
  1659. */
  1660. [[nodiscard]] inline meta_type meta_associative_container::key_type() const noexcept {
  1661. return key_type_node ? meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))} : meta_type{};
  1662. }
  1663. /**
  1664. * @brief Returns the meta mapped type of a container.
  1665. * @return The meta mapped type of the a container.
  1666. */
  1667. [[nodiscard]] inline meta_type meta_associative_container::mapped_type() const noexcept {
  1668. return mapped_type_node ? meta_type{*ctx, mapped_type_node(internal::meta_context::from(*ctx))} : meta_type{};
  1669. }
  1670. /*! @copydoc meta_sequence_container::value_type */
  1671. [[nodiscard]] inline meta_type meta_associative_container::value_type() const noexcept {
  1672. return value_type_node ? meta_type{*ctx, value_type_node(internal::meta_context::from(*ctx))} : meta_type{};
  1673. }
  1674. /*! @copydoc meta_sequence_container::size */
  1675. [[nodiscard]] inline meta_associative_container::size_type meta_associative_container::size() const noexcept {
  1676. return size_fn(data);
  1677. }
  1678. /*! @copydoc meta_sequence_container::clear */
  1679. inline bool meta_associative_container::clear() {
  1680. return !const_only && clear_fn(const_cast<void *>(data));
  1681. }
  1682. /*! @copydoc meta_sequence_container::reserve */
  1683. inline bool meta_associative_container::reserve(const size_type sz) {
  1684. return !const_only && reserve_fn(const_cast<void *>(data), sz);
  1685. }
  1686. /*! @copydoc meta_sequence_container::begin */
  1687. [[nodiscard]] inline meta_associative_container::iterator meta_associative_container::begin() {
  1688. return begin_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data);
  1689. }
  1690. /*! @copydoc meta_sequence_container::end */
  1691. [[nodiscard]] inline meta_associative_container::iterator meta_associative_container::end() {
  1692. return end_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data);
  1693. }
  1694. /**
  1695. * @brief Inserts a key-only or key/value element into a container.
  1696. * @param key The key of the element to insert.
  1697. * @param value The value of the element to insert, if needed.
  1698. * @return A bool denoting whether the insertion took place.
  1699. */
  1700. inline bool meta_associative_container::insert(meta_any key, meta_any value = {}) {
  1701. return !const_only && key.allow_cast(meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))})
  1702. && (!mapped_type_node || value.allow_cast(meta_type{*ctx, mapped_type_node(internal::meta_context::from(*ctx))}))
  1703. && insert_fn(const_cast<void *>(data), std::as_const(key).data(), std::as_const(value).data());
  1704. }
  1705. /**
  1706. * @brief Removes the specified element from a container.
  1707. * @param key The key of the element to remove.
  1708. * @return A bool denoting whether the removal took place.
  1709. */
  1710. inline meta_associative_container::size_type meta_associative_container::erase(meta_any key) {
  1711. return (!const_only && key.allow_cast(meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))})) ? erase_fn(const_cast<void *>(data), std::as_const(key).data()) : 0u;
  1712. }
  1713. /**
  1714. * @brief Returns an iterator to the element with a given key, if any.
  1715. * @param key The key of the element to search.
  1716. * @return An iterator to the element with the given key, if any.
  1717. */
  1718. [[nodiscard]] inline meta_associative_container::iterator meta_associative_container::find(meta_any key) {
  1719. return key.allow_cast(meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))}) ? find_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data, std::as_const(key).data()) : iterator{*ctx};
  1720. }
  1721. /**
  1722. * @brief Returns false if a proxy is invalid, true otherwise.
  1723. * @return False if the proxy is invalid, true otherwise.
  1724. */
  1725. [[nodiscard]] inline meta_associative_container::operator bool() const noexcept {
  1726. return (data != nullptr);
  1727. }
  1728. } // namespace entt
  1729. #endif