Skip to content

Commit 9a37516

Browse files
committed
Fixed a few bugs, thanks to Clang
1 parent 4fc506a commit 9a37516

File tree

8 files changed

+1393
-27
lines changed

8 files changed

+1393
-27
lines changed

Catch_color_tutorial_tests/color_container.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ float dcon::colored_thing_const_fat_id::get_blue() {
1919
return get_color().blue;
2020
}
2121

22-
2322
void dcon::data_container::deserialize_rgb(std::byte const* start, std::byte const* end, load_record& record_in_out) {
2423
if(!record_in_out.colored_thing_color) {
2524
float const* found_red = nullptr;

Catch_core_datacontainer_tests/Catch_core_datacontainer_tests.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,6 @@ TEST_CASE("for compatactable remove in the other direction", "[core_datacontaine
579579
REQUIRE(found_car == false);
580580
}
581581

582-
583582
TEST_CASE("for erasable basic relationship functions", "[core_datacontainer_tests]") {
584583
auto ptr = std::make_unique< cob3::data_container >();
585584

Catch_ecs_tutorial_tests/Catch_ecs_tutorial_tests.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ dcon::entity_id make_entity(dcon::data_container& dc) {
1717
return dc.try_create_entity(dcon::position_id(), dcon::sprite_id());
1818
}
1919

20+
2021
TEST_CASE("destructor test", "[ecs_tutorial_tests]") {
2122
auto ptr = std::make_unique<dcon::data_container>();
2223

Catch_serialization_tests/new_ser.hpp

Lines changed: 637 additions & 0 deletions
Large diffs are not rendered by default.

Catch_serialization_tests/old_ser.hpp

Lines changed: 637 additions & 0 deletions
Large diffs are not rendered by default.

CommonIncludes/unordered_dense.h

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
///////////////////////// ankerl::unordered_dense::{map, set} /////////////////////////
22

33
// A fast & densely stored hashmap and hashset based on robin-hood backward shift deletion.
4-
// Version 2.0.0
4+
// Version 3.0.2
55
// https://github.com/martinus/unordered_dense
66
//
77
// Licensed under the MIT License <http://opensource.org/licenses/MIT>.
@@ -30,9 +30,9 @@
3030
#define ANKERL_UNORDERED_DENSE_H
3131

3232
// see https://semver.org/spec/v2.0.0.html
33-
#define ANKERL_UNORDERED_DENSE_VERSION_MAJOR 2 // NOLINT(cppcoreguidelines-macro-usage) incompatible API changes
33+
#define ANKERL_UNORDERED_DENSE_VERSION_MAJOR 3 // NOLINT(cppcoreguidelines-macro-usage) incompatible API changes
3434
#define ANKERL_UNORDERED_DENSE_VERSION_MINOR 0 // NOLINT(cppcoreguidelines-macro-usage) backwards compatible functionality
35-
#define ANKERL_UNORDERED_DENSE_VERSION_PATCH 0 // NOLINT(cppcoreguidelines-macro-usage) backwards compatible bug fixes
35+
#define ANKERL_UNORDERED_DENSE_VERSION_PATCH 2 // NOLINT(cppcoreguidelines-macro-usage) backwards compatible bug fixes
3636

3737
// API versioning with inline namespace, see https://www.foonathan.net/2018/11/inline-namespaces/
3838
#define ANKERL_UNORDERED_DENSE_VERSION_CONCAT1(major, minor, patch) v##major##_##minor##_##patch
@@ -79,7 +79,15 @@
7979
# if __has_include(<memory_resource>)
8080
# undef ANKERL_UNORDERED_DENSE_PMR
8181
# define ANKERL_UNORDERED_DENSE_PMR 1 // NOLINT(cppcoreguidelines-macro-usage)
82-
# include <memory_resource> // for polymorphic_allocator
82+
# define ANKERL_UNORDERED_DENSE_PMR_ALLOCATOR \
83+
std::pmr::polymorphic_allocator // NOLINT(cppcoreguidelines-macro-usage)
84+
# include <memory_resource> // for polymorphic_allocator
85+
# elif __has_include(<experimental/memory_resource>)
86+
# undef ANKERL_UNORDERED_DENSE_PMR
87+
# define ANKERL_UNORDERED_DENSE_PMR 1 // NOLINT(cppcoreguidelines-macro-usage)
88+
# define ANKERL_UNORDERED_DENSE_PMR_ALLOCATOR \
89+
std::experimental::pmr::polymorphic_allocator // NOLINT(cppcoreguidelines-macro-usage)
90+
# include <experimental/memory_resource> // for polymorphic_allocator
8391
# endif
8492
# endif
8593

@@ -364,30 +372,48 @@ namespace ankerl::unordered_dense {
364372
template <typename T>
365373
using detect_iterator = typename T::iterator;
366374

375+
template <typename T>
376+
using detect_reserve = decltype(std::declval<T&>().reserve(size_t{}));
377+
367378
// enable_if helpers
368379

369380
template <typename Mapped>
370381
constexpr bool is_map_v = !std::is_void_v<Mapped>;
371382

383+
// clang-format off
372384
template <typename Hash, typename KeyEqual>
373385
constexpr bool is_transparent_v = is_detected_v<detect_is_transparent, Hash> && is_detected_v<detect_is_transparent, KeyEqual>;
386+
// clang-format on
374387

375388
template <typename From, typename To1, typename To2>
376389
constexpr bool is_neither_convertible_v = !std::is_convertible_v<From, To1> && !std::is_convertible_v<From, To2>;
377390

391+
template <typename T>
392+
constexpr bool has_reserve = is_detected_v<detect_reserve, T>;
393+
394+
// base type for map has mapped_type
395+
template <class T>
396+
struct base_table_type_map {
397+
using mapped_type = T;
398+
};
399+
400+
// base type for set doesn't have mapped_type
401+
struct base_table_type_set {
402+
};
403+
378404
// This is it, the table. Doubles as map and set, and uses `void` for T when its used as a set.
379405
template <class Key,
380406
class T, // when void, treat it as a set.
381407
class Hash,
382408
class KeyEqual,
383409
class AllocatorOrContainer,
384410
class Bucket>
385-
class table {
411+
class table : public std::conditional_t<is_map_v<T>, base_table_type_map<T>, base_table_type_set> {
386412
public:
387413
using value_container_type = std::conditional_t<
388414
is_detected_v<detect_iterator, AllocatorOrContainer>,
389415
AllocatorOrContainer,
390-
typename std::vector<typename std::conditional_t<std::is_void_v<T>, Key, std::pair<Key, T>>, AllocatorOrContainer>>;
416+
typename std::vector<typename std::conditional_t<is_map_v<T>, std::pair<Key, T>, Key>, AllocatorOrContainer>>;
391417

392418
private:
393419
using bucket_alloc =
@@ -399,7 +425,6 @@ namespace ankerl::unordered_dense {
399425

400426
public:
401427
using key_type = Key;
402-
using mapped_type = T;
403428
using value_type = typename value_container_type::value_type;
404429
using size_type = typename value_container_type::size_type;
405430
using difference_type = typename value_container_type::difference_type;
@@ -410,8 +435,8 @@ namespace ankerl::unordered_dense {
410435
using const_reference = typename value_container_type::const_reference;
411436
using pointer = typename value_container_type::pointer;
412437
using const_pointer = typename value_container_type::const_pointer;
413-
using iterator = typename value_container_type::iterator;
414438
using const_iterator = typename value_container_type::const_iterator;
439+
using iterator = std::conditional_t<is_map_v<T>, typename value_container_type::iterator, const_iterator>;
415440
using bucket_type = Bucket;
416441

417442
private:
@@ -478,10 +503,10 @@ namespace ankerl::unordered_dense {
478503
}
479504

480505
[[nodiscard]] static constexpr auto get_key(value_type const& vt) -> key_type const& {
481-
if constexpr(std::is_void_v<T>) {
482-
return vt;
483-
} else {
506+
if constexpr(is_map_v<T>) {
484507
return vt.first;
508+
} else {
509+
return vt;
485510
}
486511
}
487512

@@ -748,13 +773,16 @@ namespace ankerl::unordered_dense {
748773
: table(0) {
749774
}
750775

751-
explicit table(size_t /*bucket_count*/,
776+
explicit table(size_t bucket_count,
752777
Hash const& hash = Hash(),
753778
KeyEqual const& equal = KeyEqual(),
754779
allocator_type const& alloc_or_container = allocator_type())
755780
: m_values(alloc_or_container)
756781
, m_hash(hash)
757782
, m_equal(equal) {
783+
if(0 != bucket_count) {
784+
reserve(bucket_count);
785+
}
758786
}
759787

760788
table(size_t bucket_count, allocator_type const& alloc)
@@ -836,8 +864,10 @@ namespace ankerl::unordered_dense {
836864
}
837865

838866
~table() {
839-
auto ba = bucket_alloc(m_values.get_allocator());
840-
bucket_alloc_traits::deallocate(ba, m_buckets, bucket_count());
867+
if(nullptr != m_buckets) {
868+
auto ba = bucket_alloc(m_values.get_allocator());
869+
bucket_alloc_traits::deallocate(ba, m_buckets, bucket_count());
870+
}
841871
}
842872

843873
auto operator=(table const& other) -> table& {
@@ -1196,6 +1226,7 @@ namespace ankerl::unordered_dense {
11961226
return begin() + static_cast<difference_type>(value_idx_to_remove);
11971227
}
11981228

1229+
template <typename Q = T, std::enable_if_t<is_map_v<Q>, bool> = true>
11991230
auto erase(const_iterator it) -> iterator {
12001231
return erase(begin() + (it - cbegin()));
12011232
}
@@ -1387,7 +1418,10 @@ namespace ankerl::unordered_dense {
13871418

13881419
void reserve(size_t capa) {
13891420
capa = std::min(capa, max_size());
1390-
m_values.reserve(capa);
1421+
if constexpr(has_reserve<value_container_type>) {
1422+
// std::deque doesn't have reserve(). Make sure we only call when available
1423+
m_values.reserve(capa);
1424+
}
13911425
auto shifts = calc_shifts_for_size(std::max(capa, size()));
13921426
if(0 == m_num_buckets || shifts < m_shifts) {
13931427
m_shifts = shifts;
@@ -1423,14 +1457,14 @@ namespace ankerl::unordered_dense {
14231457
}
14241458
for(auto const& b_entry : b) {
14251459
auto it = a.find(get_key(b_entry));
1426-
if constexpr(std::is_void_v<T>) {
1427-
// set: only check that the key is here
1428-
if(a.end() == it) {
1460+
if constexpr(is_map_v<T>) {
1461+
// map: check that key is here, then also check that value is the same
1462+
if(a.end() == it || !(b_entry.second == it->second)) {
14291463
return false;
14301464
}
14311465
} else {
1432-
// map: check that key is here, then also check that value is the same
1433-
if(a.end() == it || !(b_entry.second == it->second)) {
1466+
// set: only check that the key is here
1467+
if(a.end() == it) {
14341468
return false;
14351469
}
14361470
}
@@ -1469,10 +1503,10 @@ namespace ankerl::unordered_dense {
14691503
class Hash = hash<Key>,
14701504
class KeyEqual = std::equal_to<Key>,
14711505
class Bucket = bucket_type::standard>
1472-
using map = detail::table<Key, T, Hash, KeyEqual, std::pmr::polymorphic_allocator<std::pair<Key, T>>, Bucket>;
1506+
using map = detail::table<Key, T, Hash, KeyEqual, ANKERL_UNORDERED_DENSE_PMR_ALLOCATOR<std::pair<Key, T>>, Bucket>;
14731507

14741508
template <class Key, class Hash = hash<Key>, class KeyEqual = std::equal_to<Key>, class Bucket = bucket_type::standard>
1475-
using set = detail::table<Key, void, Hash, KeyEqual, std::pmr::polymorphic_allocator<Key>, Bucket>;
1509+
using set = detail::table<Key, void, Hash, KeyEqual, ANKERL_UNORDERED_DENSE_PMR_ALLOCATOR<Key>, Bucket>;
14761510

14771511
} // namespace pmr
14781512

DataContainerGenerator/object_member_fragments.cpp

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ void make_property_member_declarations(basic_builder& o, file_def const& parsed_
628628
o + "#endif";
629629
} else {
630630
o + "DCON_RELEASE_INLINE void @namesp@set_@prop@(@index_type@ i, bool v) const" + block{
631-
"container.@obj@_set_@prop@(id, i, v);";
631+
o + "container.@obj@_set_@prop@(id, i, v);";
632632
};
633633
o + "DCON_RELEASE_INLINE void @namesp@resize_@prop@(uint32_t sz) const noexcept" + block{
634634
o + "container.@obj@_resize_@prop@(sz);";
@@ -1930,6 +1930,25 @@ void join_setter_text(basic_builder& o, property_def const& ip, bool add_prefix,
19301930
};
19311931
}
19321932
break;
1933+
case property_type::object:
1934+
if(add_prefix) {
1935+
if(as_primary_key) {
1936+
o + "void @obj@_set_@prop@_from_@rel@(@obj@_id ref_id, @type@ const& val)" + block{
1937+
o + "@rel@_set_@prop@(@rel@_id(@rel@_id::value_base_t(ref_id.index())), val);";
1938+
};
1939+
} else {
1940+
o + "void @obj@_set_@prop@_from_@rel@(@obj@_id id, @type@ const& val)" + block{
1941+
o + "if(auto ref_id = @rel@.m_link_back_@as_name@.vptr()[id.index()]; bool(ref_id))" + block{
1942+
o + "@rel@_set_@prop@(ref_id, val);";
1943+
};
1944+
};
1945+
}
1946+
} else {
1947+
o + "DCON_RELEASE_INLINE void @namesp@set_@prop@_from_@rel@(@type@ const& v) const noexcept" + block{
1948+
o + "container.@obj@_set_@prop@_from_@rel@(id, v);";
1949+
};
1950+
}
1951+
break;
19331952
case property_type::other:
19341953
break;
19351954
case property_type::array_bitfield:
@@ -1947,7 +1966,7 @@ void join_setter_text(basic_builder& o, property_def const& ip, bool add_prefix,
19471966
}
19481967
} else {
19491968
o + "DCON_RELEASE_INLINE void @namesp@set_@prop@_from_@rel@(@i_type@ i, bool v) const noexcept" + block{
1950-
"container.@obj@_set_@prop@_from_@rel@(id, i, v);";
1969+
o + "container.@obj@_set_@prop@_from_@rel@(id, i, v);";
19511970
};
19521971
}
19531972
break;
@@ -1968,7 +1987,7 @@ void join_setter_text(basic_builder& o, property_def const& ip, bool add_prefix,
19681987
}
19691988
} else {
19701989
o + "DCON_RELEASE_INLINE void @namesp@set_@prop@_from_@rel@(@i_type@ i, @type@ v) const noexcept" + block{
1971-
"container.@obj@_set_@prop@_from_@rel@(id, i, v);";
1990+
o + "container.@obj@_set_@prop@_from_@rel@(id, i, v);";
19721991
};
19731992
}
19741993
break;
@@ -2022,6 +2041,41 @@ void join_getter_text(basic_builder& o, property_def const& ip, bool add_prefix,
20222041
};
20232042
}
20242043
break;
2044+
case property_type::object:
2045+
if(add_prefix) {
2046+
if(ip.protection != protection_type::read_only && !ip.hook_set) {
2047+
if(as_primary_key) {
2048+
o + "@type@& @obj@_get_@prop@_from_@rel@(@obj@_id ref_id) const" + block{
2049+
o + "return @rel@_get_@prop@(@rel@_id(@rel@_id::value_base_t(ref_id.index())));";
2050+
};
2051+
} else {
2052+
o + "@type@& @obj@_get_@prop@_from_@rel@(@obj@_id id) const" + block{
2053+
o + "return @rel@_get_@prop@(@rel@.m_link_back_@as_name@.vptr()[id.index()]);";
2054+
};
2055+
}
2056+
} else {
2057+
if(as_primary_key) {
2058+
o + "@type@ const& @obj@_get_@prop@_from_@rel@(@obj@_id ref_id) const" + block{
2059+
o + "return @rel@_get_@prop@(@rel@_id(@rel@_id::value_base_t(ref_id.index())));";
2060+
};
2061+
} else {
2062+
o + "@type@ const& @obj@_get_@prop@_from_@rel@(@obj@_id id) const" + block{
2063+
o + "return @rel@_get_@prop@(@rel@.m_link_back_@as_name@.vptr()[id.index()]);";
2064+
};
2065+
}
2066+
}
2067+
} else {
2068+
if(ip.protection != protection_type::read_only && !ip.hook_set) {
2069+
o + "DCON_RELEASE_INLINE @type@& @namesp@get_@prop@_from_@rel@() const noexcept" + block{
2070+
o + "return container.@obj@_get_@prop@_from_@rel@(id);";
2071+
};
2072+
} else {
2073+
o + "DCON_RELEASE_INLINE @type@ const& @namesp@get_@prop@_from_@rel@() const noexcept" + block{
2074+
o + "return container.@obj@_get_@prop@_from_@rel@(id);";
2075+
};
2076+
}
2077+
}
2078+
break;
20252079
case property_type::vectorizable:
20262080
if(add_prefix) {
20272081
if(as_primary_key) {

changes.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
### version 0.2.1
22

3+
- updated unordered_dense header
4+
- Fixed a few bugs, thanks to Clang
5+
6+
### version 0.2.1
7+
38
- updated unordered_dense header
49
- added an iterator interface (supporting `for(auto i : ...)` loops) for iterating over all of the object instances in the data container and all of the relationships linked via a `many` link to an object instance.
510

0 commit comments

Comments
 (0)