meta_data.cpp 22 KB

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