From 57a84f501ed714078f05e077c158e2e8daf6bb68 Mon Sep 17 00:00:00 2001 From: Ole Erik Peistorpet Date: Thu, 13 Jun 2024 18:53:07 +0200 Subject: [PATCH] Made _detail::rangeIsSized, used in several places --- auxi/impl_algo.h | 29 ++++++++++------------- auxi/range_algo_detail.h | 51 ++++++++++++++++++++-------------------- auxi/range_traits.h | 9 +++++++ unit_test/util_gtest.cpp | 4 ++++ unit_test/view_gtest.cpp | 1 + view/all.h | 15 ++++++------ 6 files changed, 60 insertions(+), 49 deletions(-) diff --git a/auxi/impl_algo.h b/auxi/impl_algo.h index 2eebabfb..1e255395 100644 --- a/auxi/impl_algo.h +++ b/auxi/impl_algo.h @@ -128,28 +128,25 @@ namespace oel::_detail - template< typename Range, typename... None > - auto UDist(Range & r, None...) + template< typename Range > + inline constexpr auto rangeIsForwardOrSized = iter_is_forward< iterator_t > or rangeIsSized; + + // Used only if rangeIsForwardOrSized + template< typename Range > + auto UDist(Range & r) { - using I = decltype(begin(r)); - if constexpr (iter_is_forward) + if constexpr (rangeIsSized) { - auto it = begin(r); + return as_unsigned(_detail::Size(r)); + } + else + { auto it = begin(r); auto const l = end(r); - std::make_unsigned_t< iter_difference_t > n{}; + using D = iter_difference_t; + std::make_unsigned_t n{}; while (it != l) { ++it; ++n; } return n; } } - - template< typename Range > - auto UDist(Range & r) - -> decltype( as_unsigned(_detail::Size(r)) ) - { return as_unsigned(_detail::Size(r)); } - - - template< typename Range > - inline constexpr auto rangeIsForwardOrSized = - !std::is_same_v< decltype( _detail::UDist(std::declval()) ), void >; } \ No newline at end of file diff --git a/auxi/range_algo_detail.h b/auxi/range_algo_detail.h index 080b392b..b8d09ec5 100644 --- a/auxi/range_algo_detail.h +++ b/auxi/range_algo_detail.h @@ -77,36 +77,35 @@ namespace oel::_detail } - template< typename InputRange, typename OutputRange, typename... None > - bool CopyFit(InputRange & src, OutputRange & dest, None...) + template< typename InputRange, typename RandomAccessRange > + bool CopyFit(InputRange & src, RandomAccessRange & dest) { - auto it = begin(src); auto const last = end(src); - auto di = begin(dest); auto const dl = end(dest); - while (it != last) + if constexpr (rangeIsSized) { - if (di != dl) + auto n = as_unsigned(_detail::Size(src)); + auto const destSize = as_unsigned(_detail::Size(dest)); + bool const success{n <= destSize}; + if (!success) + n = destSize; + + _detail::CopyUnsf(begin(src), n, begin(dest)); + return success; + } + else + { auto it = begin(src); auto const last = end(src); + auto di = begin(dest); auto const dl = end(dest); + while (it != last) { - *di = *it; - ++di; ++it; - } - else - { return false; + if (di != dl) + { + *di = *it; + ++di; ++it; + } + else + { return false; + } } + return true; } - return true; - } - - template< typename SizedRange, typename RandomAccessRange > - auto CopyFit(SizedRange & src, RandomAccessRange & dest) - -> decltype( _detail::Size(src), bool() ) // better match if Size(src) is well-formed (SFINAE) - { - auto n = as_unsigned(_detail::Size(src)); - auto const destSize = as_unsigned(_detail::Size(dest)); - bool const success{n <= destSize}; - if (!success) - n = destSize; - - _detail::CopyUnsf(begin(src), n, begin(dest)); - return success; } } \ No newline at end of file diff --git a/auxi/range_traits.h b/auxi/range_traits.h index d479aaa8..0e294eb5 100644 --- a/auxi/range_traits.h +++ b/auxi/range_traits.h @@ -136,6 +136,15 @@ namespace _detail constexpr auto Size(Range && r, None...) -> decltype(end(r) - begin(r)) { return end(r) - begin(r); } + + + template< typename Range, typename = void > + inline constexpr bool rangeIsSized = false; + + template< typename Range > + inline constexpr bool rangeIsSized< Range, + std::void_t< decltype( _detail::Size(std::declval()) ) > + > = true; } } // oel diff --git a/unit_test/util_gtest.cpp b/unit_test/util_gtest.cpp index 2c662362..3fdc4a5d 100644 --- a/unit_test/util_gtest.cpp +++ b/unit_test/util_gtest.cpp @@ -123,6 +123,8 @@ struct DummyRange TEST(utilTest, ssize) { + static_assert(oel::_detail::rangeIsSized< DummyRange >); + using test = decltype( oel::ssize(DummyRange{0}) ); using test2 = decltype( oel::ssize(DummyRange{0}) ); @@ -247,6 +249,7 @@ int * end(EmptyRandomAccessRange) { return {}; } TEST(utilTest, detailSize_rangeNoMember) { EmptyRandomAccessRange r; + static_assert(oel::_detail::rangeIsSized); EXPECT_EQ(0, oel::_detail::Size(r)); } @@ -299,6 +302,7 @@ TEST(utilTest, detailCountOrEnd_disabledSize) A src{1}; auto v = oel::view::subrange(TooSimpleIter{src.begin()}, src.end()); + static_assert( !oel::_detail::rangeIsSized ); static_assert(oel::_detail::rangeIsForwardOrSized); auto n = oel::_detail::UDist(v); diff --git a/unit_test/view_gtest.cpp b/unit_test/view_gtest.cpp index 0e17ce74..34901131 100644 --- a/unit_test/view_gtest.cpp +++ b/unit_test/view_gtest.cpp @@ -270,6 +270,7 @@ TEST(viewTest, viewMoveEndDifferentType) oel::transform_iterator it{nonEmpty, src + 0}; auto v = view::subrange(it, makeSentinel(src + 1)) | view::move; + static_assert(oel::_detail::rangeIsSized); EXPECT_NE(v.begin(), v.end()); EXPECT_EQ(src + 1, v.end().base()._s); } diff --git a/view/all.h b/view/all.h index 4e4ab943..1c85a955 100644 --- a/view/all.h +++ b/view/all.h @@ -27,18 +27,19 @@ namespace _detail } #endif - template< typename SizedRange > - constexpr auto operator()(SizedRange & r) const - -> decltype( view::counted(begin(r), oel::ssize(r)) ) - { return view::counted(begin(r), oel::ssize(r)); } - template< typename Range > constexpr auto operator()(Range && r) const { if constexpr (std::is_lvalue_reference_v) - return view::subrange(begin(r), end(r)); + { + if constexpr (_detail::rangeIsSized) + return view::counted(begin(r), oel::ssize(r)); + else + return view::subrange(begin(r), end(r)); + } else - return view::owning(static_cast(r)); + { return view::owning(static_cast(r)); + } } }; }