diff --git a/CHANGELOG.md b/CHANGELOG.md index 2195712..61c4f2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ * Added concept `mbo::types::IsVariant`. * Added concept `mbo::types::HasVariantMember`. +* Fixed issue with `Extend` ability to handle struct names when compiled with Clang. +* Fixed issue with `Extend` handling move only types when used in decompose assignment. +* Added template struct `BinarySearch` implements templated binary search algorithm. +* Added template struct `LinearSearch` implements templated linear search algorithm. +* Added template struct `ReverseSearch` implements templated reverse linear search algorithm. +* Added template struct `MaxSearch` implements templated linear search for last match algorithm. # 0.2.24 diff --git a/README.md b/README.md index bb1f650..b3671e8 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,11 @@ The C++ library is organized in functional groups each residing in their own dir * Mainly, this prevents calling the destructor and thus prevents termination issues (initialization order fiasco). * mbo/types:ref_wrap_cc, mbo/types/ref_wrap.h * template-type `RefWrap`: similar to `std::reference_wrapper` but supports operators `->` and `*`. + * mbo/types:template_search_cc, mbo/types/template_search.h: + * template struct `BinarySearch` implements templated binary search algorithm. + * template struct `LinearSearch` implements templated linear search algorithm. + * template struct `ReverseSearch` implements templated reverse linear search algorithm. + * template struct `MaxSearch` implements templated linear search for last match algorithm. * mbo/types:traits_cc, mbo/types/traits.h * type alias `ContainerConstIteratorValueType` returned the value-type of the const_iterator of a container. * concept `ContainerIsForwardIteratable` determines whether a types can be used in forward iteration. diff --git a/mbo/types/BUILD.bazel b/mbo/types/BUILD.bazel index b801423..b6bb390 100644 --- a/mbo/types/BUILD.bazel +++ b/mbo/types/BUILD.bazel @@ -40,8 +40,8 @@ cc_library( cc_library( name = "extend_cc", - hdrs = ["extend.h"], srcs = ["extender.h"], + hdrs = ["extend.h"], visibility = ["//visibility:public"], deps = [ ":tstring_cc", @@ -85,18 +85,34 @@ cc_test( ) cc_library( - name = "ref_wrap_cc", - hdrs = ["ref_wrap.h"], - visibility = ["//visibility:public"], + name = "ref_wrap_cc", + hdrs = ["ref_wrap.h"], + visibility = ["//visibility:public"], ) cc_test( - name = "ref_wrap_test", - srcs = ["ref_wrap_test.cc"], - deps = [ - ":ref_wrap_cc", - "@com_google_googletest//:gtest_main", - ] + name = "ref_wrap_test", + srcs = ["ref_wrap_test.cc"], + deps = [ + ":ref_wrap_cc", + "@com_google_googletest//:gtest_main", + ], +) + +cc_library( + name = "template_search_cc", + hdrs = ["template_search.h"], + visibility = ["//visibility:public"], +) + +cc_test( + name = "template_search_test", + srcs = ["template_search_test.cc"], + deps = [ + ":template_search_cc", + ":traits_cc", + "@com_google_googletest//:gtest_main", + ], ) cc_library( diff --git a/mbo/types/extend_test.cc b/mbo/types/extend_test.cc index 998f194..153b5d4 100644 --- a/mbo/types/extend_test.cc +++ b/mbo/types/extend_test.cc @@ -716,5 +716,44 @@ TEST_F(ExtendTest, VariantMember) { EXPECT_THAT(data.ToString(), Conditional(kStructNameSupport, R"({.value: 69})", R"({69})")); } +struct MoveOnly { + constexpr explicit MoveOnly(int val) noexcept : value(val) {} + + constexpr MoveOnly() = delete; + constexpr ~MoveOnly() noexcept = default; + + MoveOnly(const MoveOnly&) = delete; + MoveOnly& operator=(const MoveOnly&) = delete; + MoveOnly(MoveOnly&&) noexcept = default; + MoveOnly& operator=(MoveOnly&&) noexcept = default; + + int value{0}; +}; + +struct UseMoveOnly : Extend { + MoveOnly move1{0}; + MoveOnly move2{0}; +}; + +TEST_F(ExtendTest, MoveOnlyTuple) { + // Verify that `ToTuple` works for `move-eligble` values as expected: ToTuple(Extend&&) -> std::tuple. + static constexpr int kValue1{25}; + static constexpr int kValue2{33}; + static constexpr int kValue3{42}; + UseMoveOnly data{ + .move1{MoveOnly{kValue1}}, + .move2{MoveOnly{kValue2}}, + }; + auto [move1, move2] = std::move(data); + EXPECT_THAT(move1.value, kValue1); + EXPECT_THAT(move2.value, kValue2); + + move1.value = kValue3; + EXPECT_THAT(move1.value, kValue3); + EXPECT_THAT(move2.value, kValue2); + EXPECT_THAT(data.move1.value, Ne(kValue3)) + << "It does not matter what the value is after the move, but it must not be `kValue3`."; +} + } // namespace } // namespace mbo::types diff --git a/mbo/types/internal/BUILD.bazel b/mbo/types/internal/BUILD.bazel index 32fd171..fee0abd 100644 --- a/mbo/types/internal/BUILD.bazel +++ b/mbo/types/internal/BUILD.bazel @@ -54,11 +54,13 @@ cc_test( cc_library( name = "traits_cc", hdrs = [ - "binary_search.h", "decompose_count.h", "is_braces_constructible.h", ], - deps = [":cases_cc"], + deps = [ + ":cases_cc", + "//mbo/types:template_search_cc", + ], ) cc_library( @@ -77,12 +79,3 @@ mope_test( outs = ["decompose_count.h"], clang_format = True, ) - -cc_test( - name = "binary_search_test", - srcs = ["binary_search_test.cc"], - deps = [ - ":traits_cc", - "@com_google_googletest//:gtest_main", - ] -) diff --git a/mbo/types/internal/decompose_count.h b/mbo/types/internal/decompose_count.h index bda5539..2a1e03c 100644 --- a/mbo/types/internal/decompose_count.h +++ b/mbo/types/internal/decompose_count.h @@ -25,9 +25,9 @@ #include #include // IWYU pragma: keep -#include "mbo/types/internal/binary_search.h" // IWYU pragma: keep -#include "mbo/types/internal/cases.h" // IWYU pragma: keep +#include "mbo/types/internal/cases.h" // IWYU pragma: keep #include "mbo/types/internal/is_braces_constructible.h" +#include "mbo/types/template_search.h" // IWYU pragma: keep namespace mbo::types::types_internal { @@ -833,178 +833,181 @@ struct DecomposeHelper final { if constexpr (kNumFields == 0) { return std::make_tuple(); } else if constexpr (kNumFields == 1) { - auto& [a1] = data; + auto&& [a1] = std::forward(data); return std::make_tuple(a1); } else if constexpr (kNumFields == 2) { - auto& [a1, a2] = data; + auto&& [a1, a2] = std::forward(data); return std::make_tuple(a1, a2); } else if constexpr (kNumFields == 3) { - auto& [a1, a2, a3] = data; + auto&& [a1, a2, a3] = std::forward(data); return std::make_tuple(a1, a2, a3); } else if constexpr (kNumFields == 4) { - auto& [a1, a2, a3, a4] = data; + auto&& [a1, a2, a3, a4] = std::forward(data); return std::make_tuple(a1, a2, a3, a4); } else if constexpr (kNumFields == 5) { - auto& [a1, a2, a3, a4, a5] = data; + auto&& [a1, a2, a3, a4, a5] = std::forward(data); return std::make_tuple(a1, a2, a3, a4, a5); } else if constexpr (kNumFields == 6) { - auto& [a1, a2, a3, a4, a5, a6] = data; + auto&& [a1, a2, a3, a4, a5, a6] = std::forward(data); return std::make_tuple(a1, a2, a3, a4, a5, a6); } else if constexpr (kNumFields == 7) { - auto& [a1, a2, a3, a4, a5, a6, a7] = data; + auto&& [a1, a2, a3, a4, a5, a6, a7] = std::forward(data); return std::make_tuple(a1, a2, a3, a4, a5, a6, a7); } else if constexpr (kNumFields == 8) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8] = data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8] = std::forward(data); return std::make_tuple(a1, a2, a3, a4, a5, a6, a7, a8); } else if constexpr (kNumFields == 9) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9] = data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9] = std::forward(data); return std::make_tuple(a1, a2, a3, a4, a5, a6, a7, a8, a9); } else if constexpr (kNumFields == 10) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10] = data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10] = std::forward(data); return std::make_tuple(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); } else if constexpr (kNumFields == 11) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11] = data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11] = std::forward(data); return std::make_tuple(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); } else if constexpr (kNumFields == 12) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12] = data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12] = std::forward(data); return std::make_tuple(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); } else if constexpr (kNumFields == 13) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13] = data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13] = std::forward(data); return std::make_tuple(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); } else if constexpr (kNumFields == 14) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14] = data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14] = std::forward(data); return std::make_tuple(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14); } else if constexpr (kNumFields == 15) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15] = data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15] = std::forward(data); return std::make_tuple(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15); } else if constexpr (kNumFields == 16) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16] = data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16] = std::forward(data); return std::make_tuple(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16); } else if constexpr (kNumFields == 17) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17] = data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17] = std::forward(data); return std::make_tuple(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17); } else if constexpr (kNumFields == 18) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18] = data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18] = std::forward(data); return std::make_tuple(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18); } else if constexpr (kNumFields == 19) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19] = data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19] = + std::forward(data); return std::make_tuple(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19); } else if constexpr (kNumFields == 20) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20] = data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20] = + std::forward(data); return std::make_tuple(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); } else if constexpr (kNumFields == 21) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21] = data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21] = + std::forward(data); return std::make_tuple( a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21); } else if constexpr (kNumFields == 22) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22] = - data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22] = + std::forward(data); return std::make_tuple( a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22); } else if constexpr (kNumFields == 23) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23] = - data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23] = + std::forward(data); return std::make_tuple( a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23); } else if constexpr (kNumFields == 24) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24] = - data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24] = + std::forward(data); return std::make_tuple( a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24); } else if constexpr (kNumFields == 25) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25] = - data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25] = + std::forward(data); return std::make_tuple( a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25); } else if constexpr (kNumFields == 26) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26] = - data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26] = + std::forward(data); return std::make_tuple( a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26); } else if constexpr (kNumFields == 27) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27] = - data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27] = + std::forward(data); return std::make_tuple( a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27); } else if constexpr (kNumFields == 28) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28] = - data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28] = + std::forward(data); return std::make_tuple( a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28); } else if constexpr (kNumFields == 29) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29] = - data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29] = + std::forward(data); return std::make_tuple( a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29); } else if constexpr (kNumFields == 30) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30] = - data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30] = + std::forward(data); return std::make_tuple( a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30); } else if constexpr (kNumFields == 31) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31] = - data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31] = + std::forward(data); return std::make_tuple( a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31); } else if constexpr (kNumFields == 32) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32] = - data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32] = + std::forward(data); return std::make_tuple( a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32); } else if constexpr (kNumFields == 33) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33] = - data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33] = + std::forward(data); return std::make_tuple( a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33); } else if constexpr (kNumFields == 34) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34] = - data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34] = + std::forward(data); return std::make_tuple( a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34); } else if constexpr (kNumFields == 35) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35] = - data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35] = + std::forward(data); return std::make_tuple( a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35); } else if constexpr (kNumFields == 36) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36] = - data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36] = + std::forward(data); return std::make_tuple( a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36); } else if constexpr (kNumFields == 37) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37] = - data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37] = + std::forward(data); return std::make_tuple( a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37); } else if constexpr (kNumFields == 38) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38] = - data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38] = + std::forward(data); return std::make_tuple( a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38); } else if constexpr (kNumFields == 39) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39] = - data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39] = + std::forward(data); return std::make_tuple( a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39); } else if constexpr (kNumFields == 40) { - auto& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39, a40] = - data; + auto&& [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39, a40] = + std::forward(data); return std::make_tuple( a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, a31, a32, a33, a34, a35, a36, a37, a38, a39, a40); diff --git a/mbo/types/internal/decompose_count.h.mope b/mbo/types/internal/decompose_count.h.mope index efb665b..129fd07 100644 --- a/mbo/types/internal/decompose_count.h.mope +++ b/mbo/types/internal/decompose_count.h.mope @@ -26,9 +26,9 @@ #include #include // IWYU pragma: keep -#include "mbo/types/internal/binary_search.h" // IWYU pragma: keep -#include "mbo/types/internal/cases.h" // IWYU pragma: keep +#include "mbo/types/internal/cases.h" // IWYU pragma: keep #include "mbo/types/internal/is_braces_constructible.h" +#include "mbo/types/template_search.h" // IWYU pragma: keep namespace mbo::types::types_internal { @@ -497,7 +497,7 @@ struct DecomposeHelper final { return std::make_tuple(); {{#num_fields=1;max_fields}} } else if constexpr (kNumFields == {{num_fields}}) { - auto& [{{#field=1;num_fields;;', '}}a{{field}}{{/field}}] = data; + auto&& [{{#field=1;num_fields;;', '}}a{{field}}{{/field}}] = std::forward(data); return std::make_tuple({{#field=1;num_fields;;', '}}a{{field}}{{/field}}); {{/num_fields}} } diff --git a/mbo/types/internal/struct_names_clang.h b/mbo/types/internal/struct_names_clang.h index 3d61271..7d64f9f 100644 --- a/mbo/types/internal/struct_names_clang.h +++ b/mbo/types/internal/struct_names_clang.h @@ -57,24 +57,23 @@ class StructMetaBase { Uninitialized& operator=(const Uninitialized&) = delete; Uninitialized(Uninitialized&&) = delete; Uninitialized& operator=(Uninitialized&&) = delete; - int non{0}; T value; }; public: - constexpr Storage() noexcept { std::construct_at(&storage_[0].value); } + constexpr Storage() noexcept { std::construct_at(&storage_.value); } - constexpr ~Storage() noexcept { std::destroy_at(&storage_[0].value); } + constexpr ~Storage() noexcept { std::destroy_at(&storage_.value); } Storage(const Storage&) = delete; Storage& operator=(const Storage&) = delete; Storage(Storage&&) = delete; Storage& operator=(Storage&&) = delete; - constexpr const T& Get() const noexcept { return storage_[0].value; } + constexpr const T& Get() const noexcept { return storage_.value; } private: - const std::array storage_; + const Uninitialized storage_; }; // NOLINTBEGIN(*-swappable-parameters) diff --git a/mbo/types/internal/binary_search.h b/mbo/types/template_search.h similarity index 87% rename from mbo/types/internal/binary_search.h rename to mbo/types/template_search.h index e7dccdf..ff7526a 100644 --- a/mbo/types/internal/binary_search.h +++ b/mbo/types/template_search.h @@ -13,23 +13,24 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef MBO_TYPES_INTERNAL_BINARY_SEARCH_H_ -#define MBO_TYPES_INTERNAL_BINARY_SEARCH_H_ +#ifndef MBO_TYPES_TEMPLATE_SEARCH_H_ +#define MBO_TYPES_TEMPLATE_SEARCH_H_ // IWYU pragma private, include "mbo/types/internal/decompose_count.h" #include // IWYU pragma: keep #include -namespace mbo::types::types_internal { +namespace mbo::types { // Template `BinarySearch` - find higest value in `[Start, End[` for which `Predicate` is true. // Returns `NotFound` otherwise. // The `Predicate` must provide a boolean constant `value`. - template typename Predicate, std::size_t Start, std::size_t End, std::size_t NotFound> struct BinarySearch; +namespace types_internal { + template typename Predicate, std::size_t Start, std::size_t End, std::size_t NotFound> using BinarySearchImpl = std::conditional_t < (Start + 1 >= End), std::conditional_t< @@ -42,8 +43,10 @@ using BinarySearchImpl = std::conditional_t < (Start + 1 >= End), BinarySearch, BinarySearch>>; +} // namespace types_internal + template typename Predicate, std::size_t Start, std::size_t End, size_t NotFound = End> -struct BinarySearch : BinarySearchImpl {}; +struct BinarySearch : types_internal::BinarySearchImpl {}; template typename Predicate, std::size_t Start, std::size_t End, std::size_t NotFound = End> constexpr std::size_t BinarySearchV = BinarySearch::value; @@ -57,6 +60,8 @@ constexpr std::size_t BinarySearchV = BinarySearch typename Predicate, std::size_t Start, std::size_t End, size_t NotFound> struct LinearSearch; +namespace types_internal { + template typename Predicate, std::size_t Start, std::size_t End, size_t NotFound> using LinearSearchImpl = std::conditional_t< Start >= End, @@ -66,8 +71,10 @@ using LinearSearchImpl = std::conditional_t< std::integral_constant, LinearSearch>>; +} // namespace types_internal + template typename Predicate, std::size_t Start, std::size_t End, size_t NotFound = End> -struct LinearSearch : LinearSearchImpl {}; +struct LinearSearch : types_internal::LinearSearchImpl {}; template typename Predicate, std::size_t Start, std::size_t End, size_t NotFound = End> constexpr std::size_t LinearSearchV = LinearSearch::value; @@ -83,6 +90,8 @@ constexpr std::size_t LinearSearchV = LinearSearch typename Predicate, std::size_t Start, std::size_t End, size_t NotFound> struct MaxSearch; +namespace types_internal { + template typename Predicate, std::size_t Start, std::size_t End, size_t NotFound> using MaxSearchImpl = std::conditional_t< (Start >= End), @@ -92,8 +101,10 @@ using MaxSearchImpl = std::conditional_t< MaxSearch, std::integral_constant>>; +} // namespace types_internal + template typename Predicate, std::size_t Start, std::size_t End, size_t NotFound = End> -struct MaxSearch : MaxSearchImpl {}; +struct MaxSearch : types_internal::MaxSearchImpl {}; template typename Predicate, std::size_t Start, std::size_t End, size_t NotFound = End> constexpr std::size_t MaxSearchV = MaxSearch::value; @@ -108,6 +119,8 @@ constexpr std::size_t MaxSearchV = MaxSearch::v template typename Predicate, std::size_t Start, std::size_t End, size_t NotFound> struct ReverseSearch; +namespace types_internal { + template typename Predicate, std::size_t Start, std::size_t End, size_t NotFound> using ReverseSearchImpl = std::conditional_t< (End <= Start), @@ -117,12 +130,14 @@ using ReverseSearchImpl = std::conditional_t< std::integral_constant, ReverseSearch>>; +} // namespace types_internal + template typename Predicate, std::size_t Start, std::size_t End, size_t NotFound = End> -struct ReverseSearch : ReverseSearchImpl {}; +struct ReverseSearch : types_internal::ReverseSearchImpl {}; template typename Predicate, std::size_t Start, std::size_t End, size_t NotFound = End> constexpr std::size_t ReverseSearchV = ReverseSearch::value; -} // namespace mbo::types::types_internal +} // namespace mbo::types -#endif // MBO_TYPES_INTERNAL_BINARY_SEARCH_H_ +#endif // MBO_TYPES_TEMPLATE_SEARCH_H_ diff --git a/mbo/types/internal/binary_search_test.cc b/mbo/types/template_search_test.cc similarity index 95% rename from mbo/types/internal/binary_search_test.cc rename to mbo/types/template_search_test.cc index d1421e3..c582a3e 100644 --- a/mbo/types/internal/binary_search_test.cc +++ b/mbo/types/template_search_test.cc @@ -13,15 +13,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "mbo/types/internal/binary_search.h" +#include "mbo/types/template_search.h" #include #include -#include // NOLINTBEGIN(*-magic-numbers) -namespace mbo::types::types_internal { +namespace mbo::types { namespace { template @@ -43,15 +42,15 @@ struct IsNonZero { template< std::size_t Expected, - template typename, std::size_t...> + template typename, std::size_t Start, std::size_t End, std::size_t NotFound> typename Algorithm, template typename TestFunc, typename TestType, std::size_t Start = 0, std::size_t End = TestType::size(), - std::size_t... Values> -concept TestEqual = Expected == Algorithm::template TestFunc, Start, End, Values...>::value; + std::size_t NotFound = End> +concept TestEqual = Expected == Algorithm::template TestFunc, Start, End, NotFound>::value; // BinarySearch @@ -136,6 +135,6 @@ static_assert(TestEqual<4, ReverseSearch, IsNonZero, Test<0, 2, 3, 4, 5, 0, 0>, static_assert(TestEqual<99, ReverseSearch, IsNonZero, Test<0, 2, 3, 0, 0, 0, 0>, 3, 6, 99>); } // namespace -} // namespace mbo::types::types_internal +} // namespace mbo::types // NOLINTEND(*-magic-numbers)