Skip to content

Commit

Permalink
Made _detail::rangeIsSized, used in several places
Browse files Browse the repository at this point in the history
  • Loading branch information
OleErikPeistorpet committed Jun 14, 2024
1 parent caad1e8 commit 57a84f5
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 49 deletions.
29 changes: 13 additions & 16 deletions auxi/impl_algo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<Range> > or rangeIsSized<Range>;

// Used only if rangeIsForwardOrSized
template< typename Range >
auto UDist(Range & r)
{
using I = decltype(begin(r));
if constexpr (iter_is_forward<I>)
if constexpr (rangeIsSized<Range>)
{
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<I> > n{};
using D = iter_difference_t<decltype(it)>;
std::make_unsigned_t<D> 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<Range &>()) ), void >;
}
51 changes: 25 additions & 26 deletions auxi/range_algo_detail.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<InputRange>)
{
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;
}
}
9 changes: 9 additions & 0 deletions auxi/range_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<Range &>()) ) >
> = true;
}

} // oel
Expand Down
4 changes: 4 additions & 0 deletions unit_test/util_gtest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ struct DummyRange

TEST(utilTest, ssize)
{
static_assert(oel::_detail::rangeIsSized< DummyRange<int> >);

using test = decltype( oel::ssize(DummyRange<unsigned short>{0}) );
using test2 = decltype( oel::ssize(DummyRange<std::uintmax_t>{0}) );

Expand Down Expand Up @@ -247,6 +249,7 @@ int * end(EmptyRandomAccessRange) { return {}; }
TEST(utilTest, detailSize_rangeNoMember)
{
EmptyRandomAccessRange r;
static_assert(oel::_detail::rangeIsSized<decltype(r)>);
EXPECT_EQ(0, oel::_detail::Size(r));
}

Expand Down Expand Up @@ -299,6 +302,7 @@ TEST(utilTest, detailCountOrEnd_disabledSize)
A src{1};
auto v = oel::view::subrange(TooSimpleIter<A::iterator>{src.begin()}, src.end());

static_assert( !oel::_detail::rangeIsSized<decltype(v)> );
static_assert(oel::_detail::rangeIsForwardOrSized<decltype(v)>);

auto n = oel::_detail::UDist(v);
Expand Down
1 change: 1 addition & 0 deletions unit_test/view_gtest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<decltype(v)>);
EXPECT_NE(v.begin(), v.end());
EXPECT_EQ(src + 1, v.end().base()._s);
}
Expand Down
15 changes: 8 additions & 7 deletions view/all.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<Range>)
return view::subrange(begin(r), end(r));
{
if constexpr (_detail::rangeIsSized<Range>)
return view::counted(begin(r), oel::ssize(r));
else
return view::subrange(begin(r), end(r));
}
else
return view::owning(static_cast<Range &&>(r));
{ return view::owning(static_cast<Range &&>(r));
}
}
};
}
Expand Down

0 comments on commit 57a84f5

Please sign in to comment.