diff --git a/interface/core/containers/hashmap.h b/interface/core/containers/hashmap.h index 23695cf..6855dab 100644 --- a/interface/core/containers/hashmap.h +++ b/interface/core/containers/hashmap.h @@ -17,6 +17,16 @@ namespace hud using key_type = typename hud::pair::first_type; using value_type = typename hud::pair::second_type; + explicit constexpr slot(const key_type &key) noexcept + : super(key, value_type {}) + { + } + + explicit constexpr slot(key_type &&key) noexcept + : super(std::move(key), value_type {}) + { + } + [[nodiscard]] constexpr const key_t &key() const noexcept { return hud::get<0>(*this); @@ -79,7 +89,6 @@ namespace hud typename allocator_t = hashmap_default_allocator> class hashmap : public details::hashset::hashset_impl, hasher_t, key_equal_t, allocator_t> - { private: diff --git a/interface/core/containers/hashset.h b/interface/core/containers/hashset.h index 38fefdb..9522b34 100644 --- a/interface/core/containers/hashset.h +++ b/interface/core/containers/hashset.h @@ -8,6 +8,7 @@ #include "pair.h" #include "../hash.h" #include "../bits.h" +#include "../traits/is_comparable_with_equal.h" namespace hud { @@ -470,14 +471,16 @@ namespace hud return tmp; } - friend constexpr bool operator==(const iterator &a, const iterator &b) + /** Checks if 2 iterator are equal. */ + [[nodiscard]] constexpr bool operator==(const iterator &other) const noexcept { - return a.control_ptr_ == b.control_ptr_; + return control_ptr_ == other.control_ptr_; } - friend constexpr bool operator!=(const iterator &a, const iterator &b) + /** Checks if 2 iterator are not equals. */ + [[nodiscard]] constexpr bool operator!=(const iterator &other) const noexcept { - return !(a == b); + return control_ptr_ != other.control_ptr_; } private: @@ -499,8 +502,8 @@ namespace hud typename key_equal_t, typename allocator_t> class hashset_impl - { + protected: /** Type of the slot. */ using slot_type = slot_t; @@ -592,7 +595,7 @@ namespace hud slot_type *slot_ptr = slot_ptr_ + res.first; if (res.second) { - hud::memory::construct_at(slot_ptr, key, hud::forward(args)...); + hud::memory::construct_at(slot_ptr, hud::move(key), hud::forward(args)...); } return slot_ptr->value(); } @@ -609,7 +612,26 @@ namespace hud slot_type *slot_ptr = slot_ptr_ + res.first; if (res.second) { - hud::memory::construct_at(slot_ptr, key, hud::move(value)); + hud::memory::construct_at(slot_ptr, hud::move(key), hud::move(value)); + } + return {control_ptr_ + res.first, slot_ptr}; + } + + /** + * Insert a key in the hashset. + * @param key The key associated with the `value` + * @param args List of arguments pass to `value_type` constructor after the `key` itself + * @return Iterator to the `value` + */ + template + requires(hud::is_constructible_v) + constexpr iterator add(key_type &&key, args_t &&...args) noexcept + { + hud::pair res = find_or_insert_no_construct(key); + slot_type *slot_ptr = slot_ptr_ + res.first; + if (res.second) + { + hud::memory::construct_at(slot_ptr, hud::move(key), hud::forward(args)...); } return {control_ptr_ + res.first, slot_ptr}; } @@ -635,7 +657,7 @@ namespace hud /** Find a key and return an iterator to the value. */ [[nodiscard]] - constexpr iterator find(key_type &&key) const noexcept + constexpr iterator find(key_type &&key) noexcept { u64 hash = hasher_type {}(key); u64 h1 = H1(hash); @@ -721,7 +743,7 @@ namespace hud [[nodiscard]] constexpr const_iterator end() const noexcept { - return iterator(control_ptr_sentinel()); + return const_iterator(control_ptr_sentinel()); } private: @@ -732,6 +754,9 @@ namespace hud */ [[nodiscard]] constexpr hud::pair find_or_insert_no_construct(const key_type &key) noexcept { + static_assert(hud::is_hashable_64_v, "key_type is not hashable"); + static_assert(hud::is_comparable_with_equal_v, "key_type is not comparable with equal"); + u64 hash = hasher_type {}(key); u64 h1 = H1(hash); hud::check(hud::bits::is_valid_power_of_two_mask(max_slot_count_) && "Not a mask"); diff --git a/interface/core/hash.h b/interface/core/hash.h index 0f1e841..ca1dd95 100644 --- a/interface/core/hash.h +++ b/interface/core/hash.h @@ -8,6 +8,7 @@ #include "templates/bit_cast.h" #include "cstring.h" #include "traits/decay.h" +#include "templates/declval.h" namespace hud { @@ -429,6 +430,39 @@ namespace hud u64 state_ {0}; // Default is 0, but can be a seed }; + // Traits used to check if a type is hashable + template + struct is_hashable_64 + : hud::false_type + { + }; + + template + struct is_hashable_64 {}(hud::declval()))>> + : hud::true_type + { + }; + + /** Equivalent of is_hashable::value. */ + template + inline constexpr bool is_hashable_64_v = is_hashable_64::value; + + // Traits used to check if a type is hashable + template + struct is_hashable_32 + : hud::false_type + { + }; + + template + struct is_hashable_32 {}(hud::declval()))>> + : hud::true_type + { + }; + + /** Equivalent of is_hashable::value. */ + template + inline constexpr bool is_hashable_32_v = is_hashable_32::value; } // namespace hud #endif // HD_INC_CORE_HASH_H diff --git a/test/array/array_add.cpp b/test/array/array_add.cpp index 0cf5d2d..a356be5 100644 --- a/test/array/array_add.cpp +++ b/test/array/array_add.cpp @@ -1,7 +1,7 @@ #include #include "../misc/allocator_watcher.h" -GTEST_TEST(array, add_by_copy_construct_non_bitwise_copy_constructible_type) +GTEST_TEST(array, add_by_copy_construct_non_bitwise_copy_constructible_type_same_type) { using type = hud_test::non_bitwise_copy_constructible_type; diff --git a/test/array/array_add_no_construct.cpp b/test/array/array_add_no_construct.cpp index ed46628..421c45d 100644 --- a/test/array/array_add_no_construct.cpp +++ b/test/array/array_add_no_construct.cpp @@ -4,7 +4,6 @@ GTEST_TEST(array, add_no_construct_do_not_call_constructor) { - using type = hud_test::NonDefaultConstructibleType; using array_type = hud::array>; static_assert(!hud::is_constructible_v); diff --git a/test/array/array_add_to_ref.cpp b/test/array/array_add_to_ref.cpp index 6e83c33..ebd4c09 100644 --- a/test/array/array_add_to_ref.cpp +++ b/test/array/array_add_to_ref.cpp @@ -3,7 +3,6 @@ GTEST_TEST(array, add_to_ref_by_copy_construct_non_bitwise_copy_constructible_type) { - using type = hud_test::non_bitwise_copy_constructible_type; using array_type = hud::array>; static_assert(!hud::is_bitwise_copy_constructible_v); diff --git a/test/array/array_iteration.cpp b/test/array/array_iteration.cpp index 03a7862..5b9b187 100644 --- a/test/array/array_iteration.cpp +++ b/test/array/array_iteration.cpp @@ -2,7 +2,6 @@ GTEST_TEST(array, iterators) { - // Non const Array { hud::array arr({10, 20, 30, 40}); @@ -46,7 +45,6 @@ GTEST_TEST(array, iterators) GTEST_TEST(array, range_for_loop) { - // Non const Array { hud::array arr({10, 20, 30, 40}); diff --git a/test/array/array_move_assign.cpp b/test/array/array_move_assign.cpp index b1b4eb1..04372fc 100644 --- a/test/array/array_move_assign.cpp +++ b/test/array/array_move_assign.cpp @@ -5,7 +5,6 @@ // void assign(array &&other, const usize min_slack = 0) GTEST_TEST(array, move_assign_array_of_bitwise_move_assignable_same_type_same_allocator_no_min_slack) { - using type = i32; static_assert(hud::is_bitwise_move_assignable_v); diff --git a/test/hashmap/hashmap_add.cpp b/test/hashmap/hashmap_add.cpp index e981c1d..fa27721 100644 --- a/test/hashmap/hashmap_add.cpp +++ b/test/hashmap/hashmap_add.cpp @@ -1,6 +1,269 @@ #include #include "../misc/allocator_watcher.h" +GTEST_TEST(hashmap, add_default_construct_non_bitwise_copy_constructible_type) +{ + using key_type = hud_test::non_bitwise_copy_constructible_type; + using value_type = hud_test::non_bitwise_copy_constructible_type; + using hashmap_type = hud::hashmap, hud::hashmap_default_key_equal, hud_test::allocator_watcher<1>>; + + static_assert(!hud::is_bitwise_copy_constructible_v); + static_assert(!hud::is_bitwise_copy_constructible_v); + + // With reallocation + { + const auto test = []() + { + hashmap_type map; + const key_type key_to_copy(1); + const auto it_1st = map.add(key_to_copy); + + const auto first_element_result = std::tuple { + *it_1st, + map.count(), + map.max_count(), + it_1st->first.copy_constructor_count(), + it_1st->second.copy_constructor_count(), + map.allocator().allocation_count(), + map.allocator().free_count(), + }; + const key_type key_to_copy_1(1); + const auto it_same = map.add(key_to_copy_1); + // Add same element + const auto same_element_result = std::tuple { + *it_same, + map.count(), + map.max_count(), + it_same->first.copy_constructor_count(), + it_same->second.copy_constructor_count(), + map.allocator().allocation_count(), + map.allocator().free_count(), + }; + const key_type key_to_copy_2(2); + const auto it_2nd = map.add(key_to_copy_2); + // Add 2nd element + const auto second_element_result = std::tuple { + *it_2nd, + map.count(), + map.max_count(), + it_2nd->first.copy_constructor_count(), + it_2nd->second.copy_constructor_count(), + map.allocator().allocation_count(), + map.allocator().free_count(), + }; + + return std::tuple { + first_element_result, + same_element_result, + second_element_result + }; + }; + + // Non Constant + { + const auto result = test(); + + // First element is correctly added + const auto first_element_result = std::get<0>(result); + hud_assert_eq(std::get<0>(first_element_result).first, 1u); + hud_assert_eq(std::get<0>(first_element_result).second, 0u); + hud_assert_eq(std::get<1>(first_element_result), 1u); + hud_assert_eq(std::get<2>(first_element_result), 1u); + hud_assert_eq(std::get<3>(first_element_result), 1u); + hud_assert_eq(std::get<4>(first_element_result), 1u); + hud_assert_eq(std::get<5>(first_element_result), 1u); + hud_assert_eq(std::get<6>(first_element_result), 0u); + + // Same element + const auto same_element_result = std::get<1>(result); + hud_assert_eq(std::get<0>(same_element_result).first, 1u); + hud_assert_eq(std::get<0>(same_element_result).second, 0u); + hud_assert_eq(std::get<1>(same_element_result), 1u); + hud_assert_eq(std::get<2>(same_element_result), 1u); + hud_assert_eq(std::get<3>(same_element_result), 1u); + hud_assert_eq(std::get<4>(same_element_result), 1u); + hud_assert_eq(std::get<5>(same_element_result), 1u); + hud_assert_eq(std::get<6>(same_element_result), 0u); + + // 2nd element + const auto second_element_result = std::get<2>(result); + hud_assert_eq(std::get<0>(second_element_result).first, 2u); + hud_assert_eq(std::get<0>(second_element_result).second, 0u); + hud_assert_eq(std::get<1>(second_element_result), 2u); + hud_assert_eq(std::get<2>(second_element_result), 3u); + hud_assert_eq(std::get<3>(second_element_result), 1u); + hud_assert_eq(std::get<4>(second_element_result), 1u); + hud_assert_eq(std::get<5>(second_element_result), 2u); + hud_assert_eq(std::get<6>(second_element_result), 1u); + } + // Constant + { + constexpr auto result = test(); + + // First element is correctly added + const auto first_element_result = std::get<0>(result); + hud_assert_eq(std::get<0>(first_element_result).first, 1u); + hud_assert_eq(std::get<0>(first_element_result).second, 0u); + hud_assert_eq(std::get<1>(first_element_result), 1u); + hud_assert_eq(std::get<2>(first_element_result), 1u); + hud_assert_eq(std::get<3>(first_element_result), 1u); + hud_assert_eq(std::get<4>(first_element_result), 1u); + hud_assert_eq(std::get<5>(first_element_result), 2u); + hud_assert_eq(std::get<6>(first_element_result), 0u); + + // Same element + const auto same_element_result = std::get<1>(result); + hud_assert_eq(std::get<0>(same_element_result).first, 1u); + hud_assert_eq(std::get<0>(same_element_result).second, 0u); + hud_assert_eq(std::get<1>(same_element_result), 1u); + hud_assert_eq(std::get<2>(same_element_result), 1u); + hud_assert_eq(std::get<3>(same_element_result), 1u); + hud_assert_eq(std::get<4>(same_element_result), 1u); + hud_assert_eq(std::get<5>(same_element_result), 2u); + hud_assert_eq(std::get<6>(same_element_result), 0u); + + // 2nd element + const auto second_element_result = std::get<2>(result); + hud_assert_eq(std::get<0>(second_element_result).first, 2u); + hud_assert_eq(std::get<0>(second_element_result).second, 0u); + hud_assert_eq(std::get<1>(second_element_result), 2u); + hud_assert_eq(std::get<2>(second_element_result), 3u); + hud_assert_eq(std::get<3>(second_element_result), 1u); + hud_assert_eq(std::get<4>(second_element_result), 1u); + hud_assert_eq(std::get<5>(second_element_result), 4u); + hud_assert_eq(std::get<6>(second_element_result), 2u); + } + } + + // Without reallocation + { + const auto test = []() + { + hashmap_type map; + map.reserve(2); + const key_type key_to_copy(1); + + const auto it_1st = map.add(key_to_copy); + + const auto first_element_result = std::tuple { + *it_1st, + map.count(), + map.max_count(), + it_1st->first.copy_constructor_count(), + it_1st->second.copy_constructor_count(), + map.allocator().allocation_count(), + map.allocator().free_count(), + }; + const key_type key_to_copy_1(1); + const auto it_same = map.add(key_to_copy_1); + // Add same element + const auto same_element_result = std::tuple { + *it_same, + map.count(), + map.max_count(), + it_same->first.copy_constructor_count(), + it_same->second.copy_constructor_count(), + map.allocator().allocation_count(), + map.allocator().free_count(), + }; + const key_type key_to_copy_2(2); + const auto it_2nd = map.add(key_to_copy_2); + // Add 2nd element + const auto second_element_result = std::tuple { + *it_2nd, + map.count(), + map.max_count(), + it_2nd->first.copy_constructor_count(), + it_2nd->second.copy_constructor_count(), + map.allocator().allocation_count(), + map.allocator().free_count(), + }; + + return std::tuple { + first_element_result, + same_element_result, + second_element_result + }; + }; + + // Non Constant + { + const auto result = test(); + + // First element is correctly added + const auto first_element_result = std::get<0>(result); + hud_assert_eq(std::get<0>(first_element_result).first, 1u); + hud_assert_eq(std::get<0>(first_element_result).second, 0u); + hud_assert_eq(std::get<1>(first_element_result), 1u); + hud_assert_eq(std::get<2>(first_element_result), 3u); + hud_assert_eq(std::get<3>(first_element_result), 1u); + hud_assert_eq(std::get<4>(first_element_result), 1u); + hud_assert_eq(std::get<5>(first_element_result), 1u); + hud_assert_eq(std::get<6>(first_element_result), 0u); + + // Same element + const auto same_element_result = std::get<1>(result); + hud_assert_eq(std::get<0>(same_element_result).first, 1u); + hud_assert_eq(std::get<0>(same_element_result).second, 0u); + hud_assert_eq(std::get<1>(same_element_result), 1u); + hud_assert_eq(std::get<2>(same_element_result), 3u); + hud_assert_eq(std::get<3>(same_element_result), 1u); + hud_assert_eq(std::get<4>(same_element_result), 1u); + hud_assert_eq(std::get<5>(same_element_result), 1u); + hud_assert_eq(std::get<6>(same_element_result), 0u); + + // 2nd element + const auto second_element_result = std::get<2>(result); + hud_assert_eq(std::get<0>(second_element_result).first, 2u); + hud_assert_eq(std::get<0>(second_element_result).second, 0u); + hud_assert_eq(std::get<1>(second_element_result), 2u); + hud_assert_eq(std::get<2>(second_element_result), 3u); + hud_assert_eq(std::get<3>(second_element_result), 1u); + hud_assert_eq(std::get<4>(second_element_result), 1u); + hud_assert_eq(std::get<5>(second_element_result), 1u); + hud_assert_eq(std::get<6>(second_element_result), 0u); + } + + // Constant + { + constexpr auto result = test(); + + // First element is correctly added + const auto first_element_result = std::get<0>(result); + hud_assert_eq(std::get<0>(first_element_result).first, 1u); + hud_assert_eq(std::get<0>(first_element_result).second, 0u); + hud_assert_eq(std::get<1>(first_element_result), 1u); + hud_assert_eq(std::get<2>(first_element_result), 3u); + hud_assert_eq(std::get<3>(first_element_result), 1u); + hud_assert_eq(std::get<4>(first_element_result), 1u); + hud_assert_eq(std::get<5>(first_element_result), 2u); + hud_assert_eq(std::get<6>(first_element_result), 0u); + + // Same element + const auto same_element_result = std::get<1>(result); + hud_assert_eq(std::get<0>(same_element_result).first, 1u); + hud_assert_eq(std::get<0>(same_element_result).second, 0u); + hud_assert_eq(std::get<1>(same_element_result), 1u); + hud_assert_eq(std::get<2>(same_element_result), 3u); + hud_assert_eq(std::get<3>(same_element_result), 1u); + hud_assert_eq(std::get<4>(same_element_result), 1u); + hud_assert_eq(std::get<5>(same_element_result), 2u); + hud_assert_eq(std::get<6>(same_element_result), 0u); + + // 2nd element + const auto second_element_result = std::get<2>(result); + hud_assert_eq(std::get<0>(second_element_result).first, 2u); + hud_assert_eq(std::get<0>(second_element_result).second, 0u); + hud_assert_eq(std::get<1>(second_element_result), 2u); + hud_assert_eq(std::get<2>(second_element_result), 3u); + hud_assert_eq(std::get<3>(second_element_result), 1u); + hud_assert_eq(std::get<4>(second_element_result), 1u); + hud_assert_eq(std::get<5>(second_element_result), 2u); + hud_assert_eq(std::get<6>(second_element_result), 0u); + } + } +} + GTEST_TEST(hashmap, add_by_copy_construct_non_bitwise_copy_constructible_type) { using key_type = hud_test::non_bitwise_copy_constructible_type; @@ -24,7 +287,7 @@ GTEST_TEST(hashmap, add_by_copy_construct_non_bitwise_copy_constructible_type) map.count(), map.max_count(), it_1st->first.copy_constructor_count(), - it_1st->first.copy_constructor_count(), + it_1st->second.copy_constructor_count(), map.allocator().allocation_count(), map.allocator().free_count(), }; @@ -37,7 +300,7 @@ GTEST_TEST(hashmap, add_by_copy_construct_non_bitwise_copy_constructible_type) map.count(), map.max_count(), it_same->first.copy_constructor_count(), - it_same->first.copy_constructor_count(), + it_same->second.copy_constructor_count(), map.allocator().allocation_count(), map.allocator().free_count(), }; @@ -50,7 +313,7 @@ GTEST_TEST(hashmap, add_by_copy_construct_non_bitwise_copy_constructible_type) map.count(), map.max_count(), it_2nd->first.copy_constructor_count(), - it_2nd->first.copy_constructor_count(), + it_2nd->second.copy_constructor_count(), map.allocator().allocation_count(), map.allocator().free_count(), }; @@ -154,7 +417,7 @@ GTEST_TEST(hashmap, add_by_copy_construct_non_bitwise_copy_constructible_type) map.count(), map.max_count(), it_1st->first.copy_constructor_count(), - it_1st->first.copy_constructor_count(), + it_1st->second.copy_constructor_count(), map.allocator().allocation_count(), map.allocator().free_count(), }; @@ -167,7 +430,7 @@ GTEST_TEST(hashmap, add_by_copy_construct_non_bitwise_copy_constructible_type) map.count(), map.max_count(), it_same->first.copy_constructor_count(), - it_same->first.copy_constructor_count(), + it_same->second.copy_constructor_count(), map.allocator().allocation_count(), map.allocator().free_count(), }; @@ -180,7 +443,7 @@ GTEST_TEST(hashmap, add_by_copy_construct_non_bitwise_copy_constructible_type) map.count(), map.max_count(), it_2nd->first.copy_constructor_count(), - it_2nd->first.copy_constructor_count(), + it_2nd->second.copy_constructor_count(), map.allocator().allocation_count(), map.allocator().free_count(), }; @@ -503,7 +766,7 @@ GTEST_TEST(hashmap, add_by_copy_construct_bitwise_copy_constructible_type) } } -GTEST_TEST(hashmap, add_by_move_construct_non_bitwise_copy_constructible_type) +GTEST_TEST(hashmap, add_inplace_by_copy_construct_non_bitwise_copy_constructible_type) { using key_type = hud_test::non_bitwise_copy_constructible_type; using value_type = hud_test::non_bitwise_copy_constructible_type; @@ -517,42 +780,302 @@ GTEST_TEST(hashmap, add_by_move_construct_non_bitwise_copy_constructible_type) const auto test = []() { hashmap_type map; - key_type key_to_copy(1); - value_type value_to_copy(11); - const auto it_1st = map.add(hud::move(key_to_copy), hud::move(value_to_copy)); + const auto it_1st = map.add(1, 11); const auto first_element_result = std::tuple { *it_1st, map.count(), map.max_count(), it_1st->first.copy_constructor_count(), - it_1st->first.copy_constructor_count(), + it_1st->second.copy_constructor_count(), map.allocator().allocation_count(), map.allocator().free_count(), }; - key_type key_to_copy_1(1); - value_type value_to_copy_1(00); - const auto it_same = map.add(hud::move(key_to_copy_1), hud::move(value_to_copy_1)); + + const auto it_same = map.add(1, 00); // Add same element const auto same_element_result = std::tuple { *it_same, map.count(), map.max_count(), it_same->first.copy_constructor_count(), - it_same->first.copy_constructor_count(), + it_same->second.copy_constructor_count(), map.allocator().allocation_count(), map.allocator().free_count(), }; - key_type key_to_copy_2(2); - value_type value_to_copy_2(22); - const auto it_2nd = map.add(hud::move(key_to_copy_2), hud::move(value_to_copy_2)); + const auto it_2nd = map.add(2, 22); // Add 2nd element const auto second_element_result = std::tuple { *it_2nd, map.count(), map.max_count(), it_2nd->first.copy_constructor_count(), + it_2nd->second.copy_constructor_count(), + map.allocator().allocation_count(), + map.allocator().free_count(), + }; + + return std::tuple { + first_element_result, + same_element_result, + second_element_result + }; + }; + + // Non Constant + { + const auto result = test(); + + // First element is correctly added + const auto first_element_result = std::get<0>(result); + hud_assert_eq(std::get<0>(first_element_result).first, 1u); + hud_assert_eq(std::get<0>(first_element_result).second, 11u); + hud_assert_eq(std::get<1>(first_element_result), 1u); + hud_assert_eq(std::get<2>(first_element_result), 1u); + hud_assert_eq(std::get<3>(first_element_result), 1u); + hud_assert_eq(std::get<4>(first_element_result), 1u); + hud_assert_eq(std::get<5>(first_element_result), 1u); + hud_assert_eq(std::get<6>(first_element_result), 0u); + + // Same element + const auto same_element_result = std::get<1>(result); + hud_assert_eq(std::get<0>(same_element_result).first, 1u); + hud_assert_eq(std::get<0>(same_element_result).second, 11u); + hud_assert_eq(std::get<1>(same_element_result), 1u); + hud_assert_eq(std::get<2>(same_element_result), 1u); + hud_assert_eq(std::get<3>(same_element_result), 1u); + hud_assert_eq(std::get<4>(same_element_result), 1u); + hud_assert_eq(std::get<5>(same_element_result), 1u); + hud_assert_eq(std::get<6>(same_element_result), 0u); + + // 2nd element + const auto second_element_result = std::get<2>(result); + hud_assert_eq(std::get<0>(second_element_result).first, 2u); + hud_assert_eq(std::get<0>(second_element_result).second, 22u); + hud_assert_eq(std::get<1>(second_element_result), 2u); + hud_assert_eq(std::get<2>(second_element_result), 3u); + hud_assert_eq(std::get<3>(second_element_result), 1u); + hud_assert_eq(std::get<4>(second_element_result), 1u); + hud_assert_eq(std::get<5>(second_element_result), 2u); + hud_assert_eq(std::get<6>(second_element_result), 1u); + } + // Constant + { + constexpr auto result = test(); + + // First element is correctly added + const auto first_element_result = std::get<0>(result); + hud_assert_eq(std::get<0>(first_element_result).first, 1u); + hud_assert_eq(std::get<0>(first_element_result).second, 11u); + hud_assert_eq(std::get<1>(first_element_result), 1u); + hud_assert_eq(std::get<2>(first_element_result), 1u); + hud_assert_eq(std::get<3>(first_element_result), 1u); + hud_assert_eq(std::get<4>(first_element_result), 1u); + hud_assert_eq(std::get<5>(first_element_result), 2u); + hud_assert_eq(std::get<6>(first_element_result), 0u); + + // Same element + const auto same_element_result = std::get<1>(result); + hud_assert_eq(std::get<0>(same_element_result).first, 1u); + hud_assert_eq(std::get<0>(same_element_result).second, 11u); + hud_assert_eq(std::get<1>(same_element_result), 1u); + hud_assert_eq(std::get<2>(same_element_result), 1u); + hud_assert_eq(std::get<3>(same_element_result), 1u); + hud_assert_eq(std::get<4>(same_element_result), 1u); + hud_assert_eq(std::get<5>(same_element_result), 2u); + hud_assert_eq(std::get<6>(same_element_result), 0u); + + // 2nd element + const auto second_element_result = std::get<2>(result); + hud_assert_eq(std::get<0>(second_element_result).first, 2u); + hud_assert_eq(std::get<0>(second_element_result).second, 22u); + hud_assert_eq(std::get<1>(second_element_result), 2u); + hud_assert_eq(std::get<2>(second_element_result), 3u); + hud_assert_eq(std::get<3>(second_element_result), 1u); + hud_assert_eq(std::get<4>(second_element_result), 1u); + hud_assert_eq(std::get<5>(second_element_result), 4u); + hud_assert_eq(std::get<6>(second_element_result), 2u); + } + } + + // Without reallocation + { + const auto test = []() + { + hashmap_type map; + map.reserve(2); + + const auto it_1st = map.add(1, 11); + + const auto first_element_result = std::tuple { + *it_1st, + map.count(), + map.max_count(), + it_1st->first.copy_constructor_count(), + it_1st->second.copy_constructor_count(), + map.allocator().allocation_count(), + map.allocator().free_count(), + }; + const auto it_same = map.add(1, 00); + // Add same element + const auto same_element_result = std::tuple { + *it_same, + map.count(), + map.max_count(), + it_same->first.copy_constructor_count(), + it_same->second.copy_constructor_count(), + map.allocator().allocation_count(), + map.allocator().free_count(), + }; + const auto it_2nd = map.add(2, 22); + // Add 2nd element + const auto second_element_result = std::tuple { + *it_2nd, + map.count(), + map.max_count(), it_2nd->first.copy_constructor_count(), + it_2nd->second.copy_constructor_count(), + map.allocator().allocation_count(), + map.allocator().free_count(), + }; + + return std::tuple { + first_element_result, + same_element_result, + second_element_result + }; + }; + + // Non Constant + { + const auto result = test(); + + // First element is correctly added + const auto first_element_result = std::get<0>(result); + hud_assert_eq(std::get<0>(first_element_result).first, 1u); + hud_assert_eq(std::get<0>(first_element_result).second, 11u); + hud_assert_eq(std::get<1>(first_element_result), 1u); + hud_assert_eq(std::get<2>(first_element_result), 3u); + hud_assert_eq(std::get<3>(first_element_result), 1u); + hud_assert_eq(std::get<4>(first_element_result), 1u); + hud_assert_eq(std::get<5>(first_element_result), 1u); + hud_assert_eq(std::get<6>(first_element_result), 0u); + + // Same element + const auto same_element_result = std::get<1>(result); + hud_assert_eq(std::get<0>(same_element_result).first, 1u); + hud_assert_eq(std::get<0>(same_element_result).second, 11u); + hud_assert_eq(std::get<1>(same_element_result), 1u); + hud_assert_eq(std::get<2>(same_element_result), 3u); + hud_assert_eq(std::get<3>(same_element_result), 1u); + hud_assert_eq(std::get<4>(same_element_result), 1u); + hud_assert_eq(std::get<5>(same_element_result), 1u); + hud_assert_eq(std::get<6>(same_element_result), 0u); + + // 2nd element + const auto second_element_result = std::get<2>(result); + hud_assert_eq(std::get<0>(second_element_result).first, 2u); + hud_assert_eq(std::get<0>(second_element_result).second, 22u); + hud_assert_eq(std::get<1>(second_element_result), 2u); + hud_assert_eq(std::get<2>(second_element_result), 3u); + hud_assert_eq(std::get<3>(second_element_result), 1u); + hud_assert_eq(std::get<4>(second_element_result), 1u); + hud_assert_eq(std::get<5>(second_element_result), 1u); + hud_assert_eq(std::get<6>(second_element_result), 0u); + } + + // Constant + { + constexpr auto result = test(); + + // First element is correctly added + const auto first_element_result = std::get<0>(result); + hud_assert_eq(std::get<0>(first_element_result).first, 1u); + hud_assert_eq(std::get<0>(first_element_result).second, 11u); + hud_assert_eq(std::get<1>(first_element_result), 1u); + hud_assert_eq(std::get<2>(first_element_result), 3u); + hud_assert_eq(std::get<3>(first_element_result), 1u); + hud_assert_eq(std::get<4>(first_element_result), 1u); + hud_assert_eq(std::get<5>(first_element_result), 2u); + hud_assert_eq(std::get<6>(first_element_result), 0u); + + // Same element + const auto same_element_result = std::get<1>(result); + hud_assert_eq(std::get<0>(same_element_result).first, 1u); + hud_assert_eq(std::get<0>(same_element_result).second, 11u); + hud_assert_eq(std::get<1>(same_element_result), 1u); + hud_assert_eq(std::get<2>(same_element_result), 3u); + hud_assert_eq(std::get<3>(same_element_result), 1u); + hud_assert_eq(std::get<4>(same_element_result), 1u); + hud_assert_eq(std::get<5>(same_element_result), 2u); + hud_assert_eq(std::get<6>(same_element_result), 0u); + + // 2nd element + const auto second_element_result = std::get<2>(result); + hud_assert_eq(std::get<0>(second_element_result).first, 2u); + hud_assert_eq(std::get<0>(second_element_result).second, 22u); + hud_assert_eq(std::get<1>(second_element_result), 2u); + hud_assert_eq(std::get<2>(second_element_result), 3u); + hud_assert_eq(std::get<3>(second_element_result), 1u); + hud_assert_eq(std::get<4>(second_element_result), 1u); + hud_assert_eq(std::get<5>(second_element_result), 2u); + hud_assert_eq(std::get<6>(second_element_result), 0u); + } + } +} + +GTEST_TEST(hashmap, add_by_move_construct_non_bitwise_copy_constructible_type) +{ + using key_type = hud_test::non_bitwise_copy_constructible_type; + using value_type = hud_test::non_bitwise_copy_constructible_type; + using hashmap_type = hud::hashmap, hud::hashmap_default_key_equal, hud_test::allocator_watcher<1>>; + + static_assert(!hud::is_bitwise_copy_constructible_v); + static_assert(hud::is_copy_constructible_v); + static_assert(!hud::is_bitwise_copy_constructible_v); + static_assert(hud::is_copy_constructible_v); + + // With reallocation + { + const auto test = []() + { + hashmap_type map; + key_type key_to_copy(1); + value_type value_to_copy(11); + const auto it_1st = map.add(hud::move(key_to_copy), hud::move(value_to_copy)); + + const auto first_element_result = std::tuple { + *it_1st, + map.count(), + map.max_count(), + it_1st->first.copy_constructor_count(), + it_1st->second.copy_constructor_count(), + map.allocator().allocation_count(), + map.allocator().free_count(), + }; + key_type key_to_copy_1(1); + value_type value_to_copy_1(00); + const auto it_same = map.add(hud::move(key_to_copy_1), hud::move(value_to_copy_1)); + // Add same element + const auto same_element_result = std::tuple { + *it_same, + map.count(), + map.max_count(), + it_same->first.copy_constructor_count(), + it_same->second.copy_constructor_count(), + map.allocator().allocation_count(), + map.allocator().free_count(), + }; + key_type key_to_copy_2(2); + value_type value_to_copy_2(22); + const auto it_2nd = map.add(hud::move(key_to_copy_2), hud::move(value_to_copy_2)); + // Add 2nd element + const auto second_element_result = std::tuple { + *it_2nd, + map.count(), + map.max_count(), + it_2nd->first.copy_constructor_count(), + it_2nd->second.copy_constructor_count(), map.allocator().allocation_count(), map.allocator().free_count(), }; @@ -656,7 +1179,7 @@ GTEST_TEST(hashmap, add_by_move_construct_non_bitwise_copy_constructible_type) map.count(), map.max_count(), it_1st->first.copy_constructor_count(), - it_1st->first.copy_constructor_count(), + it_1st->second.copy_constructor_count(), map.allocator().allocation_count(), map.allocator().free_count(), }; @@ -669,7 +1192,7 @@ GTEST_TEST(hashmap, add_by_move_construct_non_bitwise_copy_constructible_type) map.count(), map.max_count(), it_same->first.copy_constructor_count(), - it_same->first.copy_constructor_count(), + it_same->second.copy_constructor_count(), map.allocator().allocation_count(), map.allocator().free_count(), }; @@ -682,7 +1205,7 @@ GTEST_TEST(hashmap, add_by_move_construct_non_bitwise_copy_constructible_type) map.count(), map.max_count(), it_2nd->first.copy_constructor_count(), - it_2nd->first.copy_constructor_count(), + it_2nd->second.copy_constructor_count(), map.allocator().allocation_count(), map.allocator().free_count(), }; @@ -1005,306 +1528,307 @@ GTEST_TEST(hashmap, add_by_move_construct_bitwise_copy_constructible_type) } } -// GTEST_TEST(array, add_by_move_construct_non_bitwise_move_constructible_type) -// { -// using key_type = hud_test::non_bitwise_copy_constructible_type; -// using value_type = hud_test::non_bitwise_copy_constructible_type; -// using hashmap_type = hud::hashmap, hud::hashmap_default_key_equal, hud_test::allocator_watcher<1>>; - -// static_assert(!hud::is_bitwise_copy_constructible_v); -// static_assert(!hud::is_bitwise_copy_constructible_v); - -// // With reallocation -// { -// const auto test = []() -// { -// hashmap_type map; -// const key_type key_to_copy(1); -// const value_type value_to_copy(11); -// const auto it_1st = map.add(key_to_copy, value_to_copy); - -// const auto first_element_result = std::tuple { -// *it_1st, -// map.count(), -// map.max_count(), -// it_1st->first.copy_constructor_count(), -// it_1st -// it_1st->first.copy_constructor_count(), -// map.allocator().allocation_count(), -// map.allocator().free_count(), -// }; -// const key_type key_to_copy_1(1); -// const value_type value_to_copy_1(00); -// const auto it_same = map.add(key_to_copy_1, value_to_copy_1); -// // Add same element -// const auto same_element_result = std::tuple { -// *it_same, -// map.count(), -// map.max_count(), -// it_same->first.copy_assign_count(), -// it_same->first.copy_constructor_count(), -// it_same->second.copy_assign_count(), -// it_same->first.copy_constructor_count(), -// map.allocator().allocation_count(), -// map.allocator().free_count(), -// }; -// const key_type key_to_copy_2(2); -// const value_type value_to_copy_2(22); -// const auto it_2nd = map.add(key_to_copy_2, value_to_copy_2); -// // Add 2nd element -// const auto second_element_result = std::tuple { -// *it_2nd, -// map.count(), -// map.max_count(), -// it_2nd->first.copy_assign_count(), -// it_2nd->first.copy_constructor_count(), -// it_2nd->second.copy_assign_count(), -// it_2nd->first.copy_constructor_count(), -// map.allocator().allocation_count(), -// map.allocator().free_count(), -// }; - -// return std::tuple { -// first_element_result, -// same_element_result, -// second_element_result -// }; -// }; - -// // Non Constant -// { -// const auto result = test(); - -// // First element is correctly added -// const auto first_element_result = std::get<0>(result); -// hud_assert_eq(std::get<0>(first_element_result).first, 1u); -// hud_assert_eq(std::get<0>(first_element_result).second, 11u); -// hud_assert_eq(std::get<1>(first_element_result), 1u); -// hud_assert_eq(std::get<2>(first_element_result), 1u); -// hud_assert_eq(std::get<3>(first_element_result), 0u); -// hud_assert_eq(std::get<4>(first_element_result), 1u); -// hud_assert_eq(std::get<5>(first_element_result), 0u); -// hud_assert_eq(std::get<6>(first_element_result), 1u); -// hud_assert_eq(std::get<7>(first_element_result), 1u); -// hud_assert_eq(std::get<8>(first_element_result), 0u); - -// // Same element -// const auto same_element_result = std::get<1>(result); -// hud_assert_eq(std::get<0>(same_element_result).first, 1u); -// hud_assert_eq(std::get<0>(same_element_result).second, 11u); -// hud_assert_eq(std::get<1>(same_element_result), 1u); -// hud_assert_eq(std::get<2>(same_element_result), 1u); -// hud_assert_eq(std::get<3>(same_element_result), 0u); -// hud_assert_eq(std::get<4>(same_element_result), 1u); -// hud_assert_eq(std::get<5>(same_element_result), 0u); -// hud_assert_eq(std::get<6>(same_element_result), 1u); -// hud_assert_eq(std::get<7>(same_element_result), 1u); -// hud_assert_eq(std::get<8>(same_element_result), 0u); - -// // 2nd element -// const auto second_element_result = std::get<2>(result); -// hud_assert_eq(std::get<0>(second_element_result).first, 2u); -// hud_assert_eq(std::get<0>(second_element_result).second, 22u); -// hud_assert_eq(std::get<1>(second_element_result), 2u); -// hud_assert_eq(std::get<2>(second_element_result), 3u); -// hud_assert_eq(std::get<3>(second_element_result), 0u); -// hud_assert_eq(std::get<4>(second_element_result), 1u); -// hud_assert_eq(std::get<5>(second_element_result), 0u); -// hud_assert_eq(std::get<6>(second_element_result), 1u); -// hud_assert_eq(std::get<7>(second_element_result), 2u); -// hud_assert_eq(std::get<8>(second_element_result), 1u); -// } -// // Constant -// { -// constexpr auto result = test(); - -// // First element is correctly added -// const auto first_element_result = std::get<0>(result); -// hud_assert_eq(std::get<0>(first_element_result).first, 1u); -// hud_assert_eq(std::get<0>(first_element_result).second, 11u); -// hud_assert_eq(std::get<1>(first_element_result), 1u); -// hud_assert_eq(std::get<2>(first_element_result), 1u); -// hud_assert_eq(std::get<3>(first_element_result), 0u); -// hud_assert_eq(std::get<4>(first_element_result), 1u); -// hud_assert_eq(std::get<5>(first_element_result), 0u); -// hud_assert_eq(std::get<6>(first_element_result), 1u); -// hud_assert_eq(std::get<7>(first_element_result), 2u); -// hud_assert_eq(std::get<8>(first_element_result), 0u); - -// // Same element -// const auto same_element_result = std::get<1>(result); -// hud_assert_eq(std::get<0>(same_element_result).first, 1u); -// hud_assert_eq(std::get<0>(same_element_result).second, 11u); -// hud_assert_eq(std::get<1>(same_element_result), 1u); -// hud_assert_eq(std::get<2>(same_element_result), 1u); -// hud_assert_eq(std::get<3>(same_element_result), 0u); -// hud_assert_eq(std::get<4>(same_element_result), 1u); -// hud_assert_eq(std::get<5>(same_element_result), 0u); -// hud_assert_eq(std::get<6>(same_element_result), 1u); -// hud_assert_eq(std::get<7>(same_element_result), 2u); -// hud_assert_eq(std::get<8>(same_element_result), 0u); - -// // 2nd element -// const auto second_element_result = std::get<2>(result); -// hud_assert_eq(std::get<0>(second_element_result).first, 2u); -// hud_assert_eq(std::get<0>(second_element_result).second, 22u); -// hud_assert_eq(std::get<1>(second_element_result), 2u); -// hud_assert_eq(std::get<2>(second_element_result), 3u); -// hud_assert_eq(std::get<3>(second_element_result), 0u); -// hud_assert_eq(std::get<4>(second_element_result), 1u); -// hud_assert_eq(std::get<5>(second_element_result), 0u); -// hud_assert_eq(std::get<6>(second_element_result), 1u); -// hud_assert_eq(std::get<7>(second_element_result), 4u); -// hud_assert_eq(std::get<8>(second_element_result), 2u); -// } -// } - -// // Without reallocation -// { -// const auto test = []() -// { -// hashmap_type map; -// map.reserve(2); -// const key_type key_to_copy(1); -// const value_type value_to_copy(11); - -// const auto it_1st = map.add(key_to_copy, value_to_copy); - -// const auto first_element_result = std::tuple { -// *it_1st, -// map.count(), -// map.max_count(), -// it_1st->first.copy_assign_count(), -// it_1st->first.copy_constructor_count(), -// it_1st->second.copy_assign_count(), -// it_1st->first.copy_constructor_count(), -// map.allocator().allocation_count(), -// map.allocator().free_count(), -// }; -// const key_type key_to_copy_1(1); -// const value_type value_to_copy_1(00); -// const auto it_same = map.add(key_to_copy_1, value_to_copy_1); -// // Add same element -// const auto same_element_result = std::tuple { -// *it_same, -// map.count(), -// map.max_count(), -// it_same->first.copy_assign_count(), -// it_same->first.copy_constructor_count(), -// it_same->second.copy_assign_count(), -// it_same->first.copy_constructor_count(), -// map.allocator().allocation_count(), -// map.allocator().free_count(), -// }; -// const key_type key_to_copy_2(2); -// const value_type value_to_copy_2(22); -// const auto it_2nd = map.add(key_to_copy_2, value_to_copy_2); -// // Add 2nd element -// const auto second_element_result = std::tuple { -// *it_2nd, -// map.count(), -// map.max_count(), -// it_2nd->first.copy_assign_count(), -// it_2nd->first.copy_constructor_count(), -// it_2nd->second.copy_assign_count(), -// it_2nd->first.copy_constructor_count(), -// map.allocator().allocation_count(), -// map.allocator().free_count(), -// }; - -// return std::tuple { -// first_element_result, -// same_element_result, -// second_element_result -// }; -// }; - -// // Non Constant -// { -// const auto result = test(); - -// // First element is correctly added -// const auto first_element_result = std::get<0>(result); -// hud_assert_eq(std::get<0>(first_element_result).first, 1u); -// hud_assert_eq(std::get<0>(first_element_result).second, 11u); -// hud_assert_eq(std::get<1>(first_element_result), 1u); -// hud_assert_eq(std::get<2>(first_element_result), 3u); -// hud_assert_eq(std::get<3>(first_element_result), 0u); -// hud_assert_eq(std::get<4>(first_element_result), 1u); -// hud_assert_eq(std::get<5>(first_element_result), 0u); -// hud_assert_eq(std::get<6>(first_element_result), 1u); -// hud_assert_eq(std::get<7>(first_element_result), 1u); -// hud_assert_eq(std::get<8>(first_element_result), 0u); - -// // Same element -// const auto same_element_result = std::get<1>(result); -// hud_assert_eq(std::get<0>(same_element_result).first, 1u); -// hud_assert_eq(std::get<0>(same_element_result).second, 11u); -// hud_assert_eq(std::get<1>(same_element_result), 1u); -// hud_assert_eq(std::get<2>(same_element_result), 3u); -// hud_assert_eq(std::get<3>(same_element_result), 0u); -// hud_assert_eq(std::get<4>(same_element_result), 1u); -// hud_assert_eq(std::get<5>(same_element_result), 0u); -// hud_assert_eq(std::get<6>(same_element_result), 1u); -// hud_assert_eq(std::get<7>(same_element_result), 1u); -// hud_assert_eq(std::get<8>(same_element_result), 0u); - -// // 2nd element -// const auto second_element_result = std::get<2>(result); -// hud_assert_eq(std::get<0>(second_element_result).first, 2u); -// hud_assert_eq(std::get<0>(second_element_result).second, 22u); -// hud_assert_eq(std::get<1>(second_element_result), 2u); -// hud_assert_eq(std::get<2>(second_element_result), 3u); -// hud_assert_eq(std::get<3>(second_element_result), 0u); -// hud_assert_eq(std::get<4>(second_element_result), 1u); -// hud_assert_eq(std::get<5>(second_element_result), 0u); -// hud_assert_eq(std::get<6>(second_element_result), 1u); -// hud_assert_eq(std::get<7>(second_element_result), 1u); -// hud_assert_eq(std::get<8>(second_element_result), 0u); -// } - -// // Constant -// { -// constexpr auto result = test(); - -// // First element is correctly added -// const auto first_element_result = std::get<0>(result); -// hud_assert_eq(std::get<0>(first_element_result).first, 1u); -// hud_assert_eq(std::get<0>(first_element_result).second, 11u); -// hud_assert_eq(std::get<1>(first_element_result), 1u); -// hud_assert_eq(std::get<2>(first_element_result), 3u); -// hud_assert_eq(std::get<3>(first_element_result), 0u); -// hud_assert_eq(std::get<4>(first_element_result), 1u); -// hud_assert_eq(std::get<5>(first_element_result), 0u); -// hud_assert_eq(std::get<6>(first_element_result), 1u); -// hud_assert_eq(std::get<7>(first_element_result), 2u); -// hud_assert_eq(std::get<8>(first_element_result), 0u); - -// // Same element -// const auto same_element_result = std::get<1>(result); -// hud_assert_eq(std::get<0>(same_element_result).first, 1u); -// hud_assert_eq(std::get<0>(same_element_result).second, 11u); -// hud_assert_eq(std::get<1>(same_element_result), 1u); -// hud_assert_eq(std::get<2>(same_element_result), 3u); -// hud_assert_eq(std::get<3>(same_element_result), 0u); -// hud_assert_eq(std::get<4>(same_element_result), 1u); -// hud_assert_eq(std::get<5>(same_element_result), 0u); -// hud_assert_eq(std::get<6>(same_element_result), 1u); -// hud_assert_eq(std::get<7>(same_element_result), 2u); -// hud_assert_eq(std::get<8>(same_element_result), 0u); - -// // 2nd element -// const auto second_element_result = std::get<2>(result); -// hud_assert_eq(std::get<0>(second_element_result).first, 2u); -// hud_assert_eq(std::get<0>(second_element_result).second, 22u); -// hud_assert_eq(std::get<1>(second_element_result), 2u); -// hud_assert_eq(std::get<2>(second_element_result), 3u); -// hud_assert_eq(std::get<3>(second_element_result), 0u); -// hud_assert_eq(std::get<4>(second_element_result), 1u); -// hud_assert_eq(std::get<5>(second_element_result), 0u); -// hud_assert_eq(std::get<6>(second_element_result), 1u); -// hud_assert_eq(std::get<7>(second_element_result), 2u); -// hud_assert_eq(std::get<8>(second_element_result), 0u); -// } -// } -// } \ No newline at end of file +GTEST_TEST(hashmap, add_by_move_construct_non_bitwise_move_constructible_type) +{ + using key_type = hud_test::non_bitwise_move_constructible_type; + using value_type = hud_test::non_bitwise_move_constructible_type; + using hashmap_type = hud::hashmap, hud::hashmap_default_key_equal, hud_test::allocator_watcher<1>>; + + static_assert(!hud::is_bitwise_move_constructible_v); + static_assert(!hud::is_bitwise_move_constructible_v); + + // With reallocation + { + const auto test = []() + { + hashmap_type map; + key_type key_to_copy(1); + value_type value_to_copy(11); + const auto it_1st = map.add(hud::move(key_to_copy), hud::move(value_to_copy)); + + const auto first_element_result = std::tuple { + *it_1st, + map.count(), + map.max_count(), + it_1st->first.copy_constructor_count(), + it_1st->first.move_constructor_count(), + it_1st->second.copy_constructor_count(), + it_1st->second.move_constructor_count(), + map.allocator().allocation_count(), + map.allocator().free_count(), + }; + key_type key_to_copy_1(1); + value_type value_to_copy_1(00); + const auto it_same = map.add(hud::move(key_to_copy_1), hud::move(value_to_copy_1)); + // Add same element + const auto same_element_result = std::tuple { + *it_same, + map.count(), + map.max_count(), + it_same->first.copy_constructor_count(), + it_same->first.move_constructor_count(), + it_same->second.copy_constructor_count(), + it_same->second.move_constructor_count(), + map.allocator().allocation_count(), + map.allocator().free_count(), + }; + key_type key_to_copy_2(2); + value_type value_to_copy_2(22); + const auto it_2nd = map.add(hud::move(key_to_copy_2), hud::move(value_to_copy_2)); + // Add 2nd element + const auto second_element_result = std::tuple { + *it_2nd, + map.count(), + map.max_count(), + it_2nd->first.copy_constructor_count(), + it_2nd->first.move_constructor_count(), + it_2nd->second.copy_constructor_count(), + it_2nd->second.move_constructor_count(), + map.allocator().allocation_count(), + map.allocator().free_count(), + }; + + return std::tuple { + first_element_result, + same_element_result, + second_element_result + }; + }; + + // Non Constant + { + const auto result = test(); + + // First element is correctly added + const auto first_element_result = std::get<0>(result); + hud_assert_eq(std::get<0>(first_element_result).first, 1u); + hud_assert_eq(std::get<0>(first_element_result).second, 11u); + hud_assert_eq(std::get<1>(first_element_result), 1u); + hud_assert_eq(std::get<2>(first_element_result), 1u); + hud_assert_eq(std::get<3>(first_element_result), 0u); + hud_assert_eq(std::get<4>(first_element_result), 1u); + hud_assert_eq(std::get<5>(first_element_result), 0u); + hud_assert_eq(std::get<6>(first_element_result), 1u); + hud_assert_eq(std::get<7>(first_element_result), 1u); + hud_assert_eq(std::get<8>(first_element_result), 0u); + + // Same element + const auto same_element_result = std::get<1>(result); + hud_assert_eq(std::get<0>(same_element_result).first, 1u); + hud_assert_eq(std::get<0>(same_element_result).second, 11u); + hud_assert_eq(std::get<1>(same_element_result), 1u); + hud_assert_eq(std::get<2>(same_element_result), 1u); + hud_assert_eq(std::get<3>(same_element_result), 0u); + hud_assert_eq(std::get<4>(same_element_result), 1u); + hud_assert_eq(std::get<5>(same_element_result), 0u); + hud_assert_eq(std::get<6>(same_element_result), 1u); + hud_assert_eq(std::get<7>(same_element_result), 1u); + hud_assert_eq(std::get<8>(same_element_result), 0u); + + // 2nd element + const auto second_element_result = std::get<2>(result); + hud_assert_eq(std::get<0>(second_element_result).first, 2u); + hud_assert_eq(std::get<0>(second_element_result).second, 22u); + hud_assert_eq(std::get<1>(second_element_result), 2u); + hud_assert_eq(std::get<2>(second_element_result), 3u); + hud_assert_eq(std::get<3>(second_element_result), 0u); + hud_assert_eq(std::get<4>(second_element_result), 1u); + hud_assert_eq(std::get<5>(second_element_result), 0u); + hud_assert_eq(std::get<6>(second_element_result), 1u); + hud_assert_eq(std::get<7>(second_element_result), 2u); + hud_assert_eq(std::get<8>(second_element_result), 1u); + } + // Constant + { + constexpr auto result = test(); + + // First element is correctly added + const auto first_element_result = std::get<0>(result); + hud_assert_eq(std::get<0>(first_element_result).first, 1u); + hud_assert_eq(std::get<0>(first_element_result).second, 11u); + hud_assert_eq(std::get<1>(first_element_result), 1u); + hud_assert_eq(std::get<2>(first_element_result), 1u); + hud_assert_eq(std::get<3>(first_element_result), 0u); + hud_assert_eq(std::get<4>(first_element_result), 1u); + hud_assert_eq(std::get<5>(first_element_result), 0u); + hud_assert_eq(std::get<6>(first_element_result), 1u); + hud_assert_eq(std::get<7>(first_element_result), 2u); + hud_assert_eq(std::get<8>(first_element_result), 0u); + + // Same element + const auto same_element_result = std::get<1>(result); + hud_assert_eq(std::get<0>(same_element_result).first, 1u); + hud_assert_eq(std::get<0>(same_element_result).second, 11u); + hud_assert_eq(std::get<1>(same_element_result), 1u); + hud_assert_eq(std::get<2>(same_element_result), 1u); + hud_assert_eq(std::get<3>(same_element_result), 0u); + hud_assert_eq(std::get<4>(same_element_result), 1u); + hud_assert_eq(std::get<5>(same_element_result), 0u); + hud_assert_eq(std::get<6>(same_element_result), 1u); + hud_assert_eq(std::get<7>(same_element_result), 2u); + hud_assert_eq(std::get<8>(same_element_result), 0u); + + // 2nd element + const auto second_element_result = std::get<2>(result); + hud_assert_eq(std::get<0>(second_element_result).first, 2u); + hud_assert_eq(std::get<0>(second_element_result).second, 22u); + hud_assert_eq(std::get<1>(second_element_result), 2u); + hud_assert_eq(std::get<2>(second_element_result), 3u); + hud_assert_eq(std::get<3>(second_element_result), 0u); + hud_assert_eq(std::get<4>(second_element_result), 1u); + hud_assert_eq(std::get<5>(second_element_result), 0u); + hud_assert_eq(std::get<6>(second_element_result), 1u); + hud_assert_eq(std::get<7>(second_element_result), 4u); + hud_assert_eq(std::get<8>(second_element_result), 2u); + } + } + + // Without reallocation + { + const auto test = []() + { + hashmap_type map; + map.reserve(2); + key_type key_to_copy(1); + value_type value_to_copy(11); + + const auto it_1st = map.add(hud::move(key_to_copy), hud::move(value_to_copy)); + + const auto first_element_result = std::tuple { + *it_1st, + map.count(), + map.max_count(), + it_1st->first.copy_constructor_count(), + it_1st->first.move_constructor_count(), + it_1st->second.copy_constructor_count(), + it_1st->second.move_constructor_count(), + map.allocator().allocation_count(), + map.allocator().free_count(), + }; + key_type key_to_copy_1(1); + value_type value_to_copy_1(00); + const auto it_same = map.add(hud::move(key_to_copy_1), hud::move(value_to_copy_1)); + // Add same element + const auto same_element_result = std::tuple { + *it_same, + map.count(), + map.max_count(), + it_same->first.copy_constructor_count(), + it_same->first.move_constructor_count(), + it_same->second.copy_constructor_count(), + it_same->second.move_constructor_count(), + map.allocator().allocation_count(), + map.allocator().free_count(), + }; + key_type key_to_copy_2(2); + value_type value_to_copy_2(22); + const auto it_2nd = map.add(hud::move(key_to_copy_2), hud::move(value_to_copy_2)); + // Add 2nd element + const auto second_element_result = std::tuple { + *it_2nd, + map.count(), + map.max_count(), + it_2nd->first.copy_constructor_count(), + it_2nd->first.move_constructor_count(), + it_2nd->second.copy_constructor_count(), + it_2nd->second.move_constructor_count(), + map.allocator().allocation_count(), + map.allocator().free_count(), + }; + + return std::tuple { + first_element_result, + same_element_result, + second_element_result + }; + }; + + // Non Constant + { + const auto result = test(); + + // First element is correctly added + const auto first_element_result = std::get<0>(result); + hud_assert_eq(std::get<0>(first_element_result).first, 1u); + hud_assert_eq(std::get<0>(first_element_result).second, 11u); + hud_assert_eq(std::get<1>(first_element_result), 1u); + hud_assert_eq(std::get<2>(first_element_result), 3u); + hud_assert_eq(std::get<3>(first_element_result), 0u); + hud_assert_eq(std::get<4>(first_element_result), 1u); + hud_assert_eq(std::get<5>(first_element_result), 0u); + hud_assert_eq(std::get<6>(first_element_result), 1u); + hud_assert_eq(std::get<7>(first_element_result), 1u); + hud_assert_eq(std::get<8>(first_element_result), 0u); + + // Same element + const auto same_element_result = std::get<1>(result); + hud_assert_eq(std::get<0>(same_element_result).first, 1u); + hud_assert_eq(std::get<0>(same_element_result).second, 11u); + hud_assert_eq(std::get<1>(same_element_result), 1u); + hud_assert_eq(std::get<2>(same_element_result), 3u); + hud_assert_eq(std::get<3>(same_element_result), 0u); + hud_assert_eq(std::get<4>(same_element_result), 1u); + hud_assert_eq(std::get<5>(same_element_result), 0u); + hud_assert_eq(std::get<6>(same_element_result), 1u); + hud_assert_eq(std::get<7>(same_element_result), 1u); + hud_assert_eq(std::get<8>(same_element_result), 0u); + + // 2nd element + const auto second_element_result = std::get<2>(result); + hud_assert_eq(std::get<0>(second_element_result).first, 2u); + hud_assert_eq(std::get<0>(second_element_result).second, 22u); + hud_assert_eq(std::get<1>(second_element_result), 2u); + hud_assert_eq(std::get<2>(second_element_result), 3u); + hud_assert_eq(std::get<3>(second_element_result), 0u); + hud_assert_eq(std::get<4>(second_element_result), 1u); + hud_assert_eq(std::get<5>(second_element_result), 0u); + hud_assert_eq(std::get<6>(second_element_result), 1u); + hud_assert_eq(std::get<7>(second_element_result), 1u); + hud_assert_eq(std::get<8>(second_element_result), 0u); + } + + // Constant + { + constexpr auto result = test(); + + // First element is correctly added + const auto first_element_result = std::get<0>(result); + hud_assert_eq(std::get<0>(first_element_result).first, 1u); + hud_assert_eq(std::get<0>(first_element_result).second, 11u); + hud_assert_eq(std::get<1>(first_element_result), 1u); + hud_assert_eq(std::get<2>(first_element_result), 3u); + hud_assert_eq(std::get<3>(first_element_result), 0u); + hud_assert_eq(std::get<4>(first_element_result), 1u); + hud_assert_eq(std::get<5>(first_element_result), 0u); + hud_assert_eq(std::get<6>(first_element_result), 1u); + hud_assert_eq(std::get<7>(first_element_result), 2u); + hud_assert_eq(std::get<8>(first_element_result), 0u); + + // Same element + const auto same_element_result = std::get<1>(result); + hud_assert_eq(std::get<0>(same_element_result).first, 1u); + hud_assert_eq(std::get<0>(same_element_result).second, 11u); + hud_assert_eq(std::get<1>(same_element_result), 1u); + hud_assert_eq(std::get<2>(same_element_result), 3u); + hud_assert_eq(std::get<3>(same_element_result), 0u); + hud_assert_eq(std::get<4>(same_element_result), 1u); + hud_assert_eq(std::get<5>(same_element_result), 0u); + hud_assert_eq(std::get<6>(same_element_result), 1u); + hud_assert_eq(std::get<7>(same_element_result), 2u); + hud_assert_eq(std::get<8>(same_element_result), 0u); + + // 2nd element + const auto second_element_result = std::get<2>(result); + hud_assert_eq(std::get<0>(second_element_result).first, 2u); + hud_assert_eq(std::get<0>(second_element_result).second, 22u); + hud_assert_eq(std::get<1>(second_element_result), 2u); + hud_assert_eq(std::get<2>(second_element_result), 3u); + hud_assert_eq(std::get<3>(second_element_result), 0u); + hud_assert_eq(std::get<4>(second_element_result), 1u); + hud_assert_eq(std::get<5>(second_element_result), 0u); + hud_assert_eq(std::get<6>(second_element_result), 1u); + hud_assert_eq(std::get<7>(second_element_result), 2u); + hud_assert_eq(std::get<8>(second_element_result), 0u); + } + } +} \ No newline at end of file diff --git a/test/hashmap/hashmap_find.cpp b/test/hashmap/hashmap_find.cpp index 30d1b5c..8a5532d 100644 --- a/test/hashmap/hashmap_find.cpp +++ b/test/hashmap/hashmap_find.cpp @@ -2,5 +2,11 @@ GTEST_TEST(hashmap, find) { - hud::hashmap map; + hud::hashmap map; + map.add(1, 11); + map.add(2, 22); + map.add(3, 33); + + auto it = map.find(1); + hud_assert_ne(it, map.end()); } \ No newline at end of file diff --git a/test/misc/non_bitwise_copy_assignable_type.h b/test/misc/non_bitwise_copy_assignable_type.h index 55b21a3..f931b69 100644 --- a/test/misc/non_bitwise_copy_assignable_type.h +++ b/test/misc/non_bitwise_copy_assignable_type.h @@ -303,24 +303,4 @@ namespace hud_test static_assert(!hud::is_bitwise_copy_constructible_v); } // namespace hud_test -namespace hud -{ - template<> - struct hash_32 - { - [[nodiscard]] constexpr u32 operator()(const hud_test::non_bitwise_copy_assignable_type &custom) const - { - return hud::hash_32 {}(custom.id()); - } - }; - - template<> - struct hash_64 - { - [[nodiscard]] constexpr u64 operator()(const hud_test::non_bitwise_copy_assignable_type &custom) const - { - return hud::hash_64 {}(custom.id()); - } - }; -} // namespace hud #endif // HD_INC_MISC_NON_BITWISE_COPY_CONSTRUCTIBLE_TYPE_H diff --git a/test/misc/non_bitwise_move_assignable_type.h b/test/misc/non_bitwise_move_assignable_type.h index 87b5e16..4215509 100644 --- a/test/misc/non_bitwise_move_assignable_type.h +++ b/test/misc/non_bitwise_move_assignable_type.h @@ -370,6 +370,7 @@ namespace hud_test static_assert(hud::is_move_constructible_v); static_assert(!hud::is_bitwise_move_assignable_v); static_assert(!hud::is_bitwise_move_constructible_v); + } // namespace hud_test #endif // HD_INC_MISC_NON_BITWISE_COPY_CONSTRUCTIBLE_TYPE_H diff --git a/test/misc/non_bitwise_move_constructible_type.h b/test/misc/non_bitwise_move_constructible_type.h index 28294c0..b1a66db 100644 --- a/test/misc/non_bitwise_move_constructible_type.h +++ b/test/misc/non_bitwise_move_constructible_type.h @@ -12,7 +12,6 @@ namespace hud_test */ struct non_bitwise_move_constructible_type { - constexpr non_bitwise_move_constructible_type() noexcept = default; /** @@ -73,6 +72,16 @@ namespace hud_test unique_id = id; } + friend constexpr bool operator==(const non_bitwise_move_constructible_type &a, const non_bitwise_move_constructible_type &b) noexcept + { + return a.id() == b.id(); + } + + friend constexpr bool operator!=(const non_bitwise_move_constructible_type &a, const non_bitwise_move_constructible_type &b) noexcept + { + return !(a == b); + } + private: non_bitwise_move_constructible_type &operator=(const non_bitwise_move_constructible_type &) = delete; non_bitwise_move_constructible_type &operator=(non_bitwise_move_constructible_type &&) = delete; @@ -262,4 +271,24 @@ namespace hud_test } // namespace hud_test +namespace hud +{ + template<> + struct hash_32 + { + [[nodiscard]] constexpr u32 operator()(const hud_test::non_bitwise_move_constructible_type &custom) const + { + return hud::hash_32 {}(custom.id()); + } + }; + + template<> + struct hash_64 + { + [[nodiscard]] constexpr u64 operator()(const hud_test::non_bitwise_move_constructible_type &custom) const + { + return hud::hash_64 {}(custom.id()); + } + }; +} // namespace hud #endif // HD_INC_MISC_NON_BITWISE_MOVE_CONSTRUCTIBLE_TYPE_H