mirror of
https://github.com/BlackMATov/ecs.hpp.git
synced 2025-12-16 14:11:14 +07:00
sparse_map::insert_or_assign and noexcept fixes
This commit is contained in:
98
ecs.hpp
98
ecs.hpp
@@ -321,16 +321,19 @@ namespace ecs_hpp
|
|||||||
return insert(T(std::forward<Args>(args)...));
|
return insert(T(std::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool unordered_erase(const T& v)
|
bool unordered_erase(const T& v) noexcept(
|
||||||
noexcept(std::is_nothrow_move_assignable<T>::value)
|
noexcept(indexer_(std::declval<T>())) &&
|
||||||
|
std::is_nothrow_move_assignable<T>::value)
|
||||||
{
|
{
|
||||||
if ( !has(v) ) {
|
if ( !has(v) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const std::size_t vi = indexer_(v);
|
const std::size_t vi = indexer_(v);
|
||||||
const std::size_t dense_index = sparse_[vi];
|
const std::size_t dense_index = sparse_[vi];
|
||||||
dense_[dense_index] = std::move(dense_.back());
|
if ( dense_index != dense_.size() - 1 ) {
|
||||||
sparse_[indexer_(dense_[dense_index])] = dense_index;
|
dense_[dense_index] = std::move(dense_.back());
|
||||||
|
sparse_[indexer_(dense_[dense_index])] = dense_index;
|
||||||
|
}
|
||||||
dense_.pop_back();
|
dense_.pop_back();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -339,17 +342,20 @@ namespace ecs_hpp
|
|||||||
dense_.clear();
|
dense_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has(const T& v) const noexcept {
|
bool has(const T& v) const noexcept(
|
||||||
|
noexcept(indexer_(std::declval<T>())))
|
||||||
|
{
|
||||||
const std::size_t vi = indexer_(v);
|
const std::size_t vi = indexer_(v);
|
||||||
return vi < sparse_.size()
|
return vi < sparse_.size()
|
||||||
&& sparse_[vi] < dense_.size()
|
&& sparse_[vi] < dense_.size()
|
||||||
&& dense_[sparse_[vi]] == v;
|
&& dense_[sparse_[vi]] == v;
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator find(const T& v) const noexcept {
|
const_iterator find(const T& v) const noexcept(
|
||||||
const std::size_t vi = indexer_(v);
|
noexcept(indexer_(std::declval<T>())))
|
||||||
|
{
|
||||||
return has(v)
|
return has(v)
|
||||||
? begin() + sparse_[vi]
|
? begin() + sparse_[indexer_(v)]
|
||||||
: end();
|
: end();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,7 +367,9 @@ namespace ecs_hpp
|
|||||||
throw std::logic_error("ecs_hpp::sparse_set (value not found)");
|
throw std::logic_error("ecs_hpp::sparse_set (value not found)");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<std::size_t,bool> find_dense_index(const T& v) const noexcept {
|
std::pair<std::size_t,bool> find_dense_index(const T& v) const noexcept(
|
||||||
|
noexcept(indexer_(std::declval<T>())))
|
||||||
|
{
|
||||||
return has(v)
|
return has(v)
|
||||||
? std::make_pair(sparse_[indexer_(v)], true)
|
? std::make_pair(sparse_[indexer_(v)], true)
|
||||||
: std::make_pair(std::size_t(-1), false);
|
: std::make_pair(std::size_t(-1), false);
|
||||||
@@ -438,57 +446,59 @@ namespace ecs_hpp
|
|||||||
sparse_map(const Indexer& indexer = Indexer())
|
sparse_map(const Indexer& indexer = Indexer())
|
||||||
: keys_(indexer) {}
|
: keys_(indexer) {}
|
||||||
|
|
||||||
bool insert(const K& k, const T& v) {
|
template < typename UK, typename UT >
|
||||||
|
bool insert(UK&& k, UT&& v) {
|
||||||
if ( keys_.has(k) ) {
|
if ( keys_.has(k) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
values_.push_back(v);
|
values_.push_back(std::forward<UT>(v));
|
||||||
try {
|
try {
|
||||||
return keys_.insert(k);
|
return keys_.insert(std::forward<UK>(k));
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
values_.pop_back();
|
values_.pop_back();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool insert(const K& k, T&& v) {
|
template < typename UK, typename... Args >
|
||||||
if ( keys_.has(k) ) {
|
bool emplace(UK&& k, Args&&... args) {
|
||||||
return false;
|
|
||||||
}
|
|
||||||
values_.push_back(std::move(v));
|
|
||||||
try {
|
|
||||||
return keys_.insert(k);
|
|
||||||
} catch (...) {
|
|
||||||
values_.pop_back();
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename... Args >
|
|
||||||
bool emplace(const K& k, Args&&... args) {
|
|
||||||
if ( keys_.has(k) ) {
|
if ( keys_.has(k) ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
values_.emplace_back(std::forward<Args>(args)...);
|
values_.emplace_back(std::forward<Args>(args)...);
|
||||||
try {
|
try {
|
||||||
return keys_.insert(k);
|
return keys_.insert(std::forward<UK>(k));
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
values_.pop_back();
|
values_.pop_back();
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::enable_if_t<
|
template < typename UK, typename UT >
|
||||||
std::is_nothrow_move_assignable<K>::value,
|
bool insert_or_assign(UK&& k, UT&& v) {
|
||||||
bool>
|
if ( keys_.has(k) ) {
|
||||||
unordered_erase(const K& k)
|
get(k) = std::forward<UT>(v);
|
||||||
noexcept(std::is_nothrow_move_assignable<T>::value)
|
return false;
|
||||||
|
} else {
|
||||||
|
insert(std::forward<UK>(k), std::forward<UT>(v));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool unordered_erase(const K& k) noexcept(
|
||||||
|
noexcept(keys_.find_dense_index(k)) &&
|
||||||
|
std::is_nothrow_move_assignable<T>::value)
|
||||||
{
|
{
|
||||||
if ( !keys_.has(k) ) {
|
static_assert(
|
||||||
|
noexcept(keys_.unordered_erase(k)),
|
||||||
|
"unsupported with current key type");
|
||||||
|
const auto value_index_p = keys_.find_dense_index(k);
|
||||||
|
if ( !value_index_p.second ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const std::size_t value_index = keys_.get_dense_index(k);
|
if ( value_index_p.first != values_.size() - 1 ) {
|
||||||
values_[value_index] = std::move(values_.back());
|
values_[value_index_p.first] = std::move(values_.back());
|
||||||
|
}
|
||||||
values_.pop_back();
|
values_.pop_back();
|
||||||
keys_.unordered_erase(k);
|
keys_.unordered_erase(k);
|
||||||
return true;
|
return true;
|
||||||
@@ -499,7 +509,9 @@ namespace ecs_hpp
|
|||||||
values_.clear();
|
values_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has(const K& k) const noexcept {
|
bool has(const K& k) const noexcept(
|
||||||
|
noexcept(keys_.has(k)))
|
||||||
|
{
|
||||||
return keys_.has(k);
|
return keys_.has(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -511,14 +523,18 @@ namespace ecs_hpp
|
|||||||
return values_[keys_.get_dense_index(k)];
|
return values_[keys_.get_dense_index(k)];
|
||||||
}
|
}
|
||||||
|
|
||||||
T* find(const K& k) noexcept {
|
T* find(const K& k) noexcept(
|
||||||
|
noexcept(keys_.find_dense_index(k)))
|
||||||
|
{
|
||||||
const auto value_index_p = keys_.find_dense_index(k);
|
const auto value_index_p = keys_.find_dense_index(k);
|
||||||
return value_index_p.second
|
return value_index_p.second
|
||||||
? &values_[value_index_p.first]
|
? &values_[value_index_p.first]
|
||||||
: nullptr;
|
: nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const T* find(const K& k) const noexcept {
|
const T* find(const K& k) const noexcept(
|
||||||
|
noexcept(keys_.find_dense_index(k)))
|
||||||
|
{
|
||||||
const auto value_index_p = keys_.find_dense_index(k);
|
const auto value_index_p = keys_.find_dense_index(k);
|
||||||
return value_index_p.second
|
return value_index_p.second
|
||||||
? &values_[value_index_p.first]
|
? &values_[value_index_p.first]
|
||||||
@@ -606,9 +622,7 @@ namespace ecs_hpp
|
|||||||
template < typename T >
|
template < typename T >
|
||||||
template < typename... Args >
|
template < typename... Args >
|
||||||
void component_storage<T>::assign(entity_id id, Args&&... args) {
|
void component_storage<T>::assign(entity_id id, Args&&... args) {
|
||||||
if ( !components_.emplace(id, std::forward<Args>(args)...) ) {
|
components_.insert_or_assign(id, T(std::forward<Args>(args)...));
|
||||||
components_.get(id) = T(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename T >
|
template < typename T >
|
||||||
|
|||||||
@@ -280,6 +280,25 @@ TEST_CASE("detail") {
|
|||||||
REQUIRE(s.unordered_erase(position_c(1,2)));
|
REQUIRE(s.unordered_erase(position_c(1,2)));
|
||||||
REQUIRE(s.get(position_c(3,4)).x == 3);
|
REQUIRE(s.get(position_c(3,4)).x == 3);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
struct obj_t {
|
||||||
|
int x;
|
||||||
|
obj_t(int nx) : x(nx) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
sparse_map<unsigned, obj_t> m;
|
||||||
|
REQUIRE(m.insert_or_assign(42, obj_t(42)));
|
||||||
|
REQUIRE(m.has(42));
|
||||||
|
REQUIRE(m.get(42).x == 42);
|
||||||
|
REQUIRE_FALSE(m.insert_or_assign(42, obj_t(21)));
|
||||||
|
REQUIRE(m.has(42));
|
||||||
|
REQUIRE(m.get(42).x == 21);
|
||||||
|
REQUIRE(m.size() == 1);
|
||||||
|
REQUIRE(m.insert_or_assign(84, obj_t(84)));
|
||||||
|
REQUIRE(m.has(84));
|
||||||
|
REQUIRE(m.get(84).x == 84);
|
||||||
|
REQUIRE(m.size() == 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user