meta_data.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  1. #include <cstdlib>
  2. #include <string>
  3. #include <utility>
  4. #include <gtest/gtest.h>
  5. #include <entt/core/hashed_string.hpp>
  6. #include <entt/core/type_traits.hpp>
  7. #include <entt/locator/locator.hpp>
  8. #include <entt/meta/context.hpp>
  9. #include <entt/meta/factory.hpp>
  10. #include <entt/meta/meta.hpp>
  11. #include <entt/meta/node.hpp>
  12. #include <entt/meta/policy.hpp>
  13. #include <entt/meta/range.hpp>
  14. #include <entt/meta/resolve.hpp>
  15. #include "../../common/config.h"
  16. #include "../../common/meta_traits.h"
  17. struct base {
  18. virtual ~base() = default;
  19. int value{3};
  20. };
  21. struct derived: base {
  22. derived() = default;
  23. };
  24. struct clazz {
  25. operator int() const {
  26. return h;
  27. }
  28. int i{0};
  29. const int j{1}; // NOLINT
  30. base instance{};
  31. inline static int h{2}; // NOLINT
  32. inline static const int k{3}; // NOLINT
  33. };
  34. struct setter_getter {
  35. int setter(double val) {
  36. return value = static_cast<int>(val);
  37. }
  38. [[nodiscard]] int getter() const {
  39. return value;
  40. }
  41. int setter_with_ref(const int &val) {
  42. return value = val;
  43. }
  44. [[nodiscard]] const int &getter_with_ref() const {
  45. return value;
  46. }
  47. static int static_setter(setter_getter &type, int value) {
  48. return type.value = value;
  49. }
  50. static int static_getter(const setter_getter &type) {
  51. return type.value;
  52. }
  53. int value{0};
  54. };
  55. struct array {
  56. inline static int global[2]; // NOLINT
  57. int local[4]; // NOLINT
  58. };
  59. struct MetaData: ::testing::Test {
  60. void SetUp() override {
  61. using namespace entt::literals;
  62. entt::meta_factory<base>{}
  63. .type("base"_hs)
  64. .data<&base::value>("value"_hs);
  65. entt::meta_factory<derived>{}
  66. .type("derived"_hs)
  67. .base<base>()
  68. .data<&base::value>("value_from_base"_hs);
  69. entt::meta_factory<clazz>{}
  70. .type("clazz"_hs)
  71. .data<&clazz::i, entt::as_ref_t>("i"_hs)
  72. .custom<char>('c')
  73. .traits(test::meta_traits::one | test::meta_traits::two | test::meta_traits::three)
  74. .data<&clazz::i, entt::as_cref_t>("ci"_hs)
  75. .data<&clazz::j>("j")
  76. .traits(test::meta_traits::one)
  77. .data<&clazz::h>("h"_hs, "hhh")
  78. .traits(test::meta_traits::two)
  79. .data<&clazz::k>("k"_hs)
  80. .traits(test::meta_traits::three)
  81. .data<'c'>("l"_hs)
  82. .data<&clazz::instance>("base"_hs)
  83. .data<&clazz::i, entt::as_void_t>("void"_hs)
  84. .conv<int>();
  85. entt::meta_factory<setter_getter>{}
  86. .type("setter_getter"_hs)
  87. .data<&setter_getter::static_setter, &setter_getter::static_getter>("x"_hs)
  88. .data<&setter_getter::setter, &setter_getter::getter>("y"_hs)
  89. .data<&setter_getter::static_setter, &setter_getter::getter>("z"_hs)
  90. .data<&setter_getter::setter_with_ref, &setter_getter::getter_with_ref>("w")
  91. .data<nullptr, &setter_getter::getter>("z_ro"_hs, "readonly")
  92. .data<nullptr, &setter_getter::value>("value"_hs);
  93. entt::meta_factory<array>{}
  94. .type("array"_hs)
  95. .data<&array::global>("global"_hs)
  96. .data<&array::local>("local"_hs);
  97. }
  98. void TearDown() override {
  99. entt::meta_reset();
  100. }
  101. };
  102. using MetaDataDeathTest = MetaData;
  103. TEST_F(MetaData, UserTraits) {
  104. using namespace entt::literals;
  105. ASSERT_EQ(entt::resolve<clazz>().data("ci"_hs).traits<test::meta_traits>(), test::meta_traits::none);
  106. ASSERT_EQ(entt::resolve<clazz>().data("base"_hs).traits<test::meta_traits>(), test::meta_traits::none);
  107. ASSERT_EQ(entt::resolve<clazz>().data("i"_hs).traits<test::meta_traits>(), test::meta_traits::one | test::meta_traits::two | test::meta_traits::three);
  108. ASSERT_EQ(entt::resolve<clazz>().data("j"_hs).traits<test::meta_traits>(), test::meta_traits::one);
  109. ASSERT_EQ(entt::resolve<clazz>().data("h"_hs).traits<test::meta_traits>(), test::meta_traits::two);
  110. ASSERT_EQ(entt::resolve<clazz>().data("k"_hs).traits<test::meta_traits>(), test::meta_traits::three);
  111. }
  112. ENTT_DEBUG_TEST_F(MetaDataDeathTest, UserTraits) {
  113. using namespace entt::literals;
  114. using traits_type = entt::internal::meta_traits;
  115. constexpr auto value = traits_type{static_cast<std::underlying_type_t<traits_type>>(traits_type::_user_defined_traits) + 1u};
  116. ASSERT_DEATH(entt::meta_factory<clazz>{}.data<&clazz::i>("j"_hs).traits(value), "");
  117. }
  118. TEST_F(MetaData, Custom) {
  119. using namespace entt::literals;
  120. ASSERT_EQ(*static_cast<const char *>(entt::resolve<clazz>().data("i"_hs).custom()), 'c');
  121. ASSERT_EQ(static_cast<const char &>(entt::resolve<clazz>().data("i"_hs).custom()), 'c');
  122. ASSERT_EQ(static_cast<const int *>(entt::resolve<clazz>().data("i"_hs).custom()), nullptr);
  123. ASSERT_EQ(static_cast<const int *>(entt::resolve<clazz>().data("j"_hs).custom()), nullptr);
  124. }
  125. ENTT_DEBUG_TEST_F(MetaDataDeathTest, Custom) {
  126. using namespace entt::literals;
  127. ASSERT_DEATH([[maybe_unused]] const int value = entt::resolve<clazz>().data("i"_hs).custom(), "");
  128. ASSERT_DEATH([[maybe_unused]] const char value = entt::resolve<clazz>().data("j"_hs).custom(), "");
  129. }
  130. TEST_F(MetaData, Name) {
  131. using namespace entt::literals;
  132. const entt::meta_type type = entt::resolve<clazz>();
  133. const entt::meta_type other = entt::resolve<setter_getter>();
  134. ASSERT_EQ(type.data("i"_hs).name(), nullptr);
  135. ASSERT_STREQ(type.data("j"_hs).name(), "j");
  136. ASSERT_STREQ(type.data("h"_hs).name(), "hhh");
  137. ASSERT_EQ(other.data("z"_hs).name(), nullptr);
  138. ASSERT_STREQ(other.data("w"_hs).name(), "w");
  139. ASSERT_STREQ(other.data("z_ro"_hs).name(), "readonly");
  140. }
  141. TEST_F(MetaData, Comparison) {
  142. using namespace entt::literals;
  143. auto data = entt::resolve<clazz>().data("i"_hs);
  144. ASSERT_TRUE(data);
  145. ASSERT_EQ(data, data);
  146. ASSERT_NE(data, entt::meta_data{});
  147. ASSERT_FALSE(data != data);
  148. ASSERT_TRUE(data == data);
  149. }
  150. TEST_F(MetaData, NonConst) {
  151. using namespace entt::literals;
  152. auto data = entt::resolve<clazz>().data("i"_hs);
  153. clazz instance{};
  154. ASSERT_TRUE(data);
  155. ASSERT_EQ(data.arity(), 1u);
  156. ASSERT_EQ(data.type(), entt::resolve<int>());
  157. ASSERT_EQ(data.arg(0u), entt::resolve<int>());
  158. ASSERT_FALSE(data.is_const());
  159. ASSERT_FALSE(data.is_static());
  160. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  161. ASSERT_TRUE(data.set(instance, 1));
  162. ASSERT_EQ(data.get(instance).cast<int>(), 1);
  163. }
  164. TEST_F(MetaData, Const) {
  165. using namespace entt::literals;
  166. auto data = entt::resolve<clazz>().data("j"_hs);
  167. clazz instance{};
  168. ASSERT_TRUE(data);
  169. ASSERT_EQ(data.arity(), 1u);
  170. ASSERT_EQ(data.type(), entt::resolve<int>());
  171. ASSERT_EQ(data.arg(0u), entt::resolve<int>());
  172. ASSERT_TRUE(data.is_const());
  173. ASSERT_FALSE(data.is_static());
  174. ASSERT_EQ(data.get(instance).cast<int>(), 1);
  175. ASSERT_FALSE(data.set(instance, 1));
  176. ASSERT_EQ(data.get(instance).cast<int>(), 1);
  177. }
  178. TEST_F(MetaData, Static) {
  179. using namespace entt::literals;
  180. auto data = entt::resolve<clazz>().data("h"_hs);
  181. ASSERT_TRUE(data);
  182. ASSERT_EQ(data.arity(), 1u);
  183. ASSERT_EQ(data.type(), entt::resolve<int>());
  184. ASSERT_EQ(data.arg(0u), entt::resolve<int>());
  185. ASSERT_FALSE(data.is_const());
  186. ASSERT_TRUE(data.is_static());
  187. ASSERT_EQ(data.get({}).cast<int>(), 2);
  188. ASSERT_TRUE(data.set({}, 1));
  189. ASSERT_EQ(data.get({}).cast<int>(), 1);
  190. }
  191. TEST_F(MetaData, ConstStatic) {
  192. using namespace entt::literals;
  193. auto data = entt::resolve<clazz>().data("k"_hs);
  194. ASSERT_TRUE(data);
  195. ASSERT_EQ(data.arity(), 1u);
  196. ASSERT_EQ(data.type(), entt::resolve<int>());
  197. ASSERT_EQ(data.arg(0u), entt::resolve<int>());
  198. ASSERT_TRUE(data.is_const());
  199. ASSERT_TRUE(data.is_static());
  200. ASSERT_EQ(data.get({}).cast<int>(), 3);
  201. ASSERT_FALSE(data.set({}, 1));
  202. ASSERT_EQ(data.get({}).cast<int>(), 3);
  203. }
  204. TEST_F(MetaData, Literal) {
  205. using namespace entt::literals;
  206. auto data = entt::resolve<clazz>().data("l"_hs);
  207. ASSERT_TRUE(data);
  208. ASSERT_EQ(data.arity(), 1u);
  209. ASSERT_EQ(data.type(), entt::resolve<char>());
  210. ASSERT_EQ(data.arg(0u), entt::resolve<char>());
  211. ASSERT_TRUE(data.is_const());
  212. ASSERT_TRUE(data.is_static());
  213. ASSERT_EQ(data.get({}).cast<char>(), 'c');
  214. ASSERT_FALSE(data.set({}, 'a'));
  215. ASSERT_EQ(data.get({}).cast<char>(), 'c');
  216. }
  217. TEST_F(MetaData, GetMetaAnyArg) {
  218. using namespace entt::literals;
  219. entt::meta_any any{clazz{}};
  220. any.cast<clazz &>().i = 3;
  221. const auto value = entt::resolve<clazz>().data("i"_hs).get(any);
  222. ASSERT_TRUE(value);
  223. ASSERT_TRUE(static_cast<bool>(value.cast<int>()));
  224. ASSERT_EQ(value.cast<int>(), 3);
  225. }
  226. TEST_F(MetaData, GetInvalidArg) {
  227. using namespace entt::literals;
  228. auto instance = 0;
  229. ASSERT_FALSE(entt::resolve<clazz>().data("i"_hs).get(instance));
  230. }
  231. TEST_F(MetaData, SetMetaAnyArg) {
  232. using namespace entt::literals;
  233. entt::meta_any any{clazz{}};
  234. const entt::meta_any value{1};
  235. ASSERT_EQ(any.cast<clazz>().i, 0);
  236. ASSERT_TRUE(entt::resolve<clazz>().data("i"_hs).set(any, value));
  237. ASSERT_EQ(any.cast<clazz>().i, 1);
  238. }
  239. TEST_F(MetaData, SetInvalidArg) {
  240. using namespace entt::literals;
  241. ASSERT_FALSE(entt::resolve<clazz>().data("i"_hs).set({}, 'c'));
  242. }
  243. TEST_F(MetaData, SetCast) {
  244. using namespace entt::literals;
  245. clazz instance{};
  246. derived other{};
  247. other.value = 1;
  248. ASSERT_EQ(instance.instance.value, 3);
  249. ASSERT_TRUE(entt::resolve<clazz>().data("base"_hs).set(instance, other));
  250. ASSERT_EQ(instance.instance.value, 1);
  251. }
  252. TEST_F(MetaData, SetConvert) {
  253. using namespace entt::literals;
  254. clazz instance{};
  255. clazz::h = 1;
  256. ASSERT_EQ(instance.i, 0);
  257. ASSERT_TRUE(entt::resolve<clazz>().data("i"_hs).set(instance, instance));
  258. ASSERT_EQ(instance.i, 1);
  259. }
  260. TEST_F(MetaData, SetByRef) {
  261. using namespace entt::literals;
  262. entt::meta_any any{clazz{}};
  263. int value{1};
  264. ASSERT_EQ(any.cast<clazz>().i, 0);
  265. ASSERT_TRUE(entt::resolve<clazz>().data("i"_hs).set(any, entt::forward_as_meta(value)));
  266. ASSERT_EQ(any.cast<clazz>().i, 1);
  267. value = 3;
  268. auto wrapper = entt::forward_as_meta(value);
  269. ASSERT_TRUE(entt::resolve<clazz>().data("i"_hs).set(any, wrapper.as_ref()));
  270. ASSERT_EQ(any.cast<clazz>().i, 3);
  271. }
  272. TEST_F(MetaData, SetByConstRef) {
  273. using namespace entt::literals;
  274. entt::meta_any any{clazz{}};
  275. int value{1};
  276. ASSERT_EQ(any.cast<clazz>().i, 0);
  277. ASSERT_TRUE(entt::resolve<clazz>().data("i"_hs).set(any, entt::forward_as_meta(std::as_const(value))));
  278. ASSERT_EQ(any.cast<clazz>().i, 1);
  279. value = 3;
  280. auto wrapper = entt::forward_as_meta(std::as_const(value));
  281. ASSERT_TRUE(entt::resolve<clazz>().data("i"_hs).set(any, wrapper.as_ref()));
  282. ASSERT_EQ(any.cast<clazz>().i, 3);
  283. }
  284. TEST_F(MetaData, SetterGetterAsFreeFunctions) {
  285. using namespace entt::literals;
  286. auto data = entt::resolve<setter_getter>().data("x"_hs);
  287. setter_getter instance{};
  288. ASSERT_TRUE(data);
  289. ASSERT_EQ(data.arity(), 1u);
  290. ASSERT_EQ(data.type(), entt::resolve<int>());
  291. ASSERT_EQ(data.arg(0u), entt::resolve<int>());
  292. ASSERT_FALSE(data.is_const());
  293. ASSERT_FALSE(data.is_static());
  294. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  295. ASSERT_TRUE(data.set(instance, 1));
  296. ASSERT_EQ(data.get(instance).cast<int>(), 1);
  297. }
  298. TEST_F(MetaData, SetterGetterAsMemberFunctions) {
  299. using namespace entt::literals;
  300. auto data = entt::resolve<setter_getter>().data("y"_hs);
  301. setter_getter instance{};
  302. ASSERT_TRUE(data);
  303. ASSERT_EQ(data.arity(), 1u);
  304. ASSERT_EQ(data.type(), entt::resolve<int>());
  305. ASSERT_EQ(data.arg(0u), entt::resolve<double>());
  306. ASSERT_FALSE(data.is_const());
  307. ASSERT_FALSE(data.is_static());
  308. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  309. ASSERT_TRUE(data.set(instance, 1.));
  310. ASSERT_EQ(data.get(instance).cast<int>(), 1);
  311. ASSERT_TRUE(data.set(instance, 3));
  312. ASSERT_EQ(data.get(instance).cast<int>(), 3);
  313. }
  314. TEST_F(MetaData, SetterGetterWithRefAsMemberFunctions) {
  315. using namespace entt::literals;
  316. auto data = entt::resolve<setter_getter>().data("w"_hs);
  317. setter_getter instance{};
  318. ASSERT_TRUE(data);
  319. ASSERT_EQ(data.arity(), 1u);
  320. ASSERT_EQ(data.type(), entt::resolve<int>());
  321. ASSERT_EQ(data.arg(0u), entt::resolve<int>());
  322. ASSERT_FALSE(data.is_const());
  323. ASSERT_FALSE(data.is_static());
  324. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  325. ASSERT_TRUE(data.set(instance, 1));
  326. ASSERT_EQ(data.get(instance).cast<int>(), 1);
  327. }
  328. TEST_F(MetaData, SetterGetterMixed) {
  329. using namespace entt::literals;
  330. auto data = entt::resolve<setter_getter>().data("z"_hs);
  331. setter_getter instance{};
  332. ASSERT_TRUE(data);
  333. ASSERT_EQ(data.arity(), 1u);
  334. ASSERT_EQ(data.type(), entt::resolve<int>());
  335. ASSERT_EQ(data.arg(0u), entt::resolve<int>());
  336. ASSERT_FALSE(data.is_const());
  337. ASSERT_FALSE(data.is_static());
  338. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  339. ASSERT_TRUE(data.set(instance, 1));
  340. ASSERT_EQ(data.get(instance).cast<int>(), 1);
  341. }
  342. TEST_F(MetaData, SetterGetterReadOnly) {
  343. using namespace entt::literals;
  344. auto data = entt::resolve<setter_getter>().data("z_ro"_hs);
  345. setter_getter instance{};
  346. ASSERT_TRUE(data);
  347. ASSERT_EQ(data.arity(), 0u);
  348. ASSERT_EQ(data.type(), entt::resolve<int>());
  349. ASSERT_EQ(data.arg(0u), entt::meta_type{});
  350. ASSERT_TRUE(data.is_const());
  351. ASSERT_FALSE(data.is_static());
  352. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  353. ASSERT_FALSE(data.set(instance, 1));
  354. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  355. }
  356. TEST_F(MetaData, SetterGetterReadOnlyDataMember) {
  357. using namespace entt::literals;
  358. auto data = entt::resolve<setter_getter>().data("value"_hs);
  359. setter_getter instance{};
  360. ASSERT_TRUE(data);
  361. ASSERT_EQ(data.arity(), 0u);
  362. ASSERT_EQ(data.type(), entt::resolve<int>());
  363. ASSERT_EQ(data.arg(0u), entt::meta_type{});
  364. ASSERT_TRUE(data.is_const());
  365. ASSERT_FALSE(data.is_static());
  366. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  367. ASSERT_FALSE(data.set(instance, 1));
  368. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  369. }
  370. TEST_F(MetaData, ConstInstance) {
  371. using namespace entt::literals;
  372. clazz instance{};
  373. ASSERT_NE(entt::resolve<clazz>().data("i"_hs).get(instance).try_cast<int>(), nullptr);
  374. ASSERT_NE(entt::resolve<clazz>().data("i"_hs).get(instance).try_cast<const int>(), nullptr);
  375. ASSERT_EQ(entt::resolve<clazz>().data("i"_hs).get(std::as_const(instance)).try_cast<int>(), nullptr);
  376. // as_ref_t adapts to the constness of the passed object and returns const references in case
  377. ASSERT_NE(entt::resolve<clazz>().data("i"_hs).get(std::as_const(instance)).try_cast<const int>(), nullptr);
  378. ASSERT_TRUE(entt::resolve<clazz>().data("i"_hs).get(instance));
  379. ASSERT_TRUE(entt::resolve<clazz>().data("i"_hs).set(instance, 3));
  380. ASSERT_TRUE(entt::resolve<clazz>().data("i"_hs).get(std::as_const(instance)));
  381. ASSERT_FALSE(entt::resolve<clazz>().data("i"_hs).set(std::as_const(instance), 3));
  382. ASSERT_TRUE(entt::resolve<clazz>().data("ci"_hs).get(instance));
  383. ASSERT_TRUE(entt::resolve<clazz>().data("ci"_hs).set(instance, 3));
  384. ASSERT_TRUE(entt::resolve<clazz>().data("ci"_hs).get(std::as_const(instance)));
  385. ASSERT_FALSE(entt::resolve<clazz>().data("ci"_hs).set(std::as_const(instance), 3));
  386. ASSERT_TRUE(entt::resolve<clazz>().data("j"_hs).get(instance));
  387. ASSERT_FALSE(entt::resolve<clazz>().data("j"_hs).set(instance, 3));
  388. ASSERT_TRUE(entt::resolve<clazz>().data("j"_hs).get(std::as_const(instance)));
  389. ASSERT_FALSE(entt::resolve<clazz>().data("j"_hs).set(std::as_const(instance), 3));
  390. }
  391. TEST_F(MetaData, ArrayStatic) {
  392. using namespace entt::literals;
  393. auto data = entt::resolve<array>().data("global"_hs);
  394. ASSERT_TRUE(data);
  395. ASSERT_EQ(data.arity(), 1u);
  396. // NOLINTBEGIN(*-avoid-c-arrays)
  397. ASSERT_EQ(data.type(), entt::resolve<int[2]>());
  398. ASSERT_EQ(data.arg(0u), entt::resolve<int[2]>());
  399. // NOLINTEND(*-avoid-c-arrays)
  400. ASSERT_FALSE(data.is_const());
  401. ASSERT_TRUE(data.is_static());
  402. ASSERT_TRUE(data.type().is_array());
  403. ASSERT_FALSE(data.get({}));
  404. }
  405. TEST_F(MetaData, Array) {
  406. using namespace entt::literals;
  407. auto data = entt::resolve<array>().data("local"_hs);
  408. array instance{};
  409. ASSERT_TRUE(data);
  410. ASSERT_EQ(data.arity(), 1u);
  411. // NOLINTBEGIN(*-avoid-c-arrays)
  412. ASSERT_EQ(data.type(), entt::resolve<int[4]>());
  413. ASSERT_EQ(data.arg(0u), entt::resolve<int[4]>());
  414. // NOLINTEND(*-avoid-c-arrays)
  415. ASSERT_FALSE(data.is_const());
  416. ASSERT_FALSE(data.is_static());
  417. ASSERT_TRUE(data.type().is_array());
  418. ASSERT_FALSE(data.get(instance));
  419. }
  420. TEST_F(MetaData, AsVoid) {
  421. using namespace entt::literals;
  422. auto data = entt::resolve<clazz>().data("void"_hs);
  423. clazz instance{};
  424. ASSERT_TRUE(data);
  425. ASSERT_EQ(data.arity(), 1u);
  426. ASSERT_EQ(data.type(), entt::resolve<int>());
  427. ASSERT_EQ(data.arg(0u), entt::resolve<int>());
  428. ASSERT_TRUE(data.set(instance, 1));
  429. ASSERT_EQ(instance.i, 1);
  430. ASSERT_EQ(data.get(instance), entt::meta_any{std::in_place_type<void>});
  431. }
  432. TEST_F(MetaData, AsRef) {
  433. using namespace entt::literals;
  434. clazz instance{};
  435. auto data = entt::resolve<clazz>().data("i"_hs);
  436. ASSERT_TRUE(data);
  437. ASSERT_EQ(data.arity(), 1u);
  438. ASSERT_EQ(data.type(), entt::resolve<int>());
  439. ASSERT_EQ(data.arg(0u), entt::resolve<int>());
  440. ASSERT_EQ(instance.i, 0);
  441. data.get(instance).cast<int &>() = 3;
  442. ASSERT_EQ(instance.i, 3);
  443. }
  444. TEST_F(MetaData, AsConstRef) {
  445. using namespace entt::literals;
  446. clazz instance{};
  447. auto data = entt::resolve<clazz>().data("ci"_hs);
  448. ASSERT_EQ(instance.i, 0);
  449. ASSERT_EQ(data.arity(), 1u);
  450. ASSERT_EQ(data.type(), entt::resolve<int>());
  451. ASSERT_EQ(data.arg(0u), entt::resolve<int>());
  452. ASSERT_EQ(data.get(instance).cast<const int &>(), 0);
  453. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  454. ASSERT_EQ(instance.i, 0);
  455. }
  456. ENTT_DEBUG_TEST_F(MetaDataDeathTest, AsConstRef) {
  457. using namespace entt::literals;
  458. clazz instance{};
  459. auto data = entt::resolve<clazz>().data("ci"_hs);
  460. ASSERT_DEATH(data.get(instance).cast<int &>() = 3, "");
  461. }
  462. TEST_F(MetaData, SetGetBaseData) {
  463. using namespace entt::literals;
  464. auto type = entt::resolve<derived>();
  465. derived instance{};
  466. ASSERT_TRUE(type.data("value"_hs));
  467. ASSERT_EQ(instance.value, 3);
  468. ASSERT_TRUE(type.data("value"_hs).set(instance, 1));
  469. ASSERT_EQ(type.data("value"_hs).get(instance).cast<int>(), 1);
  470. ASSERT_EQ(instance.value, 1);
  471. }
  472. TEST_F(MetaData, SetGetFromBase) {
  473. using namespace entt::literals;
  474. auto type = entt::resolve<derived>();
  475. derived instance{};
  476. ASSERT_TRUE(type.data("value_from_base"_hs));
  477. ASSERT_EQ(instance.value, 3);
  478. ASSERT_TRUE(type.data("value_from_base"_hs).set(instance, 1));
  479. ASSERT_EQ(type.data("value_from_base"_hs).get(instance).cast<int>(), 1);
  480. ASSERT_EQ(instance.value, 1);
  481. }
  482. TEST_F(MetaData, ReRegistration) {
  483. using namespace entt::literals;
  484. SetUp();
  485. auto &&node = entt::internal::resolve<base>(entt::internal::meta_context::from(entt::locator<entt::meta_ctx>::value_or()));
  486. auto type = entt::resolve<base>();
  487. ASSERT_TRUE(node.details);
  488. ASSERT_FALSE(node.details->data.empty());
  489. ASSERT_EQ(node.details->data.size(), 1u);
  490. ASSERT_TRUE(type.data("value"_hs));
  491. entt::meta_factory<base>{}.data<&base::value>("field"_hs);
  492. ASSERT_TRUE(node.details);
  493. ASSERT_EQ(node.details->data.size(), 2u);
  494. ASSERT_TRUE(type.data("value"_hs));
  495. ASSERT_TRUE(type.data("field"_hs));
  496. entt::meta_factory<base>{}
  497. .data<&base::value>("field"_hs)
  498. .traits(test::meta_traits::one)
  499. .custom<int>(3)
  500. // this should not overwrite traits and custom data
  501. .data<&base::value>("field"_hs);
  502. ASSERT_EQ(type.data("field"_hs).traits<test::meta_traits>(), test::meta_traits::one);
  503. ASSERT_NE(static_cast<const int *>(type.data("field"_hs).custom()), nullptr);
  504. }
  505. TEST_F(MetaData, CollisionAndReuse) {
  506. using namespace entt::literals;
  507. ASSERT_TRUE(entt::resolve<clazz>().data("j"_hs));
  508. ASSERT_FALSE(entt::resolve<clazz>().data("cj"_hs));
  509. ASSERT_TRUE(entt::resolve<clazz>().data("j"_hs).is_const());
  510. ASSERT_NO_THROW(entt::meta_factory<clazz>{}.data<&clazz::i>("j"_hs));
  511. ASSERT_NO_THROW(entt::meta_factory<clazz>{}.data<&clazz::j>("cj"_hs));
  512. ASSERT_TRUE(entt::resolve<clazz>().data("j"_hs));
  513. ASSERT_TRUE(entt::resolve<clazz>().data("cj"_hs));
  514. ASSERT_FALSE(entt::resolve<clazz>().data("j"_hs).is_const());
  515. }