view.cpp 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697
  1. #include <algorithm>
  2. #include <array>
  3. #include <iterator>
  4. #include <tuple>
  5. #include <utility>
  6. #include <gtest/gtest.h>
  7. #include <entt/core/type_info.hpp>
  8. #include <entt/entity/entity.hpp>
  9. #include <entt/entity/storage.hpp>
  10. #include <entt/entity/view.hpp>
  11. #include "../../common/value_type.h"
  12. TEST(ViewSingleStorage, Functionalities) {
  13. entt::storage<char> storage{};
  14. const entt::basic_view view{storage};
  15. const entt::basic_view cview{std::as_const(storage)};
  16. const std::array entity{entt::entity{1}, entt::entity{3}};
  17. ASSERT_TRUE(view.empty());
  18. storage.emplace(entity[1u]);
  19. ASSERT_NO_THROW(view.begin()++);
  20. ASSERT_NO_THROW(++cview.begin());
  21. ASSERT_NO_THROW([](auto it) { return it++; }(view.rbegin()));
  22. ASSERT_NO_THROW([](auto it) { return ++it; }(cview.rbegin()));
  23. ASSERT_NE(view.begin(), view.end());
  24. ASSERT_NE(cview.begin(), cview.end());
  25. ASSERT_NE(view.rbegin(), view.rend());
  26. ASSERT_NE(cview.rbegin(), cview.rend());
  27. ASSERT_EQ(view.size(), 1u);
  28. ASSERT_FALSE(view.empty());
  29. storage.emplace(entity[0u]);
  30. ASSERT_EQ(view.size(), 2u);
  31. view.get<char>(entity[0u]) = '1';
  32. std::get<0>(view.get(entity[1u])) = '2';
  33. ASSERT_EQ(view.get<0u>(entity[0u]), '1');
  34. ASSERT_EQ(cview.get<0u>(entity[0u]), view.get<char>(entity[0u]));
  35. ASSERT_EQ(view.get<char>(entity[1u]), '2');
  36. for(auto entt: view) {
  37. ASSERT_TRUE(entt == entity[0u] || entt == entity[1u]);
  38. ASSERT_TRUE(entt != entity[0u] || cview.get<const char>(entt) == '1');
  39. ASSERT_TRUE(entt != entity[1u] || std::get<const char &>(cview.get(entt)) == '2');
  40. }
  41. storage.erase(entity.begin(), entity.end());
  42. ASSERT_EQ(view.begin(), view.end());
  43. ASSERT_EQ(view.rbegin(), view.rend());
  44. ASSERT_TRUE(view.empty());
  45. const decltype(view) invalid{};
  46. ASSERT_TRUE(view);
  47. ASSERT_TRUE(cview);
  48. ASSERT_FALSE(invalid);
  49. }
  50. TEST(ViewSingleStorage, Conversion) {
  51. entt::basic_view<entt::get_t<entt::storage<char>>, entt::exclude_t<>> view{};
  52. entt::basic_view<entt::get_t<const entt::storage<char>>, entt::exclude_t<>> cview{view};
  53. ASSERT_FALSE(view);
  54. ASSERT_FALSE(cview);
  55. entt::storage<char> storage{};
  56. view.storage(storage);
  57. cview = view;
  58. ASSERT_TRUE(view);
  59. ASSERT_TRUE(cview);
  60. ASSERT_TRUE(view.empty());
  61. ASSERT_TRUE(cview.empty());
  62. const entt::entity entity{1};
  63. storage.emplace(entity, 'c');
  64. ASSERT_FALSE(view.empty());
  65. ASSERT_FALSE(cview.empty());
  66. }
  67. TEST(ViewSingleStorage, InvalidView) {
  68. entt::basic_view<entt::get_t<entt::storage<int>>, entt::exclude_t<>> view{};
  69. auto iterable = view.each();
  70. ASSERT_FALSE(view);
  71. ASSERT_EQ(view.size(), 0u);
  72. ASSERT_TRUE(view.empty());
  73. ASSERT_FALSE(view.contains(entt::null));
  74. ASSERT_EQ(view.find(entt::null), view.end());
  75. ASSERT_EQ(view.front(), static_cast<entt::entity>(entt::null));
  76. ASSERT_EQ(view.back(), static_cast<entt::entity>(entt::null));
  77. ASSERT_EQ(view.begin(), typename decltype(view)::iterator{});
  78. ASSERT_EQ(view.begin(), view.end());
  79. ASSERT_EQ(view.rbegin(), typename decltype(view)::reverse_iterator{});
  80. ASSERT_EQ(view.rbegin(), view.rend());
  81. ASSERT_EQ(iterable.begin(), iterable.end());
  82. ASSERT_EQ(iterable.cbegin(), iterable.cend());
  83. view.each([](const int &) { FAIL(); });
  84. view.each([](const entt::entity, const int &) { FAIL(); });
  85. entt::storage<int> storage;
  86. view.storage(storage);
  87. ASSERT_TRUE(view);
  88. }
  89. TEST(ViewSingleStorage, Constructors) {
  90. entt::storage<int> storage{};
  91. const entt::basic_view<entt::get_t<entt::storage<int>>, entt::exclude_t<>> invalid{};
  92. const entt::basic_view from_storage{storage};
  93. const entt::basic_view from_tuple{std::forward_as_tuple(storage)};
  94. ASSERT_FALSE(invalid);
  95. ASSERT_TRUE(from_storage);
  96. ASSERT_TRUE(from_tuple);
  97. ASSERT_NE(from_storage.handle(), nullptr);
  98. ASSERT_EQ(from_storage.handle(), from_tuple.handle());
  99. }
  100. TEST(ViewSingleStorage, Handle) {
  101. entt::storage<int> storage{};
  102. const entt::basic_view view{storage};
  103. const entt::entity entity{0};
  104. const auto *handle = view.handle();
  105. ASSERT_NE(handle, nullptr);
  106. ASSERT_TRUE(handle->empty());
  107. ASSERT_FALSE(handle->contains(entity));
  108. ASSERT_EQ(handle, view.handle());
  109. storage.emplace(entity);
  110. ASSERT_FALSE(handle->empty());
  111. ASSERT_TRUE(handle->contains(entity));
  112. ASSERT_EQ(handle, view.handle());
  113. }
  114. TEST(ViewSingleStorage, ElementAccess) {
  115. entt::storage<int> storage{};
  116. const entt::basic_view view{storage};
  117. const entt::basic_view cview{std::as_const(storage)};
  118. const std::array entity{entt::entity{1}, entt::entity{3}};
  119. storage.emplace(entity[0u], 4);
  120. storage.emplace(entity[1u], 1);
  121. ASSERT_EQ(view[entity[0u]], 4);
  122. ASSERT_EQ(cview[entity[1u]], 1);
  123. }
  124. TEST(ViewSingleStorage, Contains) {
  125. entt::storage<int> storage{};
  126. const entt::basic_view view{storage};
  127. const std::array entity{entt::entity{1}, entt::entity{3}};
  128. storage.emplace(entity[0u]);
  129. storage.emplace(entity[1u]);
  130. storage.erase(entity[0u]);
  131. ASSERT_FALSE(view.contains(entity[0u]));
  132. ASSERT_TRUE(view.contains(entity[1u]));
  133. }
  134. TEST(ViewSingleStorage, Empty) {
  135. entt::storage<int> storage{};
  136. const entt::basic_view view{storage};
  137. ASSERT_EQ(view.size(), 0u);
  138. ASSERT_EQ(view.begin(), view.end());
  139. ASSERT_EQ(view.rbegin(), view.rend());
  140. }
  141. TEST(ViewSingleStorage, Each) {
  142. std::tuple<entt::storage<int>, entt::storage<double>> storage{};
  143. const entt::basic_view view{std::forward_as_tuple(std::get<0>(storage)), std::forward_as_tuple(std::get<1>(storage))};
  144. const entt::basic_view cview{std::as_const(std::get<0>(storage))};
  145. const std::array entity{entt::entity{0}, entt::entity{1}};
  146. std::get<0>(storage).emplace(entity[0u], 0);
  147. std::get<0>(storage).emplace(entity[1u], 1);
  148. auto iterable = view.each();
  149. auto citerable = cview.each();
  150. ASSERT_NE(citerable.begin(), citerable.end());
  151. ASSERT_NO_THROW(iterable.begin()->operator=(*iterable.begin()));
  152. ASSERT_EQ(decltype(iterable.end()){}, iterable.end());
  153. auto it = iterable.begin();
  154. ASSERT_EQ(it.base(), view.begin());
  155. ASSERT_EQ((it++, ++it), iterable.end());
  156. ASSERT_EQ(it.base(), view.end());
  157. view.each([expected = 1](auto entt, int &value) mutable {
  158. ASSERT_EQ(static_cast<int>(entt::to_integral(entt)), expected);
  159. ASSERT_EQ(value, expected);
  160. --expected;
  161. });
  162. cview.each([expected = 1](const int &value) mutable {
  163. ASSERT_EQ(value, expected);
  164. --expected;
  165. });
  166. ASSERT_EQ(std::get<0>(*iterable.begin()), entity[1u]);
  167. ASSERT_EQ(std::get<0>(*++citerable.begin()), entity[0u]);
  168. testing::StaticAssertTypeEq<decltype(std::get<1>(*iterable.begin())), int &>();
  169. testing::StaticAssertTypeEq<decltype(std::get<1>(*citerable.begin())), const int &>();
  170. // do not use iterable, make sure an iterable view works when created from a temporary
  171. for(auto [entt, value]: view.each()) {
  172. ASSERT_EQ(static_cast<int>(entt::to_integral(entt)), value);
  173. }
  174. }
  175. TEST(ViewSingleStorage, ConstNonConstAndAllInBetween) {
  176. entt::storage<int> storage{};
  177. const entt::basic_view view{storage};
  178. const entt::basic_view cview{std::as_const(storage)};
  179. const entt::entity entity{0};
  180. ASSERT_EQ(view.size(), 0u);
  181. ASSERT_EQ(cview.size(), 0u);
  182. storage.emplace(entity, 0);
  183. ASSERT_EQ(view.size(), 1u);
  184. ASSERT_EQ(cview.size(), 1u);
  185. testing::StaticAssertTypeEq<decltype(view.get<0u>({})), int &>();
  186. testing::StaticAssertTypeEq<decltype(view.get<int>({})), int &>();
  187. testing::StaticAssertTypeEq<decltype(view.get({})), std::tuple<int &>>();
  188. testing::StaticAssertTypeEq<decltype(cview.get<0u>({})), const int &>();
  189. testing::StaticAssertTypeEq<decltype(cview.get<const int>({})), const int &>();
  190. testing::StaticAssertTypeEq<decltype(cview.get({})), std::tuple<const int &>>();
  191. view.each([](auto &&iv) {
  192. testing::StaticAssertTypeEq<decltype(iv), int &>();
  193. });
  194. cview.each([](auto &&iv) {
  195. testing::StaticAssertTypeEq<decltype(iv), const int &>();
  196. });
  197. for([[maybe_unused]] auto [entt, iv]: view.each()) {
  198. testing::StaticAssertTypeEq<decltype(entt), entt::entity>();
  199. testing::StaticAssertTypeEq<decltype(iv), int &>();
  200. }
  201. for([[maybe_unused]] auto [entt, iv]: cview.each()) {
  202. testing::StaticAssertTypeEq<decltype(entt), entt::entity>();
  203. testing::StaticAssertTypeEq<decltype(iv), const int &>();
  204. }
  205. }
  206. TEST(ViewSingleStorage, ConstNonConstAndAllInBetweenWithEmptyType) {
  207. entt::storage<test::empty> storage{};
  208. const entt::basic_view view{storage};
  209. const entt::basic_view cview{std::as_const(storage)};
  210. const entt::entity entity{0};
  211. ASSERT_EQ(view.size(), 0u);
  212. ASSERT_EQ(cview.size(), 0u);
  213. storage.emplace(entity);
  214. ASSERT_EQ(view.size(), 1u);
  215. ASSERT_EQ(cview.size(), 1u);
  216. testing::StaticAssertTypeEq<decltype(view.get({})), std::tuple<>>();
  217. testing::StaticAssertTypeEq<decltype(cview.get({})), std::tuple<>>();
  218. for([[maybe_unused]] auto [entt]: view.each()) {
  219. testing::StaticAssertTypeEq<decltype(entt), entt::entity>();
  220. }
  221. for([[maybe_unused]] auto [entt]: cview.each()) {
  222. testing::StaticAssertTypeEq<decltype(entt), entt::entity>();
  223. }
  224. }
  225. TEST(ViewSingleStorage, Find) {
  226. entt::storage<int> storage{};
  227. const entt::basic_view view{storage};
  228. const std::array entity{entt::entity{0}, entt::entity{1}, entt::entity{2}};
  229. storage.emplace(entity[0u]);
  230. storage.emplace(entity[1u]);
  231. storage.emplace(entity[2u]);
  232. storage.erase(entity[1u]);
  233. ASSERT_NE(view.find(entity[0u]), view.end());
  234. ASSERT_EQ(view.find(entity[1u]), view.end());
  235. ASSERT_NE(view.find(entity[2u]), view.end());
  236. auto it = view.find(entity[2u]);
  237. ASSERT_EQ(*it, entity[2u]);
  238. ASSERT_EQ(*(++it), entity[0u]);
  239. ASSERT_EQ(++it, view.end());
  240. }
  241. TEST(ViewSingleStorage, EmptyType) {
  242. entt::storage<test::empty> storage{};
  243. const entt::basic_view view{storage};
  244. const entt::entity entity{0};
  245. storage.emplace(entity);
  246. view.each([&](const auto entt) {
  247. ASSERT_EQ(entity, entt);
  248. });
  249. view.each([check = true]() mutable {
  250. ASSERT_TRUE(check);
  251. check = false;
  252. });
  253. for(auto [entt]: view.each()) {
  254. testing::StaticAssertTypeEq<decltype(entt), entt::entity>();
  255. ASSERT_EQ(entity, entt);
  256. }
  257. }
  258. TEST(ViewSingleStorage, FrontBack) {
  259. entt::storage<char> storage{};
  260. const entt::basic_view view{std::as_const(storage)};
  261. const std::array entity{entt::entity{1}, entt::entity{3}};
  262. ASSERT_EQ(view.front(), static_cast<entt::entity>(entt::null));
  263. ASSERT_EQ(view.back(), static_cast<entt::entity>(entt::null));
  264. storage.emplace(entity[0u]);
  265. storage.emplace(entity[1u]);
  266. ASSERT_EQ(view.front(), entity[1u]);
  267. ASSERT_EQ(view.back(), entity[0u]);
  268. }
  269. TEST(ViewSingleStorage, DeductionGuide) {
  270. testing::StaticAssertTypeEq<entt::basic_view<entt::get_t<entt::storage<int>>, entt::exclude_t<>>, decltype(entt::basic_view{std::declval<entt::storage<int> &>()})>();
  271. testing::StaticAssertTypeEq<entt::basic_view<entt::get_t<const entt::storage<int>>, entt::exclude_t<>>, decltype(entt::basic_view{std::declval<const entt::storage<int> &>()})>();
  272. testing::StaticAssertTypeEq<entt::basic_view<entt::get_t<entt::storage<test::pointer_stable>>, entt::exclude_t<>>, decltype(entt::basic_view{std::declval<entt::storage<test::pointer_stable> &>()})>();
  273. testing::StaticAssertTypeEq<entt::basic_view<entt::get_t<entt::storage<int>>, entt::exclude_t<>>, decltype(entt::basic_view{std::forward_as_tuple(std::declval<entt::storage<int> &>()), std::make_tuple()})>();
  274. testing::StaticAssertTypeEq<entt::basic_view<entt::get_t<const entt::storage<int>>, entt::exclude_t<>>, decltype(entt::basic_view{std::forward_as_tuple(std::declval<const entt::storage<int> &>())})>();
  275. testing::StaticAssertTypeEq<entt::basic_view<entt::get_t<entt::storage<test::pointer_stable>>, entt::exclude_t<>>, decltype(entt::basic_view{std::forward_as_tuple(std::declval<entt::storage<test::pointer_stable> &>())})>();
  276. }
  277. TEST(ViewSingleStorage, IterableViewAlgorithmCompatibility) {
  278. entt::storage<char> storage{};
  279. const entt::basic_view view{storage};
  280. const entt::entity entity{0};
  281. storage.emplace(entity);
  282. const auto iterable = view.each();
  283. const auto it = std::find_if(iterable.begin(), iterable.end(), [entity](auto args) { return std::get<0>(args) == entity; });
  284. ASSERT_EQ(std::get<0>(*it), entity);
  285. }
  286. TEST(ViewSingleStorage, StableType) {
  287. entt::storage<test::pointer_stable> storage{};
  288. entt::basic_view<entt::get_t<entt::storage<test::pointer_stable>>, entt::exclude_t<>> view{};
  289. const std::array entity{entt::entity{1}, entt::entity{3}};
  290. ASSERT_EQ(view.front(), static_cast<entt::entity>(entt::null));
  291. ASSERT_EQ(view.back(), static_cast<entt::entity>(entt::null));
  292. ASSERT_EQ(view.find(entity[0u]), view.end());
  293. view.storage(storage);
  294. storage.emplace(entity[0u], 0);
  295. storage.emplace(entity[1u], 1);
  296. storage.erase(entity[0u]);
  297. ASSERT_EQ(view.size_hint(), 2u);
  298. ASSERT_EQ(view->size(), 2u);
  299. ASSERT_FALSE(view.contains(entity[0u]));
  300. ASSERT_FALSE(view->contains(entity[0u]));
  301. ASSERT_TRUE(view.contains(entity[1u]));
  302. ASSERT_EQ(std::distance(view.begin(), view.end()), 1);
  303. ASSERT_EQ(std::distance(view->begin(), view->end()), 2);
  304. ASSERT_EQ(*view.begin(), entity[1u]);
  305. ASSERT_EQ(++view.begin(), view.end());
  306. ASSERT_EQ(view.front(), entity[1u]);
  307. ASSERT_EQ(view.back(), entity[1u]);
  308. ASSERT_EQ(view.find(entity[0u]), view.end());
  309. ASSERT_NE(view.find(entity[1u]), view.end());
  310. for(auto [entt, elem]: view.each()) {
  311. testing::StaticAssertTypeEq<decltype(entt), entt::entity>();
  312. testing::StaticAssertTypeEq<decltype(elem), test::pointer_stable &>();
  313. ASSERT_EQ(entt, entity[1u]);
  314. }
  315. view.each([&](const auto entt, const auto &elem) {
  316. ASSERT_EQ(elem, view->get(entity[1u]));
  317. ASSERT_EQ(entt, entity[1u]);
  318. });
  319. view.each([&](const auto &elem) {
  320. ASSERT_EQ(elem, view->get(entity[1u]));
  321. });
  322. storage.erase(view.begin(), view.end());
  323. ASSERT_EQ(view.size_hint(), 2u);
  324. ASSERT_EQ(view->size(), 2u);
  325. ASSERT_EQ(std::distance(view.begin(), view.end()), 0);
  326. ASSERT_EQ(std::distance(view->begin(), view->end()), 2);
  327. ASSERT_EQ(view.front(), static_cast<entt::entity>(entt::null));
  328. ASSERT_EQ(view.back(), static_cast<entt::entity>(entt::null));
  329. storage.compact();
  330. ASSERT_EQ(view.size_hint(), 0u);
  331. ASSERT_EQ(view->size(), 0u);
  332. }
  333. TEST(ViewSingleStorage, Storage) {
  334. std::tuple<entt::storage<int>, entt::storage<char>> storage{};
  335. entt::basic_view view{std::get<0>(storage)};
  336. entt::basic_view cview{std::as_const(std::get<1>(storage))};
  337. const entt::entity entity{0};
  338. testing::StaticAssertTypeEq<decltype(view.storage()), entt::storage<int> *>();
  339. testing::StaticAssertTypeEq<decltype(view.storage<0u>()), entt::storage<int> *>();
  340. testing::StaticAssertTypeEq<decltype(view.storage<int>()), entt::storage<int> *>();
  341. testing::StaticAssertTypeEq<decltype(view.storage<const int>()), entt::storage<int> *>();
  342. testing::StaticAssertTypeEq<decltype(cview.storage()), const entt::storage<char> *>();
  343. testing::StaticAssertTypeEq<decltype(cview.storage<0u>()), const entt::storage<char> *>();
  344. testing::StaticAssertTypeEq<decltype(cview.storage<char>()), const entt::storage<char> *>();
  345. testing::StaticAssertTypeEq<decltype(cview.storage<const char>()), const entt::storage<char> *>();
  346. ASSERT_TRUE(view);
  347. ASSERT_TRUE(cview);
  348. ASSERT_NE(view.storage<int>(), nullptr);
  349. ASSERT_NE(cview.storage<0u>(), nullptr);
  350. ASSERT_EQ(view.size(), 0u);
  351. ASSERT_EQ(cview.size(), 0u);
  352. view.storage()->emplace(entity);
  353. std::get<1>(storage).emplace(entity);
  354. ASSERT_EQ(view.size(), 1u);
  355. ASSERT_EQ(cview.size(), 1u);
  356. ASSERT_TRUE(view.storage<int>()->contains(entity));
  357. ASSERT_TRUE(cview.storage<0u>()->contains(entity));
  358. view.storage()->erase(entity);
  359. ASSERT_EQ(view.size(), 0u);
  360. ASSERT_EQ(cview.size(), 1u);
  361. ASSERT_FALSE(view.storage<0u>()->contains(entity));
  362. ASSERT_TRUE(cview.storage<const char>()->contains(entity));
  363. view = {};
  364. cview = {};
  365. ASSERT_FALSE(view);
  366. ASSERT_FALSE(cview);
  367. ASSERT_EQ(view.storage<0u>(), nullptr);
  368. ASSERT_EQ(cview.storage<const char>(), nullptr);
  369. }
  370. TEST(ViewSingleStorage, ArrowOperator) {
  371. std::tuple<entt::storage<int>, entt::storage<char>> storage{};
  372. entt::basic_view view{std::get<0>(storage)};
  373. entt::basic_view cview{std::as_const(std::get<1>(storage))};
  374. const entt::entity entity{0};
  375. testing::StaticAssertTypeEq<decltype(view.operator->()), entt::storage<int> *>();
  376. testing::StaticAssertTypeEq<decltype(cview.operator->()), const entt::storage<char> *>();
  377. ASSERT_TRUE(view);
  378. ASSERT_TRUE(cview);
  379. ASSERT_NE(view.operator->(), nullptr);
  380. ASSERT_NE(cview.operator->(), nullptr);
  381. view->emplace(entity);
  382. std::get<1>(storage).emplace(entity);
  383. ASSERT_EQ(view.operator->(), &std::get<0>(storage));
  384. ASSERT_EQ(cview.operator->(), &std::get<1>(storage));
  385. ASSERT_EQ(view.operator->(), view.storage());
  386. ASSERT_EQ(cview.operator->(), cview.storage());
  387. view = {};
  388. cview = {};
  389. ASSERT_EQ(view.operator->(), nullptr);
  390. ASSERT_EQ(cview.operator->(), nullptr);
  391. }
  392. TEST(ViewSingleStorage, SwapStorage) {
  393. std::tuple<entt::storage<int>, entt::storage<int>> storage{};
  394. entt::basic_view<entt::get_t<entt::storage<int>>, entt::exclude_t<>> view{};
  395. entt::basic_view<entt::get_t<const entt::storage<int>>, entt::exclude_t<>> cview{};
  396. const entt::entity entity{0};
  397. ASSERT_FALSE(view);
  398. ASSERT_FALSE(cview);
  399. ASSERT_EQ(view.storage<0u>(), nullptr);
  400. ASSERT_EQ(cview.storage<const int>(), nullptr);
  401. std::get<0>(storage).emplace(entity);
  402. view.storage(std::get<0>(storage));
  403. cview.storage(std::get<0>(storage));
  404. ASSERT_TRUE(view);
  405. ASSERT_TRUE(cview);
  406. ASSERT_NE(view.storage<0u>(), nullptr);
  407. ASSERT_NE(cview.storage<const int>(), nullptr);
  408. ASSERT_EQ(view.size(), 1u);
  409. ASSERT_EQ(cview.size(), 1u);
  410. ASSERT_TRUE(view.contains(entity));
  411. ASSERT_TRUE(cview.contains(entity));
  412. view.storage(std::get<1>(storage));
  413. cview.storage(std::get<1>(storage));
  414. ASSERT_TRUE(view.empty());
  415. ASSERT_TRUE(cview.empty());
  416. }
  417. TEST(ViewSingleStorage, StorageEntity) {
  418. entt::storage<entt::entity> storage{};
  419. entt::basic_view<entt::get_t<entt::storage<entt::entity>>, entt::exclude_t<>> view{};
  420. const std::array entity{storage.generate(), storage.generate()};
  421. ASSERT_EQ(view.front(), static_cast<entt::entity>(entt::null));
  422. ASSERT_EQ(view.back(), static_cast<entt::entity>(entt::null));
  423. ASSERT_EQ(view.find(entity[0u]), view.end());
  424. view.storage(storage);
  425. storage.erase(entity[0u]);
  426. storage.bump(entity[0u]);
  427. ASSERT_EQ(view.size(), 1u);
  428. ASSERT_EQ(view->size(), 2u);
  429. ASSERT_FALSE(view.empty());
  430. ASSERT_FALSE(view->empty());
  431. ASSERT_FALSE(view.contains(entity[0u]));
  432. ASSERT_TRUE(view->contains(entity[0u]));
  433. ASSERT_TRUE(view.contains(entity[1u]));
  434. ASSERT_NE(view.begin(), view->begin());
  435. ASSERT_EQ(view.end(), view->end());
  436. ASSERT_EQ(std::distance(view.begin(), view.end()), 1);
  437. ASSERT_EQ(std::distance(view->begin(), view->end()), 2);
  438. ASSERT_EQ(*view.begin(), entity[1u]);
  439. ASSERT_EQ(*view->begin(), entity[0u]);
  440. ASSERT_EQ(++view->begin(), view.begin());
  441. ASSERT_EQ(++view.begin(), view.end());
  442. ASSERT_EQ(view.rbegin(), view->rbegin());
  443. ASSERT_NE(view.rend(), view->rend());
  444. ASSERT_EQ(std::distance(view.rbegin(), view.rend()), 1);
  445. ASSERT_EQ(std::distance(view->rbegin(), view->rend()), 2);
  446. ASSERT_EQ(++view.rbegin(), view.rend());
  447. ASSERT_EQ(++view.rend(), view->rend());
  448. ASSERT_EQ(view.front(), entity[1u]);
  449. ASSERT_EQ(view.back(), entity[1u]);
  450. ASSERT_EQ(view.find(entity[0u]), view.end());
  451. ASSERT_NE(view->find(entity[0u]), view.end());
  452. ASSERT_NE(view.find(entity[1u]), view.end());
  453. for(auto elem: view.each()) {
  454. ASSERT_EQ(std::get<0>(elem), entity[1u]);
  455. }
  456. view.each([&entity](auto entt) {
  457. ASSERT_EQ(entt, entity[1u]);
  458. });
  459. view.each([&]() {
  460. storage.erase(entity[1u]);
  461. });
  462. ASSERT_EQ(view.size(), 0u);
  463. ASSERT_EQ(view->size(), 2u);
  464. ASSERT_TRUE(view.empty());
  465. ASSERT_FALSE(view->empty());
  466. ASSERT_EQ(std::distance(view.begin(), view.end()), 0);
  467. ASSERT_EQ(std::distance(view->begin(), view->end()), 2);
  468. ASSERT_EQ(view.front(), static_cast<entt::entity>(entt::null));
  469. ASSERT_EQ(view.back(), static_cast<entt::entity>(entt::null));
  470. }
  471. TEST(ViewMultiStorage, Functionalities) {
  472. std::tuple<entt::storage<int>, entt::storage<char>> storage{};
  473. const entt::basic_view view{std::get<0>(storage), std::get<1>(storage)};
  474. const entt::basic_view cview{std::as_const(std::get<0>(storage)), std::as_const(std::get<1>(storage))};
  475. const std::array entity{entt::entity{1}, entt::entity{3}};
  476. std::get<1>(storage).emplace(entity[0u], '1');
  477. std::get<0>(storage).emplace(entity[1u], 4);
  478. std::get<1>(storage).emplace(entity[1u], '2');
  479. ASSERT_EQ(*view.begin(), entity[1u]);
  480. ASSERT_EQ(*cview.begin(), entity[1u]);
  481. ASSERT_EQ(++view.begin(), (view.end()));
  482. ASSERT_EQ(++cview.begin(), (cview.end()));
  483. ASSERT_NO_THROW((view.begin()++));
  484. ASSERT_NO_THROW((++cview.begin()));
  485. ASSERT_NE(view.begin(), view.end());
  486. ASSERT_NE(cview.begin(), cview.end());
  487. ASSERT_EQ(view.size_hint(), 1u);
  488. for(auto entt: view) {
  489. ASSERT_EQ(std::get<0>(cview.get<const int, const char>(entt)), 4);
  490. ASSERT_EQ(std::get<0>(cview.get<0u, 1u>(entt)), 4);
  491. ASSERT_EQ(std::get<1>(view.get<int, char>(entt)), '2');
  492. ASSERT_EQ(std::get<1>(view.get<0u, 1u>(entt)), '2');
  493. ASSERT_EQ(cview.get<const char>(entt), '2');
  494. ASSERT_EQ(cview.get<1u>(entt), '2');
  495. }
  496. const decltype(view) invalid{};
  497. ASSERT_TRUE(view);
  498. ASSERT_TRUE(cview);
  499. ASSERT_FALSE(invalid);
  500. }
  501. TEST(ViewMultiStorage, Conversion) {
  502. entt::basic_view<entt::get_t<entt::storage<int>, const entt::storage<char>>, entt::exclude_t<entt::storage<double>, const entt::storage<float>>> view1{};
  503. entt::basic_view<entt::get_t<const entt::storage<int>, const entt::storage<char>>, entt::exclude_t<const entt::storage<double>, const entt::storage<float>>> view2{view1};
  504. entt::basic_view<entt::get_t<entt::storage<int>>, entt::exclude_t<const entt::storage<double>>> view3{view1};
  505. entt::basic_view<entt::get_t<const entt::storage<char>>, entt::exclude_t<>> view4{view1};
  506. ASSERT_FALSE(view1);
  507. ASSERT_FALSE(view2);
  508. ASSERT_FALSE(view3);
  509. ASSERT_FALSE(view4);
  510. entt::storage<int> istorage{};
  511. entt::storage<char> cstorage{};
  512. entt::storage<double> dstorage{};
  513. entt::storage<float> fstorage{};
  514. view1.storage(istorage);
  515. view1.storage(cstorage);
  516. view1.storage(dstorage);
  517. view1.storage(fstorage);
  518. view2 = view1;
  519. view3 = view1;
  520. view4 = view1;
  521. ASSERT_TRUE(view1);
  522. ASSERT_TRUE(view2);
  523. ASSERT_TRUE(view3);
  524. ASSERT_TRUE(view4);
  525. ASSERT_EQ(0u, view1.size_hint());
  526. ASSERT_EQ(0u, view2.size_hint());
  527. ASSERT_EQ(0u, view3.size_hint());
  528. ASSERT_EQ(0u, view4.size());
  529. const entt::entity entity{1};
  530. istorage.emplace(entity);
  531. cstorage.emplace(entity);
  532. dstorage.emplace(entity);
  533. fstorage.emplace(entity);
  534. ASSERT_EQ(1u, view1.size_hint());
  535. ASSERT_EQ(1u, view2.size_hint());
  536. ASSERT_EQ(1u, view3.size_hint());
  537. ASSERT_EQ(1u, view4.size());
  538. }
  539. TEST(ViewMultiStorage, InvalidView) {
  540. entt::basic_view<entt::get_t<entt::storage<int>>, entt::exclude_t<entt::storage<char>>> view{};
  541. auto iterable = view.each();
  542. ASSERT_FALSE(view);
  543. ASSERT_EQ(view.size_hint(), 0u);
  544. ASSERT_FALSE(view.contains(entt::null));
  545. ASSERT_EQ(view.find(entt::null), view.end());
  546. ASSERT_EQ(view.front(), static_cast<entt::entity>(entt::null));
  547. ASSERT_EQ(view.back(), static_cast<entt::entity>(entt::null));
  548. ASSERT_EQ(view.begin(), typename decltype(view)::iterator{});
  549. ASSERT_EQ(view.begin(), view.end());
  550. ASSERT_EQ(iterable.begin(), iterable.end());
  551. ASSERT_EQ(iterable.cbegin(), iterable.cend());
  552. view.each([](const int &) { FAIL(); });
  553. view.each([](const entt::entity, const int &) { FAIL(); });
  554. entt::storage<int> storage{};
  555. const entt::entity entity{0};
  556. view.storage(storage);
  557. storage.emplace(entity);
  558. ASSERT_FALSE(view);
  559. ASSERT_EQ(view.size_hint(), 1u);
  560. ASSERT_TRUE(view.contains(entity));
  561. ASSERT_NE(view.find(entity), view.end());
  562. ASSERT_EQ(view.front(), entity);
  563. ASSERT_EQ(view.back(), entity);
  564. ASSERT_NE(view.begin(), typename decltype(view)::iterator{});
  565. ASSERT_NE(view.begin(), view.end());
  566. ASSERT_EQ(iterable.begin(), iterable.end());
  567. ASSERT_EQ(iterable.cbegin(), iterable.cend());
  568. entt::storage<char> other{};
  569. view.storage(other);
  570. ASSERT_TRUE(view);
  571. }
  572. TEST(ViewMultiStorage, Constructors) {
  573. entt::storage<int> storage{};
  574. const entt::basic_view<entt::get_t<entt::storage<int>, entt::storage<int>>, entt::exclude_t<>> invalid{};
  575. const entt::basic_view from_storage{storage, storage};
  576. const entt::basic_view from_tuple{std::forward_as_tuple(storage, storage)};
  577. ASSERT_FALSE(invalid);
  578. ASSERT_TRUE(from_storage);
  579. ASSERT_TRUE(from_tuple);
  580. ASSERT_NE(from_storage.handle(), nullptr);
  581. ASSERT_EQ(from_storage.handle(), from_tuple.handle());
  582. }
  583. TEST(ViewMultiStorage, Handle) {
  584. std::tuple<entt::storage<int>, entt::storage<char>> storage{};
  585. entt::basic_view view{std::get<0>(storage), std::get<1>(storage)};
  586. const auto *handle = view.handle();
  587. const entt::entity entity{0};
  588. ASSERT_NE(handle, nullptr);
  589. ASSERT_TRUE(handle->empty());
  590. ASSERT_FALSE(handle->contains(entity));
  591. ASSERT_EQ(handle, view.handle());
  592. std::get<0>(storage).emplace(entity);
  593. ASSERT_FALSE(handle->empty());
  594. ASSERT_TRUE(handle->contains(entity));
  595. ASSERT_EQ(handle, view.handle());
  596. view.refresh();
  597. const auto *other = view.handle();
  598. ASSERT_NE(other, nullptr);
  599. ASSERT_TRUE(other->empty());
  600. ASSERT_FALSE(other->contains(entity));
  601. ASSERT_EQ(other, view.handle());
  602. ASSERT_NE(handle, other);
  603. view.use<int>();
  604. ASSERT_NE(other, view.handle());
  605. ASSERT_EQ(handle, view.handle());
  606. }
  607. TEST(ViewMultiStorage, Iterator) {
  608. std::tuple<entt::storage<int>, entt::storage<char>> storage{};
  609. const entt::basic_view view{std::get<0>(storage), std::get<1>(storage)};
  610. const std::array entity{entt::entity{0}, entt::entity{1}};
  611. std::get<0>(storage).insert(entity.begin(), entity.end());
  612. std::get<1>(storage).insert(entity.begin(), entity.end());
  613. using iterator = decltype(view)::iterator;
  614. iterator end{view.begin()};
  615. iterator begin{};
  616. begin = view.end();
  617. std::swap(begin, end);
  618. ASSERT_EQ(begin, view.begin());
  619. ASSERT_EQ(end, view.end());
  620. ASSERT_NE(begin, end);
  621. ASSERT_EQ(*begin, entity[1u]);
  622. ASSERT_EQ(*begin.operator->(), entity[1u]);
  623. ASSERT_EQ(begin++, view.begin());
  624. ASSERT_EQ(*begin, entity[0u]);
  625. ASSERT_EQ(*begin.operator->(), entity[0u]);
  626. ASSERT_EQ(++begin, view.end());
  627. }
  628. TEST(ViewMultiStorage, ElementAccess) {
  629. std::tuple<entt::storage<int>, entt::storage<char>> storage{};
  630. const entt::basic_view view{std::get<0>(storage), std::get<1>(storage)};
  631. const entt::basic_view cview{std::as_const(std::get<0>(storage)), std::as_const(std::get<1>(storage))};
  632. const std::array entity{entt::entity{1}, entt::entity{3}};
  633. std::get<0>(storage).emplace(entity[0u], 4);
  634. std::get<0>(storage).emplace(entity[1u], 1);
  635. std::get<1>(storage).emplace(entity[0u], '0');
  636. std::get<1>(storage).emplace(entity[1u], '1');
  637. ASSERT_EQ(view[entity[0u]], std::make_tuple(4, '0'));
  638. ASSERT_EQ(cview[entity[1u]], std::make_tuple(1, '1'));
  639. }
  640. TEST(ViewMultiStorage, Contains) {
  641. std::tuple<entt::storage<int>, entt::storage<char>> storage{};
  642. const entt::basic_view view{std::get<0>(storage), std::get<1>(storage)};
  643. const std::array entity{entt::entity{1}, entt::entity{3}};
  644. std::get<0>(storage).emplace(entity[0u]);
  645. std::get<0>(storage).emplace(entity[1u]);
  646. std::get<1>(storage).emplace(entity[0u]);
  647. std::get<1>(storage).emplace(entity[1u]);
  648. std::get<0>(storage).erase(entity[0u]);
  649. ASSERT_FALSE(view.contains(entity[0u]));
  650. ASSERT_TRUE(view.contains(entity[1u]));
  651. }
  652. TEST(ViewMultiStorage, SizeHint) {
  653. std::tuple<entt::storage<int>, entt::storage<char>> storage{};
  654. entt::basic_view view{std::get<0>(storage), std::get<1>(storage)};
  655. const std::array entity{entt::entity{1}, entt::entity{3}};
  656. std::get<0>(storage).emplace(entity[0u]);
  657. std::get<1>(storage).emplace(entity[0u]);
  658. std::get<1>(storage).emplace(entity[1u]);
  659. view.use<int>();
  660. ASSERT_EQ(view.size_hint(), 1u);
  661. ASSERT_NE(view.begin(), view.end());
  662. ASSERT_EQ(++view.begin(), view.end());
  663. view.use<char>();
  664. ASSERT_EQ(view.size_hint(), 2u);
  665. ASSERT_NE(view.begin(), view.end());
  666. ASSERT_EQ(++view.begin(), view.end());
  667. }
  668. TEST(ViewMultiStorage, UseAndRefresh) {
  669. std::tuple<entt::storage<int>, entt::storage<char>, entt::storage<double>> storage{};
  670. entt::basic_view view{std::forward_as_tuple(std::get<0>(storage), std::get<1>(storage)), std::forward_as_tuple(std::get<2>(storage))};
  671. const std::array entity{entt::entity{0u}, entt::entity{1u}, entt::entity{2u}};
  672. std::get<0>(storage).emplace(entity[0u]);
  673. std::get<0>(storage).emplace(entity[1u]);
  674. std::get<1>(storage).emplace(entity[1u]);
  675. std::get<1>(storage).emplace(entity[0u]);
  676. std::get<1>(storage).emplace(entity[2u]);
  677. view.use<int>();
  678. ASSERT_EQ(view.handle()->info(), entt::type_id<int>());
  679. ASSERT_EQ(view.front(), entity[1u]);
  680. ASSERT_EQ(view.back(), entity[0u]);
  681. view.use<char>();
  682. ASSERT_EQ(view.handle()->info(), entt::type_id<char>());
  683. ASSERT_EQ(view.front(), entity[0u]);
  684. ASSERT_EQ(view.back(), entity[1u]);
  685. view.refresh();
  686. ASSERT_EQ(view.handle()->info(), entt::type_id<int>());
  687. }
  688. TEST(ViewMultiStorage, Each) {
  689. std::tuple<entt::storage<int>, entt::storage<char>, entt::storage<double>> storage{};
  690. const entt::basic_view view{std::forward_as_tuple(std::get<0>(storage), std::get<1>(storage)), std::forward_as_tuple(std::get<2>(storage))};
  691. const entt::basic_view cview{std::as_const(std::get<0>(storage)), std::as_const(std::get<1>(storage))};
  692. const std::array entity{entt::entity{0}, entt::entity{1}};
  693. std::get<0>(storage).emplace(entity[0u], 0);
  694. std::get<1>(storage).emplace(entity[0u], static_cast<char>(0));
  695. std::get<0>(storage).emplace(entity[1u], 1);
  696. std::get<1>(storage).emplace(entity[1u], static_cast<char>(1));
  697. auto iterable = view.each();
  698. auto citerable = cview.each();
  699. ASSERT_NE(citerable.begin(), citerable.end());
  700. ASSERT_NO_THROW(iterable.begin()->operator=(*iterable.begin()));
  701. ASSERT_EQ(decltype(iterable.end()){}, iterable.end());
  702. auto it = iterable.begin();
  703. ASSERT_EQ(it.base(), view.begin());
  704. ASSERT_EQ((it++, ++it), iterable.end());
  705. ASSERT_EQ(it.base(), view.end());
  706. view.each([expected = 1](auto entt, int &ivalue, char &cvalue) mutable {
  707. ASSERT_EQ(static_cast<int>(entt::to_integral(entt)), expected);
  708. ASSERT_EQ(ivalue, expected);
  709. ASSERT_EQ(cvalue, expected);
  710. --expected;
  711. });
  712. cview.each([expected = 1](const int &ivalue, const char &cvalue) mutable {
  713. ASSERT_EQ(ivalue, expected);
  714. ASSERT_EQ(cvalue, expected);
  715. --expected;
  716. });
  717. ASSERT_EQ(std::get<0>(*iterable.begin()), entity[1u]);
  718. ASSERT_EQ(std::get<0>(*++citerable.begin()), entity[0u]);
  719. testing::StaticAssertTypeEq<decltype(std::get<1>(*iterable.begin())), int &>();
  720. testing::StaticAssertTypeEq<decltype(std::get<2>(*citerable.begin())), const char &>();
  721. // do not use iterable, make sure an iterable view works when created from a temporary
  722. for(auto [entt, ivalue, cvalue]: entt::basic_view{std::get<0>(storage), std::get<1>(storage)}.each()) {
  723. ASSERT_EQ(static_cast<int>(entt::to_integral(entt)), ivalue);
  724. ASSERT_EQ(static_cast<char>(entt::to_integral(entt)), cvalue);
  725. }
  726. }
  727. TEST(ViewMultiStorage, EachWithSuggestedType) {
  728. std::tuple<entt::storage<int>, entt::storage<char>> storage{};
  729. entt::basic_view view{std::get<0>(storage), std::get<1>(storage)};
  730. const std::array entity{entt::entity{0}, entt::entity{1}, entt::entity{2}, entt::entity{3}};
  731. std::get<0>(storage).emplace(entity[0u], 0);
  732. std::get<1>(storage).emplace(entity[0u]);
  733. std::get<0>(storage).emplace(entity[1u], 1);
  734. std::get<1>(storage).emplace(entity[1u]);
  735. std::get<0>(storage).emplace(entity[2u], 2);
  736. std::get<1>(storage).emplace(entity[2u]);
  737. // makes char a better candidate during iterations
  738. std::get<0>(storage).emplace(entity[3u], 3);
  739. view.use<int>();
  740. view.each([value = 2](const auto curr, const auto) mutable {
  741. ASSERT_EQ(curr, value--);
  742. });
  743. std::get<0>(storage).sort([](const auto lhs, const auto rhs) {
  744. return lhs < rhs;
  745. });
  746. view.use<0u>();
  747. view.each([value = 0](const auto curr, const auto) mutable {
  748. ASSERT_EQ(curr, value++);
  749. });
  750. std::get<0>(storage).sort([](const auto lhs, const auto rhs) {
  751. return lhs > rhs;
  752. });
  753. auto value = entt::basic_view{std::get<0>(storage), std::get<1>(storage)}.size_hint();
  754. for(auto &&curr: entt::basic_view{std::get<0>(storage), std::get<1>(storage)}.each()) {
  755. ASSERT_EQ(std::get<1>(curr), static_cast<int>(--value));
  756. }
  757. std::get<0>(storage).sort([](const auto lhs, const auto rhs) {
  758. return lhs < rhs;
  759. });
  760. value = {};
  761. view.use<int>();
  762. for(auto &&curr: view.each()) {
  763. ASSERT_EQ(std::get<1>(curr), static_cast<int>(value++));
  764. }
  765. }
  766. TEST(ViewMultiStorage, EachWithHoles) {
  767. std::tuple<entt::storage<char>, entt::storage<test::boxed_int>> storage{};
  768. const entt::basic_view view{std::get<0>(storage), std::get<1>(storage)};
  769. const std::array entity{entt::entity{0}, entt::entity{1}, entt::entity{2}};
  770. std::get<0>(storage).emplace(entity[0u], '0');
  771. std::get<0>(storage).emplace(entity[1u], '1');
  772. std::get<1>(storage).emplace(entity[0u], 0);
  773. std::get<1>(storage).emplace(entity[2u], 2);
  774. view.each([&entity](auto entt, const char &cv, const test::boxed_int &iv) {
  775. ASSERT_EQ(entt, entity[0u]);
  776. ASSERT_EQ(cv, '0');
  777. ASSERT_EQ(iv.value, 0);
  778. });
  779. for(auto &&curr: view.each()) {
  780. ASSERT_EQ(std::get<0>(curr), entity[0u]);
  781. ASSERT_EQ(std::get<1>(curr), '0');
  782. ASSERT_EQ(std::get<2>(curr).value, 0);
  783. }
  784. }
  785. TEST(ViewMultiStorage, ConstNonConstAndAllInBetween) {
  786. std::tuple<entt::storage<int>, entt::storage<test::empty>, entt::storage<char>> storage{};
  787. const entt::basic_view view{std::get<0>(storage), std::get<1>(storage), std::as_const(std::get<2>(storage))};
  788. const entt::entity entity{0};
  789. ASSERT_EQ(view.size_hint(), 0u);
  790. std::get<0>(storage).emplace(entity, 0);
  791. std::get<1>(storage).emplace(entity);
  792. std::get<2>(storage).emplace(entity, 'c');
  793. ASSERT_EQ(view.size_hint(), 1u);
  794. testing::StaticAssertTypeEq<decltype(view.get<0u>({})), int &>();
  795. testing::StaticAssertTypeEq<decltype(view.get<2u>({})), const char &>();
  796. testing::StaticAssertTypeEq<decltype(view.get<0u, 2u>({})), std::tuple<int &, const char &>>();
  797. testing::StaticAssertTypeEq<decltype(view.get<int>({})), int &>();
  798. testing::StaticAssertTypeEq<decltype(view.get<const char>({})), const char &>();
  799. testing::StaticAssertTypeEq<decltype(view.get<int, const char>({})), std::tuple<int &, const char &>>();
  800. testing::StaticAssertTypeEq<decltype(view.get({})), std::tuple<int &, const char &>>();
  801. view.each([](auto &&iv, auto &&cv) {
  802. testing::StaticAssertTypeEq<decltype(iv), int &>();
  803. testing::StaticAssertTypeEq<decltype(cv), const char &>();
  804. });
  805. for([[maybe_unused]] auto [entt, iv, cv]: view.each()) {
  806. testing::StaticAssertTypeEq<decltype(entt), entt::entity>();
  807. testing::StaticAssertTypeEq<decltype(iv), int &>();
  808. testing::StaticAssertTypeEq<decltype(cv), const char &>();
  809. }
  810. }
  811. TEST(ViewMultiStorage, Find) {
  812. std::tuple<entt::storage<int>, entt::storage<char>> storage{};
  813. const entt::basic_view view{std::get<0>(storage), std::as_const(std::get<1>(storage))};
  814. const std::array entity{entt::entity{0}, entt::entity{1}, entt::entity{2}};
  815. std::get<0>(storage).emplace(entity[0u]);
  816. std::get<0>(storage).emplace(entity[1u]);
  817. std::get<0>(storage).emplace(entity[2u]);
  818. std::get<1>(storage).emplace(entity[0u]);
  819. std::get<1>(storage).emplace(entity[1u]);
  820. std::get<1>(storage).emplace(entity[2u]);
  821. std::get<0>(storage).erase(entity[1u]);
  822. ASSERT_NE(view.find(entity[0u]), view.end());
  823. ASSERT_EQ(view.find(entity[1u]), view.end());
  824. ASSERT_NE(view.find(entity[2u]), view.end());
  825. auto it = view.find(entity[2u]);
  826. ASSERT_EQ(*it, entity[2u]);
  827. ASSERT_EQ(*(++it), entity[0u]);
  828. ASSERT_EQ(++it, view.end());
  829. }
  830. TEST(ViewMultiStorage, Exclude) {
  831. std::tuple<entt::storage<int>, entt::storage<char>> storage{};
  832. const entt::basic_view view{std::forward_as_tuple(std::get<0>(storage)), std::forward_as_tuple(std::as_const(std::get<1>(storage)))};
  833. const std::array entity{entt::entity{0}, entt::entity{1}, entt::entity{2}, entt::entity{3}};
  834. std::get<0>(storage).emplace(entity[0u], 0);
  835. std::get<0>(storage).emplace(entity[1u], 1);
  836. std::get<1>(storage).emplace(entity[1u]);
  837. std::get<0>(storage).emplace(entity[2u], 2);
  838. std::get<0>(storage).emplace(entity[3u], 3);
  839. std::get<1>(storage).emplace(entity[3u]);
  840. for(const auto entt: view) {
  841. ASSERT_TRUE(entt == entity[0u] || entt == entity[2u]);
  842. if(entt == entity[0u]) {
  843. ASSERT_EQ(view.get<const int>(entity[0u]), 0);
  844. ASSERT_EQ(view.get<0u>(entity[0u]), 0);
  845. } else if(entt == entity[2u]) {
  846. ASSERT_EQ(std::get<0>(view.get(entity[2u])), 2);
  847. }
  848. }
  849. std::get<1>(storage).emplace(entity[0u]);
  850. std::get<1>(storage).emplace(entity[2u]);
  851. std::get<1>(storage).erase(entity[1u]);
  852. std::get<1>(storage).erase(entity[3u]);
  853. for(const auto entt: view) {
  854. ASSERT_TRUE(entt == entity[1u] || entt == entity[3u]);
  855. if(entt == entity[1u]) {
  856. ASSERT_EQ(std::get<0>(view.get(entity[1u])), 1);
  857. } else if(entt == entity[3u]) {
  858. ASSERT_EQ(view.get<const int>(entity[3u]), 3);
  859. ASSERT_EQ(view.get<0u>(entity[3u]), 3);
  860. }
  861. }
  862. }
  863. TEST(ViewMultiStorage, EmptyType) {
  864. std::tuple<entt::storage<int>, entt::storage<test::empty>> storage{};
  865. entt::basic_view view{std::get<0>(storage), std::get<1>(storage)};
  866. const entt::entity entity{0};
  867. std::get<0>(storage).emplace(entity, 3);
  868. std::get<1>(storage).emplace(entity);
  869. view.each([](int value) mutable {
  870. ASSERT_EQ(value, 3);
  871. });
  872. for(auto [entt, value]: view.each()) {
  873. testing::StaticAssertTypeEq<decltype(entt), entt::entity>();
  874. testing::StaticAssertTypeEq<decltype(value), int &>();
  875. ASSERT_EQ(entity, entt);
  876. ASSERT_EQ(value, 3);
  877. }
  878. view.use<1u>();
  879. view.each([](int value) mutable {
  880. ASSERT_EQ(value, 3);
  881. });
  882. view.use<test::empty>();
  883. for(auto [entt, value]: view.each()) {
  884. testing::StaticAssertTypeEq<decltype(entt), entt::entity>();
  885. testing::StaticAssertTypeEq<decltype(value), int &>();
  886. ASSERT_EQ(entity, entt);
  887. ASSERT_EQ(value, 3);
  888. }
  889. }
  890. TEST(ViewMultiStorage, FrontBack) {
  891. std::tuple<entt::storage<int>, entt::storage<char>> storage{};
  892. const entt::basic_view view{std::as_const(std::get<0>(storage)), std::as_const(std::get<1>(storage))};
  893. const std::array entity{entt::entity{0}, entt::entity{1}, entt::entity{2}};
  894. ASSERT_EQ(view.front(), static_cast<entt::entity>(entt::null));
  895. ASSERT_EQ(view.back(), static_cast<entt::entity>(entt::null));
  896. std::get<0>(storage).emplace(entity[0u]);
  897. std::get<0>(storage).emplace(entity[1u]);
  898. std::get<1>(storage).emplace(entity[0u]);
  899. std::get<1>(storage).emplace(entity[1u]);
  900. std::get<1>(storage).emplace(entity[2u]);
  901. ASSERT_EQ(view.front(), entity[1u]);
  902. ASSERT_EQ(view.back(), entity[0u]);
  903. }
  904. TEST(ViewMultiStorage, ExtendedGet) {
  905. using type = decltype(std::declval<entt::basic_view<entt::get_t<entt::storage<int>, entt::storage<test::empty>, entt::storage<char>>, entt::exclude_t<>>>().get({}));
  906. ASSERT_EQ(std::tuple_size_v<type>, 2u);
  907. testing::StaticAssertTypeEq<std::tuple_element_t<0, type>, int &>();
  908. testing::StaticAssertTypeEq<std::tuple_element_t<1, type>, char &>();
  909. }
  910. TEST(ViewMultiStorage, DeductionGuide) {
  911. testing::StaticAssertTypeEq<entt::basic_view<entt::get_t<entt::storage<int>, entt::storage<double>>, entt::exclude_t<>>, decltype(entt::basic_view{std::declval<entt::storage<int> &>(), std::declval<entt::storage<double> &>()})>();
  912. testing::StaticAssertTypeEq<entt::basic_view<entt::get_t<const entt::storage<int>, entt::storage<double>>, entt::exclude_t<>>, decltype(entt::basic_view{std::declval<const entt::storage<int> &>(), std::declval<entt::storage<double> &>()})>();
  913. testing::StaticAssertTypeEq<entt::basic_view<entt::get_t<entt::storage<int>, const entt::storage<double>>, entt::exclude_t<>>, decltype(entt::basic_view{std::declval<entt::storage<int> &>(), std::declval<const entt::storage<double> &>()})>();
  914. testing::StaticAssertTypeEq<entt::basic_view<entt::get_t<const entt::storage<int>, const entt::storage<double>>, entt::exclude_t<>>, decltype(entt::basic_view{std::declval<const entt::storage<int> &>(), std::declval<const entt::storage<double> &>()})>();
  915. testing::StaticAssertTypeEq<entt::basic_view<entt::get_t<entt::storage<int>, entt::storage<test::pointer_stable>>, entt::exclude_t<>>, decltype(entt::basic_view{std::declval<entt::storage<int> &>(), std::declval<entt::storage<test::pointer_stable> &>()})>();
  916. testing::StaticAssertTypeEq<entt::basic_view<entt::get_t<entt::storage<int>, entt::storage<double>>, entt::exclude_t<>>, decltype(entt::basic_view{std::forward_as_tuple(std::declval<entt::storage<int> &>(), std::declval<entt::storage<double> &>()), std::make_tuple()})>();
  917. testing::StaticAssertTypeEq<entt::basic_view<entt::get_t<const entt::storage<int>, entt::storage<double>>, entt::exclude_t<>>, decltype(entt::basic_view{std::forward_as_tuple(std::declval<const entt::storage<int> &>(), std::declval<entt::storage<double> &>())})>();
  918. testing::StaticAssertTypeEq<entt::basic_view<entt::get_t<entt::storage<int>, const entt::storage<double>>, entt::exclude_t<>>, decltype(entt::basic_view{std::forward_as_tuple(std::declval<entt::storage<int> &>(), std::declval<const entt::storage<double> &>())})>();
  919. testing::StaticAssertTypeEq<entt::basic_view<entt::get_t<const entt::storage<int>, const entt::storage<double>>, entt::exclude_t<>>, decltype(entt::basic_view{std::forward_as_tuple(std::declval<const entt::storage<int> &>(), std::declval<const entt::storage<double> &>())})>();
  920. testing::StaticAssertTypeEq<entt::basic_view<entt::get_t<entt::storage<int>, entt::storage<test::pointer_stable>>, entt::exclude_t<>>, decltype(entt::basic_view{std::forward_as_tuple(std::declval<entt::storage<int> &>(), std::declval<entt::storage<test::pointer_stable> &>())})>();
  921. testing::StaticAssertTypeEq<entt::basic_view<entt::get_t<entt::storage<int>>, entt::exclude_t<entt::storage<double>>>, decltype(entt::basic_view{std::forward_as_tuple(std::declval<entt::storage<int> &>()), std::forward_as_tuple(std::declval<entt::storage<double> &>())})>();
  922. testing::StaticAssertTypeEq<entt::basic_view<entt::get_t<const entt::storage<int>>, entt::exclude_t<entt::storage<double>>>, decltype(entt::basic_view{std::forward_as_tuple(std::declval<const entt::storage<int> &>()), std::forward_as_tuple(std::declval<entt::storage<double> &>())})>();
  923. testing::StaticAssertTypeEq<entt::basic_view<entt::get_t<entt::storage<int>>, entt::exclude_t<const entt::storage<double>>>, decltype(entt::basic_view{std::forward_as_tuple(std::declval<entt::storage<int> &>()), std::forward_as_tuple(std::declval<const entt::storage<double> &>())})>();
  924. testing::StaticAssertTypeEq<entt::basic_view<entt::get_t<const entt::storage<int>>, entt::exclude_t<const entt::storage<double>>>, decltype(entt::basic_view{std::forward_as_tuple(std::declval<const entt::storage<int> &>()), std::forward_as_tuple(std::declval<const entt::storage<double> &>())})>();
  925. testing::StaticAssertTypeEq<entt::basic_view<entt::get_t<entt::storage<int>>, entt::exclude_t<entt::storage<test::pointer_stable>>>, decltype(entt::basic_view{std::forward_as_tuple(std::declval<entt::storage<int> &>()), std::forward_as_tuple(std::declval<entt::storage<test::pointer_stable> &>())})>();
  926. }
  927. TEST(ViewMultiStorage, IterableViewAlgorithmCompatibility) {
  928. std::tuple<entt::storage<int>, entt::storage<char>> storage{};
  929. const entt::basic_view view{std::as_const(std::get<0>(storage)), std::as_const(std::get<1>(storage))};
  930. const entt::entity entity{0};
  931. std::get<0>(storage).emplace(entity);
  932. std::get<1>(storage).emplace(entity);
  933. const auto iterable = view.each();
  934. const auto it = std::find_if(iterable.begin(), iterable.end(), [entity](auto args) { return std::get<0>(args) == entity; });
  935. ASSERT_EQ(std::get<0>(*it), entity);
  936. }
  937. TEST(ViewMultiStorage, StableType) {
  938. std::tuple<entt::storage<int>, entt::storage<test::pointer_stable>> storage{};
  939. entt::basic_view view{std::get<0>(storage), std::get<1>(storage)};
  940. const std::array entity{entt::entity{1}, entt::entity{3}};
  941. std::get<0>(storage).emplace(entity[0u]);
  942. std::get<0>(storage).emplace(entity[1u]);
  943. std::get<0>(storage).erase(entity[0u]);
  944. std::get<1>(storage).emplace(entity[0u]);
  945. std::get<1>(storage).emplace(entity[1u]);
  946. std::get<1>(storage).erase(entity[0u]);
  947. ASSERT_EQ(view.size_hint(), 1u);
  948. view.use<test::pointer_stable>();
  949. ASSERT_EQ(view.size_hint(), 2u);
  950. ASSERT_FALSE(view.contains(entity[0u]));
  951. ASSERT_TRUE(view.contains(entity[1u]));
  952. ASSERT_EQ(view.front(), entity[1u]);
  953. ASSERT_EQ(view.back(), entity[1u]);
  954. ASSERT_EQ(*view.begin(), entity[1u]);
  955. ASSERT_EQ(++view.begin(), view.end());
  956. view.each([&entity](const auto entt, int, test::pointer_stable) {
  957. ASSERT_EQ(entity[1u], entt);
  958. });
  959. view.each([check = true](int, test::pointer_stable) mutable {
  960. ASSERT_TRUE(check);
  961. check = false;
  962. });
  963. for(auto [entt, iv, st]: view.each()) {
  964. testing::StaticAssertTypeEq<decltype(entt), entt::entity>();
  965. testing::StaticAssertTypeEq<decltype(iv), int &>();
  966. testing::StaticAssertTypeEq<decltype(st), test::pointer_stable &>();
  967. ASSERT_EQ(entity[1u], entt);
  968. }
  969. std::get<1>(storage).compact();
  970. ASSERT_EQ(view.size_hint(), 1u);
  971. }
  972. TEST(ViewMultiStorage, StableTypeWithExclude) {
  973. std::tuple<entt::storage<test::pointer_stable>, entt::storage<int>> storage{};
  974. const entt::basic_view view{std::forward_as_tuple(std::get<0>(storage)), std::forward_as_tuple(std::get<1>(storage))};
  975. const std::array entity{entt::entity{1}, entt::entity{3}};
  976. const entt::entity tombstone = entt::tombstone;
  977. std::get<0>(storage).emplace(entity[0u], 0);
  978. std::get<0>(storage).emplace(entity[1u], 4);
  979. std::get<1>(storage).emplace(entity[0u]);
  980. ASSERT_EQ(view.size_hint(), 2u);
  981. ASSERT_FALSE(view.contains(entity[0u]));
  982. ASSERT_TRUE(view.contains(entity[1u]));
  983. std::get<0>(storage).erase(entity[0u]);
  984. std::get<1>(storage).erase(entity[0u]);
  985. ASSERT_EQ(view.size_hint(), 2u);
  986. ASSERT_FALSE(view.contains(entity[0u]));
  987. ASSERT_TRUE(view.contains(entity[1u]));
  988. for(auto entt: view) {
  989. ASSERT_NE(entt, tombstone);
  990. ASSERT_EQ(entt, entity[1u]);
  991. }
  992. for(auto [entt, comp]: view.each()) {
  993. ASSERT_NE(entt, tombstone);
  994. ASSERT_EQ(entt, entity[1u]);
  995. ASSERT_EQ(comp.value, 4);
  996. }
  997. view.each([&entity, tombstone](const auto entt, auto &&...) {
  998. ASSERT_NE(entt, tombstone);
  999. ASSERT_EQ(entt, entity[1u]);
  1000. });
  1001. }
  1002. TEST(ViewMultiStorage, SameStorageTypes) {
  1003. std::tuple<entt::storage<int>, entt::storage<int>> storage{};
  1004. entt::basic_view view{std::get<0>(storage), std::get<1>(storage)};
  1005. const std::array entity{entt::entity{1}, entt::entity{3}};
  1006. std::get<0>(storage).emplace(entity[0u], 2);
  1007. std::get<1>(storage).emplace(entity[0u], 3);
  1008. std::get<1>(storage).emplace(entity[1u], 1);
  1009. ASSERT_TRUE(view.contains(entity[0u]));
  1010. ASSERT_FALSE(view.contains(entity[1u]));
  1011. ASSERT_EQ((view.get<0u, 1u>(entity[0u])), (std::make_tuple(2, 3)));
  1012. ASSERT_EQ(view.get<1u>(entity[0u]), 3);
  1013. for(auto entt: view) {
  1014. ASSERT_EQ(entt, entity[0u]);
  1015. }
  1016. view.each([&](auto entt, auto &&first, auto &&second) {
  1017. ASSERT_EQ(entt, entity[0u]);
  1018. ASSERT_EQ(first, 2);
  1019. ASSERT_EQ(second, 3);
  1020. });
  1021. for(auto [entt, first, second]: view.each()) {
  1022. ASSERT_EQ(entt, entity[0u]);
  1023. ASSERT_EQ(first, 2);
  1024. ASSERT_EQ(second, 3);
  1025. }
  1026. ASSERT_EQ(view.handle(), &std::get<0>(storage));
  1027. view.use<1u>();
  1028. ASSERT_EQ(view.handle(), &std::get<1>(storage));
  1029. }
  1030. TEST(ViewMultiStorage, Storage) {
  1031. std::tuple<entt::storage<int>, entt::storage<char>, entt::storage<double>, entt::storage<float>> storage{};
  1032. entt::basic_view view{std::forward_as_tuple(std::get<0>(storage), std::as_const(std::get<1>(storage))), std::forward_as_tuple(std::get<2>(storage), std::as_const(std::get<3>(storage)))};
  1033. const entt::entity entity{0};
  1034. testing::StaticAssertTypeEq<decltype(view.storage<0u>()), entt::storage<int> *>();
  1035. testing::StaticAssertTypeEq<decltype(view.storage<int>()), entt::storage<int> *>();
  1036. testing::StaticAssertTypeEq<decltype(view.storage<const int>()), entt::storage<int> *>();
  1037. testing::StaticAssertTypeEq<decltype(view.storage<1u>()), const entt::storage<char> *>();
  1038. testing::StaticAssertTypeEq<decltype(view.storage<char>()), const entt::storage<char> *>();
  1039. testing::StaticAssertTypeEq<decltype(view.storage<const char>()), const entt::storage<char> *>();
  1040. testing::StaticAssertTypeEq<decltype(view.storage<2u>()), entt::storage<double> *>();
  1041. testing::StaticAssertTypeEq<decltype(view.storage<double>()), entt::storage<double> *>();
  1042. testing::StaticAssertTypeEq<decltype(view.storage<const double>()), entt::storage<double> *>();
  1043. testing::StaticAssertTypeEq<decltype(view.storage<3u>()), const entt::storage<float> *>();
  1044. testing::StaticAssertTypeEq<decltype(view.storage<float>()), const entt::storage<float> *>();
  1045. testing::StaticAssertTypeEq<decltype(view.storage<const float>()), const entt::storage<float> *>();
  1046. ASSERT_TRUE(view);
  1047. ASSERT_NE(view.storage<int>(), nullptr);
  1048. ASSERT_NE(view.storage<1u>(), nullptr);
  1049. ASSERT_NE(view.storage<double>(), nullptr);
  1050. ASSERT_NE(view.storage<3u>(), nullptr);
  1051. ASSERT_EQ(view.size_hint(), 0u);
  1052. view.storage<int>()->emplace(entity);
  1053. view.storage<double>()->emplace(entity);
  1054. std::get<1>(storage).emplace(entity);
  1055. std::get<3>(storage).emplace(entity);
  1056. ASSERT_EQ(view.size_hint(), 1u);
  1057. ASSERT_EQ(view.begin(), view.end());
  1058. ASSERT_TRUE(view.storage<int>()->contains(entity));
  1059. ASSERT_TRUE(view.storage<const char>()->contains(entity));
  1060. ASSERT_TRUE(view.storage<double>()->contains(entity));
  1061. ASSERT_TRUE(view.storage<const float>()->contains(entity));
  1062. view.storage<double>()->erase(entity);
  1063. std::get<3>(storage).erase(entity);
  1064. ASSERT_EQ(view.size_hint(), 1u);
  1065. ASSERT_NE(view.begin(), view.end());
  1066. ASSERT_TRUE(view.storage<const int>()->contains(entity));
  1067. ASSERT_TRUE(view.storage<char>()->contains(entity));
  1068. ASSERT_FALSE(view.storage<const double>()->contains(entity));
  1069. ASSERT_FALSE(view.storage<float>()->contains(entity));
  1070. view.storage<0u>()->erase(entity);
  1071. ASSERT_EQ(view.size_hint(), 0u);
  1072. ASSERT_EQ(view.begin(), view.end());
  1073. ASSERT_FALSE(view.storage<0u>()->contains(entity));
  1074. ASSERT_TRUE(view.storage<1u>()->contains(entity));
  1075. ASSERT_FALSE(view.storage<2u>()->contains(entity));
  1076. ASSERT_FALSE(view.storage<3u>()->contains(entity));
  1077. view = {};
  1078. ASSERT_FALSE(view);
  1079. ASSERT_EQ(view.storage<0u>(), nullptr);
  1080. ASSERT_EQ(view.storage<const char>(), nullptr);
  1081. ASSERT_EQ(view.storage<2u>(), nullptr);
  1082. ASSERT_EQ(view.storage<const float>(), nullptr);
  1083. }
  1084. TEST(ViewMultiStorage, SwapStorage) {
  1085. std::tuple<entt::storage<int>, entt::storage<char>, entt::storage<int>, entt::storage<char>> storage{};
  1086. entt::basic_view<entt::get_t<entt::storage<int>>, entt::exclude_t<const entt::storage<char>>> view{};
  1087. const entt::entity entity{0};
  1088. ASSERT_FALSE(view);
  1089. ASSERT_EQ(view.storage<0u>(), nullptr);
  1090. ASSERT_EQ(view.storage<const char>(), nullptr);
  1091. std::get<0>(storage).emplace(entity);
  1092. std::get<1>(storage).emplace(entity);
  1093. view.storage(std::get<0>(storage));
  1094. view.storage<1u>(std::get<1>(storage));
  1095. ASSERT_TRUE(view);
  1096. ASSERT_NE(view.storage<int>(), nullptr);
  1097. ASSERT_NE(view.storage<1u>(), nullptr);
  1098. ASSERT_EQ(view.size_hint(), 1u);
  1099. ASSERT_FALSE(view.contains(entity));
  1100. view.storage(std::get<3>(storage));
  1101. ASSERT_EQ(view.size_hint(), 1u);
  1102. ASSERT_TRUE(view.contains(entity));
  1103. view.storage(std::get<2>(storage));
  1104. ASSERT_EQ(view.size_hint(), 0u);
  1105. }
  1106. TEST(ViewMultiStorage, StorageEntity) {
  1107. std::tuple<entt::storage<entt::entity>, entt::storage<char>> storage{};
  1108. const entt::basic_view view{std::get<0>(storage), std::get<1>(storage)};
  1109. const std::array entity{std::get<0>(storage).generate(), std::get<0>(storage).generate()};
  1110. std::get<1>(storage).emplace(entity[0u]);
  1111. std::get<1>(storage).emplace(entity[1u]);
  1112. std::get<1>(storage).erase(entity[0u]);
  1113. std::get<0>(storage).erase(entity[0u]);
  1114. std::get<0>(storage).bump(entity[0u]);
  1115. ASSERT_FALSE(view.contains(entity[0u]));
  1116. ASSERT_TRUE(view.contains(entity[1u]));
  1117. ASSERT_EQ(view.front(), entity[1u]);
  1118. ASSERT_EQ(view.back(), entity[1u]);
  1119. ASSERT_EQ(view.size_hint(), 1u);
  1120. ASSERT_NE(view.begin(), view.end());
  1121. ASSERT_EQ(std::distance(view.begin(), view.end()), 1);
  1122. ASSERT_EQ(*view.begin(), entity[1u]);
  1123. for(auto elem: view.each()) {
  1124. ASSERT_EQ(std::get<0>(elem), entity[1u]);
  1125. }
  1126. view.each([&entity](auto entt, auto &&...) {
  1127. ASSERT_EQ(entt, entity[1u]);
  1128. });
  1129. }
  1130. TEST(ViewMultiStorage, StorageEntityWithExclude) {
  1131. std::tuple<entt::storage<entt::entity>, entt::storage<int>, entt::storage<char>> storage{};
  1132. const entt::basic_view view{std::forward_as_tuple(std::get<0>(storage), std::get<1>(storage)), std::forward_as_tuple(std::get<2>(storage))};
  1133. const std::array entity{std::get<0>(storage).generate(), std::get<0>(storage).generate(), std::get<0>(storage).generate()};
  1134. std::get<1>(storage).emplace(entity[0u]);
  1135. std::get<1>(storage).emplace(entity[1u]);
  1136. std::get<1>(storage).emplace(entity[2u]);
  1137. std::get<2>(storage).emplace(entity[2u]);
  1138. std::get<1>(storage).erase(entity[0u]);
  1139. std::get<0>(storage).erase(entity[0u]);
  1140. std::get<0>(storage).bump(entity[0u]);
  1141. ASSERT_FALSE(view.contains(entity[0u]));
  1142. ASSERT_TRUE(view.contains(entity[1u]));
  1143. ASSERT_FALSE(view.contains(entity[2u]));
  1144. ASSERT_EQ(view.front(), entity[1u]);
  1145. ASSERT_EQ(view.back(), entity[1u]);
  1146. ASSERT_EQ(view.size_hint(), 2u);
  1147. ASSERT_NE(view.begin(), view.end());
  1148. ASSERT_EQ(std::distance(view.begin(), view.end()), 1);
  1149. ASSERT_EQ(*view.begin(), entity[1u]);
  1150. for(auto elem: view.each()) {
  1151. ASSERT_EQ(std::get<0>(elem), entity[1u]);
  1152. }
  1153. view.each([&entity](auto entt, auto &&...) {
  1154. ASSERT_EQ(entt, entity[1u]);
  1155. });
  1156. }
  1157. TEST(ViewMultiStorage, StorageEntityExcludeOnly) {
  1158. std::tuple<entt::storage<entt::entity>, entt::storage<int>> storage{};
  1159. const entt::basic_view view{std::forward_as_tuple(std::get<0>(storage)), std::forward_as_tuple(std::get<1>(storage))};
  1160. const std::array entity{std::get<0>(storage).generate(), std::get<0>(storage).generate(), std::get<0>(storage).generate()};
  1161. std::get<1>(storage).emplace(entity[2u]);
  1162. std::get<0>(storage).erase(entity[0u]);
  1163. std::get<0>(storage).bump(entity[0u]);
  1164. ASSERT_FALSE(view.contains(entity[0u]));
  1165. ASSERT_TRUE(view.contains(entity[1u]));
  1166. ASSERT_FALSE(view.contains(entity[2u]));
  1167. ASSERT_EQ(view.front(), entity[1u]);
  1168. ASSERT_EQ(view.back(), entity[1u]);
  1169. ASSERT_EQ(view.size_hint(), 2u);
  1170. ASSERT_NE(view.begin(), view.end());
  1171. ASSERT_EQ(std::distance(view.begin(), view.end()), 1);
  1172. ASSERT_EQ(*view.begin(), entity[1u]);
  1173. for(auto [entt]: view.each()) {
  1174. ASSERT_EQ(entt, entity[1u]);
  1175. }
  1176. view.each([&entity](auto entt) {
  1177. ASSERT_EQ(entt, entity[1u]);
  1178. });
  1179. }
  1180. TEST(View, Pipe) {
  1181. std::tuple<entt::storage<int>, entt::storage<double>, entt::storage<test::empty>, entt::storage<test::pointer_stable>, entt::storage<float>> storage{};
  1182. const std::array entity{entt::entity{1}, entt::entity{3}};
  1183. std::get<0>(storage).emplace(entity[0u]);
  1184. std::get<1>(storage).emplace(entity[0u]);
  1185. std::get<2>(storage).emplace(entity[0u]);
  1186. std::get<0>(storage).emplace(entity[1u]);
  1187. std::get<3>(storage).emplace(entity[1u]);
  1188. entt::basic_view view1{std::forward_as_tuple(std::get<0>(storage)), std::forward_as_tuple(std::as_const(std::get<1>(storage)))};
  1189. const entt::basic_view view2{std::forward_as_tuple(std::as_const(std::get<0>(storage))), std::forward_as_tuple(std::get<4>(storage))};
  1190. entt::basic_view view3{std::get<2>(storage)};
  1191. const entt::basic_view view4{std::as_const(std::get<3>(storage))};
  1192. testing::StaticAssertTypeEq<decltype(view1 | std::get<2>(storage)), decltype(view1 | view3)>();
  1193. testing::StaticAssertTypeEq<decltype(view1 | std::get<3>(std::as_const(storage))), decltype(view1 | view4)>();
  1194. testing::StaticAssertTypeEq<decltype(view1 | std::get<2>(storage) | view4), decltype(view1 | view3 | view4)>();
  1195. testing::StaticAssertTypeEq<entt::basic_view<entt::get_t<entt::storage<int>, const entt::storage<int>>, entt::exclude_t<const entt::storage<double>, entt::storage<float>>>, decltype(view1 | view2)>();
  1196. testing::StaticAssertTypeEq<entt::basic_view<entt::get_t<const entt::storage<int>, entt::storage<int>>, entt::exclude_t<entt::storage<float>, const entt::storage<double>>>, decltype(view2 | view1)>();
  1197. testing::StaticAssertTypeEq<decltype((view3 | view2) | view1), decltype(view3 | (view2 | view1))>();
  1198. ASSERT_FALSE((view1 | view2).contains(entity[0u]));
  1199. ASSERT_TRUE((view1 | view2).contains(entity[1u]));
  1200. ASSERT_TRUE((view3 | view2).contains(entity[0u]));
  1201. ASSERT_FALSE((view3 | view2).contains(entity[1u]));
  1202. ASSERT_FALSE((view1 | view2 | view3).contains(entity[0u]));
  1203. ASSERT_FALSE((view1 | view2 | view3).contains(entity[1u]));
  1204. ASSERT_FALSE((view1 | view4 | view2).contains(entity[0u]));
  1205. ASSERT_TRUE((view1 | view4 | view2).contains(entity[1u]));
  1206. view1 = {};
  1207. view3 = {};
  1208. ASSERT_FALSE(view1);
  1209. ASSERT_TRUE(view2);
  1210. ASSERT_FALSE(view3);
  1211. ASSERT_TRUE(view4);
  1212. auto pack14 = view1 | view4;
  1213. auto pack32 = view3 | view2;
  1214. ASSERT_FALSE(pack14);
  1215. ASSERT_FALSE(pack32);
  1216. ASSERT_EQ(pack14.storage<int>(), nullptr);
  1217. ASSERT_EQ(pack14.storage<const double>(), nullptr);
  1218. ASSERT_NE(pack14.storage<test::pointer_stable>(), nullptr);
  1219. ASSERT_EQ(pack32.storage<test::empty>(), nullptr);
  1220. ASSERT_NE(pack32.storage<const int>(), nullptr);
  1221. ASSERT_NE(pack32.storage<float>(), nullptr);
  1222. }
  1223. TEST(View, PipeNoFilter) {
  1224. std::tuple<entt::storage<int>, entt::storage<double>> storage{};
  1225. const std::array entity{entt::entity{1}, entt::entity{3}};
  1226. std::get<0>(storage).emplace(entity[0u]);
  1227. std::get<1>(storage).emplace(entity[0u]);
  1228. std::get<0>(storage).emplace(entity[1u]);
  1229. const entt::basic_view view1{std::forward_as_tuple(std::get<0>(storage))};
  1230. const entt::basic_view view2{std::forward_as_tuple(std::as_const(std::get<1>(storage)))};
  1231. ASSERT_TRUE((view1 | view2).contains(entity[0u]));
  1232. ASSERT_FALSE((view1 | view2).contains(entity[1u]));
  1233. }
  1234. TEST(View, PipeWithPlaceholder) {
  1235. entt::storage<void> storage{};
  1236. const entt::entity entity{0};
  1237. const entt::basic_view view{storage};
  1238. entt::basic_view<entt::get_t<entt::storage<void>>, entt::exclude_t<entt::storage<int>>> other{};
  1239. other.storage(storage);
  1240. ASSERT_FALSE(view.contains(entity));
  1241. ASSERT_FALSE(other.contains(entity));
  1242. auto pack = view | other;
  1243. ASSERT_FALSE(pack.contains(entity));
  1244. storage.emplace(entity);
  1245. ASSERT_TRUE(view.contains(entity));
  1246. ASSERT_TRUE(other.contains(entity));
  1247. pack = view | other;
  1248. ASSERT_TRUE(pack.contains(entity));
  1249. }