meta_container.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. #include <gtest/gtest.h>
  2. #include <entt/core/hashed_string.hpp>
  3. #include <entt/meta/container.hpp>
  4. #include <entt/meta/factory.hpp>
  5. #include <entt/meta/meta.hpp>
  6. #include <entt/meta/resolve.hpp>
  7. struct MetaContainer: ::testing::Test {
  8. static void SetUpTestCase() {
  9. entt::meta<double>().conv<int>();
  10. entt::meta<int>().conv<char>();
  11. }
  12. };
  13. TEST_F(MetaContainer, InvalidContainer) {
  14. ASSERT_FALSE(entt::meta_any{42}.as_sequence_container());
  15. ASSERT_FALSE(entt::meta_any{42}.as_associative_container());
  16. ASSERT_FALSE((entt::meta_any{std::map<int, char>{}}.as_sequence_container()));
  17. ASSERT_FALSE(entt::meta_any{std::vector<int>{}}.as_associative_container());
  18. }
  19. TEST_F(MetaContainer, EmptySequenceContainer) {
  20. entt::meta_sequence_container container{};
  21. ASSERT_FALSE(container);
  22. entt::meta_any any{std::vector<int>{}};
  23. container = any.as_sequence_container();
  24. ASSERT_TRUE(container);
  25. }
  26. TEST_F(MetaContainer, EmptyAssociativeContainer) {
  27. entt::meta_associative_container container{};
  28. ASSERT_FALSE(container);
  29. entt::meta_any any{std::map<int, char>{}};
  30. container = any.as_associative_container();
  31. ASSERT_TRUE(container);
  32. }
  33. TEST_F(MetaContainer, SequenceContainerIterator) {
  34. std::vector<int> vec{2, 3, 4};
  35. entt::meta_any any{std::ref(vec)};
  36. entt::meta_sequence_container::iterator first{};
  37. auto view = any.as_sequence_container();
  38. ASSERT_FALSE(first);
  39. first = view.begin();
  40. const auto last = view.end();
  41. ASSERT_TRUE(first);
  42. ASSERT_TRUE(last);
  43. ASSERT_FALSE(first == last);
  44. ASSERT_TRUE(first != last);
  45. ASSERT_NE(first, last);
  46. ASSERT_EQ((*(first++)).cast<int>(), 2);
  47. ASSERT_EQ((*(++first)).cast<int>(), 4);
  48. ASSERT_NE(first++, last);
  49. ASSERT_EQ(first, last);
  50. ASSERT_TRUE(first == last);
  51. ASSERT_FALSE(first != last);
  52. }
  53. TEST_F(MetaContainer, AssociativeContainerIterator) {
  54. std::map<int, char> map{{2, 'c'}, {3, 'd'}, {4, 'e'}};
  55. entt::meta_any any{std::ref(map)};
  56. entt::meta_associative_container::iterator first{};
  57. auto view = any.as_associative_container();
  58. ASSERT_FALSE(first);
  59. first = view.begin();
  60. const auto last = view.end();
  61. ASSERT_TRUE(first);
  62. ASSERT_TRUE(last);
  63. ASSERT_FALSE(first == last);
  64. ASSERT_TRUE(first != last);
  65. ASSERT_NE(first, last);
  66. ASSERT_EQ((*(first++)).first.cast<int>(), 2);
  67. ASSERT_EQ((*(++first)).second.cast<char>(), 'e');
  68. ASSERT_NE(first++, last);
  69. ASSERT_EQ(first, last);
  70. ASSERT_TRUE(first == last);
  71. ASSERT_FALSE(first != last);
  72. }
  73. TEST_F(MetaContainer, StdVector) {
  74. std::vector<int> vec{};
  75. entt::meta_any any{std::ref(vec)};
  76. auto view = any.as_sequence_container();
  77. ASSERT_TRUE(view);
  78. ASSERT_EQ(view.value_type(), entt::resolve<int>());
  79. ASSERT_EQ(view.size(), 0u);
  80. ASSERT_EQ(view.begin(), view.end());
  81. ASSERT_TRUE(view.resize(3u));
  82. ASSERT_EQ(view.size(), 3u);
  83. ASSERT_NE(view.begin(), view.end());
  84. view[0].cast<int &>() = 2;
  85. view[1].cast<int &>() = 3;
  86. view[2].cast<int &>() = 4;
  87. ASSERT_EQ(view[1u].cast<int>(), 3);
  88. auto it = view.begin();
  89. auto ret = view.insert(it, 0);
  90. ASSERT_TRUE(ret.second);
  91. ASSERT_FALSE(view.insert(ret.first, 'c').second);
  92. ASSERT_TRUE(view.insert(++ret.first, 1.).second);
  93. ASSERT_EQ(view.size(), 5u);
  94. ASSERT_EQ((*view.begin()).cast<int>(), 0);
  95. ASSERT_EQ((*++view.begin()).cast<int>(), 1);
  96. it = view.begin();
  97. ret = view.erase(it);
  98. ASSERT_TRUE(ret.second);
  99. ASSERT_EQ(view.size(), 4u);
  100. ASSERT_EQ((*ret.first).cast<int>(), 1);
  101. ASSERT_TRUE(view.clear());
  102. ASSERT_EQ(view.size(), 0u);
  103. }
  104. TEST_F(MetaContainer, StdArray) {
  105. std::array<int, 3> arr{};
  106. entt::meta_any any{std::ref(arr)};
  107. auto view = any.as_sequence_container();
  108. ASSERT_TRUE(view);
  109. ASSERT_EQ(view.value_type(), entt::resolve<int>());
  110. ASSERT_EQ(view.size(), 3u);
  111. ASSERT_NE(view.begin(), view.end());
  112. ASSERT_FALSE(view.resize(5u));
  113. ASSERT_EQ(view.size(), 3u);
  114. view[0].cast<int &>() = 2;
  115. view[1].cast<int &>() = 3;
  116. view[2].cast<int &>() = 4;
  117. ASSERT_EQ(view[1u].cast<int>(), 3);
  118. auto it = view.begin();
  119. auto ret = view.insert(it, 0);
  120. ASSERT_FALSE(ret.second);
  121. ASSERT_FALSE(view.insert(it, 'c').second);
  122. ASSERT_FALSE(view.insert(++it, 1).second);
  123. ASSERT_EQ(view.size(), 3u);
  124. ASSERT_EQ((*view.begin()).cast<int>(), 2);
  125. ASSERT_EQ((*++view.begin()).cast<int>(), 3);
  126. it = view.begin();
  127. ret = view.erase(it);
  128. ASSERT_FALSE(ret.second);
  129. ASSERT_EQ(view.size(), 3u);
  130. ASSERT_EQ((*it).cast<int>(), 2);
  131. ASSERT_FALSE(view.clear());
  132. ASSERT_EQ(view.size(), 3u);
  133. }
  134. TEST_F(MetaContainer, StdMap) {
  135. std::map<int, char> map{{2, 'c'}, {3, 'd'}, {4, 'e'}};
  136. entt::meta_any any{std::ref(map)};
  137. auto view = any.as_associative_container();
  138. ASSERT_TRUE(view);
  139. ASSERT_FALSE(view.key_only());
  140. ASSERT_EQ(view.key_type(), entt::resolve<int>());
  141. ASSERT_EQ(view.mapped_type(), entt::resolve<char>());
  142. ASSERT_EQ(view.value_type(), (entt::resolve<std::pair<const int, char>>()));
  143. ASSERT_EQ(view.size(), 3u);
  144. ASSERT_NE(view.begin(), view.end());
  145. ASSERT_EQ((*view.find(3)).second.cast<char>(), 'd');
  146. ASSERT_FALSE(view.insert('a', 'a'));
  147. ASSERT_FALSE(view.insert(1, 1.));
  148. ASSERT_TRUE(view.insert(0, 'a'));
  149. ASSERT_TRUE(view.insert(1., static_cast<int>('b')));
  150. ASSERT_EQ(view.size(), 5u);
  151. ASSERT_EQ((*view.find(0)).second.cast<char>(), 'a');
  152. ASSERT_EQ((*view.find(1.)).second.cast<char>(), 'b');
  153. ASSERT_FALSE(view.erase('c'));
  154. ASSERT_EQ(view.size(), 5u);
  155. ASSERT_FALSE(view.find('c'));
  156. ASSERT_TRUE(view.erase(0));
  157. ASSERT_EQ(view.size(), 4u);
  158. ASSERT_EQ(view.find(0), view.end());
  159. (*view.find(1)).second.cast<char &>() = 'f';
  160. ASSERT_EQ((*view.find(1)).second.cast<char>(), 'f');
  161. ASSERT_TRUE(view.erase(1.));
  162. ASSERT_TRUE(view.clear());
  163. ASSERT_EQ(view.size(), 0u);
  164. }
  165. TEST_F(MetaContainer, StdSet) {
  166. std::set<int> set{2, 3, 4};
  167. entt::meta_any any{std::ref(set)};
  168. auto view = any.as_associative_container();
  169. ASSERT_TRUE(view);
  170. ASSERT_TRUE(view.key_only());
  171. ASSERT_EQ(view.key_type(), entt::resolve<int>());
  172. ASSERT_EQ(view.mapped_type(), entt::meta_type{});
  173. ASSERT_EQ(view.value_type(), entt::resolve<int>());
  174. ASSERT_EQ(view.size(), 3u);
  175. ASSERT_NE(view.begin(), view.end());
  176. ASSERT_EQ((*view.find(3)).first.cast<int>(), 3);
  177. ASSERT_FALSE(view.insert('0'));
  178. ASSERT_TRUE(view.insert(0));
  179. ASSERT_TRUE(view.insert(1));
  180. ASSERT_EQ(view.size(), 5u);
  181. ASSERT_EQ((*view.find(0)).first.cast<int>(), 0);
  182. ASSERT_EQ((*view.find(1.)).first.cast<int>(), 1);
  183. ASSERT_FALSE(view.erase('c'));
  184. ASSERT_EQ(view.size(), 5u);
  185. ASSERT_FALSE(view.find('c'));
  186. ASSERT_TRUE(view.erase(0));
  187. ASSERT_EQ(view.size(), 4u);
  188. ASSERT_EQ(view.find(0), view.end());
  189. ASSERT_EQ((*view.find(1)).first.try_cast<int>(), nullptr);
  190. ASSERT_NE((*view.find(1)).first.try_cast<const int>(), nullptr);
  191. ASSERT_EQ((*view.find(1)).first.cast<const int &>(), 1);
  192. ASSERT_TRUE(view.erase(1.));
  193. ASSERT_TRUE(view.clear());
  194. ASSERT_EQ(view.size(), 0u);
  195. }
  196. TEST_F(MetaContainer, ConstSequenceContainer) {
  197. std::vector<int> vec{};
  198. entt::meta_any any{std::cref(vec)};
  199. auto view = any.as_sequence_container();
  200. ASSERT_TRUE(view);
  201. ASSERT_EQ(view.value_type(), entt::resolve<int>());
  202. ASSERT_EQ(view.size(), 0u);
  203. ASSERT_EQ(view.begin(), view.end());
  204. ASSERT_FALSE(view.resize(3u));
  205. ASSERT_EQ(view.size(), 0u);
  206. ASSERT_EQ(view.begin(), view.end());
  207. vec.push_back(42);
  208. ASSERT_EQ(view.size(), 1u);
  209. ASSERT_NE(view.begin(), view.end());
  210. ASSERT_DEATH(view[0].cast<int &>() = 2, ".*");
  211. ASSERT_EQ(view[0].cast<const int &>(), 42);
  212. auto it = view.begin();
  213. auto ret = view.insert(it, 0);
  214. ASSERT_FALSE(ret.second);
  215. ASSERT_EQ(view.size(), 1u);
  216. ASSERT_EQ((*it).cast<int>(), 42);
  217. ASSERT_EQ(++it, view.end());
  218. it = view.begin();
  219. ret = view.erase(it);
  220. ASSERT_FALSE(ret.second);
  221. ASSERT_EQ(view.size(), 1u);
  222. ASSERT_FALSE(view.clear());
  223. ASSERT_EQ(view.size(), 1u);
  224. }
  225. TEST_F(MetaContainer, ConstKeyValueAssociativeContainer) {
  226. std::map<int, char> map{};
  227. entt::meta_any any{std::cref(map)};
  228. auto view = any.as_associative_container();
  229. ASSERT_TRUE(view);
  230. ASSERT_FALSE(view.key_only());
  231. ASSERT_EQ(view.key_type(), entt::resolve<int>());
  232. ASSERT_EQ(view.mapped_type(), entt::resolve<char>());
  233. ASSERT_EQ(view.value_type(), (entt::resolve<std::pair<const int, char>>()));
  234. ASSERT_EQ(view.size(), 0u);
  235. ASSERT_EQ(view.begin(), view.end());
  236. map[2] = 'c';
  237. ASSERT_EQ(view.size(), 1u);
  238. ASSERT_NE(view.begin(), view.end());
  239. ASSERT_DEATH((*view.find(2)).second.cast<char &>() = 'a', ".*");
  240. ASSERT_EQ((*view.find(2)).second.cast<const char &>(), 'c');
  241. ASSERT_FALSE(view.insert(0, 'a'));
  242. ASSERT_EQ(view.size(), 1u);
  243. ASSERT_EQ(view.find(0), view.end());
  244. ASSERT_EQ((*view.find(2)).second.cast<char>(), 'c');
  245. ASSERT_FALSE(view.erase(2));
  246. ASSERT_EQ(view.size(), 1u);
  247. ASSERT_NE(view.find(2), view.end());
  248. ASSERT_FALSE(view.clear());
  249. ASSERT_EQ(view.size(), 1u);
  250. }
  251. TEST_F(MetaContainer, ConstKeyOnlyAssociativeContainer) {
  252. std::set<int> set{};
  253. entt::meta_any any{std::cref(set)};
  254. auto view = any.as_associative_container();
  255. ASSERT_TRUE(view);
  256. ASSERT_TRUE(view.key_only());
  257. ASSERT_EQ(view.key_type(), entt::resolve<int>());
  258. ASSERT_EQ(view.mapped_type(), entt::meta_type{});
  259. ASSERT_EQ(view.value_type(), (entt::resolve<int>()));
  260. ASSERT_EQ(view.size(), 0u);
  261. ASSERT_EQ(view.begin(), view.end());
  262. set.insert(2);
  263. ASSERT_EQ(view.size(), 1u);
  264. ASSERT_NE(view.begin(), view.end());
  265. ASSERT_EQ((*view.find(2)).first.try_cast<int>(), nullptr);
  266. ASSERT_NE((*view.find(2)).first.try_cast<const int>(), nullptr);
  267. ASSERT_EQ((*view.find(2)).first.cast<int>(), 2);
  268. ASSERT_EQ((*view.find(2)).first.cast<const int &>(), 2);
  269. ASSERT_FALSE(view.insert(0));
  270. ASSERT_EQ(view.size(), 1u);
  271. ASSERT_EQ(view.find(0), view.end());
  272. ASSERT_EQ((*view.find(2)).first.cast<int>(), 2);
  273. ASSERT_FALSE(view.erase(2));
  274. ASSERT_EQ(view.size(), 1u);
  275. ASSERT_NE(view.find(2), view.end());
  276. ASSERT_FALSE(view.clear());
  277. ASSERT_EQ(view.size(), 1u);
  278. }
  279. TEST_F(MetaContainer, SequenceContainerConstMetaAny) {
  280. auto test = [](const entt::meta_any any) {
  281. auto view = any.as_sequence_container();
  282. ASSERT_TRUE(view);
  283. ASSERT_EQ(view.value_type(), entt::resolve<int>());
  284. ASSERT_DEATH(view[0].cast<int &>() = 2, ".*");
  285. ASSERT_EQ(view[0].cast<const int &>(), 42);
  286. };
  287. std::vector<int> vec{42};
  288. test(vec);
  289. test(std::ref(vec));
  290. test(std::cref(vec));
  291. }
  292. TEST_F(MetaContainer, KeyValueAssociativeContainerConstMetaAny) {
  293. auto test = [](const entt::meta_any any) {
  294. auto view = any.as_associative_container();
  295. ASSERT_TRUE(view);
  296. ASSERT_EQ(view.value_type(), (entt::resolve<std::pair<const int, char>>()));
  297. ASSERT_DEATH((*view.find(2)).second.cast<char &>() = 'a', ".*");
  298. ASSERT_EQ((*view.find(2)).second.cast<const char &>(), 'c');
  299. };
  300. std::map<int, char> map{{2, 'c'}};
  301. test(map);
  302. test(std::ref(map));
  303. test(std::cref(map));
  304. }
  305. TEST_F(MetaContainer, KeyOnlyAssociativeContainerConstMetaAny) {
  306. auto test = [](const entt::meta_any any) {
  307. auto view = any.as_associative_container();
  308. ASSERT_TRUE(view);
  309. ASSERT_EQ(view.value_type(), (entt::resolve<int>()));
  310. ASSERT_EQ((*view.find(2)).first.try_cast<int>(), nullptr);
  311. ASSERT_NE((*view.find(2)).first.try_cast<const int>(), nullptr);
  312. ASSERT_EQ((*view.find(2)).first.cast<int>(), 2);
  313. ASSERT_EQ((*view.find(2)).first.cast<const int &>(), 2);
  314. };
  315. std::set<int> set{2};
  316. test(set);
  317. test(std::ref(set));
  318. test(std::cref(set));
  319. }
  320. TEST_F(MetaContainer, StdVectorBool) {
  321. using proxy_type = typename std::vector<bool>::reference;
  322. using const_proxy_type = typename std::vector<bool>::const_reference;
  323. std::vector<bool> vec{};
  324. entt::meta_any any{std::ref(vec)};
  325. auto cany = std::as_const(any).as_ref();
  326. auto view = any.as_sequence_container();
  327. auto cview = cany.as_sequence_container();
  328. ASSERT_TRUE(view);
  329. ASSERT_EQ(view.value_type(), entt::resolve<bool>());
  330. ASSERT_EQ(view.size(), 0u);
  331. ASSERT_EQ(view.begin(), view.end());
  332. ASSERT_TRUE(view.resize(3u));
  333. ASSERT_EQ(view.size(), 3u);
  334. ASSERT_NE(view.begin(), view.end());
  335. view[0].cast<proxy_type>() = true;
  336. view[1].cast<proxy_type>() = true;
  337. view[2].cast<proxy_type>() = false;
  338. ASSERT_EQ(cview[1u].cast<const_proxy_type>(), true);
  339. auto it = view.begin();
  340. auto ret = view.insert(it, true);
  341. ASSERT_TRUE(ret.second);
  342. ASSERT_FALSE(view.insert(ret.first, 'c').second);
  343. ASSERT_TRUE(view.insert(++ret.first, false).second);
  344. ASSERT_EQ(view.size(), 5u);
  345. ASSERT_EQ((*view.begin()).cast<proxy_type>(), true);
  346. ASSERT_EQ((*++cview.begin()).cast<const_proxy_type>(), false);
  347. it = view.begin();
  348. ret = view.erase(it);
  349. ASSERT_TRUE(ret.second);
  350. ASSERT_EQ(view.size(), 4u);
  351. ASSERT_EQ((*ret.first).cast<proxy_type>(), false);
  352. ASSERT_TRUE(view.clear());
  353. ASSERT_EQ(cview.size(), 0u);
  354. }