meta_any.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925
  1. #include <algorithm>
  2. #include <gtest/gtest.h>
  3. #include <entt/core/hashed_string.hpp>
  4. #include <entt/meta/factory.hpp>
  5. #include <entt/meta/meta.hpp>
  6. #include <entt/meta/resolve.hpp>
  7. struct clazz_t {
  8. clazz_t(): value{0} {}
  9. void member(int i) { value = i; }
  10. static void func() { c = 'd'; }
  11. static inline char c = 'c';
  12. int value;
  13. };
  14. struct empty_t {
  15. virtual ~empty_t() {
  16. ++destructor_counter;
  17. }
  18. static void destroy(empty_t &) {
  19. ++destroy_counter;
  20. }
  21. inline static int destroy_counter = 0;
  22. inline static int destructor_counter = 0;
  23. };
  24. struct fat_t: empty_t {
  25. fat_t()
  26. : value{.0, .0, .0, .0}
  27. {}
  28. fat_t(double v1, double v2, double v3, double v4)
  29. : value{v1, v2, v3, v4}
  30. {}
  31. bool operator==(const fat_t &other) const {
  32. return std::equal(std::begin(value), std::end(value), std::begin(other.value), std::end(other.value));
  33. }
  34. double value[4];
  35. };
  36. struct not_comparable_t {
  37. bool operator==(const not_comparable_t &) const = delete;
  38. };
  39. struct unmanageable_t {
  40. unmanageable_t() = default;
  41. unmanageable_t(const unmanageable_t &) = delete;
  42. unmanageable_t(unmanageable_t &&) = delete;
  43. unmanageable_t & operator=(const unmanageable_t &) = delete;
  44. unmanageable_t & operator=(unmanageable_t &&) = delete;
  45. };
  46. struct MetaAny: ::testing::Test {
  47. void SetUp() override {
  48. using namespace entt::literals;
  49. entt::meta<double>()
  50. .type("double"_hs)
  51. .conv<int>();
  52. entt::meta<empty_t>()
  53. .type("empty"_hs)
  54. .dtor<&empty_t::destroy>();
  55. entt::meta<fat_t>()
  56. .type("fat"_hs)
  57. .base<empty_t>()
  58. .dtor<&fat_t::destroy>();
  59. entt::meta<clazz_t>()
  60. .type("clazz"_hs)
  61. .data<&clazz_t::value>("value"_hs)
  62. .func<&clazz_t::member>("member"_hs)
  63. .func<&clazz_t::func>("func"_hs);
  64. empty_t::destroy_counter = 0;
  65. empty_t::destructor_counter = 0;
  66. }
  67. void TearDown() override {
  68. for(auto type: entt::resolve()) {
  69. type.reset();
  70. }
  71. }
  72. };
  73. TEST_F(MetaAny, SBO) {
  74. entt::meta_any any{'c'};
  75. ASSERT_TRUE(any);
  76. ASSERT_FALSE(any.try_cast<std::size_t>());
  77. ASSERT_EQ(any.cast<char>(), 'c');
  78. ASSERT_NE(any.data(), nullptr);
  79. ASSERT_EQ(any, entt::meta_any{'c'});
  80. ASSERT_NE(entt::meta_any{'h'}, any);
  81. }
  82. TEST_F(MetaAny, NoSBO) {
  83. fat_t instance{.1, .2, .3, .4};
  84. entt::meta_any any{instance};
  85. ASSERT_TRUE(any);
  86. ASSERT_FALSE(any.try_cast<std::size_t>());
  87. ASSERT_EQ(any.cast<fat_t>(), instance);
  88. ASSERT_NE(any.data(), nullptr);
  89. ASSERT_EQ(any, entt::meta_any{instance});
  90. ASSERT_NE(fat_t{}, any);
  91. }
  92. TEST_F(MetaAny, Empty) {
  93. entt::meta_any any{};
  94. ASSERT_FALSE(any);
  95. ASSERT_FALSE(any.type());
  96. ASSERT_FALSE(any.try_cast<std::size_t>());
  97. ASSERT_EQ(any.data(), nullptr);
  98. ASSERT_EQ(any, entt::meta_any{});
  99. ASSERT_NE(entt::meta_any{'c'}, any);
  100. ASSERT_FALSE(any.as_ref());
  101. ASSERT_FALSE(any.as_sequence_container());
  102. ASSERT_FALSE(any.as_associative_container());
  103. ASSERT_FALSE(std::as_const(any).as_ref());
  104. ASSERT_FALSE(std::as_const(any).as_sequence_container());
  105. ASSERT_FALSE(std::as_const(any).as_associative_container());
  106. }
  107. TEST_F(MetaAny, SBOInPlaceTypeConstruction) {
  108. entt::meta_any any{std::in_place_type<int>, 42};
  109. ASSERT_TRUE(any);
  110. ASSERT_FALSE(any.try_cast<std::size_t>());
  111. ASSERT_EQ(any.cast<int>(), 42);
  112. ASSERT_NE(any.data(), nullptr);
  113. ASSERT_EQ(any, (entt::meta_any{std::in_place_type<int>, 42}));
  114. ASSERT_EQ(any, entt::meta_any{42});
  115. ASSERT_NE(entt::meta_any{3}, any);
  116. }
  117. TEST_F(MetaAny, SBOAsRefConstruction) {
  118. int value = 3;
  119. int compare = 42;
  120. entt::meta_any any{std::ref(value)};
  121. ASSERT_TRUE(any);
  122. ASSERT_EQ(any.type(), entt::resolve<int>());
  123. ASSERT_FALSE(any.try_cast<std::size_t>());
  124. ASSERT_EQ(any.cast<int &>(), 3);
  125. ASSERT_EQ(any.cast<const int &>(), 3);
  126. ASSERT_EQ(any.cast<int>(), 3);
  127. ASSERT_EQ(any.data(), &value);
  128. ASSERT_EQ(std::as_const(any).data(), &value);
  129. ASSERT_EQ(any, (entt::meta_any{std::ref(value)}));
  130. ASSERT_NE(any, (entt::meta_any{std::ref(compare)}));
  131. ASSERT_NE(any, entt::meta_any{42});
  132. ASSERT_EQ(entt::meta_any{3}, any);
  133. any = std::ref(value);
  134. ASSERT_TRUE(any);
  135. ASSERT_EQ(any.type(), entt::resolve<int>());
  136. ASSERT_EQ(std::as_const(any).data(), &value);
  137. auto other = any.as_ref();
  138. ASSERT_TRUE(other);
  139. ASSERT_EQ(any.type(), entt::resolve<int>());
  140. ASSERT_EQ(any.cast<int>(), 3);
  141. ASSERT_EQ(other.data(), any.data());
  142. }
  143. TEST_F(MetaAny, SBOAsConstRefConstruction) {
  144. int value = 3;
  145. int compare = 42;
  146. entt::meta_any any{std::cref(value)};
  147. ASSERT_TRUE(any);
  148. ASSERT_EQ(any.type(), entt::resolve<int>());
  149. ASSERT_FALSE(any.try_cast<std::size_t>());
  150. ASSERT_DEATH(any.cast<int &>() = 3, "");
  151. ASSERT_EQ(any.cast<const int &>(), 3);
  152. ASSERT_EQ(any.cast<int>(), 3);
  153. ASSERT_EQ(any.data(), nullptr);
  154. ASSERT_EQ(std::as_const(any).data(), &value);
  155. ASSERT_EQ(any, (entt::meta_any{std::cref(value)}));
  156. ASSERT_NE(any, (entt::meta_any{std::cref(compare)}));
  157. ASSERT_NE(any, entt::meta_any{42});
  158. ASSERT_EQ(entt::meta_any{3}, any);
  159. any = std::cref(value);
  160. ASSERT_TRUE(any);
  161. ASSERT_EQ(any.type(), entt::resolve<int>());
  162. ASSERT_EQ(std::as_const(any).data(), &value);
  163. auto other = any.as_ref();
  164. ASSERT_TRUE(other);
  165. ASSERT_EQ(any.type(), entt::resolve<int>());
  166. ASSERT_EQ(any.cast<int>(), 3);
  167. ASSERT_EQ(other.data(), any.data());
  168. }
  169. TEST_F(MetaAny, SBOCopyConstruction) {
  170. entt::meta_any any{42};
  171. entt::meta_any other{any};
  172. ASSERT_TRUE(any);
  173. ASSERT_TRUE(other);
  174. ASSERT_FALSE(other.try_cast<std::size_t>());
  175. ASSERT_EQ(other.cast<int>(), 42);
  176. ASSERT_EQ(other, entt::meta_any{42});
  177. ASSERT_NE(other, entt::meta_any{0});
  178. }
  179. TEST_F(MetaAny, SBOCopyAssignment) {
  180. entt::meta_any any{42};
  181. entt::meta_any other{3};
  182. other = any;
  183. ASSERT_TRUE(any);
  184. ASSERT_TRUE(other);
  185. ASSERT_FALSE(other.try_cast<std::size_t>());
  186. ASSERT_EQ(other.cast<int>(), 42);
  187. ASSERT_EQ(other, entt::meta_any{42});
  188. ASSERT_NE(other, entt::meta_any{0});
  189. }
  190. TEST_F(MetaAny, SBOMoveConstruction) {
  191. entt::meta_any any{42};
  192. entt::meta_any other{std::move(any)};
  193. ASSERT_FALSE(any);
  194. ASSERT_TRUE(other);
  195. ASSERT_FALSE(other.try_cast<std::size_t>());
  196. ASSERT_EQ(other.cast<int>(), 42);
  197. ASSERT_EQ(other, entt::meta_any{42});
  198. ASSERT_NE(other, entt::meta_any{0});
  199. }
  200. TEST_F(MetaAny, SBOMoveAssignment) {
  201. entt::meta_any any{42};
  202. entt::meta_any other{3};
  203. other = std::move(any);
  204. ASSERT_FALSE(any);
  205. ASSERT_TRUE(other);
  206. ASSERT_FALSE(other.try_cast<std::size_t>());
  207. ASSERT_EQ(other.cast<int>(), 42);
  208. ASSERT_EQ(other, entt::meta_any{42});
  209. ASSERT_NE(other, entt::meta_any{0});
  210. }
  211. TEST_F(MetaAny, SBODirectAssignment) {
  212. entt::meta_any any{};
  213. any = 42;
  214. ASSERT_FALSE(any.try_cast<std::size_t>());
  215. ASSERT_EQ(any.cast<int>(), 42);
  216. ASSERT_EQ(any, entt::meta_any{42});
  217. ASSERT_NE(entt::meta_any{0}, any);
  218. }
  219. TEST_F(MetaAny, NoSBOInPlaceTypeConstruction) {
  220. fat_t instance{.1, .2, .3, .4};
  221. entt::meta_any any{std::in_place_type<fat_t>, instance};
  222. ASSERT_TRUE(any);
  223. ASSERT_FALSE(any.try_cast<std::size_t>());
  224. ASSERT_EQ(any.cast<fat_t>(), instance);
  225. ASSERT_NE(any.data(), nullptr);
  226. ASSERT_EQ(any, (entt::meta_any{std::in_place_type<fat_t>, instance}));
  227. ASSERT_EQ(any, entt::meta_any{instance});
  228. ASSERT_NE(entt::meta_any{fat_t{}}, any);
  229. }
  230. TEST_F(MetaAny, NoSBOAsRefConstruction) {
  231. fat_t instance{.1, .2, .3, .4};
  232. entt::meta_any any{std::ref(instance)};
  233. ASSERT_TRUE(any);
  234. ASSERT_EQ(any.type(), entt::resolve<fat_t>());
  235. ASSERT_FALSE(any.try_cast<std::size_t>());
  236. ASSERT_EQ(any.cast<fat_t &>(), instance);
  237. ASSERT_EQ(any.cast<const fat_t &>(), instance);
  238. ASSERT_EQ(any.cast<fat_t>(), instance);
  239. ASSERT_EQ(any.data(), &instance);
  240. ASSERT_EQ(std::as_const(any).data(), &instance);
  241. ASSERT_EQ(any, (entt::meta_any{std::ref(instance)}));
  242. ASSERT_EQ(any, entt::meta_any{instance});
  243. ASSERT_NE(entt::meta_any{fat_t{}}, any);
  244. any = std::ref(instance);
  245. ASSERT_TRUE(any);
  246. ASSERT_EQ(any.type(), entt::resolve<fat_t>());
  247. ASSERT_EQ(std::as_const(any).data(), &instance);
  248. auto other = any.as_ref();
  249. ASSERT_TRUE(other);
  250. ASSERT_EQ(any.type(), entt::resolve<fat_t>());
  251. ASSERT_EQ(any, entt::meta_any{instance});
  252. ASSERT_EQ(other.data(), any.data());
  253. }
  254. TEST_F(MetaAny, NoSBOAsConstRefConstruction) {
  255. fat_t instance{.1, .2, .3, .4};
  256. entt::meta_any any{std::cref(instance)};
  257. ASSERT_TRUE(any);
  258. ASSERT_EQ(any.type(), entt::resolve<fat_t>());
  259. ASSERT_FALSE(any.try_cast<std::size_t>());
  260. ASSERT_DEATH(any.cast<fat_t &>() = {}, "");
  261. ASSERT_EQ(any.cast<const fat_t &>(), instance);
  262. ASSERT_EQ(any.cast<fat_t>(), instance);
  263. ASSERT_EQ(any.data(), nullptr);
  264. ASSERT_EQ(std::as_const(any).data(), &instance);
  265. ASSERT_EQ(any, (entt::meta_any{std::cref(instance)}));
  266. ASSERT_EQ(any, entt::meta_any{instance});
  267. ASSERT_NE(entt::meta_any{fat_t{}}, any);
  268. any = std::cref(instance);
  269. ASSERT_TRUE(any);
  270. ASSERT_EQ(any.type(), entt::resolve<fat_t>());
  271. ASSERT_EQ(std::as_const(any).data(), &instance);
  272. auto other = any.as_ref();
  273. ASSERT_TRUE(other);
  274. ASSERT_EQ(any.type(), entt::resolve<fat_t>());
  275. ASSERT_EQ(any, entt::meta_any{instance});
  276. ASSERT_EQ(other.data(), any.data());
  277. }
  278. TEST_F(MetaAny, NoSBOCopyConstruction) {
  279. fat_t instance{.1, .2, .3, .4};
  280. entt::meta_any any{instance};
  281. entt::meta_any other{any};
  282. ASSERT_TRUE(any);
  283. ASSERT_TRUE(other);
  284. ASSERT_FALSE(other.try_cast<std::size_t>());
  285. ASSERT_EQ(other.cast<fat_t>(), instance);
  286. ASSERT_EQ(other, entt::meta_any{instance});
  287. ASSERT_NE(other, fat_t{});
  288. }
  289. TEST_F(MetaAny, NoSBOCopyAssignment) {
  290. fat_t instance{.1, .2, .3, .4};
  291. entt::meta_any any{instance};
  292. entt::meta_any other{3};
  293. other = any;
  294. ASSERT_TRUE(any);
  295. ASSERT_TRUE(other);
  296. ASSERT_FALSE(other.try_cast<std::size_t>());
  297. ASSERT_EQ(other.cast<fat_t>(), instance);
  298. ASSERT_EQ(other, entt::meta_any{instance});
  299. ASSERT_NE(other, fat_t{});
  300. }
  301. TEST_F(MetaAny, NoSBOMoveConstruction) {
  302. fat_t instance{.1, .2, .3, .4};
  303. entt::meta_any any{instance};
  304. entt::meta_any other{std::move(any)};
  305. ASSERT_FALSE(any);
  306. ASSERT_TRUE(other);
  307. ASSERT_FALSE(other.try_cast<std::size_t>());
  308. ASSERT_EQ(other.cast<fat_t>(), instance);
  309. ASSERT_EQ(other, entt::meta_any{instance});
  310. ASSERT_NE(other, fat_t{});
  311. }
  312. TEST_F(MetaAny, NoSBOMoveAssignment) {
  313. fat_t instance{.1, .2, .3, .4};
  314. entt::meta_any any{instance};
  315. entt::meta_any other{3};
  316. other = std::move(any);
  317. ASSERT_FALSE(any);
  318. ASSERT_TRUE(other);
  319. ASSERT_FALSE(other.try_cast<std::size_t>());
  320. ASSERT_EQ(other.cast<fat_t>(), instance);
  321. ASSERT_EQ(other, entt::meta_any{instance});
  322. ASSERT_NE(other, fat_t{});
  323. }
  324. TEST_F(MetaAny, NoSBODirectAssignment) {
  325. fat_t instance{.1, .2, .3, .4};
  326. entt::meta_any any{};
  327. any = instance;
  328. ASSERT_FALSE(any.try_cast<std::size_t>());
  329. ASSERT_EQ(any.cast<fat_t>(), instance);
  330. ASSERT_EQ(any, (entt::meta_any{fat_t{.1, .2, .3, .4}}));
  331. ASSERT_NE(fat_t{}, any);
  332. }
  333. TEST_F(MetaAny, VoidInPlaceTypeConstruction) {
  334. entt::meta_any any{std::in_place_type<void>};
  335. ASSERT_TRUE(any);
  336. ASSERT_FALSE(any.try_cast<char>());
  337. ASSERT_EQ(any.data(), nullptr);
  338. ASSERT_EQ(any.type(), entt::resolve<void>());
  339. ASSERT_EQ(any, entt::meta_any{std::in_place_type<void>});
  340. ASSERT_NE(entt::meta_any{3}, any);
  341. }
  342. TEST_F(MetaAny, VoidCopyConstruction) {
  343. entt::meta_any any{std::in_place_type<void>};
  344. entt::meta_any other{any};
  345. ASSERT_TRUE(any);
  346. ASSERT_TRUE(other);
  347. ASSERT_EQ(any.type(), entt::resolve<void>());
  348. ASSERT_EQ(other, entt::meta_any{std::in_place_type<void>});
  349. }
  350. TEST_F(MetaAny, VoidCopyAssignment) {
  351. entt::meta_any any{std::in_place_type<void>};
  352. entt::meta_any other{std::in_place_type<void>};
  353. other = any;
  354. ASSERT_TRUE(any);
  355. ASSERT_TRUE(other);
  356. ASSERT_EQ(any.type(), entt::resolve<void>());
  357. ASSERT_EQ(other, entt::meta_any{std::in_place_type<void>});
  358. }
  359. TEST_F(MetaAny, VoidMoveConstruction) {
  360. entt::meta_any any{std::in_place_type<void>};
  361. entt::meta_any other{std::move(any)};
  362. ASSERT_FALSE(any);
  363. ASSERT_TRUE(other);
  364. ASSERT_EQ(other.type(), entt::resolve<void>());
  365. ASSERT_EQ(other, entt::meta_any{std::in_place_type<void>});
  366. }
  367. TEST_F(MetaAny, VoidMoveAssignment) {
  368. entt::meta_any any{std::in_place_type<void>};
  369. entt::meta_any other{std::in_place_type<void>};
  370. other = std::move(any);
  371. ASSERT_FALSE(any);
  372. ASSERT_TRUE(other);
  373. ASSERT_EQ(other.type(), entt::resolve<void>());
  374. ASSERT_EQ(other, entt::meta_any{std::in_place_type<void>});
  375. }
  376. TEST_F(MetaAny, SBOMoveInvalidate) {
  377. entt::meta_any any{42};
  378. entt::meta_any other{std::move(any)};
  379. entt::meta_any valid = std::move(other);
  380. ASSERT_FALSE(any);
  381. ASSERT_FALSE(other);
  382. ASSERT_TRUE(valid);
  383. }
  384. TEST_F(MetaAny, NoSBOMoveInvalidate) {
  385. fat_t instance{.1, .2, .3, .4};
  386. entt::meta_any any{instance};
  387. entt::meta_any other{std::move(any)};
  388. entt::meta_any valid = std::move(other);
  389. ASSERT_FALSE(any);
  390. ASSERT_FALSE(other);
  391. ASSERT_TRUE(valid);
  392. }
  393. TEST_F(MetaAny, VoidMoveInvalidate) {
  394. entt::meta_any any{std::in_place_type<void>};
  395. entt::meta_any other{std::move(any)};
  396. entt::meta_any valid = std::move(other);
  397. ASSERT_FALSE(any);
  398. ASSERT_FALSE(other);
  399. ASSERT_TRUE(valid);
  400. }
  401. TEST_F(MetaAny, SBODestruction) {
  402. {
  403. entt::meta_any any{std::in_place_type<empty_t>};
  404. any.emplace<empty_t>();
  405. any = empty_t{};
  406. entt::meta_any other{std::move(any)};
  407. any = std::move(other);
  408. }
  409. ASSERT_EQ(empty_t::destroy_counter, 3);
  410. ASSERT_EQ(empty_t::destructor_counter,6);
  411. }
  412. TEST_F(MetaAny, NoSBODestruction) {
  413. {
  414. entt::meta_any any{std::in_place_type<fat_t>, 1., 2., 3., 4.};
  415. any.emplace<fat_t>(1., 2., 3., 4.);
  416. any = fat_t{1., 2., 3., 4.};
  417. entt::meta_any other{std::move(any)};
  418. any = std::move(other);
  419. }
  420. ASSERT_EQ(fat_t::destroy_counter, 3);
  421. ASSERT_EQ(empty_t::destructor_counter, 4);
  422. }
  423. TEST_F(MetaAny, VoidDestruction) {
  424. // just let asan tell us if everything is ok here
  425. [[maybe_unused]] entt::meta_any any{std::in_place_type<void>};
  426. }
  427. TEST_F(MetaAny, Emplace) {
  428. entt::meta_any any{};
  429. any.emplace<int>(42);
  430. ASSERT_TRUE(any);
  431. ASSERT_FALSE(any.try_cast<std::size_t>());
  432. ASSERT_EQ(any.cast<int>(), 42);
  433. ASSERT_NE(any.data(), nullptr);
  434. ASSERT_EQ(any, (entt::meta_any{std::in_place_type<int>, 42}));
  435. ASSERT_EQ(any, entt::meta_any{42});
  436. ASSERT_NE(entt::meta_any{3}, any);
  437. }
  438. TEST_F(MetaAny, EmplaceVoid) {
  439. entt::meta_any any{};
  440. any.emplace<void>();
  441. ASSERT_TRUE(any);
  442. ASSERT_EQ(any.data(), nullptr);
  443. ASSERT_EQ(any.type(), entt::resolve<void>());
  444. ASSERT_EQ(any, (entt::meta_any{std::in_place_type<void>}));
  445. }
  446. TEST_F(MetaAny, Reset) {
  447. entt::meta_any any{42};
  448. ASSERT_TRUE(any);
  449. ASSERT_EQ(any.type(), entt::resolve<int>());
  450. any.reset();
  451. ASSERT_FALSE(any);
  452. ASSERT_EQ(any.type(), entt::meta_type{});
  453. }
  454. TEST_F(MetaAny, SBOSwap) {
  455. entt::meta_any lhs{'c'};
  456. entt::meta_any rhs{42};
  457. std::swap(lhs, rhs);
  458. ASSERT_FALSE(lhs.try_cast<char>());
  459. ASSERT_EQ(lhs.cast<int>(), 42);
  460. ASSERT_FALSE(rhs.try_cast<int>());
  461. ASSERT_EQ(rhs.cast<char>(), 'c');
  462. }
  463. TEST_F(MetaAny, NoSBOSwap) {
  464. entt::meta_any lhs{fat_t{.1, .2, .3, .4}};
  465. entt::meta_any rhs{fat_t{.4, .3, .2, .1}};
  466. std::swap(lhs, rhs);
  467. ASSERT_EQ(lhs.cast<fat_t>(), (fat_t{.4, .3, .2, .1}));
  468. ASSERT_EQ(rhs.cast<fat_t>(), (fat_t{.1, .2, .3, .4}));
  469. }
  470. TEST_F(MetaAny, VoidSwap) {
  471. entt::meta_any lhs{std::in_place_type<void>};
  472. entt::meta_any rhs{std::in_place_type<void>};
  473. const auto *pre = lhs.data();
  474. std::swap(lhs, rhs);
  475. ASSERT_EQ(pre, lhs.data());
  476. }
  477. TEST_F(MetaAny, SBOWithNoSBOSwap) {
  478. entt::meta_any lhs{fat_t{.1, .2, .3, .4}};
  479. entt::meta_any rhs{'c'};
  480. std::swap(lhs, rhs);
  481. ASSERT_FALSE(lhs.try_cast<fat_t>());
  482. ASSERT_EQ(lhs.cast<char>(), 'c');
  483. ASSERT_FALSE(rhs.try_cast<char>());
  484. ASSERT_EQ(rhs.cast<fat_t>(), (fat_t{.1, .2, .3, .4}));
  485. }
  486. TEST_F(MetaAny, SBOWithEmptySwap) {
  487. entt::meta_any lhs{'c'};
  488. entt::meta_any rhs{};
  489. std::swap(lhs, rhs);
  490. ASSERT_FALSE(lhs);
  491. ASSERT_EQ(rhs.cast<char>(), 'c');
  492. std::swap(lhs, rhs);
  493. ASSERT_FALSE(rhs);
  494. ASSERT_EQ(lhs.cast<char>(), 'c');
  495. }
  496. TEST_F(MetaAny, SBOWithVoidSwap) {
  497. entt::meta_any lhs{'c'};
  498. entt::meta_any rhs{std::in_place_type<void>};
  499. std::swap(lhs, rhs);
  500. ASSERT_EQ(lhs.type(), entt::resolve<void>());
  501. ASSERT_EQ(rhs.cast<char>(), 'c');
  502. }
  503. TEST_F(MetaAny, NoSBOWithEmptySwap) {
  504. entt::meta_any lhs{fat_t{.1, .2, .3, .4}};
  505. entt::meta_any rhs{};
  506. std::swap(lhs, rhs);
  507. ASSERT_FALSE(lhs);
  508. ASSERT_EQ(rhs.cast<fat_t>(), (fat_t{.1, .2, .3, .4}));
  509. std::swap(lhs, rhs);
  510. ASSERT_FALSE(rhs);
  511. ASSERT_EQ(lhs.cast<fat_t>(), (fat_t{.1, .2, .3, .4}));
  512. }
  513. TEST_F(MetaAny, NoSBOWithVoidSwap) {
  514. entt::meta_any lhs{fat_t{.1, .2, .3, .4}};
  515. entt::meta_any rhs{std::in_place_type<void>};
  516. std::swap(lhs, rhs);
  517. ASSERT_EQ(lhs.type(), entt::resolve<void>());
  518. ASSERT_EQ(rhs.cast<fat_t>(), (fat_t{.1, .2, .3, .4}));
  519. std::swap(lhs, rhs);
  520. ASSERT_EQ(rhs.type(), entt::resolve<void>());
  521. ASSERT_EQ(lhs.cast<fat_t>(), (fat_t{.1, .2, .3, .4}));
  522. }
  523. TEST_F(MetaAny, AsRef) {
  524. entt::meta_any any{42};
  525. auto ref = any.as_ref();
  526. auto cref = std::as_const(any).as_ref();
  527. ASSERT_EQ(any.try_cast<int>(), any.data());
  528. ASSERT_EQ(ref.try_cast<int>(), any.data());
  529. ASSERT_EQ(cref.try_cast<int>(), nullptr);
  530. ASSERT_EQ(any.try_cast<const int>(), any.data());
  531. ASSERT_EQ(ref.try_cast<const int>(), any.data());
  532. ASSERT_EQ(cref.try_cast<const int>(), any.data());
  533. ASSERT_EQ(any.cast<int>(), 42);
  534. ASSERT_EQ(ref.cast<int>(), 42);
  535. ASSERT_EQ(cref.cast<int>(), 42);
  536. ASSERT_EQ(any.cast<const int>(), 42);
  537. ASSERT_EQ(ref.cast<const int>(), 42);
  538. ASSERT_EQ(cref.cast<const int>(), 42);
  539. ASSERT_EQ(any.cast<int &>(), 42);
  540. ASSERT_EQ(any.cast<const int &>(), 42);
  541. ASSERT_EQ(ref.cast<int &>(), 42);
  542. ASSERT_EQ(ref.cast<const int &>(), 42);
  543. ASSERT_DEATH(cref.cast<int &>() = 3, "");
  544. ASSERT_EQ(cref.cast<const int &>(), 42);
  545. any.cast<int &>() = 3;
  546. ASSERT_EQ(any.cast<int>(), 3);
  547. ASSERT_EQ(ref.cast<int>(), 3);
  548. ASSERT_EQ(cref.cast<int>(), 3);
  549. std::swap(ref, cref);
  550. ASSERT_EQ(ref.try_cast<int>(), nullptr);
  551. ASSERT_EQ(cref.try_cast<int>(), any.data());
  552. ref = ref.as_ref();
  553. cref = std::as_const(cref).as_ref();
  554. ASSERT_EQ(ref.try_cast<int>(), nullptr);
  555. ASSERT_EQ(cref.try_cast<int>(), nullptr);
  556. ASSERT_EQ(ref.try_cast<const int>(), any.data());
  557. ASSERT_EQ(cref.try_cast<const int>(), any.data());
  558. ASSERT_DEATH(ref.cast<int &>() = 3, "");
  559. ASSERT_DEATH(cref.cast<int &>() = 3, "");
  560. ASSERT_EQ(ref.cast<const int &>(), 3);
  561. ASSERT_EQ(cref.cast<const int &>(), 3);
  562. ref = 42;
  563. cref = 42;
  564. ASSERT_NE(ref.try_cast<int>(), nullptr);
  565. ASSERT_NE(cref.try_cast<int>(), nullptr);
  566. ASSERT_EQ(ref.cast<int &>(), 42);
  567. ASSERT_EQ(cref.cast<int &>(), 42);
  568. ASSERT_EQ(ref.cast<const int &>(), 42);
  569. ASSERT_EQ(cref.cast<const int &>(), 42);
  570. ASSERT_NE(ref.try_cast<int>(), any.data());
  571. ASSERT_NE(cref.try_cast<int>(), any.data());
  572. any.emplace<void>();
  573. ref = any.as_ref();
  574. cref = std::as_const(any).as_ref();
  575. ASSERT_TRUE(any);
  576. ASSERT_FALSE(ref);
  577. ASSERT_FALSE(cref);
  578. }
  579. TEST_F(MetaAny, Comparable) {
  580. entt::meta_any any{'c'};
  581. ASSERT_EQ(any, any);
  582. ASSERT_EQ(any, entt::meta_any{'c'});
  583. ASSERT_NE(entt::meta_any{'a'}, any);
  584. ASSERT_NE(any, entt::meta_any{});
  585. ASSERT_TRUE(any == any);
  586. ASSERT_TRUE(any == entt::meta_any{'c'});
  587. ASSERT_FALSE(entt::meta_any{'a'} == any);
  588. ASSERT_TRUE(any != entt::meta_any{'a'});
  589. ASSERT_TRUE(entt::meta_any{} != any);
  590. }
  591. TEST_F(MetaAny, NotComparable) {
  592. entt::meta_any any{not_comparable_t{}};
  593. ASSERT_EQ(any, any);
  594. ASSERT_NE(any, entt::meta_any{not_comparable_t{}});
  595. ASSERT_NE(entt::meta_any{}, any);
  596. ASSERT_TRUE(any == any);
  597. ASSERT_FALSE(any == entt::meta_any{not_comparable_t{}});
  598. ASSERT_TRUE(entt::meta_any{} != any);
  599. }
  600. TEST_F(MetaAny, CompareVoid) {
  601. entt::meta_any any{std::in_place_type<void>};
  602. ASSERT_EQ(any, any);
  603. ASSERT_EQ(any, entt::meta_any{std::in_place_type<void>});
  604. ASSERT_NE(entt::meta_any{'a'}, any);
  605. ASSERT_NE(any, entt::meta_any{});
  606. ASSERT_TRUE(any == any);
  607. ASSERT_TRUE(any == entt::meta_any{std::in_place_type<void>});
  608. ASSERT_FALSE(entt::meta_any{'a'} == any);
  609. ASSERT_TRUE(any != entt::meta_any{'a'});
  610. ASSERT_TRUE(entt::meta_any{} != any);
  611. }
  612. TEST_F(MetaAny, TryCast) {
  613. entt::meta_any any{fat_t{}};
  614. ASSERT_TRUE(any);
  615. ASSERT_EQ(any.type(), entt::resolve<fat_t>());
  616. ASSERT_EQ(any.try_cast<void>(), nullptr);
  617. ASSERT_NE(any.try_cast<empty_t>(), nullptr);
  618. ASSERT_EQ(any.try_cast<fat_t>(), any.data());
  619. ASSERT_EQ(std::as_const(any).try_cast<empty_t>(), any.try_cast<empty_t>());
  620. ASSERT_EQ(std::as_const(any).try_cast<fat_t>(), any.data());
  621. }
  622. TEST_F(MetaAny, Cast) {
  623. entt::meta_any any{fat_t{}};
  624. ASSERT_TRUE(any);
  625. ASSERT_EQ(any.type(), entt::resolve<fat_t>());
  626. ASSERT_EQ(std::as_const(any).cast<const fat_t &>(), fat_t{});
  627. ASSERT_EQ(any.cast<const fat_t>(), fat_t{});
  628. ASSERT_EQ(any.cast<fat_t &>(), fat_t{});
  629. ASSERT_EQ(any.cast<fat_t>(), fat_t{});
  630. ASSERT_EQ(any.cast<fat_t>().value[0u], 0.);
  631. any.cast<fat_t &>().value[0u] = 3.;
  632. ASSERT_EQ(any.cast<fat_t>().value[0u], 3.);
  633. }
  634. TEST_F(MetaAny, Convert) {
  635. entt::meta_any any{42.};
  636. ASSERT_TRUE(any);
  637. ASSERT_EQ(any.type(), entt::resolve<double>());
  638. ASSERT_TRUE(any.allow_cast<double>());
  639. ASSERT_FALSE(any.allow_cast<char>());
  640. ASSERT_EQ(any.type(), entt::resolve<double>());
  641. ASSERT_EQ(any.cast<double>(), 42.);
  642. ASSERT_TRUE(any.allow_cast<int>());
  643. ASSERT_EQ(any.type(), entt::resolve<int>());
  644. ASSERT_EQ(any.cast<int>(), 42);
  645. }
  646. TEST_F(MetaAny, ConstConvert) {
  647. const entt::meta_any any{42.};
  648. ASSERT_TRUE(any);
  649. ASSERT_EQ(any.type(), entt::resolve<double>());
  650. ASSERT_TRUE(any.allow_cast<double>());
  651. ASSERT_FALSE(any.allow_cast<char>());
  652. ASSERT_EQ(any.type(), entt::resolve<double>());
  653. ASSERT_EQ(any.cast<double>(), 42.);
  654. auto other = any.allow_cast<int>();
  655. ASSERT_EQ(any.type(), entt::resolve<double>());
  656. ASSERT_EQ(any.cast<double>(), 42.);
  657. ASSERT_EQ(other.type(), entt::resolve<int>());
  658. ASSERT_EQ(other.cast<int>(), 42);
  659. }
  660. TEST_F(MetaAny, UnmanageableType) {
  661. unmanageable_t instance;
  662. entt::meta_any any{std::ref(instance)};
  663. entt::meta_any other = any.as_ref();
  664. std::swap(any, other);
  665. ASSERT_TRUE(any);
  666. ASSERT_TRUE(other);
  667. ASSERT_EQ(any.type(), entt::resolve<unmanageable_t>());
  668. ASSERT_NE(any.data(), nullptr);
  669. ASSERT_EQ(any.try_cast<int>(), nullptr);
  670. ASSERT_NE(any.try_cast<unmanageable_t>(), nullptr);
  671. ASSERT_TRUE(any.allow_cast<unmanageable_t>());
  672. ASSERT_FALSE(any.allow_cast<int>());
  673. ASSERT_TRUE(std::as_const(any).allow_cast<unmanageable_t>());
  674. ASSERT_FALSE(std::as_const(any).allow_cast<int>());
  675. }
  676. TEST_F(MetaAny, Invoke) {
  677. using namespace entt::literals;
  678. clazz_t instance;
  679. entt::meta_any any{std::ref(instance)};
  680. ASSERT_TRUE(any.invoke("func"_hs));
  681. ASSERT_TRUE(any.invoke("member"_hs, 42));
  682. ASSERT_FALSE(std::as_const(any).invoke("member"_hs, 42));
  683. ASSERT_FALSE(std::as_const(any).as_ref().invoke("member"_hs, 42));
  684. ASSERT_FALSE(any.invoke("non_existent"_hs, 42));
  685. ASSERT_EQ(clazz_t::c, 'd');
  686. ASSERT_EQ(instance.value, 42);
  687. }
  688. TEST_F(MetaAny, SetGet) {
  689. using namespace entt::literals;
  690. clazz_t instance;
  691. entt::meta_any any{std::ref(instance)};
  692. ASSERT_TRUE(any.set("value"_hs, 42));
  693. const auto value = std::as_const(any).get("value"_hs);
  694. ASSERT_TRUE(value);
  695. ASSERT_EQ(value, any.get("value"_hs));
  696. ASSERT_EQ(value, std::as_const(any).as_ref().get("value"_hs));
  697. ASSERT_NE(value.try_cast<int>(), nullptr);
  698. ASSERT_EQ(value.cast<int>(), 42);
  699. ASSERT_EQ(instance.value, 42);
  700. ASSERT_FALSE(any.set("non_existent"_hs, 42));
  701. ASSERT_FALSE(any.get("non_existent"_hs));
  702. }
  703. TEST_F(MetaAny, MakeMetaAny) {
  704. int value = 42;
  705. auto any = entt::make_meta_any<int>(value);
  706. auto ref = entt::make_meta_any<int &>(value);
  707. ASSERT_TRUE(any);
  708. ASSERT_TRUE(ref);
  709. ASSERT_EQ(any.cast<const int &>(), 42);
  710. ASSERT_EQ(ref.cast<const int &>(), 42);
  711. ASSERT_NE(any.data(), &value);
  712. ASSERT_EQ(ref.data(), &value);
  713. }