meta_any.cpp 21 KB

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