diff --git a/TODO b/TODO index 2cafa529f4..c72e36002c 100644 --- a/TODO +++ b/TODO @@ -33,4 +33,5 @@ TODO * multi component registry::remove and some others? * range based registry::remove and some others? * nested groups: AB/ABC/ABCD/... (hints: sort, check functions) + - doc, test * ::size_type - c'mon diff --git a/src/entt/entity/group.hpp b/src/entt/entity/group.hpp index c7ebb7b456..904b378c34 100644 --- a/src/entt/entity/group.hpp +++ b/src/entt/entity/group.hpp @@ -63,11 +63,10 @@ class basic_group; * * @tparam Entity A valid entity type (see entt_traits for more details). * @tparam Exclude Types of components used to filter the group. - * @tparam Get Type of component observed by the group. - * @tparam Other Other types of components observed by the group. + * @tparam Get Type of components observed by the group. */ -template -class basic_group, get_t> { +template +class basic_group, get_t> { /*! @brief A registry is allowed to create groups. */ friend class basic_registry; @@ -75,9 +74,9 @@ class basic_group, get_t> { using pool_type = std::conditional_t, const storage>, storage>; // we could use pool_type *..., but vs complains about it and refuses to compile for unknown reasons (most likely a bug) - basic_group(sparse_set *ref, storage> *get, storage> *... other) ENTT_NOEXCEPT + basic_group(sparse_set *ref, storage> *... get) ENTT_NOEXCEPT : handler{ref}, - pools{get, other...} + pools{get...} {} template @@ -93,9 +92,9 @@ class basic_group, get_t> { public: /*! @brief Underlying entity identifier. */ - using entity_type = typename sparse_set::entity_type; + using entity_type = Entity; /*! @brief Unsigned integer type. */ - using size_type = typename sparse_set::size_type; + using size_type = std::size_t; /*! @brief Input iterator type. */ using iterator_type = typename sparse_set::iterator_type; @@ -306,8 +305,8 @@ class basic_group, get_t> { * forms: * * @code{.cpp} - * void(const entity_type, Get &, Other &...); - * void(Get &, Other &...); + * void(const entity_type, Get &...); + * void(Get &...); * @endcode * * @note @@ -320,7 +319,7 @@ class basic_group, get_t> { */ template void each(Func func) const { - traverse(std::move(func), type_list{}); + traverse(std::move(func), type_list{}); } /** @@ -345,9 +344,8 @@ class basic_group, get_t> { */ template void less(Func func) const { - using get_type_list = std::conditional_t, type_list<>, type_list>; - using other_type_list = type_list_cat_t, type_list<>, type_list>...>; - traverse(std::move(func), type_list_cat_t{}); + using get_type_list = type_list_cat_t, type_list<>, type_list>...>; + traverse(std::move(func), get_type_list{}); } /** @@ -430,7 +428,7 @@ class basic_group, get_t> { private: sparse_set *handler; - const std::tuple *, pool_type *...> pools; + const std::tuple *...> pools; }; @@ -479,11 +477,10 @@ class basic_group, get_t> { * @tparam Entity A valid entity type (see entt_traits for more details). * @tparam Exclude Types of components used to filter the group. * @tparam Get Types of components observed by the group. - * @tparam Owned Type of component owned by the group. - * @tparam Other Other types of components owned by the group. + * @tparam Owned Types of components owned by the group. */ -template -class basic_group, get_t, Owned, Other...> { +template +class basic_group, get_t, Owned...> { /*! @brief A registry is allowed to create groups. */ friend class basic_registry; @@ -494,15 +491,16 @@ class basic_group, get_t, Owned, Other...> using component_iterator_type = decltype(std::declval>().begin()); // we could use pool_type *..., but vs complains about it and refuses to compile for unknown reasons (most likely a bug) - basic_group(const typename basic_registry::size_type *sz, storage> *owned, storage> *... other, storage> *... get) ENTT_NOEXCEPT - : length{sz}, - pools{owned, other..., get...} + basic_group(const std::size_t *ref, const std::size_t *extent, storage> *... owned, storage> *... get) ENTT_NOEXCEPT + : pools{owned..., get...}, + length{extent}, + super{ref} {} template void traverse(Func func, type_list, type_list) const { [[maybe_unused]] auto raw = std::make_tuple((std::get *>(pools)->end() - *length)...); - [[maybe_unused]] auto data = std::get *>(pools)->sparse_set::end() - *length; + [[maybe_unused]] auto data = std::get<0>(pools)->sparse_set::end() - *length; for(auto next = *length; next; --next) { if constexpr(std::is_invocable_v({}))..., decltype(get({}))...>) { @@ -521,9 +519,9 @@ class basic_group, get_t, Owned, Other...> public: /*! @brief Underlying entity identifier. */ - using entity_type = typename sparse_set::entity_type; + using entity_type = Entity; /*! @brief Unsigned integer type. */ - using size_type = typename sparse_set::size_type; + using size_type = std::size_t; /*! @brief Input iterator type. */ using iterator_type = typename sparse_set::iterator_type; @@ -618,7 +616,7 @@ class basic_group, get_t, Owned, Other...> * @return A pointer to the array of entities. */ const entity_type * data() const ENTT_NOEXCEPT { - return std::get *>(pools)->data(); + return std::get<0>(pools)->data(); } /** @@ -636,7 +634,7 @@ class basic_group, get_t, Owned, Other...> * @return An iterator to the first entity that has the given components. */ iterator_type begin() const ENTT_NOEXCEPT { - return std::get *>(pools)->sparse_set::end() - *length; + return std::get<0>(pools)->sparse_set::end() - *length; } /** @@ -655,7 +653,7 @@ class basic_group, get_t, Owned, Other...> * given components. */ iterator_type end() const ENTT_NOEXCEPT { - return std::get *>(pools)->sparse_set::end(); + return std::get<0>(pools)->sparse_set::end(); } /** @@ -665,7 +663,7 @@ class basic_group, get_t, Owned, Other...> * iterator otherwise. */ iterator_type find(const entity_type entt) const ENTT_NOEXCEPT { - const auto it = std::get *>(pools)->find(entt); + const auto it = std::get<0>(pools)->find(entt); return it != end() && it >= begin() && *it == entt ? it : end(); } @@ -726,8 +724,8 @@ class basic_group, get_t, Owned, Other...> * forms: * * @code{.cpp} - * void(const entity_type, Owned &, Other &..., Get &...); - * void(Owned &, Other &..., Get &...); + * void(const entity_type, Owned &..., Get &...); + * void(Owned &..., Get &...); * @endcode * * @note @@ -740,7 +738,7 @@ class basic_group, get_t, Owned, Other...> */ template void each(Func func) const { - traverse(std::move(func), type_list{}, type_list{}); + traverse(std::move(func), type_list{}, type_list{}); } /** @@ -765,10 +763,18 @@ class basic_group, get_t, Owned, Other...> */ template void less(Func func) const { - using owned_type_list = std::conditional_t, type_list<>, type_list>; - using other_type_list = type_list_cat_t, type_list<>, type_list>...>; + using owned_type_list = type_list_cat_t, type_list<>, type_list>...>; using get_type_list = type_list_cat_t, type_list<>, type_list>...>; - traverse(std::move(func), type_list_cat_t{}, get_type_list{}); + traverse(std::move(func), owned_type_list{}, get_type_list{}); + } + + /** + * @brief Checks whether the group can be sorted. + * @return True if the group can be sorted, false otherwise. + */ + bool sortable() const ENTT_NOEXCEPT { + constexpr auto size = sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude); + return *super == size; } /** @@ -815,7 +821,8 @@ class basic_group, get_t, Owned, Other...> */ template void sort(Compare compare, Sort algo = Sort{}, Args &&... args) { - auto *cpool = std::get *>(pools); + ENTT_ASSERT(sortable()); + auto *cpool = std::get<0>(pools); if constexpr(sizeof...(Component) == 0) { static_assert(std::is_invocable_v); @@ -830,16 +837,19 @@ class basic_group, get_t, Owned, Other...> }, std::move(algo), std::forward(args)...); } - for(auto next = *length; next; --next) { - const auto pos = next - 1; - [[maybe_unused]] const auto entt = cpool->data()[pos]; - (std::get *>(pools)->swap(std::get *>(pools)->data()[pos], entt), ...); - } + [](std::size_t length, auto *cpool, auto *... other) { + for(auto next = length; next; --next) { + const auto pos = next - 1; + [[maybe_unused]] const auto entt = cpool->data()[pos]; + (other->swap(other->data()[pos], entt), ...); + } + }(*length, std::get *>(pools)...); } private: - const typename basic_registry::size_type *length; - const std::tuple *, pool_type *..., pool_type *...> pools; + const std::tuple *..., pool_type *...> pools; + const size_type *length; + const size_type *super; }; diff --git a/src/entt/entity/registry.hpp b/src/entt/entity/registry.hpp index f1aae9e9db..97d77add47 100644 --- a/src/entt/entity/registry.hpp +++ b/src/entt/entity/registry.hpp @@ -48,7 +48,7 @@ class basic_registry { template struct pool_handler: storage { - std::size_t *owned; + std::size_t super{}; pool_handler() ENTT_NOEXCEPT = default; @@ -201,11 +201,11 @@ class basic_registry { }; struct group_data { - const std::size_t extent[3]; + std::size_t extent[3]; std::unique_ptr group; - bool(* const owned)(const component) ENTT_NOEXCEPT; - bool(* const get)(const component) ENTT_NOEXCEPT; - bool(* const exclude)(const component) ENTT_NOEXCEPT; + bool(* owned)(const component) ENTT_NOEXCEPT; + bool(* get)(const component) ENTT_NOEXCEPT; + bool(* exclude)(const component) ENTT_NOEXCEPT; }; struct ctx_variable { @@ -323,7 +323,7 @@ class basic_registry { /*! @brief Underlying version type. */ using version_type = typename traits_type::version_type; /*! @brief Unsigned integer type. */ - using size_type = typename sparse_set::size_type; + using size_type = std::size_t; /*! @brief Default constructor. */ basic_registry() ENTT_NOEXCEPT = default; @@ -1088,12 +1088,9 @@ class basic_registry { */ template void sort(Compare compare, Sort algo = Sort{}, Args &&... args) { - if(auto *cpool = assure(); cpool->owned) { - const auto last = cpool->end() - *cpool->owned; - cpool->sort(cpool->begin(), last, std::move(compare), std::move(algo), std::forward(args)...); - } else { - cpool->sort(cpool->begin(), cpool->end(), std::move(compare), std::move(algo), std::forward(args)...); - } + auto *cpool = assure(); + ENTT_ASSERT(!cpool->super); + cpool->sort(cpool->begin(), cpool->end(), std::move(compare), std::move(algo), std::forward(args)...); } /** @@ -1133,8 +1130,9 @@ class basic_registry { */ template void sort() { - ENTT_ASSERT(!owned()); - assure()->respect(*assure()); + auto *cpool = assure(); + ENTT_ASSERT(!cpool->super); + cpool->respect(*assure()); } /** @@ -1322,17 +1320,6 @@ class basic_registry { return const_cast(this)->view(exclude); } - /** - * @brief Checks whether a given component belongs to a group. - * @tparam Component Type of component in which one is interested. - * @return True if the component belongs to a group, false otherwise. - */ - template - bool owned() const ENTT_NOEXCEPT { - const auto *cpool = pool(); - return cpool && cpool->owned; - } - /** * @brief Returns a group for the given components. * @@ -1366,6 +1353,8 @@ class basic_registry { static_assert(sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude) > 1); using handler_type = group_handler, get_t, Owned...>; + + [[maybe_unused]] constexpr auto size = sizeof...(Owned) + sizeof...(Get) + sizeof...(Exclude); const auto cpools = std::make_tuple(assure()..., assure()..., assure()...); const std::size_t extent[3]{sizeof...(Owned), sizeof...(Get), sizeof...(Exclude)}; handler_type *curr = nullptr; @@ -1381,27 +1370,48 @@ class basic_registry { } if(!curr) { - groups.push_back(group_data{ + void *maybe_valid_if = nullptr; + void *discard_if = nullptr; + + group_data gdata{ { sizeof...(Owned), sizeof...(Get), sizeof...(Exclude) }, decltype(group_data::group){new handler_type{cpools}, [](void *gptr) { delete static_cast(gptr); }}, [](const component ctype) ENTT_NOEXCEPT { return ((ctype == type()) || ...); }, [](const component ctype) ENTT_NOEXCEPT { return ((ctype == type()) || ...); }, [](const component ctype) ENTT_NOEXCEPT { return ((ctype == type()) || ...); } - }); + }; - curr = static_cast(groups.back().group.get()); + if constexpr(sizeof...(Owned) == 0) { + curr = static_cast(groups.emplace_back(std::move(gdata)).group.get()); + } else { + ENTT_ASSERT(std::all_of(groups.cbegin(), groups.cend(), [&extent](const auto &gdata) { + const std::size_t diff[3]{ (0u + ... + gdata.owned(type())), (0u + ... + gdata.get(type())), (0u + ... + gdata.exclude(type())) }; + return !diff[0] || ((std::equal(std::begin(diff), std::end(diff), extent) || std::equal(std::begin(diff), std::end(diff), gdata.extent))); + })); + + const auto next = std::find_if_not(groups.cbegin(), groups.cend(), [&size](const auto &gdata) { + const std::size_t diff = (0u + ... + gdata.owned(type())); + return !diff || (size < (gdata.extent[0] + gdata.extent[1] + gdata.extent[2])); + }); + + const auto prev = std::find_if(std::reverse_iterator(next), groups.crend(), [](const auto &gdata) { + return (0u + ... + gdata.owned(type())); + }); - ENTT_ASSERT((!std::get *>(cpools)->owned && ...)); - ((std::get *>(cpools)->owned = &curr->owned), ...); + maybe_valid_if = (next == groups.cend() ? nullptr : next->group.get()); + discard_if = (prev == groups.crend() ? nullptr : prev->group.get()); + curr = static_cast(groups.insert(next, std::move(gdata))->group.get()); + } - (std::get *>(cpools)->on_construct().template connect<&handler_type::template maybe_valid_if>(*curr), ...); - (std::get *>(cpools)->on_destroy().template connect<&handler_type::discard_if>(*curr), ...); + ((std::get *>(cpools)->super = std::max(std::get *>(cpools)->super, size)), ...); - (std::get *>(cpools)->on_construct().template connect<&handler_type::template maybe_valid_if>(*curr), ...); - (std::get *>(cpools)->on_destroy().template connect<&handler_type::discard_if>(*curr), ...); + (std::get *>(cpools)->on_construct().before(maybe_valid_if).template connect<&handler_type::template maybe_valid_if>(*curr), ...); + (std::get *>(cpools)->on_construct().before(maybe_valid_if).template connect<&handler_type::template maybe_valid_if>(*curr), ...); + (std::get *>(cpools)->on_destroy().before(maybe_valid_if).template connect<&handler_type::template maybe_valid_if>(*curr), ...); - (std::get *>(cpools)->on_destroy().template connect<&handler_type::template maybe_valid_if>(*curr), ...); - (std::get *>(cpools)->on_construct().template connect<&handler_type::discard_if>(*curr), ...); + (std::get *>(cpools)->on_destroy().before(discard_if).template connect<&handler_type::discard_if>(*curr), ...); + (std::get *>(cpools)->on_destroy().before(discard_if).template connect<&handler_type::discard_if>(*curr), ...); + (std::get *>(cpools)->on_construct().before(discard_if).template connect<&handler_type::discard_if>(*curr), ...); const auto *cpool = std::min({ static_cast *>(std::get *>(cpools))..., @@ -1419,8 +1429,10 @@ class basic_registry { if constexpr(sizeof...(Owned) == 0) { curr->set.construct(entity); } else { - const auto pos = curr->owned++; - (std::get *>(cpools)->swap(std::get *>(cpools)->data()[pos], entity), ...); + if(!(std::get<0>(cpools)->index(entity) < curr->owned)) { + const auto pos = curr->owned++; + (std::get *>(cpools)->swap(std::get *>(cpools)->data()[pos], entity), ...); + } } } }); @@ -1429,7 +1441,7 @@ class basic_registry { if constexpr(sizeof...(Owned) == 0) { return { &curr->set, std::get *>(cpools)... }; } else { - return { &curr->owned, std::get *>(cpools)... , std::get *>(cpools)... }; + return { &std::get<0>(cpools)->super, &curr->owned, std::get *>(cpools)... , std::get *>(cpools)... }; } } diff --git a/test/entt/entity/registry.cpp b/test/entt/entity/registry.cpp index 303fae7610..27fe05e12b 100644 --- a/test/entt/entity/registry.cpp +++ b/test/entt/entity/registry.cpp @@ -321,9 +321,9 @@ TEST(Registry, Each) { entt::registry::size_type match; registry.create(); - registry.assign(registry.create()); + registry.create(); registry.create(); - registry.assign(registry.create()); + registry.create(); registry.create(); tot = 0u; @@ -372,9 +372,9 @@ TEST(Registry, Orphans) { entt::registry registry; entt::registry::size_type tot{}; - registry.assign(registry.create()); + registry.create(); registry.create(); - registry.assign(registry.create()); + registry.create(); registry.orphans([&](auto) { ++tot; }); ASSERT_EQ(tot, 1u); @@ -450,26 +450,14 @@ TEST(Registry, View) { TEST(Registry, NonOwningGroupInitOnFirstUse) { entt::registry registry; - const auto e0 = registry.create(); - registry.assign(e0, 0); - registry.assign(e0, 'c'); - - const auto e1 = registry.create(); - registry.assign(e1, 0); - - const auto e2 = registry.create(); - registry.assign(e2, 0); - registry.assign(e2, 'c'); - - ASSERT_FALSE(registry.owned()); - ASSERT_FALSE(registry.owned()); + std::get<2>(registry.create()) = 'c'; + registry.create(); + std::get<2>(registry.create()) = 'c'; std::size_t cnt{}; auto group = registry.group<>(entt::get); group.each([&cnt](auto...) { ++cnt; }); - ASSERT_FALSE(registry.owned()); - ASSERT_FALSE(registry.owned()); ASSERT_EQ(cnt, 2u); } @@ -477,51 +465,27 @@ TEST(Registry, NonOwningGroupInitOnAssign) { entt::registry registry; auto group = registry.group<>(entt::get); - const auto e0 = registry.create(); - registry.assign(e0, 0); - registry.assign(e0, 'c'); - - const auto e1 = registry.create(); - registry.assign(e1, 0); - - const auto e2 = registry.create(); - registry.assign(e2, 0); - registry.assign(e2, 'c'); - - ASSERT_FALSE(registry.owned()); - ASSERT_FALSE(registry.owned()); + std::get<2>(registry.create()) = 'c'; + registry.create(); + std::get<2>(registry.create()) = 'c'; std::size_t cnt{}; group.each([&cnt](auto...) { ++cnt; }); - ASSERT_FALSE(registry.owned()); - ASSERT_FALSE(registry.owned()); ASSERT_EQ(cnt, 2u); } TEST(Registry, FullOwningGroupInitOnFirstUse) { entt::registry registry; - const auto e0 = registry.create(); - registry.assign(e0, 0); - registry.assign(e0, 'c'); - - const auto e1 = registry.create(); - registry.assign(e1, 0); - - const auto e2 = registry.create(); - registry.assign(e2, 0); - registry.assign(e2, 'c'); - - ASSERT_FALSE(registry.owned()); - ASSERT_FALSE(registry.owned()); + std::get<2>(registry.create()) = 'c'; + registry.create(); + std::get<2>(registry.create()) = 'c'; std::size_t cnt{}; auto group = registry.group(); group.each([&cnt](auto...) { ++cnt; }); - ASSERT_TRUE(registry.owned()); - ASSERT_TRUE(registry.owned()); ASSERT_EQ(cnt, 2u); } @@ -529,51 +493,27 @@ TEST(Registry, FullOwningGroupInitOnAssign) { entt::registry registry; auto group = registry.group(); - const auto e0 = registry.create(); - registry.assign(e0, 0); - registry.assign(e0, 'c'); - - const auto e1 = registry.create(); - registry.assign(e1, 0); - - const auto e2 = registry.create(); - registry.assign(e2, 0); - registry.assign(e2, 'c'); - - ASSERT_TRUE(registry.owned()); - ASSERT_TRUE(registry.owned()); + std::get<2>(registry.create()) = 'c'; + registry.create(); + std::get<2>(registry.create()) = 'c'; std::size_t cnt{}; group.each([&cnt](auto...) { ++cnt; }); - ASSERT_TRUE(registry.owned()); - ASSERT_TRUE(registry.owned()); ASSERT_EQ(cnt, 2u); } TEST(Registry, PartialOwningGroupInitOnFirstUse) { entt::registry registry; - const auto e0 = registry.create(); - registry.assign(e0, 0); - registry.assign(e0, 'c'); - - const auto e1 = registry.create(); - registry.assign(e1, 1); - - const auto e2 = registry.create(); - registry.assign(e2, 2); - registry.assign(e2, 'c'); - - ASSERT_FALSE(registry.owned()); - ASSERT_FALSE(registry.owned()); + std::get<2>(registry.create()) = 'c'; + registry.create(); + std::get<2>(registry.create()) = 'c'; std::size_t cnt{}; auto group = registry.group(entt::get); group.each([&cnt](auto...) { ++cnt; }); - ASSERT_TRUE(registry.owned()); - ASSERT_FALSE(registry.owned()); ASSERT_EQ(cnt, 2u); } @@ -582,25 +522,13 @@ TEST(Registry, PartialOwningGroupInitOnAssign) { entt::registry registry; auto group = registry.group(entt::get); - const auto e0 = registry.create(); - registry.assign(e0, 0); - registry.assign(e0, 'c'); - - const auto e1 = registry.create(); - registry.assign(e1, 0); - - const auto e2 = registry.create(); - registry.assign(e2, 0); - registry.assign(e2, 'c'); - - ASSERT_TRUE(registry.owned()); - ASSERT_FALSE(registry.owned()); + std::get<2>(registry.create()) = 'c'; + registry.create(); + std::get<2>(registry.create()) = 'c'; std::size_t cnt{}; group.each([&cnt](auto...) { ++cnt; }); - ASSERT_TRUE(registry.owned()); - ASSERT_FALSE(registry.owned()); ASSERT_EQ(cnt, 2u); } @@ -728,6 +656,55 @@ TEST(Registry, CleanPartialOwningGroupViewAfterReset) { ASSERT_EQ(group.size(), entt::registry::size_type{0}); } +TEST(Registry, NestedGroups) { + entt::registry registry; + entt::entity entities[10]; + + registry.create(std::begin(entities), std::end(entities)); + const auto g1 = registry.group(entt::get, entt::exclude); + + ASSERT_TRUE(g1.sortable()); + ASSERT_EQ(g1.size(), 10u); + + for(auto i = 0u; i < 10u; ++i) { + ASSERT_EQ(g1[i], entities[i]); + } + + const auto g2 = registry.group(entt::get); + + ASSERT_TRUE(g1.sortable()); + ASSERT_FALSE(g2.sortable()); + ASSERT_EQ(g1.size(), 10u); + ASSERT_EQ(g2.size(), 10u); + + for(auto i = 0u; i < 5u; ++i) { + ASSERT_TRUE((registry.has(entities[i*2]))); + registry.assign(entities[i*2]); + } + + ASSERT_EQ(g1.size(), 5u); + ASSERT_EQ(g2.size(), 10u); + + for(auto i = 0u; i < 5u; ++i) { + ASSERT_TRUE((registry.has(entities[i*2]))); + ASSERT_FALSE(g1.contains(entities[i*2])); + registry.remove(entities[i*2+1]); + } + + // TODO + + ASSERT_EQ(g1.size(), 0u); + ASSERT_EQ(g2.size(), 5u); + + const auto g3= registry.group(entt::get, entt::exclude); + + ASSERT_FALSE(g1.sortable()); + ASSERT_FALSE(g2.sortable()); + ASSERT_TRUE(g3.sortable()); + + // TODO +} + TEST(Registry, SortSingle) { entt::registry registry; @@ -780,75 +757,6 @@ TEST(Registry, SortMulti) { } } -TEST(Registry, SortOwned) { - entt::registry registry; - registry.group(entt::get); - - for(auto i = 0; i < 5; ++i) { - const auto entity = registry.create(); - registry.assign(entity, i); - - if(i < 2) { - registry.assign(entity); - } - } - - ASSERT_TRUE((registry.has(*(registry.data()+0)))); - ASSERT_TRUE((registry.has(*(registry.data()+1)))); - - ASSERT_EQ(*(registry.raw()+0), 0); - ASSERT_EQ(*(registry.raw()+1), 1); - ASSERT_EQ(*(registry.raw()+2), 2); - ASSERT_EQ(*(registry.raw()+3), 3); - ASSERT_EQ(*(registry.raw()+4), 4); - - registry.sort([](const int lhs, const int rhs) { - return lhs < rhs; - }); - - ASSERT_EQ(*(registry.raw()+0), 0); - ASSERT_EQ(*(registry.raw()+1), 1); - ASSERT_EQ(*(registry.raw()+2), 4); - ASSERT_EQ(*(registry.raw()+3), 3); - ASSERT_EQ(*(registry.raw()+4), 2); - - registry.reset(); - registry.sort([](const int lhs, const int rhs) { - return lhs < rhs; - }); - - ASSERT_EQ(*(registry.raw()+0), 4); - ASSERT_EQ(*(registry.raw()+1), 3); - ASSERT_EQ(*(registry.raw()+2), 2); - ASSERT_EQ(*(registry.raw()+3), 1); - ASSERT_EQ(*(registry.raw()+4), 0); - - registry.each([®istry](const auto entity) { - registry.assign(entity); - }); - - registry.sort([](const int lhs, const int rhs) { - return lhs > rhs; - }); - - ASSERT_EQ(*(registry.raw()+0), 4); - ASSERT_EQ(*(registry.raw()+1), 3); - ASSERT_EQ(*(registry.raw()+2), 2); - ASSERT_EQ(*(registry.raw()+3), 1); - ASSERT_EQ(*(registry.raw()+4), 0); - - registry.reset(); - registry.sort([](const int lhs, const int rhs) { - return lhs > rhs; - }); - - ASSERT_EQ(*(registry.raw()+0), 0); - ASSERT_EQ(*(registry.raw()+1), 1); - ASSERT_EQ(*(registry.raw()+2), 2); - ASSERT_EQ(*(registry.raw()+3), 3); - ASSERT_EQ(*(registry.raw()+4), 4); -} - TEST(Registry, ComponentsWithTypesFromStandardTemplateLibrary) { // see #37 - the test shouldn't crash, that's all entt::registry registry;