sparse_set/storage: drop length in favor of a temporary function to make the transition easier
This commit is contained in:
@@ -252,6 +252,14 @@ protected:
|
||||
/*! @brief Random access iterator type. */
|
||||
using basic_iterator = internal::sparse_set_iterator<packed_container_type>;
|
||||
|
||||
/**
|
||||
* @brief Temporary function to make the transition easier. Don't use me.
|
||||
* @param len The length to use.
|
||||
*/
|
||||
void swap_only_length_temporary_function(const std::size_t len) {
|
||||
head = static_cast<underlying_type>(len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Erases an entity from a sparse set.
|
||||
* @param it An iterator to the element to pop.
|
||||
|
||||
@@ -967,7 +967,7 @@ class basic_storage<Entity, Entity, Allocator>
|
||||
|
||||
private:
|
||||
void swap_or_move([[maybe_unused]] const std::size_t lhs, [[maybe_unused]] const std::size_t rhs) override {
|
||||
ENTT_ASSERT(((lhs < length) + (rhs < length)) != 1u, "Cross swapping is not supported");
|
||||
ENTT_ASSERT(((lhs < base_type::free_list()) + (rhs < base_type::free_list())) != 1u, "Cross swapping is not supported");
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -978,24 +978,18 @@ protected:
|
||||
*/
|
||||
void pop(underlying_iterator first, underlying_iterator last) override {
|
||||
for(; first != last; ++first) {
|
||||
if(const auto pos = base_type::index(*first); pos < length) {
|
||||
if(const auto pos = base_type::index(*first); pos < base_type::free_list()) {
|
||||
base_type::bump(local_traits_type::next(*first));
|
||||
|
||||
if(const size_type slot = length - 1u; pos != slot) {
|
||||
if(const size_type slot = base_type::free_list() - 1u; pos != slot) {
|
||||
base_type::swap_elements(base_type::data()[pos], base_type::data()[slot]);
|
||||
}
|
||||
|
||||
--length;
|
||||
base_type::swap_only_length_temporary_function(base_type::free_list() - 1u);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*! @brief Erases all entities of a sparse set. */
|
||||
void pop_all() override {
|
||||
length = 0u;
|
||||
base_type::pop_all();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assigns an entity to a storage.
|
||||
* @param hint A valid identifier.
|
||||
@@ -1037,16 +1031,14 @@ public:
|
||||
* @param allocator The allocator to use.
|
||||
*/
|
||||
explicit basic_storage(const allocator_type &allocator)
|
||||
: base_type{type_id<value_type>(), deletion_policy::swap_only, allocator},
|
||||
length{} {}
|
||||
: base_type{type_id<value_type>(), deletion_policy::swap_only, allocator} {}
|
||||
|
||||
/**
|
||||
* @brief Move constructor.
|
||||
* @param other The instance to move from.
|
||||
*/
|
||||
basic_storage(basic_storage &&other) noexcept
|
||||
: base_type{std::move(other)},
|
||||
length{std::exchange(other.length, size_type{})} {}
|
||||
: base_type{std::move(other)} {}
|
||||
|
||||
/**
|
||||
* @brief Allocator-extended move constructor.
|
||||
@@ -1054,8 +1046,7 @@ public:
|
||||
* @param allocator The allocator to use.
|
||||
*/
|
||||
basic_storage(basic_storage &&other, const allocator_type &allocator) noexcept
|
||||
: base_type{std::move(other), allocator},
|
||||
length{std::exchange(other.length, size_type{})} {}
|
||||
: base_type{std::move(other), allocator} {}
|
||||
|
||||
/**
|
||||
* @brief Move assignment operator.
|
||||
@@ -1064,7 +1055,6 @@ public:
|
||||
*/
|
||||
basic_storage &operator=(basic_storage &&other) noexcept {
|
||||
base_type::operator=(std::move(other));
|
||||
length = std::exchange(other.length, size_type{});
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -1078,7 +1068,7 @@ public:
|
||||
* @param entt A valid identifier.
|
||||
*/
|
||||
void get([[maybe_unused]] const entity_type entt) const noexcept {
|
||||
ENTT_ASSERT(base_type::index(entt) < length, "The requested entity is not a live one");
|
||||
ENTT_ASSERT(base_type::index(entt) < base_type::free_list(), "The requested entity is not a live one");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1092,30 +1082,18 @@ public:
|
||||
* @return Returns an empty tuple.
|
||||
*/
|
||||
[[nodiscard]] std::tuple<> get_as_tuple([[maybe_unused]] const entity_type entt) const noexcept {
|
||||
ENTT_ASSERT(base_type::index(entt) < length, "The requested entity is not a live one");
|
||||
ENTT_ASSERT(base_type::index(entt) < base_type::free_list(), "The requested entity is not a live one");
|
||||
return std::tuple{};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exchanges the contents with those of a given storage.
|
||||
* @param other Storage to exchange the content with.
|
||||
*/
|
||||
void swap(basic_storage &other) {
|
||||
using std::swap;
|
||||
base_type::swap(other);
|
||||
swap(length, other.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a new identifier or recycles a destroyed one.
|
||||
* @return A valid identifier.
|
||||
*/
|
||||
entity_type emplace() {
|
||||
if(length == base_type::size()) {
|
||||
return *base_type::try_emplace(entity_at(length++), true);
|
||||
}
|
||||
|
||||
return base_type::operator[](length++);
|
||||
const auto len = base_type::free_list();
|
||||
base_type::swap_only_length_temporary_function(len + 1u);
|
||||
return (len == base_type::size()) ? *base_type::try_emplace(entity_at(len), true) : base_type::operator[](len);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1137,13 +1115,13 @@ public:
|
||||
base_type::try_emplace(entity_at(base_type::size()), true);
|
||||
}
|
||||
|
||||
base_type::swap_elements(base_type::data()[pos], base_type::data()[length]);
|
||||
++length;
|
||||
} else if(const auto idx = base_type::index(curr); idx < length) {
|
||||
base_type::swap_elements(base_type::data()[pos], base_type::data()[base_type::free_list()]);
|
||||
base_type::swap_only_length_temporary_function(base_type::free_list() + 1u);
|
||||
} else if(const auto idx = base_type::index(curr); idx < base_type::free_list()) {
|
||||
return emplace();
|
||||
} else {
|
||||
base_type::swap_elements(base_type::data()[idx], base_type::data()[length]);
|
||||
++length;
|
||||
base_type::swap_elements(base_type::data()[idx], base_type::data()[base_type::free_list()]);
|
||||
base_type::swap_only_length_temporary_function(base_type::free_list() + 1u);
|
||||
}
|
||||
|
||||
base_type::bump(hint);
|
||||
@@ -1171,12 +1149,13 @@ public:
|
||||
*/
|
||||
template<typename It>
|
||||
void insert(It first, It last) {
|
||||
for(const auto sz = base_type::size(); first != last && length != sz; ++first, ++length) {
|
||||
*first = base_type::operator[](length);
|
||||
for(const auto sz = base_type::size(); first != last && base_type::free_list() != sz; ++first, base_type::swap_only_length_temporary_function(base_type::free_list() + 1u)) {
|
||||
*first = base_type::operator[](base_type::free_list());
|
||||
}
|
||||
|
||||
for(; first != last; ++first) {
|
||||
*first = *base_type::try_emplace(entity_at(length++), true);
|
||||
*first = *base_type::try_emplace(entity_at(base_type::free_list()), true);
|
||||
base_type::swap_only_length_temporary_function(base_type::free_list() + 1u);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1189,15 +1168,15 @@ public:
|
||||
*/
|
||||
template<typename It>
|
||||
size_type pack(It first, It last) {
|
||||
size_type len = length;
|
||||
size_type len = base_type::free_list();
|
||||
|
||||
for(; first != last; ++first, --len) {
|
||||
const auto pos = base_type::index(*first);
|
||||
ENTT_ASSERT(pos < length, "Invalid element");
|
||||
ENTT_ASSERT(pos < base_type::free_list(), "Invalid element");
|
||||
base_type::swap_elements(base_type::data()[pos], base_type::data()[static_cast<size_type>(len - 1u)]);
|
||||
}
|
||||
|
||||
return (length - len);
|
||||
return (base_type::free_list() - len);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1205,7 +1184,7 @@ public:
|
||||
* @return The number of elements considered still in use.
|
||||
*/
|
||||
[[nodiscard]] size_type in_use() const noexcept {
|
||||
return length;
|
||||
return base_type::free_list();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1214,7 +1193,7 @@ public:
|
||||
*/
|
||||
void in_use(const size_type len) noexcept {
|
||||
ENTT_ASSERT(!(len > base_type::size()), "Invalid length");
|
||||
length = len;
|
||||
base_type::swap_only_length_temporary_function(len);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1225,12 +1204,12 @@ public:
|
||||
* @return An iterable object to use to _visit_ the storage.
|
||||
*/
|
||||
[[nodiscard]] iterable each() noexcept {
|
||||
return {internal::extended_storage_iterator{base_type::end() - length}, internal::extended_storage_iterator{base_type::end()}};
|
||||
return {internal::extended_storage_iterator{base_type::end() - base_type::free_list()}, internal::extended_storage_iterator{base_type::end()}};
|
||||
}
|
||||
|
||||
/*! @copydoc each */
|
||||
[[nodiscard]] const_iterable each() const noexcept {
|
||||
return {internal::extended_storage_iterator{base_type::cend() - length}, internal::extended_storage_iterator{base_type::cend()}};
|
||||
return {internal::extended_storage_iterator{base_type::cend() - base_type::free_list()}, internal::extended_storage_iterator{base_type::cend()}};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1241,16 +1220,13 @@ public:
|
||||
* @return A reverse iterable object to use to _visit_ the storage.
|
||||
*/
|
||||
[[nodiscard]] reverse_iterable reach() noexcept {
|
||||
return {internal::extended_storage_iterator{base_type::rbegin()}, internal::extended_storage_iterator{base_type::rbegin() + length}};
|
||||
return {internal::extended_storage_iterator{base_type::rbegin()}, internal::extended_storage_iterator{base_type::rbegin() + base_type::free_list()}};
|
||||
}
|
||||
|
||||
/*! @copydoc reach */
|
||||
[[nodiscard]] const_reverse_iterable reach() const noexcept {
|
||||
return {internal::extended_storage_iterator{base_type::crbegin()}, internal::extended_storage_iterator{base_type::crbegin() + length}};
|
||||
return {internal::extended_storage_iterator{base_type::crbegin()}, internal::extended_storage_iterator{base_type::crbegin() + base_type::free_list()}};
|
||||
}
|
||||
|
||||
private:
|
||||
size_type length;
|
||||
};
|
||||
|
||||
} // namespace entt
|
||||
|
||||
Reference in New Issue
Block a user