meta_any.cpp 22 KB

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