view.cpp 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123
  1. #include <algorithm>
  2. #include <tuple>
  3. #include <utility>
  4. #include <type_traits>
  5. #include <gtest/gtest.h>
  6. #include <entt/entity/component.hpp>
  7. #include <entt/entity/registry.hpp>
  8. #include <entt/entity/view.hpp>
  9. struct empty_type {};
  10. struct stable_type { int value; };
  11. template<>
  12. struct entt::component_traits<stable_type>: basic_component_traits {
  13. using in_place_delete = std::true_type;
  14. };
  15. TEST(SingleComponentView, Functionalities) {
  16. entt::registry registry;
  17. auto view = registry.view<char>();
  18. auto cview = std::as_const(registry).view<const char>();
  19. const auto e0 = registry.create();
  20. const auto e1 = registry.create();
  21. ASSERT_TRUE(view.empty());
  22. registry.emplace<int>(e1);
  23. registry.emplace<char>(e1);
  24. ASSERT_NO_FATAL_FAILURE(view.begin()++);
  25. ASSERT_NO_FATAL_FAILURE(++cview.begin());
  26. ASSERT_NO_FATAL_FAILURE([](auto it) { return it++; }(view.rbegin()));
  27. ASSERT_NO_FATAL_FAILURE([](auto it) { return ++it; }(cview.rbegin()));
  28. ASSERT_NE(view.begin(), view.end());
  29. ASSERT_NE(cview.begin(), cview.end());
  30. ASSERT_NE(view.rbegin(), view.rend());
  31. ASSERT_NE(cview.rbegin(), cview.rend());
  32. ASSERT_EQ(view.size(), 1u);
  33. ASSERT_FALSE(view.empty());
  34. registry.emplace<char>(e0);
  35. ASSERT_EQ(view.size(), 2u);
  36. view.get<char>(e0) = '1';
  37. std::get<0>(view.get(e1)) = '2';
  38. for(auto entity: view) {
  39. ASSERT_TRUE(cview.get<const char>(entity) == '1' || std::get<const char &>(cview.get(entity)) == '2');
  40. }
  41. ASSERT_EQ(view.data()[0u], e1);
  42. ASSERT_EQ(view.data()[1u], e0);
  43. ASSERT_EQ(view.raw()[0u][0u], '2');
  44. ASSERT_EQ(cview.raw()[0u][1u], '1');
  45. registry.erase<char>(e0);
  46. registry.erase<char>(e1);
  47. ASSERT_EQ(view.begin(), view.end());
  48. ASSERT_EQ(view.rbegin(), view.rend());
  49. ASSERT_TRUE(view.empty());
  50. decltype(view) invalid{};
  51. ASSERT_TRUE(view);
  52. ASSERT_TRUE(cview);
  53. ASSERT_FALSE(invalid);
  54. }
  55. TEST(SingleComponentView, RawData) {
  56. entt::registry registry;
  57. auto view = registry.view<int>();
  58. auto cview = std::as_const(registry).view<const int>();
  59. const auto entity = registry.create();
  60. ASSERT_EQ(view.size(), 0u);
  61. ASSERT_EQ(cview.size(), 0u);
  62. ASSERT_EQ(view.raw(), cview.raw());
  63. ASSERT_EQ(view.data(), cview.data());
  64. registry.emplace<int>(entity, 42);
  65. ASSERT_NE(view.size(), 0u);
  66. ASSERT_NE(cview.size(), 0u);
  67. ASSERT_EQ(view.raw()[0u][0u], 42);
  68. ASSERT_EQ(cview.raw()[0u][0u], 42);
  69. ASSERT_EQ(view.data()[0u], entity);
  70. ASSERT_EQ(cview.data()[0u], entity);
  71. registry.destroy(entity);
  72. ASSERT_EQ(view.size(), 0u);
  73. ASSERT_EQ(cview.size(), 0u);
  74. }
  75. TEST(SingleComponentView, LazyTypeFromConstRegistry) {
  76. entt::registry registry{};
  77. auto eview = std::as_const(registry).view<const empty_type>();
  78. auto cview = std::as_const(registry).view<const int>();
  79. const auto entity = registry.create();
  80. registry.emplace<empty_type>(entity);
  81. registry.emplace<int>(entity);
  82. ASSERT_TRUE(cview);
  83. ASSERT_TRUE(eview);
  84. ASSERT_NE(cview.raw(), nullptr);
  85. ASSERT_NE(eview.data(), nullptr);
  86. ASSERT_FALSE(cview.empty());
  87. ASSERT_EQ(eview.size(), 1u);
  88. ASSERT_TRUE(cview.contains(entity));
  89. ASSERT_NE(cview.begin(), cview.end());
  90. ASSERT_NE(eview.rbegin(), eview.rend());
  91. ASSERT_NE(eview.find(entity), eview.end());
  92. ASSERT_EQ(cview.front(), entity);
  93. ASSERT_EQ(eview.back(), entity);
  94. }
  95. TEST(SingleComponentView, ElementAccess) {
  96. entt::registry registry;
  97. auto view = registry.view<int>();
  98. auto cview = std::as_const(registry).view<const int>();
  99. const auto e0 = registry.create();
  100. registry.emplace<int>(e0, 42);
  101. const auto e1 = registry.create();
  102. registry.emplace<int>(e1, 3);
  103. for(auto i = 0u; i < view.size(); ++i) {
  104. ASSERT_EQ(view[i], i ? e0 : e1);
  105. ASSERT_EQ(cview[i], i ? e0 : e1);
  106. }
  107. ASSERT_EQ(view[e0], 42);
  108. ASSERT_EQ(view[e1], 3);
  109. }
  110. TEST(SingleComponentView, Contains) {
  111. entt::registry registry;
  112. const auto e0 = registry.create();
  113. registry.emplace<int>(e0);
  114. const auto e1 = registry.create();
  115. registry.emplace<int>(e1);
  116. registry.destroy(e0);
  117. auto view = registry.view<int>();
  118. ASSERT_FALSE(view.contains(e0));
  119. ASSERT_TRUE(view.contains(e1));
  120. }
  121. TEST(SingleComponentView, Empty) {
  122. entt::registry registry;
  123. const auto e0 = registry.create();
  124. registry.emplace<char>(e0);
  125. registry.emplace<double>(e0);
  126. const auto e1 = registry.create();
  127. registry.emplace<char>(e1);
  128. auto view = registry.view<int>();
  129. ASSERT_EQ(view.size(), 0u);
  130. ASSERT_EQ(view.begin(), view.end());
  131. ASSERT_EQ(view.rbegin(), view.rend());
  132. }
  133. TEST(SingleComponentView, Each) {
  134. entt::registry registry;
  135. registry.emplace<int>(registry.create(), 0);
  136. registry.emplace<int>(registry.create(), 1);
  137. auto view = registry.view<int>();
  138. auto iterable = view.each();
  139. auto cview = std::as_const(registry).view<const int>();
  140. auto citerable = cview.each();
  141. std::size_t cnt = 0;
  142. for(auto first = citerable.rbegin(), last = citerable.rend(); first != last; ++first) {
  143. static_assert(std::is_same_v<decltype(*first), std::tuple<entt::entity, const int &>>);
  144. ASSERT_EQ(std::get<1>(*first), cnt++);
  145. }
  146. view.each([&cnt](auto, int &) { ++cnt; });
  147. view.each([&cnt](int &) { ++cnt; });
  148. ASSERT_EQ(cnt, std::size_t{6});
  149. cview.each([&cnt](const int &) { --cnt; });
  150. cview.each([&cnt](auto, const int &) { --cnt; });
  151. // do not use iterable, make sure an iterable view works when created from a temporary
  152. for(auto [entt, iv]: registry.view<int>().each()) {
  153. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  154. static_assert(std::is_same_v<decltype(iv), int &>);
  155. ASSERT_EQ(iv, --cnt);
  156. }
  157. ASSERT_EQ(cnt, std::size_t{0});
  158. auto it = iterable.begin();
  159. auto rit = iterable.rbegin();
  160. ASSERT_EQ((it++, ++it), iterable.end());
  161. ASSERT_EQ((rit++, ++rit), iterable.rend());
  162. }
  163. TEST(SingleComponentView, ConstNonConstAndAllInBetween) {
  164. entt::registry registry;
  165. auto view = registry.view<int>();
  166. auto cview = std::as_const(registry).view<const int>();
  167. ASSERT_EQ(view.size(), 0u);
  168. ASSERT_EQ(cview.size(), 0u);
  169. registry.emplace<int>(registry.create(), 0);
  170. ASSERT_EQ(view.size(), 1u);
  171. ASSERT_EQ(cview.size(), 1u);
  172. static_assert(std::is_same_v<decltype(view.raw()), int **>);
  173. static_assert(std::is_same_v<decltype(cview.raw()), const int * const *>);
  174. static_assert(std::is_same_v<decltype(view.get<int>({})), int &>);
  175. static_assert(std::is_same_v<decltype(view.get({})), std::tuple<int &>>);
  176. static_assert(std::is_same_v<decltype(view.raw()), int **>);
  177. static_assert(std::is_same_v<decltype(cview.get<const int>({})), const int &>);
  178. static_assert(std::is_same_v<decltype(cview.get({})), std::tuple<const int &>>);
  179. static_assert(std::is_same_v<decltype(cview.raw()), const int * const *>);
  180. static_assert(std::is_same_v<decltype(std::as_const(registry).view<int>()), decltype(cview)>);
  181. view.each([](auto &&i) {
  182. static_assert(std::is_same_v<decltype(i), int &>);
  183. });
  184. cview.each([](auto &&i) {
  185. static_assert(std::is_same_v<decltype(i), const int &>);
  186. });
  187. for(auto [entt, iv]: view.each()) {
  188. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  189. static_assert(std::is_same_v<decltype(iv), int &>);
  190. }
  191. for(auto [entt, iv]: cview.each()) {
  192. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  193. static_assert(std::is_same_v<decltype(iv), const int &>);
  194. }
  195. }
  196. TEST(SingleComponentView, ConstNonConstAndAllInBetweenWithEmptyType) {
  197. entt::registry registry;
  198. auto view = registry.view<empty_type>();
  199. auto cview = std::as_const(registry).view<const empty_type>();
  200. ASSERT_EQ(view.size(), 0u);
  201. ASSERT_EQ(cview.size(), 0u);
  202. registry.emplace<empty_type>(registry.create());
  203. ASSERT_EQ(view.size(), 1u);
  204. ASSERT_EQ(cview.size(), 1u);
  205. static_assert(std::is_same_v<decltype(view.get({})), std::tuple<>>);
  206. static_assert(std::is_same_v<decltype(cview.get({})), std::tuple<>>);
  207. static_assert(std::is_same_v<decltype(std::as_const(registry).view<empty_type>()), decltype(cview)>);
  208. for(auto [entt]: view.each()) {
  209. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  210. }
  211. for(auto [entt]: cview.each()) {
  212. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  213. }
  214. }
  215. TEST(SingleComponentView, Find) {
  216. entt::registry registry;
  217. auto view = registry.view<int>();
  218. const auto e0 = registry.create();
  219. registry.emplace<int>(e0);
  220. const auto e1 = registry.create();
  221. registry.emplace<int>(e1);
  222. const auto e2 = registry.create();
  223. registry.emplace<int>(e2);
  224. const auto e3 = registry.create();
  225. registry.emplace<int>(e3);
  226. registry.erase<int>(e1);
  227. ASSERT_NE(view.find(e0), view.end());
  228. ASSERT_EQ(view.find(e1), view.end());
  229. ASSERT_NE(view.find(e2), view.end());
  230. ASSERT_NE(view.find(e3), view.end());
  231. auto it = view.find(e2);
  232. ASSERT_EQ(*it, e2);
  233. ASSERT_EQ(*(++it), e3);
  234. ASSERT_EQ(*(++it), e0);
  235. ASSERT_EQ(++it, view.end());
  236. ASSERT_EQ(++view.find(e0), view.end());
  237. const auto e4 = registry.create();
  238. registry.destroy(e4);
  239. const auto e5 = registry.create();
  240. registry.emplace<int>(e5);
  241. ASSERT_NE(view.find(e5), view.end());
  242. ASSERT_EQ(view.find(e4), view.end());
  243. }
  244. TEST(SingleComponentView, EmptyTypes) {
  245. entt::registry registry;
  246. auto create = [&](auto... component) {
  247. const auto entt = registry.create();
  248. (registry.emplace<decltype(component)>(entt, component), ...);
  249. return entt;
  250. };
  251. const auto entity = create(0, empty_type{});
  252. create('c');
  253. registry.view<empty_type>().each([entity](const auto entt) {
  254. ASSERT_EQ(entity, entt);
  255. });
  256. registry.view<empty_type>().each([check = true]() mutable {
  257. ASSERT_TRUE(check);
  258. check = false;
  259. });
  260. for(auto [entt]: registry.view<empty_type>().each()) {
  261. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  262. ASSERT_EQ(entity, entt);
  263. }
  264. registry.view<int>().each([entity](const auto entt, int) {
  265. ASSERT_EQ(entity, entt);
  266. });
  267. registry.view<int>().each([check = true](int) mutable {
  268. ASSERT_TRUE(check);
  269. check = false;
  270. });
  271. for(auto [entt, iv]: registry.view<int>().each()) {
  272. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  273. static_assert(std::is_same_v<decltype(iv), int &>);
  274. ASSERT_EQ(entity, entt);
  275. }
  276. }
  277. TEST(SingleComponentView, FrontBack) {
  278. entt::registry registry;
  279. auto view = registry.view<const int>();
  280. ASSERT_EQ(view.front(), static_cast<entt::entity>(entt::null));
  281. ASSERT_EQ(view.back(), static_cast<entt::entity>(entt::null));
  282. const auto e0 = registry.create();
  283. registry.emplace<int>(e0);
  284. const auto e1 = registry.create();
  285. registry.emplace<int>(e1);
  286. ASSERT_EQ(view.front(), e1);
  287. ASSERT_EQ(view.back(), e0);
  288. }
  289. TEST(SingleComponentView, DeductionGuide) {
  290. entt::registry registry;
  291. typename entt::storage_traits<entt::entity, int>::storage_type istorage;
  292. typename entt::storage_traits<entt::entity, stable_type>::storage_type sstorage;
  293. static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::get_t<int>, entt::exclude_t<>>, decltype(entt::basic_view{istorage})>);
  294. static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::get_t<const int>, entt::exclude_t<>>, decltype(entt::basic_view{std::as_const(istorage)})>);
  295. static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::get_t<stable_type>, entt::exclude_t<>>, decltype(entt::basic_view{sstorage})>);
  296. }
  297. TEST(SingleComponentView, IterableViewAlgorithmCompatibility) {
  298. entt::registry registry;
  299. const auto entity = registry.create();
  300. registry.emplace<int>(entity);
  301. const auto view = registry.view<int>();
  302. const auto iterable = view.each();
  303. const auto it = std::find_if(iterable.begin(), iterable.end(), [entity](auto args) { return std::get<0>(args) == entity; });
  304. ASSERT_EQ(std::get<0>(*it), entity);
  305. }
  306. TEST(SingleComponentView, StableType) {
  307. entt::registry registry;
  308. auto view = registry.view<stable_type>();
  309. const auto entity = registry.create();
  310. const auto other = registry.create();
  311. registry.emplace<stable_type>(entity);
  312. registry.emplace<stable_type>(other);
  313. registry.destroy(entity);
  314. ASSERT_EQ(view.size_hint(), 2u);
  315. ASSERT_FALSE(view.contains(entity));
  316. ASSERT_TRUE(view.contains(other));
  317. ASSERT_EQ(view.front(), other);
  318. ASSERT_EQ(view.back(), other);
  319. ASSERT_EQ(*view.begin(), other);
  320. ASSERT_EQ(++view.begin(), view.end());
  321. view.each([other](const auto entt, stable_type) {
  322. ASSERT_EQ(other, entt);
  323. });
  324. view.each([check = true](stable_type) mutable {
  325. ASSERT_TRUE(check);
  326. check = false;
  327. });
  328. for(auto [entt, st]: view.each()) {
  329. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  330. static_assert(std::is_same_v<decltype(st), stable_type &>);
  331. ASSERT_EQ(other, entt);
  332. }
  333. registry.compact();
  334. ASSERT_EQ(view.size_hint(), 1u);
  335. }
  336. TEST(MultiComponentView, Functionalities) {
  337. entt::registry registry;
  338. auto view = registry.view<int, char>();
  339. auto cview = std::as_const(registry).view<const int, const char>();
  340. const auto e0 = registry.create();
  341. registry.emplace<char>(e0, '1');
  342. const auto e1 = registry.create();
  343. registry.emplace<int>(e1, 42);
  344. registry.emplace<char>(e1, '2');
  345. ASSERT_EQ(*view.begin(), e1);
  346. ASSERT_EQ(*view.rbegin(), e1);
  347. ASSERT_EQ(++view.begin(), (view.end()));
  348. ASSERT_EQ(++view.rbegin(), (view.rend()));
  349. ASSERT_NO_FATAL_FAILURE((view.begin()++));
  350. ASSERT_NO_FATAL_FAILURE((++cview.begin()));
  351. ASSERT_NO_FATAL_FAILURE(view.rbegin()++);
  352. ASSERT_NO_FATAL_FAILURE(++cview.rbegin());
  353. ASSERT_NE(view.begin(), view.end());
  354. ASSERT_NE(cview.begin(), cview.end());
  355. ASSERT_NE(view.rbegin(), view.rend());
  356. ASSERT_NE(cview.rbegin(), cview.rend());
  357. ASSERT_EQ(view.size_hint(), 1u);
  358. for(auto entity: view) {
  359. ASSERT_EQ(std::get<0>(cview.get<const int, const char>(entity)), 42);
  360. ASSERT_EQ(std::get<1>(view.get<int, char>(entity)), '2');
  361. ASSERT_EQ(cview.get<const char>(entity), '2');
  362. }
  363. decltype(view) invalid{};
  364. ASSERT_TRUE(view);
  365. ASSERT_TRUE(cview);
  366. ASSERT_FALSE(invalid);
  367. }
  368. TEST(MultiComponentView, LazyTypesFromConstRegistry) {
  369. entt::registry registry{};
  370. auto view = std::as_const(registry).view<const empty_type, const int>();
  371. const auto entity = registry.create();
  372. registry.emplace<empty_type>(entity);
  373. registry.emplace<int>(entity);
  374. ASSERT_TRUE(view);
  375. ASSERT_EQ(view.size_hint(), 1u);
  376. ASSERT_TRUE(view.contains(entity));
  377. ASSERT_NE(view.begin(), view.end());
  378. ASSERT_NE(view.find(entity), view.end());
  379. ASSERT_EQ(view.front(), entity);
  380. ASSERT_EQ(view.back(), entity);
  381. }
  382. TEST(MultiComponentView, LazyExcludedTypeFromConstRegistry) {
  383. entt::registry registry;
  384. auto entity = registry.create();
  385. registry.emplace<int>(entity);
  386. auto view = std::as_const(registry).view<const int>(entt::exclude<char>);
  387. ASSERT_TRUE(view);
  388. ASSERT_EQ(view.size_hint(), 1u);
  389. ASSERT_TRUE(view.contains(entity));
  390. ASSERT_NE(view.begin(), view.end());
  391. ASSERT_NE(view.find(entity), view.end());
  392. ASSERT_EQ(view.front(), entity);
  393. ASSERT_EQ(view.back(), entity);
  394. }
  395. TEST(MultiComponentView, Iterator) {
  396. entt::registry registry;
  397. const auto entity = registry.create();
  398. registry.emplace<int>(entity);
  399. registry.emplace<char>(entity);
  400. const auto view = registry.view<int, char>();
  401. using iterator = typename decltype(view)::iterator;
  402. iterator end{view.begin()};
  403. iterator begin{};
  404. begin = view.end();
  405. std::swap(begin, end);
  406. ASSERT_EQ(begin, view.begin());
  407. ASSERT_EQ(end, view.end());
  408. ASSERT_NE(begin, end);
  409. ASSERT_EQ(begin++, view.begin());
  410. ASSERT_EQ(begin--, view.end());
  411. ASSERT_EQ(++begin, view.end());
  412. ASSERT_EQ(--begin, view.begin());
  413. ASSERT_EQ(*begin, entity);
  414. ASSERT_EQ(*begin.operator->(), entity);
  415. registry.emplace<int>(registry.create());
  416. registry.emplace<char>(registry.create());
  417. const auto other = registry.create();
  418. registry.emplace<int>(other);
  419. registry.emplace<char>(other);
  420. begin = view.begin();
  421. ASSERT_EQ(*(begin++), other);
  422. ASSERT_EQ(*(begin++), entity);
  423. ASSERT_EQ(begin--, end);
  424. ASSERT_EQ(*(begin--), entity);
  425. ASSERT_EQ(*begin, other);
  426. }
  427. TEST(MultiComponentView, ReverseIterator) {
  428. entt::registry registry;
  429. const auto entity = registry.create();
  430. registry.emplace<int>(entity);
  431. registry.emplace<char>(entity);
  432. const auto view = registry.view<int, char>();
  433. using iterator = typename decltype(view)::reverse_iterator;
  434. iterator end{view.rbegin()};
  435. iterator begin{};
  436. begin = view.rend();
  437. std::swap(begin, end);
  438. ASSERT_EQ(begin, view.rbegin());
  439. ASSERT_EQ(end, view.rend());
  440. ASSERT_NE(begin, end);
  441. ASSERT_EQ(begin++, view.rbegin());
  442. ASSERT_EQ(begin--, view.rend());
  443. ASSERT_EQ(++begin, view.rend());
  444. ASSERT_EQ(--begin, view.rbegin());
  445. ASSERT_EQ(*begin, entity);
  446. ASSERT_EQ(*begin.operator->(), entity);
  447. }
  448. TEST(MultiComponentView, ElementAccess) {
  449. entt::registry registry;
  450. auto view = registry.view<int, char>();
  451. auto cview = std::as_const(registry).view<const int, const char>();
  452. const auto e0 = registry.create();
  453. registry.emplace<int>(e0, 42);
  454. registry.emplace<char>(e0, '0');
  455. const auto e1 = registry.create();
  456. registry.emplace<int>(e1, 3);
  457. registry.emplace<char>(e1, '1');
  458. ASSERT_EQ(view[e0], std::make_tuple(42, '0'));
  459. ASSERT_EQ(view[e1], std::make_tuple(3, '1'));
  460. }
  461. TEST(MultiComponentView, Contains) {
  462. entt::registry registry;
  463. const auto e0 = registry.create();
  464. registry.emplace<int>(e0);
  465. registry.emplace<char>(e0);
  466. const auto e1 = registry.create();
  467. registry.emplace<int>(e1);
  468. registry.emplace<char>(e1);
  469. registry.destroy(e0);
  470. auto view = registry.view<int, char>();
  471. ASSERT_FALSE(view.contains(e0));
  472. ASSERT_TRUE(view.contains(e1));
  473. }
  474. TEST(MultiComponentView, SizeHint) {
  475. entt::registry registry;
  476. const auto e0 = registry.create();
  477. registry.emplace<double>(e0);
  478. registry.emplace<int>(e0);
  479. registry.emplace<float>(e0);
  480. const auto e1 = registry.create();
  481. registry.emplace<char>(e1);
  482. registry.emplace<float>(e1);
  483. auto view = registry.view<char, int, float>();
  484. ASSERT_EQ(view.size_hint(), 1u);
  485. ASSERT_EQ(view.begin(), view.end());
  486. ASSERT_EQ(view.rbegin(), view.rend());
  487. }
  488. TEST(MultiComponentView, Each) {
  489. entt::registry registry;
  490. const auto e0 = registry.create();
  491. registry.emplace<int>(e0, 0);
  492. registry.emplace<char>(e0);
  493. const auto e1 = registry.create();
  494. registry.emplace<int>(e1, 1);
  495. registry.emplace<char>(e1);
  496. auto view = registry.view<int, char>();
  497. auto iterable = view.each();
  498. auto cview = std::as_const(registry).view<const int, const char>();
  499. auto citerable = cview.each();
  500. std::size_t cnt = 0;
  501. for(auto first = citerable.rbegin(), last = citerable.rend(); first != last; ++first) {
  502. static_assert(std::is_same_v<decltype(*first), std::tuple<entt::entity, const int &, const char &>>);
  503. ASSERT_EQ(std::get<1>(*first), cnt++);
  504. }
  505. view.each([&cnt](auto, int &, char &) { ++cnt; });
  506. view.each([&cnt](int &, char &) { ++cnt; });
  507. ASSERT_EQ(cnt, std::size_t{6});
  508. cview.each([&cnt](const int &, const char &) { --cnt; });
  509. cview.each([&cnt](auto, const int &, const char &) { --cnt; });
  510. // do not use iterable, make sure an iterable view works when created from a temporary
  511. for(auto [entt, iv, cv]: registry.view<int, char>().each()) {
  512. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  513. static_assert(std::is_same_v<decltype(iv), int &>);
  514. static_assert(std::is_same_v<decltype(cv), char &>);
  515. ASSERT_EQ(iv, --cnt);
  516. }
  517. ASSERT_EQ(cnt, std::size_t{0});
  518. auto it = iterable.begin();
  519. auto rit = iterable.rbegin();
  520. ASSERT_EQ((it++, ++it), iterable.end());
  521. ASSERT_EQ((rit++, ++rit), iterable.rend());
  522. }
  523. TEST(MultiComponentView, EachWithSuggestedType) {
  524. entt::registry registry;
  525. for(auto i = 0; i < 3; ++i) {
  526. const auto entity = registry.create();
  527. registry.emplace<int>(entity, i);
  528. registry.emplace<char>(entity);
  529. }
  530. // makes char a better candidate during iterations
  531. const auto entity = registry.create();
  532. registry.emplace<int>(entity, 99);
  533. registry.view<int, char>().each<int>([value = 2](const auto curr, const auto) mutable {
  534. ASSERT_EQ(curr, value--);
  535. });
  536. registry.sort<int>([](const auto lhs, const auto rhs) {
  537. return lhs < rhs;
  538. });
  539. registry.view<int, char>().each<int>([value = 0](const auto curr, const auto) mutable {
  540. ASSERT_EQ(curr, value++);
  541. });
  542. registry.sort<int>([](const auto lhs, const auto rhs) {
  543. return lhs > rhs;
  544. });
  545. auto value = registry.view<int, char>().size_hint();
  546. for(auto &&curr: registry.view<int, char>().each()) {
  547. ASSERT_EQ(std::get<1>(curr), static_cast<int>(--value));
  548. }
  549. registry.sort<int>([](const auto lhs, const auto rhs) {
  550. return lhs < rhs;
  551. });
  552. value = {};
  553. for(auto &&curr: registry.view<int, char>().each<int>()) {
  554. ASSERT_EQ(std::get<1>(curr), static_cast<int>(value++));
  555. }
  556. }
  557. TEST(MultiComponentView, EachWithHoles) {
  558. entt::registry registry;
  559. const auto e0 = registry.create();
  560. const auto e1 = registry.create();
  561. const auto e2 = registry.create();
  562. registry.emplace<char>(e0, '0');
  563. registry.emplace<char>(e1, '1');
  564. registry.emplace<int>(e0, 0);
  565. registry.emplace<int>(e2, 2);
  566. auto view = registry.view<char, int>();
  567. view.each([e0](auto entity, const char &c, const int &i) {
  568. ASSERT_EQ(entity, e0);
  569. ASSERT_EQ(c, '0');
  570. ASSERT_EQ(i, 0);
  571. });
  572. for(auto &&curr: view.each()) {
  573. ASSERT_EQ(std::get<0>(curr), e0);
  574. ASSERT_EQ(std::get<1>(curr), '0');
  575. ASSERT_EQ(std::get<2>(curr), 0);
  576. }
  577. }
  578. TEST(MultiComponentView, ConstNonConstAndAllInBetween) {
  579. entt::registry registry;
  580. auto view = registry.view<int, empty_type, const char>();
  581. ASSERT_EQ(view.size_hint(), 0u);
  582. const auto entity = registry.create();
  583. registry.emplace<int>(entity, 0);
  584. registry.emplace<empty_type>(entity);
  585. registry.emplace<char>(entity, 'c');
  586. ASSERT_EQ(view.size_hint(), 1u);
  587. static_assert(std::is_same_v<decltype(view.get<int>({})), int &>);
  588. static_assert(std::is_same_v<decltype(view.get<const char>({})), const char &>);
  589. static_assert(std::is_same_v<decltype(view.get<int, const char>({})), std::tuple<int &, const char &>>);
  590. static_assert(std::is_same_v<decltype(view.get({})), std::tuple<int &, const char &>>);
  591. static_assert(std::is_same_v<decltype(std::as_const(registry).view<char, int>()), decltype(std::as_const(registry).view<const char, const int>())>);
  592. static_assert(std::is_same_v<decltype(std::as_const(registry).view<char, const int>()), decltype(std::as_const(registry).view<const char, const int>())>);
  593. static_assert(std::is_same_v<decltype(std::as_const(registry).view<const char, int>()), decltype(std::as_const(registry).view<const char, const int>())>);
  594. view.each([](auto &&i, auto &&c) {
  595. static_assert(std::is_same_v<decltype(i), int &>);
  596. static_assert(std::is_same_v<decltype(c), const char &>);
  597. });
  598. for(auto [entt, iv, cv]: view.each()) {
  599. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  600. static_assert(std::is_same_v<decltype(iv), int &>);
  601. static_assert(std::is_same_v<decltype(cv), const char &>);
  602. }
  603. }
  604. TEST(MultiComponentView, Find) {
  605. entt::registry registry;
  606. auto view = registry.view<int, const char>();
  607. const auto e0 = registry.create();
  608. registry.emplace<int>(e0);
  609. registry.emplace<char>(e0);
  610. const auto e1 = registry.create();
  611. registry.emplace<int>(e1);
  612. registry.emplace<char>(e1);
  613. const auto e2 = registry.create();
  614. registry.emplace<int>(e2);
  615. registry.emplace<char>(e2);
  616. const auto e3 = registry.create();
  617. registry.emplace<int>(e3);
  618. registry.emplace<char>(e3);
  619. registry.erase<int>(e1);
  620. ASSERT_NE(view.find(e0), view.end());
  621. ASSERT_EQ(view.find(e1), view.end());
  622. ASSERT_NE(view.find(e2), view.end());
  623. ASSERT_NE(view.find(e3), view.end());
  624. auto it = view.find(e2);
  625. ASSERT_EQ(*it, e2);
  626. ASSERT_EQ(*(++it), e3);
  627. ASSERT_EQ(*(++it), e0);
  628. ASSERT_EQ(++it, view.end());
  629. ASSERT_EQ(++view.find(e0), view.end());
  630. const auto e4 = registry.create();
  631. registry.destroy(e4);
  632. const auto e5 = registry.create();
  633. registry.emplace<int>(e5);
  634. registry.emplace<char>(e5);
  635. ASSERT_NE(view.find(e5), view.end());
  636. ASSERT_EQ(view.find(e4), view.end());
  637. }
  638. TEST(MultiComponentView, ExcludedComponents) {
  639. entt::registry registry;
  640. const auto e0 = registry.create();
  641. registry.emplace<int>(e0, 0);
  642. const auto e1 = registry.create();
  643. registry.emplace<int>(e1, 1);
  644. registry.emplace<char>(e1);
  645. const auto e2 = registry.create();
  646. registry.emplace<int>(e2, 2);
  647. const auto e3 = registry.create();
  648. registry.emplace<int>(e3, 3);
  649. registry.emplace<char>(e3);
  650. const auto view = std::as_const(registry).view<const int>(entt::exclude<char>);
  651. for(const auto entity: view) {
  652. ASSERT_TRUE(entity == e0 || entity == e2);
  653. if(entity == e0) {
  654. ASSERT_EQ(view.get<const int>(e0), 0);
  655. } else if(entity == e2) {
  656. ASSERT_EQ(std::get<0>(view.get(e2)), 2);
  657. }
  658. }
  659. registry.emplace<char>(e0);
  660. registry.emplace<char>(e2);
  661. registry.erase<char>(e1);
  662. registry.erase<char>(e3);
  663. for(const auto entity: view) {
  664. ASSERT_TRUE(entity == e1 || entity == e3);
  665. if(entity == e1) {
  666. ASSERT_EQ(std::get<0>(view.get(e1)), 1);
  667. } else if(entity == e3) {
  668. ASSERT_EQ(view.get<const int>(e3), 3);
  669. }
  670. }
  671. }
  672. TEST(MultiComponentView, EmptyTypes) {
  673. entt::registry registry;
  674. const auto entity = registry.create();
  675. registry.emplace<int>(entity);
  676. registry.emplace<char>(entity);
  677. registry.emplace<empty_type>(entity);
  678. const auto other = registry.create();
  679. registry.emplace<int>(other);
  680. registry.emplace<char>(other);
  681. registry.emplace<double>(other);
  682. registry.emplace<empty_type>(other);
  683. const auto ignored = registry.create();
  684. registry.emplace<int>(ignored);
  685. registry.emplace<char>(ignored);
  686. registry.view<int, char, empty_type>(entt::exclude<double>).each([entity](const auto entt, int, char) {
  687. ASSERT_EQ(entity, entt);
  688. });
  689. for(auto [entt, iv, cv]: registry.view<int, char, empty_type>(entt::exclude<double>).each()) {
  690. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  691. static_assert(std::is_same_v<decltype(iv), int &>);
  692. static_assert(std::is_same_v<decltype(cv), char &>);
  693. ASSERT_EQ(entity, entt);
  694. }
  695. registry.view<int, empty_type, char>(entt::exclude<double>).each([check = true](int, char) mutable {
  696. ASSERT_TRUE(check);
  697. check = false;
  698. });
  699. for(auto [entt, iv, cv]: registry.view<int, empty_type, char>(entt::exclude<double>).each()) {
  700. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  701. static_assert(std::is_same_v<decltype(iv), int &>);
  702. static_assert(std::is_same_v<decltype(cv), char &>);
  703. ASSERT_EQ(entity, entt);
  704. }
  705. registry.view<empty_type, int, char>(entt::exclude<double>).each([entity](const auto entt, int, char) {
  706. ASSERT_EQ(entity, entt);
  707. });
  708. for(auto [entt, iv, cv]: registry.view<empty_type, int, char>(entt::exclude<double>).each()) {
  709. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  710. static_assert(std::is_same_v<decltype(iv), int &>);
  711. static_assert(std::is_same_v<decltype(cv), char &>);
  712. ASSERT_EQ(entity, entt);
  713. }
  714. registry.view<empty_type, int, char>(entt::exclude<double>).each<empty_type>([entity](const auto entt, int, char) {
  715. ASSERT_EQ(entity, entt);
  716. });
  717. for(auto [entt, iv, cv]: registry.view<empty_type, int, char>(entt::exclude<double>).each<empty_type>()) {
  718. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  719. static_assert(std::is_same_v<decltype(iv), int &>);
  720. static_assert(std::is_same_v<decltype(cv), char &>);
  721. ASSERT_EQ(entity, entt);
  722. }
  723. registry.view<int, empty_type, char>(entt::exclude<double>).each<empty_type>([check = true](int, char) mutable {
  724. ASSERT_TRUE(check);
  725. check = false;
  726. });
  727. for(auto [entt, iv, cv]: registry.view<int, empty_type, char>(entt::exclude<double>).each<empty_type>()) {
  728. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  729. static_assert(std::is_same_v<decltype(iv), int &>);
  730. static_assert(std::is_same_v<decltype(cv), char &>);
  731. ASSERT_EQ(entity, entt);
  732. }
  733. }
  734. TEST(MultiComponentView, FrontBack) {
  735. entt::registry registry;
  736. auto view = registry.view<const int, const char>();
  737. ASSERT_EQ(view.front(), static_cast<entt::entity>(entt::null));
  738. ASSERT_EQ(view.back(), static_cast<entt::entity>(entt::null));
  739. const auto e0 = registry.create();
  740. registry.emplace<int>(e0);
  741. registry.emplace<char>(e0);
  742. const auto e1 = registry.create();
  743. registry.emplace<int>(e1);
  744. registry.emplace<char>(e1);
  745. const auto entity = registry.create();
  746. registry.emplace<char>(entity);
  747. ASSERT_EQ(view.front(), e1);
  748. ASSERT_EQ(view.back(), e0);
  749. }
  750. TEST(MultiComponentView, ExtendedGet) {
  751. using type = decltype(std::declval<entt::registry>().view<int, empty_type, char>().get({}));
  752. static_assert(std::tuple_size_v<type> == 2u);
  753. static_assert(std::is_same_v<std::tuple_element_t<0, type>, int &>);
  754. static_assert(std::is_same_v<std::tuple_element_t<1, type>, char &>);
  755. }
  756. TEST(MultiComponentView, DeductionGuide) {
  757. entt::registry registry;
  758. typename entt::storage_traits<entt::entity, int>::storage_type istorage;
  759. typename entt::storage_traits<entt::entity, double>::storage_type dstorage;
  760. typename entt::storage_traits<entt::entity, stable_type>::storage_type sstorage;
  761. static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::get_t<int, double>, entt::exclude_t<>>, decltype(entt::basic_view{istorage, dstorage})>);
  762. static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::get_t<const int, double>, entt::exclude_t<>>, decltype(entt::basic_view{std::as_const(istorage), dstorage})>);
  763. static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::get_t<int, const double>, entt::exclude_t<>>, decltype(entt::basic_view{istorage, std::as_const(dstorage)})>);
  764. static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::get_t<const int, const double>, entt::exclude_t<>>, decltype(entt::basic_view{std::as_const(istorage), std::as_const(dstorage)})>);
  765. static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::get_t<int, stable_type>, entt::exclude_t<>>, decltype(entt::basic_view{istorage, sstorage})>);
  766. }
  767. TEST(MultiComponentView, IterableViewAlgorithmCompatibility) {
  768. entt::registry registry;
  769. const auto entity = registry.create();
  770. registry.emplace<int>(entity);
  771. registry.emplace<char>(entity);
  772. const auto view = registry.view<int, char>();
  773. const auto iterable = view.each();
  774. const auto it = std::find_if(iterable.begin(), iterable.end(), [entity](auto args) { return std::get<0>(args) == entity; });
  775. ASSERT_EQ(std::get<0>(*it), entity);
  776. }
  777. TEST(MultiComponentView, StableType) {
  778. entt::registry registry;
  779. auto view = registry.view<int, stable_type>();
  780. const auto entity = registry.create();
  781. const auto other = registry.create();
  782. registry.emplace<int>(entity);
  783. registry.emplace<int>(other);
  784. registry.emplace<stable_type>(entity);
  785. registry.emplace<stable_type>(other);
  786. registry.destroy(entity);
  787. ASSERT_EQ(view.size_hint(), 1u);
  788. view = view.use<stable_type>();
  789. ASSERT_EQ(view.size_hint(), 2u);
  790. ASSERT_FALSE(view.contains(entity));
  791. ASSERT_TRUE(view.contains(other));
  792. ASSERT_EQ(view.front(), other);
  793. ASSERT_EQ(view.back(), other);
  794. ASSERT_EQ(*view.begin(), other);
  795. ASSERT_EQ(++view.begin(), view.end());
  796. view.each([other](const auto entt, int, stable_type) {
  797. ASSERT_EQ(other, entt);
  798. });
  799. view.each([check = true](int, stable_type) mutable {
  800. ASSERT_TRUE(check);
  801. check = false;
  802. });
  803. for(auto [entt, iv, st]: view.each()) {
  804. static_assert(std::is_same_v<decltype(entt), entt::entity>);
  805. static_assert(std::is_same_v<decltype(iv), int &>);
  806. static_assert(std::is_same_v<decltype(st), stable_type &>);
  807. ASSERT_EQ(other, entt);
  808. }
  809. registry.compact();
  810. ASSERT_EQ(view.size_hint(), 1u);
  811. }
  812. TEST(View, Pipe) {
  813. entt::registry registry;
  814. const auto entity = registry.create();
  815. const auto other = registry.create();
  816. registry.emplace<int>(entity);
  817. registry.emplace<char>(entity);
  818. registry.emplace<double>(entity);
  819. registry.emplace<empty_type>(entity);
  820. registry.emplace<int>(other);
  821. registry.emplace<char>(other);
  822. registry.emplace<stable_type>(other);
  823. const auto view1 = registry.view<int>(entt::exclude<double>);
  824. const auto view2 = registry.view<const char>(entt::exclude<float>);
  825. const auto view3 = registry.view<empty_type>();
  826. const auto view4 = registry.view<stable_type>();
  827. static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::get_t<int, const char>, entt::exclude_t<double, float>>, decltype(view1 | view2)>);
  828. static_assert(std::is_same_v<entt::basic_view<entt::entity, entt::get_t<const char, int>, entt::exclude_t<float, double>>, decltype(view2 | view1)>);
  829. static_assert(std::is_same_v<decltype((view3 | view2) | view1), decltype(view3 | (view2 | view1))>);
  830. ASSERT_FALSE((view1 | view2).contains(entity));
  831. ASSERT_TRUE((view1 | view2).contains(other));
  832. ASSERT_TRUE((view3 | view2).contains(entity));
  833. ASSERT_FALSE((view3 | view2).contains(other));
  834. ASSERT_FALSE((view1 | view2 | view3).contains(entity));
  835. ASSERT_FALSE((view1 | view2 | view3).contains(other));
  836. ASSERT_FALSE((view1 | view4 | view2).contains(entity));
  837. ASSERT_TRUE((view1 | view4 | view2).contains(other));
  838. }