meta_data.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. #include <gtest/gtest.h>
  2. #include <entt/core/hashed_string.hpp>
  3. #include <entt/meta/factory.hpp>
  4. #include <entt/meta/meta.hpp>
  5. #include <entt/meta/resolve.hpp>
  6. struct base_t {
  7. virtual ~base_t() = default;
  8. static void destroy(base_t &) {
  9. ++counter;
  10. }
  11. inline static int counter = 0;
  12. int value{3};
  13. };
  14. struct derived_t: base_t {};
  15. struct clazz_t {
  16. int i{0};
  17. const int j{1};
  18. base_t base{};
  19. inline static int h{2};
  20. inline static const int k{3};
  21. };
  22. struct setter_getter_t {
  23. int setter(int val) {
  24. return value = val;
  25. }
  26. int getter() {
  27. return value;
  28. }
  29. int setter_with_ref(const int &val) {
  30. return value = val;
  31. }
  32. const int & getter_with_ref() {
  33. return value;
  34. }
  35. static int static_setter(setter_getter_t &type, int value) {
  36. return type.value = value;
  37. }
  38. static int static_getter(const setter_getter_t &type) {
  39. return type.value;
  40. }
  41. int value{};
  42. };
  43. struct array_t {
  44. static inline int global[3];
  45. int local[3];
  46. };
  47. enum class property_t {
  48. random,
  49. value
  50. };
  51. struct Meta: ::testing::Test {
  52. static void SetUpTestCase() {
  53. entt::meta<double>().conv<int>();
  54. entt::meta<base_t>().dtor<&base_t::destroy>().data<&base_t::value>("value"_hs);
  55. entt::meta<derived_t>().base<base_t>().dtor<&derived_t::destroy>();
  56. entt::meta<clazz_t>().type("clazz"_hs)
  57. .data<&clazz_t::i, entt::as_ref_t>("i"_hs).prop(3, 0)
  58. .data<&clazz_t::j>("j"_hs).prop(true, 1)
  59. .data<&clazz_t::h>("h"_hs).prop(property_t::random, 2)
  60. .data<&clazz_t::k>("k"_hs).prop(property_t::value, 3)
  61. .data<&clazz_t::base>("base"_hs)
  62. .data<&clazz_t::i, entt::as_void_t>("void"_hs);
  63. entt::meta<setter_getter_t>()
  64. .type("setter_getter"_hs)
  65. .data<&setter_getter_t::static_setter, &setter_getter_t::static_getter>("x"_hs)
  66. .data<&setter_getter_t::setter, &setter_getter_t::getter>("y"_hs)
  67. .data<&setter_getter_t::static_setter, &setter_getter_t::getter>("z"_hs)
  68. .data<&setter_getter_t::setter_with_ref, &setter_getter_t::getter_with_ref>("w"_hs)
  69. .data<nullptr, &setter_getter_t::getter>("z_ro"_hs)
  70. .data<nullptr, &setter_getter_t::value>("value"_hs);
  71. entt::meta<array_t>()
  72. .type("array"_hs)
  73. .data<&array_t::global>("global"_hs)
  74. .data<&array_t::local>("local"_hs);
  75. }
  76. void SetUp() override {
  77. base_t::counter = 0;
  78. }
  79. };
  80. TEST_F(Meta, MetaData) {
  81. auto data = entt::resolve<clazz_t>().data("i"_hs);
  82. clazz_t instance{};
  83. ASSERT_TRUE(data);
  84. ASSERT_EQ(data.parent(), entt::resolve_id("clazz"_hs));
  85. ASSERT_EQ(data.type(), entt::resolve<int>());
  86. ASSERT_EQ(data.id(), "i"_hs);
  87. ASSERT_FALSE(data.is_const());
  88. ASSERT_FALSE(data.is_static());
  89. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  90. ASSERT_TRUE(data.set(instance, 42));
  91. ASSERT_EQ(data.get(instance).cast<int>(), 42);
  92. data.prop([](auto prop) {
  93. ASSERT_EQ(prop.key(), 3);
  94. ASSERT_EQ(prop.value(), 0);
  95. });
  96. ASSERT_FALSE(data.prop(2));
  97. ASSERT_FALSE(data.prop('c'));
  98. auto prop = data.prop(3);
  99. ASSERT_TRUE(prop);
  100. ASSERT_EQ(prop.key(), 3);
  101. ASSERT_EQ(prop.value(), 0);
  102. }
  103. TEST_F(Meta, MetaDataConst) {
  104. auto data = entt::resolve<clazz_t>().data("j"_hs);
  105. clazz_t instance{};
  106. ASSERT_TRUE(data);
  107. ASSERT_EQ(data.parent(), entt::resolve_id("clazz"_hs));
  108. ASSERT_EQ(data.type(), entt::resolve<int>());
  109. ASSERT_EQ(data.id(), "j"_hs);
  110. ASSERT_TRUE(data.is_const());
  111. ASSERT_FALSE(data.is_static());
  112. ASSERT_EQ(data.get(instance).cast<int>(), 1);
  113. ASSERT_FALSE(data.set(instance, 42));
  114. ASSERT_EQ(data.get(instance).cast<int>(), 1);
  115. data.prop([](auto prop) {
  116. ASSERT_EQ(prop.key(), true);
  117. ASSERT_EQ(prop.value(), 1);
  118. });
  119. ASSERT_FALSE(data.prop(false));
  120. ASSERT_FALSE(data.prop('c'));
  121. auto prop = data.prop(true);
  122. ASSERT_TRUE(prop);
  123. ASSERT_EQ(prop.key(), true);
  124. ASSERT_EQ(prop.value(), 1);
  125. }
  126. TEST_F(Meta, MetaDataStatic) {
  127. auto data = entt::resolve<clazz_t>().data("h"_hs);
  128. ASSERT_TRUE(data);
  129. ASSERT_EQ(data.parent(), entt::resolve_id("clazz"_hs));
  130. ASSERT_EQ(data.type(), entt::resolve<int>());
  131. ASSERT_EQ(data.id(), "h"_hs);
  132. ASSERT_FALSE(data.is_const());
  133. ASSERT_TRUE(data.is_static());
  134. ASSERT_EQ(data.get({}).cast<int>(), 2);
  135. ASSERT_TRUE(data.set({}, 42));
  136. ASSERT_EQ(data.get({}).cast<int>(), 42);
  137. data.prop([](auto prop) {
  138. ASSERT_EQ(prop.key(), property_t::random);
  139. ASSERT_EQ(prop.value(), 2);
  140. });
  141. ASSERT_FALSE(data.prop(property_t::value));
  142. ASSERT_FALSE(data.prop('c'));
  143. auto prop = data.prop(property_t::random);
  144. ASSERT_TRUE(prop);
  145. ASSERT_EQ(prop.key(), property_t::random);
  146. ASSERT_EQ(prop.value(), 2);
  147. }
  148. TEST_F(Meta, MetaDataConstStatic) {
  149. auto data = entt::resolve<clazz_t>().data("k"_hs);
  150. ASSERT_TRUE(data);
  151. ASSERT_EQ(data.parent(), entt::resolve_id("clazz"_hs));
  152. ASSERT_EQ(data.type(), entt::resolve<int>());
  153. ASSERT_EQ(data.id(), "k"_hs);
  154. ASSERT_TRUE(data.is_const());
  155. ASSERT_TRUE(data.is_static());
  156. ASSERT_EQ(data.get({}).cast<int>(), 3);
  157. ASSERT_FALSE(data.set({}, 42));
  158. ASSERT_EQ(data.get({}).cast<int>(), 3);
  159. data.prop([](auto prop) {
  160. ASSERT_EQ(prop.key(), property_t::value);
  161. ASSERT_EQ(prop.value(), 3);
  162. });
  163. ASSERT_FALSE(data.prop(property_t::random));
  164. ASSERT_FALSE(data.prop('c'));
  165. auto prop = data.prop(property_t::value);
  166. ASSERT_TRUE(prop);
  167. ASSERT_EQ(prop.key(), property_t::value);
  168. ASSERT_EQ(prop.value(), 3);
  169. }
  170. TEST_F(Meta, MetaDataGetMetaAnyArg) {
  171. entt::meta_any any{clazz_t{}};
  172. any.cast<clazz_t>().i = 99;
  173. const auto value = entt::resolve<clazz_t>().data("i"_hs).get(any);
  174. ASSERT_TRUE(value);
  175. ASSERT_TRUE(value.cast<int>());
  176. ASSERT_EQ(value.cast<int>(), 99);
  177. }
  178. TEST_F(Meta, MetaDataGetInvalidArg) {
  179. auto instance = 0;
  180. ASSERT_FALSE(entt::resolve<clazz_t>().data("i"_hs).get(instance));
  181. }
  182. TEST_F(Meta, MetaDataSetMetaAnyArg) {
  183. entt::meta_any any{clazz_t{}};
  184. entt::meta_any value{42};
  185. ASSERT_EQ(any.cast<clazz_t>().i, 0);
  186. ASSERT_TRUE(entt::resolve<clazz_t>().data("i"_hs).set(any, value));
  187. ASSERT_EQ(any.cast<clazz_t>().i, 42);
  188. }
  189. TEST_F(Meta, MetaDataSetInvalidArg) {
  190. ASSERT_FALSE(entt::resolve<clazz_t>().data("i"_hs).set({}, 'c'));
  191. }
  192. TEST_F(Meta, MetaDataSetCast) {
  193. clazz_t instance{};
  194. ASSERT_EQ(base_t::counter, 0);
  195. ASSERT_TRUE(entt::resolve<clazz_t>().data("base"_hs).set(instance, derived_t{}));
  196. ASSERT_EQ(base_t::counter, 1);
  197. }
  198. TEST_F(Meta, MetaDataSetConvert) {
  199. clazz_t instance{};
  200. ASSERT_EQ(instance.i, 0);
  201. ASSERT_TRUE(entt::resolve<clazz_t>().data("i"_hs).set(instance, 3.));
  202. ASSERT_EQ(instance.i, 3);
  203. }
  204. TEST_F(Meta, MetaDataSetterGetterAsFreeFunctions) {
  205. auto data = entt::resolve<setter_getter_t>().data("x"_hs);
  206. setter_getter_t instance{};
  207. ASSERT_TRUE(data);
  208. ASSERT_EQ(data.parent(), entt::resolve_id("setter_getter"_hs));
  209. ASSERT_EQ(data.type(), entt::resolve<int>());
  210. ASSERT_EQ(data.id(), "x"_hs);
  211. ASSERT_FALSE(data.is_const());
  212. ASSERT_FALSE(data.is_static());
  213. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  214. ASSERT_TRUE(data.set(instance, 42));
  215. ASSERT_EQ(data.get(instance).cast<int>(), 42);
  216. }
  217. TEST_F(Meta, MetaDataSetterGetterAsMemberFunctions) {
  218. auto data = entt::resolve<setter_getter_t>().data("y"_hs);
  219. setter_getter_t instance{};
  220. ASSERT_TRUE(data);
  221. ASSERT_EQ(data.parent(), entt::resolve_id("setter_getter"_hs));
  222. ASSERT_EQ(data.type(), entt::resolve<int>());
  223. ASSERT_EQ(data.id(), "y"_hs);
  224. ASSERT_FALSE(data.is_const());
  225. ASSERT_FALSE(data.is_static());
  226. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  227. ASSERT_TRUE(data.set(instance, 42));
  228. ASSERT_EQ(data.get(instance).cast<int>(), 42);
  229. }
  230. TEST_F(Meta, MetaDataSetterGetterWithRefAsMemberFunctions) {
  231. auto data = entt::resolve<setter_getter_t>().data("w"_hs);
  232. setter_getter_t instance{};
  233. ASSERT_TRUE(data);
  234. ASSERT_EQ(data.parent(), entt::resolve_id("setter_getter"_hs));
  235. ASSERT_EQ(data.type(), entt::resolve<int>());
  236. ASSERT_EQ(data.id(), "w"_hs);
  237. ASSERT_FALSE(data.is_const());
  238. ASSERT_FALSE(data.is_static());
  239. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  240. ASSERT_TRUE(data.set(instance, 42));
  241. ASSERT_EQ(data.get(instance).cast<int>(), 42);
  242. }
  243. TEST_F(Meta, MetaDataSetterGetterMixed) {
  244. auto data = entt::resolve<setter_getter_t>().data("z"_hs);
  245. setter_getter_t instance{};
  246. ASSERT_TRUE(data);
  247. ASSERT_EQ(data.parent(), entt::resolve_id("setter_getter"_hs));
  248. ASSERT_EQ(data.type(), entt::resolve<int>());
  249. ASSERT_EQ(data.id(), "z"_hs);
  250. ASSERT_FALSE(data.is_const());
  251. ASSERT_FALSE(data.is_static());
  252. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  253. ASSERT_TRUE(data.set(instance, 42));
  254. ASSERT_EQ(data.get(instance).cast<int>(), 42);
  255. }
  256. TEST_F(Meta, MetaDataSetterGetterReadOnly) {
  257. auto data = entt::resolve<setter_getter_t>().data("z_ro"_hs);
  258. setter_getter_t instance{};
  259. ASSERT_TRUE(data);
  260. ASSERT_EQ(data.parent(), entt::resolve_id("setter_getter"_hs));
  261. ASSERT_EQ(data.type(), entt::resolve<int>());
  262. ASSERT_EQ(data.id(), "z_ro"_hs);
  263. ASSERT_TRUE(data.is_const());
  264. ASSERT_FALSE(data.is_static());
  265. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  266. ASSERT_FALSE(data.set(instance, 42));
  267. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  268. }
  269. TEST_F(Meta, MetaDataSetterGetterReadOnlyDataMember) {
  270. auto data = entt::resolve<setter_getter_t>().data("value"_hs);
  271. setter_getter_t instance{};
  272. ASSERT_TRUE(data);
  273. ASSERT_EQ(data.parent(), entt::resolve_id("setter_getter"_hs));
  274. ASSERT_EQ(data.type(), entt::resolve<int>());
  275. ASSERT_EQ(data.id(), "value"_hs);
  276. ASSERT_TRUE(data.is_const());
  277. ASSERT_FALSE(data.is_static());
  278. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  279. ASSERT_FALSE(data.set(instance, 42));
  280. ASSERT_EQ(data.get(instance).cast<int>(), 0);
  281. }
  282. TEST_F(Meta, MetaDataArrayStatic) {
  283. auto data = entt::resolve<array_t>().data("global"_hs);
  284. array_t::global[0] = 3;
  285. array_t::global[1] = 5;
  286. array_t::global[2] = 7;
  287. ASSERT_TRUE(data);
  288. ASSERT_EQ(data.parent(), entt::resolve_id("array"_hs));
  289. ASSERT_EQ(data.type(), entt::resolve<int[3]>());
  290. ASSERT_EQ(data.id(), "global"_hs);
  291. ASSERT_FALSE(data.is_const());
  292. ASSERT_TRUE(data.is_static());
  293. ASSERT_TRUE(data.type().is_array());
  294. ASSERT_EQ(data.type().extent(), 3);
  295. ASSERT_EQ(data.get({}, 0).cast<int>(), 3);
  296. ASSERT_EQ(data.get({}, 1).cast<int>(), 5);
  297. ASSERT_EQ(data.get({}, 2).cast<int>(), 7);
  298. ASSERT_FALSE(data.set({}, 0, 'c'));
  299. ASSERT_EQ(data.get({}, 0).cast<int>(), 3);
  300. ASSERT_TRUE(data.set({}, 0, data.get({}, 0).cast<int>()+2));
  301. ASSERT_TRUE(data.set({}, 1, data.get({}, 1).cast<int>()+2));
  302. ASSERT_TRUE(data.set({}, 2, data.get({}, 2).cast<int>()+2));
  303. ASSERT_EQ(data.get({}, 0).cast<int>(), 5);
  304. ASSERT_EQ(data.get({}, 1).cast<int>(), 7);
  305. ASSERT_EQ(data.get({}, 2).cast<int>(), 9);
  306. }
  307. TEST_F(Meta, MetaDataArray) {
  308. auto data = entt::resolve<array_t>().data("local"_hs);
  309. array_t instance;
  310. instance.local[0] = 3;
  311. instance.local[1] = 5;
  312. instance.local[2] = 7;
  313. ASSERT_TRUE(data);
  314. ASSERT_EQ(data.parent(), entt::resolve_id("array"_hs));
  315. ASSERT_EQ(data.type(), entt::resolve<int[3]>());
  316. ASSERT_EQ(data.id(), "local"_hs);
  317. ASSERT_FALSE(data.is_const());
  318. ASSERT_FALSE(data.is_static());
  319. ASSERT_TRUE(data.type().is_array());
  320. ASSERT_EQ(data.type().extent(), 3);
  321. ASSERT_EQ(data.get(instance, 0).cast<int>(), 3);
  322. ASSERT_EQ(data.get(instance, 1).cast<int>(), 5);
  323. ASSERT_EQ(data.get(instance, 2).cast<int>(), 7);
  324. ASSERT_FALSE(data.set(instance, 0, 'c'));
  325. ASSERT_EQ(data.get(instance, 0).cast<int>(), 3);
  326. ASSERT_TRUE(data.set(instance, 0, data.get(instance, 0).cast<int>()+2));
  327. ASSERT_TRUE(data.set(instance, 1, data.get(instance, 1).cast<int>()+2));
  328. ASSERT_TRUE(data.set(instance, 2, data.get(instance, 2).cast<int>()+2));
  329. ASSERT_EQ(data.get(instance, 0).cast<int>(), 5);
  330. ASSERT_EQ(data.get(instance, 1).cast<int>(), 7);
  331. ASSERT_EQ(data.get(instance, 2).cast<int>(), 9);
  332. }
  333. TEST_F(Meta, MetaDataAsVoid) {
  334. auto data = entt::resolve<clazz_t>().data("void"_hs);
  335. clazz_t instance{};
  336. ASSERT_TRUE(data.set(instance, 42));
  337. ASSERT_EQ(instance.i, 42);
  338. ASSERT_EQ(data.get(instance), entt::meta_any{std::in_place_type<void>});
  339. }
  340. TEST_F(Meta, MetaDataAsRef) {
  341. clazz_t instance{};
  342. auto h_data = entt::resolve<clazz_t>().data("h"_hs);
  343. auto i_data = entt::resolve<clazz_t>().data("i"_hs);
  344. ASSERT_EQ(h_data.type(), entt::resolve<int>());
  345. ASSERT_EQ(i_data.type(), entt::resolve<int>());
  346. h_data.get(instance).cast<int>() = 3;
  347. i_data.get(instance).cast<int>() = 3;
  348. ASSERT_NE(instance.h, 3);
  349. ASSERT_EQ(instance.i, 3);
  350. }
  351. TEST_F(Meta, MetaDataFromBase) {
  352. auto type = entt::resolve<derived_t>();
  353. derived_t instance;
  354. ASSERT_TRUE(type.data("value"_hs));
  355. ASSERT_EQ(instance.value, 3);
  356. ASSERT_TRUE(type.data("value"_hs).set(instance, 42));
  357. ASSERT_EQ(instance.value, 42);
  358. }