meta.hpp 71 KB

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