diff --git a/interface/core/containers/hashmap.h b/interface/core/containers/hashmap.h index e63f288..422e431 100644 --- a/interface/core/containers/hashmap.h +++ b/interface/core/containers/hashmap.h @@ -165,21 +165,32 @@ namespace hud return add(hud::move(pair.first), hud::move(pair.second)); } }; -} // namespace hud -namespace std -{ + /** Specialize tuple_size for slot that permit structured binding. */ template struct tuple_size> - : std::integral_constant + : hud::integral_constant { }; + /** Specialize tuple_element for slot that permit structured binding. */ template struct tuple_element> { using type = std::conditional_t; }; +} // namespace hud + +namespace std +{ + + template + struct tuple_element> + : hud::tuple_element> + { + }; + } // namespace std + #endif // HD_INC_CORE_HASHMAP_H \ No newline at end of file diff --git a/interface/core/containers/hashset.h b/interface/core/containers/hashset.h index 71bf696..6f7222b 100644 --- a/interface/core/containers/hashset.h +++ b/interface/core/containers/hashset.h @@ -494,12 +494,12 @@ namespace hud return control_ptr_ != other.control_ptr_; } - template - requires(hud::is_same_v>) - friend constexpr decltype(auto) get(iterator_t &&it) noexcept - { - return get(*it); - } + // template + // requires(hud::is_same_v>) + // friend constexpr decltype(auto) get(iterator_t &&it) noexcept + // { + // return get(*it); + // } private: // The control to iterate over @@ -514,6 +514,30 @@ namespace hud usize slot_index_; }; + template + [[nodiscard]] HD_FORCEINLINE constexpr tuple_element_t> &get(iterator &it) noexcept + { + return get(*it); + } + + template + [[nodiscard]] HD_FORCEINLINE constexpr const tuple_element_t> &get(const iterator &it) noexcept + { + return get(*it); + } + + template + [[nodiscard]] HD_FORCEINLINE constexpr tuple_element_t> &&get(iterator &&it) noexcept + { + return hud::forward>>(get(*it)); + } + + template + [[nodiscard]] HD_FORCEINLINE constexpr const tuple_element_t> &&get(const iterator &&it) noexcept + { + return hud::forward>>(get(*it)); + } + template< typename slot_t, typename hasher_t, @@ -1069,23 +1093,56 @@ namespace hud public: /** Type of the hash function. */ using hasher_type = typename super::hasher_type; + /** Type of the key. */ + using key_type = typename super::key_type; /** Type of the value. */ using value_type = typename super::value_type; + using typename super::const_iterator; + using typename super::iterator; + }; + + /** Specialize tuple_size for slot that permit structured binding. */ + template + struct tuple_size> + : hud::integral_constant + { + }; + + /** Specialize tuple_element for slot that permit structured binding. */ + template + struct tuple_element> + { + using type = value_t; + }; + + /** Specialize tuple_size for iterator that permit structured binding. */ + template + struct tuple_size> + : hud::tuple_size::slot_type> + { + }; + + /** Specialize tuple_element for iterator that permit structured binding. */ + template + struct tuple_element> + : hud::tuple_element::slot_type> + { }; + } // namespace hud namespace std { template - struct tuple_size> - : tuple_size::slot_type> + struct tuple_size + : hud::tuple_size> { }; template struct tuple_element> + : hud::tuple_element> { - using type = tuple_element::slot_type>::type; }; } // namespace std diff --git a/interface/core/containers/tuple.h b/interface/core/containers/tuple.h index a2d08eb..0e9bbac 100644 --- a/interface/core/containers/tuple.h +++ b/interface/core/containers/tuple.h @@ -1024,4 +1024,19 @@ namespace hud } // namespace hud +namespace std +{ + template + struct tuple_size> + : hud::tuple_size> + { + }; + + template + struct tuple_element> + : hud::tuple_element> + { + }; + +} // namespace std #endif // HD_INC_CORE_TUPLE_H \ No newline at end of file diff --git a/test/pair/pair_misc.cpp b/test/pair/pair_misc.cpp index 59cb962..ed01aac 100644 --- a/test/pair/pair_misc.cpp +++ b/test/pair/pair_misc.cpp @@ -177,7 +177,7 @@ GTEST_TEST(pair, tuple_element) hud_assert_true(is_tuple_element_1_same); } -GTEST_TEST(pair, structure_binding) +GTEST_TEST(pair, structure_binding_by_copy) { using type = hud_test::non_bitwise_type; static_assert(hud::is_constructible_v); @@ -186,8 +186,9 @@ GTEST_TEST(pair, structure_binding) const auto test = [](type &&t1, type &&t2) { const auto pair = hud::make_pair(hud::move(t1), hud::move(t2)); - auto &[first_cpy, second_cpy] = pair; - + auto [first_cpy, second_cpy] = pair; + first_cpy = type {321, nullptr}; + second_cpy = type {654, nullptr}; return std::tuple { first_cpy.constructor_count(), first_cpy.move_constructor_count(), @@ -199,6 +200,247 @@ GTEST_TEST(pair, structure_binding) second_cpy.copy_constructor_count(), second_cpy.move_assign_count(), second_cpy.copy_assign_count(), + hud::get<0>(pair).id() == 123, + hud::get<1>(pair).id() == 456 + }; + }; + // Non constant + { + const auto result = test(type {123, nullptr}, type {456, nullptr}); + hud_assert_eq(std::get<0>(result), 1); + hud_assert_eq(std::get<1>(result), 0); + hud_assert_eq(std::get<2>(result), 0); + hud_assert_eq(std::get<3>(result), 1); + hud_assert_eq(std::get<4>(result), 0); + hud_assert_eq(std::get<5>(result), 1); + hud_assert_eq(std::get<6>(result), 0); + hud_assert_eq(std::get<7>(result), 0); + hud_assert_eq(std::get<8>(result), 1); + hud_assert_eq(std::get<9>(result), 0); + hud_assert_true(std::get<10>(result)); + hud_assert_true(std::get<11>(result)); + } + + // Non constant + { + constexpr auto result = test(type {123, nullptr}, type {456, nullptr}); + hud_assert_eq(std::get<0>(result), 1); + hud_assert_eq(std::get<1>(result), 0); + hud_assert_eq(std::get<2>(result), 0); + hud_assert_eq(std::get<3>(result), 1); + hud_assert_eq(std::get<4>(result), 0); + hud_assert_eq(std::get<5>(result), 1); + hud_assert_eq(std::get<6>(result), 0); + hud_assert_eq(std::get<7>(result), 0); + hud_assert_eq(std::get<8>(result), 1); + hud_assert_eq(std::get<9>(result), 0); + hud_assert_true(std::get<10>(result)); + hud_assert_true(std::get<11>(result)); + } +} + +GTEST_TEST(pair, structure_binding_rvalue) +{ + using type = hud_test::non_bitwise_type; + static_assert(hud::is_constructible_v); + static_assert(!hud::is_trivially_constructible_v); + + const auto test = [](type &&t1, type &&t2) + { + auto pair = hud::make_pair(hud::move(t1), hud::move(t2)); + auto &[first_ref, second_ref] = pair; + first_ref = type {951, nullptr}; + second_ref = type {357, nullptr}; + return std::tuple { + first_ref.constructor_count(), + first_ref.move_constructor_count(), + first_ref.copy_constructor_count(), + first_ref.move_assign_count(), + first_ref.copy_assign_count(), + second_ref.constructor_count(), + second_ref.move_constructor_count(), + second_ref.copy_constructor_count(), + second_ref.move_assign_count(), + second_ref.copy_assign_count(), + hud::get<0>(pair).id() == 951, + hud::get<1>(pair).id() == 357 + }; + }; + // Non constant + { + const auto result = test(type {123, nullptr}, type {456, nullptr}); + hud_assert_eq(std::get<0>(result), 1); + hud_assert_eq(std::get<1>(result), 0); + hud_assert_eq(std::get<2>(result), 0); + hud_assert_eq(std::get<3>(result), 1); + hud_assert_eq(std::get<4>(result), 0); + hud_assert_eq(std::get<5>(result), 1); + hud_assert_eq(std::get<6>(result), 0); + hud_assert_eq(std::get<7>(result), 0); + hud_assert_eq(std::get<8>(result), 1); + hud_assert_eq(std::get<9>(result), 0); + hud_assert_true(std::get<10>(result)); + hud_assert_true(std::get<11>(result)); + } + + // Non constant + { + constexpr auto result = test(type {123, nullptr}, type {456, nullptr}); + hud_assert_eq(std::get<0>(result), 1); + hud_assert_eq(std::get<1>(result), 0); + hud_assert_eq(std::get<2>(result), 0); + hud_assert_eq(std::get<3>(result), 1); + hud_assert_eq(std::get<4>(result), 0); + hud_assert_eq(std::get<5>(result), 1); + hud_assert_eq(std::get<6>(result), 0); + hud_assert_eq(std::get<7>(result), 0); + hud_assert_eq(std::get<8>(result), 1); + hud_assert_eq(std::get<9>(result), 0); + hud_assert_true(std::get<10>(result)); + hud_assert_true(std::get<11>(result)); + } +} + +GTEST_TEST(pair, structure_binding_const_rvalue) +{ + using type = hud_test::non_bitwise_type; + static_assert(hud::is_constructible_v); + static_assert(!hud::is_trivially_constructible_v); + + const auto test = [](type &&t1, type &&t2) + { + auto pair = hud::make_pair(hud::move(t1), hud::move(t2)); + const auto &[first_ref, second_ref] = pair; + return std::tuple { + first_ref.constructor_count(), + first_ref.move_constructor_count(), + first_ref.copy_constructor_count(), + first_ref.move_assign_count(), + first_ref.copy_assign_count(), + second_ref.constructor_count(), + second_ref.move_constructor_count(), + second_ref.copy_constructor_count(), + second_ref.move_assign_count(), + second_ref.copy_assign_count(), + }; + }; + // Non constant + { + const auto result = test(type {123, nullptr}, type {456, nullptr}); + hud_assert_eq(std::get<0>(result), 1); + hud_assert_eq(std::get<1>(result), 1); + hud_assert_eq(std::get<2>(result), 0); + hud_assert_eq(std::get<3>(result), 0); + hud_assert_eq(std::get<4>(result), 0); + hud_assert_eq(std::get<5>(result), 1); + hud_assert_eq(std::get<6>(result), 1); + hud_assert_eq(std::get<7>(result), 0); + hud_assert_eq(std::get<8>(result), 0); + hud_assert_eq(std::get<9>(result), 0); + } + + // Non constant + { + constexpr auto result = test(type {123, nullptr}, type {456, nullptr}); + hud_assert_eq(std::get<0>(result), 1); + hud_assert_eq(std::get<1>(result), 1); + hud_assert_eq(std::get<2>(result), 0); + hud_assert_eq(std::get<3>(result), 0); + hud_assert_eq(std::get<4>(result), 0); + hud_assert_eq(std::get<5>(result), 1); + hud_assert_eq(std::get<6>(result), 1); + hud_assert_eq(std::get<7>(result), 0); + hud_assert_eq(std::get<8>(result), 0); + hud_assert_eq(std::get<9>(result), 0); + } +} + +GTEST_TEST(pair, structure_binding_pair_lvalue) +{ + using type = hud_test::non_bitwise_type; + static_assert(hud::is_constructible_v); + static_assert(!hud::is_trivially_constructible_v); + + const auto test = [](type &&t1, type &&t2) + { + auto pair = hud::make_pair(hud::move(t1), hud::move(t2)); + auto &&[first_ref, second_ref] = pair; + first_ref = type {951, nullptr}; + second_ref = type {357, nullptr}; + return std::tuple { + first_ref.constructor_count(), + first_ref.move_constructor_count(), + first_ref.copy_constructor_count(), + first_ref.move_assign_count(), + first_ref.copy_assign_count(), + second_ref.constructor_count(), + second_ref.move_constructor_count(), + second_ref.copy_constructor_count(), + second_ref.move_assign_count(), + second_ref.copy_assign_count(), + hud::get<0>(pair).id() == 951, + hud::get<1>(pair).id() == 357 + }; + }; + // Non constant + { + const auto result = test(type {123, nullptr}, type {456, nullptr}); + hud_assert_eq(std::get<0>(result), 1); + hud_assert_eq(std::get<1>(result), 0); + hud_assert_eq(std::get<2>(result), 0); + hud_assert_eq(std::get<3>(result), 1); + hud_assert_eq(std::get<4>(result), 0); + hud_assert_eq(std::get<5>(result), 1); + hud_assert_eq(std::get<6>(result), 0); + hud_assert_eq(std::get<7>(result), 0); + hud_assert_eq(std::get<8>(result), 1); + hud_assert_eq(std::get<9>(result), 0); + hud_assert_true(std::get<10>(result)); + hud_assert_true(std::get<11>(result)); + } + + // Non constant + { + constexpr auto result = test(type {123, nullptr}, type {456, nullptr}); + hud_assert_eq(std::get<0>(result), 1); + hud_assert_eq(std::get<1>(result), 0); + hud_assert_eq(std::get<2>(result), 0); + hud_assert_eq(std::get<3>(result), 1); + hud_assert_eq(std::get<4>(result), 0); + hud_assert_eq(std::get<5>(result), 1); + hud_assert_eq(std::get<6>(result), 0); + hud_assert_eq(std::get<7>(result), 0); + hud_assert_eq(std::get<8>(result), 1); + hud_assert_eq(std::get<9>(result), 0); + hud_assert_true(std::get<10>(result)); + hud_assert_true(std::get<11>(result)); + } +} + +GTEST_TEST(pair, structure_binding_const_pair_lvalue) +{ + using type = hud_test::non_bitwise_type; + static_assert(hud::is_constructible_v); + static_assert(!hud::is_trivially_constructible_v); + + const auto test = [](type &&t1, type &&t2) + { + const auto pair = hud::make_pair(hud::move(t1), hud::move(t2)); + auto &&[first_ref, second_ref] = pair; + // Not possible, pair is const + // first_ref = type {951, nullptr}; + // second_ref = type {357, nullptr}; + return std::tuple { + first_ref.constructor_count(), + first_ref.move_constructor_count(), + first_ref.copy_constructor_count(), + first_ref.move_assign_count(), + first_ref.copy_assign_count(), + second_ref.constructor_count(), + second_ref.move_constructor_count(), + second_ref.copy_constructor_count(), + second_ref.move_assign_count(), + second_ref.copy_assign_count(), }; }; // Non constant diff --git a/test/tuple/tuple_misc.cpp b/test/tuple/tuple_misc.cpp index 0c553bf..9a5117b 100644 --- a/test/tuple/tuple_misc.cpp +++ b/test/tuple/tuple_misc.cpp @@ -49,7 +49,8 @@ GTEST_TEST(tuple, get) hud::get<2>(tuple) == L'w', hud::get<0>(hud::move(tuple)) == 12, hud::get<1>(hud::move(tuple)) == 15.0f, - hud::get<2>(hud::move(tuple)) == L'w'}; + hud::get<2>(hud::move(tuple)) == L'w' + }; }; // Non constant @@ -130,4 +131,408 @@ GTEST_TEST(tuple, tuple_cat) using EmptyCatType = decltype(hud::tuple_cat()); hud_assert_eq(hud::tuple_size_v, 0u); +} + +GTEST_TEST(tuple, structure_binding_by_copy) +{ + using type = hud_test::non_bitwise_type; + static_assert(hud::is_constructible_v); + static_assert(!hud::is_trivially_constructible_v); + + const auto test = [](type &&t1, type &&t2, type &&t3) + { + auto tuple = hud::make_tuple(hud::move(t1), hud::move(t2), hud::move(t3)); + auto [first_cpy, second_cpy, third_cpy] = tuple; + first_cpy = type {321, nullptr}; + second_cpy = type {654, nullptr}; + third_cpy = type {987, nullptr}; + return std::tuple { + first_cpy.constructor_count(), + first_cpy.move_constructor_count(), + first_cpy.copy_constructor_count(), + first_cpy.move_assign_count(), + first_cpy.copy_assign_count(), + second_cpy.constructor_count(), + second_cpy.move_constructor_count(), + second_cpy.copy_constructor_count(), + second_cpy.move_assign_count(), + second_cpy.copy_assign_count(), + third_cpy.constructor_count(), + third_cpy.move_constructor_count(), + third_cpy.copy_constructor_count(), + third_cpy.move_assign_count(), + third_cpy.copy_assign_count(), + hud::get<0>(tuple).id() == 123, + hud::get<1>(tuple).id() == 456, + hud::get<2>(tuple).id() == 789 + }; + }; + // Non constant + { + const auto result = test(type {123, nullptr}, type {456, nullptr}, type {789, nullptr}); + hud_assert_eq(std::get<0>(result), 1); + hud_assert_eq(std::get<1>(result), 0); + hud_assert_eq(std::get<2>(result), 0); + hud_assert_eq(std::get<3>(result), 1); + hud_assert_eq(std::get<4>(result), 0); + hud_assert_eq(std::get<5>(result), 1); + hud_assert_eq(std::get<6>(result), 0); + hud_assert_eq(std::get<7>(result), 0); + hud_assert_eq(std::get<8>(result), 1); + hud_assert_eq(std::get<9>(result), 0); + hud_assert_eq(std::get<10>(result), 1); + hud_assert_eq(std::get<11>(result), 0); + hud_assert_eq(std::get<12>(result), 0); + hud_assert_eq(std::get<13>(result), 1); + hud_assert_eq(std::get<14>(result), 0); + hud_assert_true(std::get<15>(result)); + hud_assert_true(std::get<16>(result)); + hud_assert_true(std::get<17>(result)); + } + + // Non constant + { + constexpr auto result = test(type {123, nullptr}, type {456, nullptr}, type {789, nullptr}); + hud_assert_eq(std::get<0>(result), 1); + hud_assert_eq(std::get<1>(result), 0); + hud_assert_eq(std::get<2>(result), 0); + hud_assert_eq(std::get<3>(result), 1); + hud_assert_eq(std::get<4>(result), 0); + hud_assert_eq(std::get<5>(result), 1); + hud_assert_eq(std::get<6>(result), 0); + hud_assert_eq(std::get<7>(result), 0); + hud_assert_eq(std::get<8>(result), 1); + hud_assert_eq(std::get<9>(result), 0); + hud_assert_eq(std::get<10>(result), 1); + hud_assert_eq(std::get<11>(result), 0); + hud_assert_eq(std::get<12>(result), 0); + hud_assert_eq(std::get<13>(result), 1); + hud_assert_eq(std::get<14>(result), 0); + hud_assert_true(std::get<15>(result)); + hud_assert_true(std::get<16>(result)); + hud_assert_true(std::get<17>(result)); + } +} + +GTEST_TEST(tuple, structure_binding_rvalue) +{ + using type = hud_test::non_bitwise_type; + static_assert(hud::is_constructible_v); + static_assert(!hud::is_trivially_constructible_v); + + const auto test = [](type &&t1, type &&t2, type &&t3) + { + auto tuple = hud::make_tuple(hud::move(t1), hud::move(t2), hud::move(t3)); + auto &[first_ref, second_ref, third_ref] = tuple; + first_ref = type {321, nullptr}; + second_ref = type {654, nullptr}; + third_ref = type {987, nullptr}; + return std::tuple { + first_ref.constructor_count(), + first_ref.move_constructor_count(), + first_ref.copy_constructor_count(), + first_ref.move_assign_count(), + first_ref.copy_assign_count(), + second_ref.constructor_count(), + second_ref.move_constructor_count(), + second_ref.copy_constructor_count(), + second_ref.move_assign_count(), + second_ref.copy_assign_count(), + third_ref.constructor_count(), + third_ref.move_constructor_count(), + third_ref.copy_constructor_count(), + third_ref.move_assign_count(), + third_ref.copy_assign_count(), + hud::get<0>(tuple).id() == 321, + hud::get<1>(tuple).id() == 654, + hud::get<2>(tuple).id() == 987 + }; + }; + // Non constant + { + const auto result = test(type {123, nullptr}, type {456, nullptr}, type {789, nullptr}); + hud_assert_eq(std::get<0>(result), 1); + hud_assert_eq(std::get<1>(result), 0); + hud_assert_eq(std::get<2>(result), 0); + hud_assert_eq(std::get<3>(result), 1); + hud_assert_eq(std::get<4>(result), 0); + hud_assert_eq(std::get<5>(result), 1); + hud_assert_eq(std::get<6>(result), 0); + hud_assert_eq(std::get<7>(result), 0); + hud_assert_eq(std::get<8>(result), 1); + hud_assert_eq(std::get<9>(result), 0); + hud_assert_eq(std::get<10>(result), 1); + hud_assert_eq(std::get<11>(result), 0); + hud_assert_eq(std::get<12>(result), 0); + hud_assert_eq(std::get<13>(result), 1); + hud_assert_eq(std::get<14>(result), 0); + hud_assert_true(std::get<15>(result)); + hud_assert_true(std::get<16>(result)); + hud_assert_true(std::get<17>(result)); + } + + // Non constant + { + constexpr auto result = test(type {123, nullptr}, type {456, nullptr}, type {789, nullptr}); + hud_assert_eq(std::get<0>(result), 1); + hud_assert_eq(std::get<1>(result), 0); + hud_assert_eq(std::get<2>(result), 0); + hud_assert_eq(std::get<3>(result), 1); + hud_assert_eq(std::get<4>(result), 0); + hud_assert_eq(std::get<5>(result), 1); + hud_assert_eq(std::get<6>(result), 0); + hud_assert_eq(std::get<7>(result), 0); + hud_assert_eq(std::get<8>(result), 1); + hud_assert_eq(std::get<9>(result), 0); + hud_assert_eq(std::get<10>(result), 1); + hud_assert_eq(std::get<11>(result), 0); + hud_assert_eq(std::get<12>(result), 0); + hud_assert_eq(std::get<13>(result), 1); + hud_assert_eq(std::get<14>(result), 0); + hud_assert_true(std::get<15>(result)); + hud_assert_true(std::get<16>(result)); + hud_assert_true(std::get<17>(result)); + } +} + +GTEST_TEST(tuple, structure_binding_const_rvalue) +{ + using type = hud_test::non_bitwise_type; + static_assert(hud::is_constructible_v); + static_assert(!hud::is_trivially_constructible_v); + + const auto test = [](type &&t1, type &&t2, type &&t3) + { + auto tuple = hud::make_tuple(hud::move(t1), hud::move(t2), hud::move(t3)); + const auto &[first_ref, second_ref, third_ref] = tuple; + return std::tuple { + first_ref.constructor_count(), + first_ref.move_constructor_count(), + first_ref.copy_constructor_count(), + first_ref.move_assign_count(), + first_ref.copy_assign_count(), + second_ref.constructor_count(), + second_ref.move_constructor_count(), + second_ref.copy_constructor_count(), + second_ref.move_assign_count(), + second_ref.copy_assign_count(), + third_ref.constructor_count(), + third_ref.move_constructor_count(), + third_ref.copy_constructor_count(), + third_ref.move_assign_count(), + third_ref.copy_assign_count(), + hud::get<0>(tuple).id() == 123, + hud::get<1>(tuple).id() == 456, + hud::get<2>(tuple).id() == 789 + }; + }; + + // Non constant + { + const auto result = test(type {123, nullptr}, type {456, nullptr}, type {789, nullptr}); + hud_assert_eq(std::get<0>(result), 1); + hud_assert_eq(std::get<1>(result), 1); + hud_assert_eq(std::get<2>(result), 0); + hud_assert_eq(std::get<3>(result), 0); + hud_assert_eq(std::get<4>(result), 0); + hud_assert_eq(std::get<5>(result), 1); + hud_assert_eq(std::get<6>(result), 1); + hud_assert_eq(std::get<7>(result), 0); + hud_assert_eq(std::get<8>(result), 0); + hud_assert_eq(std::get<9>(result), 0); + hud_assert_eq(std::get<10>(result), 1); + hud_assert_eq(std::get<11>(result), 1); + hud_assert_eq(std::get<12>(result), 0); + hud_assert_eq(std::get<13>(result), 0); + hud_assert_eq(std::get<14>(result), 0); + hud_assert_true(std::get<15>(result)); + hud_assert_true(std::get<16>(result)); + hud_assert_true(std::get<17>(result)); + } + + // Non constant + { + constexpr auto result = test(type {123, nullptr}, type {456, nullptr}, type {789, nullptr}); + hud_assert_eq(std::get<0>(result), 1); + hud_assert_eq(std::get<1>(result), 1); + hud_assert_eq(std::get<2>(result), 0); + hud_assert_eq(std::get<3>(result), 0); + hud_assert_eq(std::get<4>(result), 0); + hud_assert_eq(std::get<5>(result), 1); + hud_assert_eq(std::get<6>(result), 1); + hud_assert_eq(std::get<7>(result), 0); + hud_assert_eq(std::get<8>(result), 0); + hud_assert_eq(std::get<9>(result), 0); + hud_assert_eq(std::get<10>(result), 1); + hud_assert_eq(std::get<11>(result), 1); + hud_assert_eq(std::get<12>(result), 0); + hud_assert_eq(std::get<13>(result), 0); + hud_assert_eq(std::get<14>(result), 0); + hud_assert_true(std::get<15>(result)); + hud_assert_true(std::get<16>(result)); + hud_assert_true(std::get<17>(result)); + } +} + +GTEST_TEST(tuple, structure_binding_lvalue) +{ + using type = hud_test::non_bitwise_type; + static_assert(hud::is_constructible_v); + static_assert(!hud::is_trivially_constructible_v); + + const auto test = [](type &&t1, type &&t2, type &&t3) + { + auto tuple = hud::make_tuple(hud::move(t1), hud::move(t2), hud::move(t3)); + auto &[first_ref, second_ref, third_ref] = tuple; + first_ref = type {321, nullptr}; + second_ref = type {654, nullptr}; + third_ref = type {987, nullptr}; + return std::tuple { + first_ref.constructor_count(), + first_ref.move_constructor_count(), + first_ref.copy_constructor_count(), + first_ref.move_assign_count(), + first_ref.copy_assign_count(), + second_ref.constructor_count(), + second_ref.move_constructor_count(), + second_ref.copy_constructor_count(), + second_ref.move_assign_count(), + second_ref.copy_assign_count(), + third_ref.constructor_count(), + third_ref.move_constructor_count(), + third_ref.copy_constructor_count(), + third_ref.move_assign_count(), + third_ref.copy_assign_count(), + hud::get<0>(tuple).id() == 321, + hud::get<1>(tuple).id() == 654, + hud::get<2>(tuple).id() == 987 + }; + }; + // Non constant + { + const auto result = test(type {123, nullptr}, type {456, nullptr}, type {789, nullptr}); + hud_assert_eq(std::get<0>(result), 1); + hud_assert_eq(std::get<1>(result), 0); + hud_assert_eq(std::get<2>(result), 0); + hud_assert_eq(std::get<3>(result), 1); + hud_assert_eq(std::get<4>(result), 0); + hud_assert_eq(std::get<5>(result), 1); + hud_assert_eq(std::get<6>(result), 0); + hud_assert_eq(std::get<7>(result), 0); + hud_assert_eq(std::get<8>(result), 1); + hud_assert_eq(std::get<9>(result), 0); + hud_assert_eq(std::get<10>(result), 1); + hud_assert_eq(std::get<11>(result), 0); + hud_assert_eq(std::get<12>(result), 0); + hud_assert_eq(std::get<13>(result), 1); + hud_assert_eq(std::get<14>(result), 0); + hud_assert_true(std::get<15>(result)); + hud_assert_true(std::get<16>(result)); + hud_assert_true(std::get<17>(result)); + } + + // Non constant + { + constexpr auto result = test(type {123, nullptr}, type {456, nullptr}, type {789, nullptr}); + hud_assert_eq(std::get<0>(result), 1); + hud_assert_eq(std::get<1>(result), 0); + hud_assert_eq(std::get<2>(result), 0); + hud_assert_eq(std::get<3>(result), 1); + hud_assert_eq(std::get<4>(result), 0); + hud_assert_eq(std::get<5>(result), 1); + hud_assert_eq(std::get<6>(result), 0); + hud_assert_eq(std::get<7>(result), 0); + hud_assert_eq(std::get<8>(result), 1); + hud_assert_eq(std::get<9>(result), 0); + hud_assert_eq(std::get<10>(result), 1); + hud_assert_eq(std::get<11>(result), 0); + hud_assert_eq(std::get<12>(result), 0); + hud_assert_eq(std::get<13>(result), 1); + hud_assert_eq(std::get<14>(result), 0); + hud_assert_true(std::get<15>(result)); + hud_assert_true(std::get<16>(result)); + hud_assert_true(std::get<17>(result)); + } +} + +GTEST_TEST(tuple, structure_binding_const_tuple_lvalue) +{ + using type = hud_test::non_bitwise_type; + static_assert(hud::is_constructible_v); + static_assert(!hud::is_trivially_constructible_v); + + const auto test = [](type &&t1, type &&t2, type &&t3) + { + const auto tuple = hud::make_tuple(hud::move(t1), hud::move(t2), hud::move(t3)); + auto &[first_ref, second_ref, third_ref] = tuple; + // Not possible, tuple is const + // first_ref = type {321, nullptr}; + // second_ref = type {654, nullptr}; + // third_ref = type {987, nullptr}; + return std::tuple { + first_ref.constructor_count(), + first_ref.move_constructor_count(), + first_ref.copy_constructor_count(), + first_ref.move_assign_count(), + first_ref.copy_assign_count(), + second_ref.constructor_count(), + second_ref.move_constructor_count(), + second_ref.copy_constructor_count(), + second_ref.move_assign_count(), + second_ref.copy_assign_count(), + third_ref.constructor_count(), + third_ref.move_constructor_count(), + third_ref.copy_constructor_count(), + third_ref.move_assign_count(), + third_ref.copy_assign_count(), + hud::get<0>(tuple).id() == 123, + hud::get<1>(tuple).id() == 456, + hud::get<2>(tuple).id() == 789 + }; + }; + // Non constant + { + const auto result = test(type {123, nullptr}, type {456, nullptr}, type {789, nullptr}); + hud_assert_eq(std::get<0>(result), 1); + hud_assert_eq(std::get<1>(result), 1); + hud_assert_eq(std::get<2>(result), 0); + hud_assert_eq(std::get<3>(result), 0); + hud_assert_eq(std::get<4>(result), 0); + hud_assert_eq(std::get<5>(result), 1); + hud_assert_eq(std::get<6>(result), 1); + hud_assert_eq(std::get<7>(result), 0); + hud_assert_eq(std::get<8>(result), 0); + hud_assert_eq(std::get<9>(result), 0); + hud_assert_eq(std::get<10>(result), 1); + hud_assert_eq(std::get<11>(result), 1); + hud_assert_eq(std::get<12>(result), 0); + hud_assert_eq(std::get<13>(result), 0); + hud_assert_eq(std::get<14>(result), 0); + hud_assert_true(std::get<15>(result)); + hud_assert_true(std::get<16>(result)); + hud_assert_true(std::get<17>(result)); + } + + // Non constant + { + constexpr auto result = test(type {123, nullptr}, type {456, nullptr}, type {789, nullptr}); + hud_assert_eq(std::get<0>(result), 1); + hud_assert_eq(std::get<1>(result), 1); + hud_assert_eq(std::get<2>(result), 0); + hud_assert_eq(std::get<3>(result), 0); + hud_assert_eq(std::get<4>(result), 0); + hud_assert_eq(std::get<5>(result), 1); + hud_assert_eq(std::get<6>(result), 1); + hud_assert_eq(std::get<7>(result), 0); + hud_assert_eq(std::get<8>(result), 0); + hud_assert_eq(std::get<9>(result), 0); + hud_assert_eq(std::get<10>(result), 1); + hud_assert_eq(std::get<11>(result), 1); + hud_assert_eq(std::get<12>(result), 0); + hud_assert_eq(std::get<13>(result), 0); + hud_assert_eq(std::get<14>(result), 0); + hud_assert_true(std::get<15>(result)); + hud_assert_true(std::get<16>(result)); + hud_assert_true(std::get<17>(result)); + } } \ No newline at end of file