|
@@ -200,12 +200,14 @@ namespace simple::support
|
|
|
|
|
|
constexpr offset_range() = default;
|
|
|
|
|
|
+ template <typename A,
|
|
|
+ std::enable_if_t<std::is_same_v<A,Anchor>>* = nullptr>
|
|
|
constexpr explicit offset_range
|
|
|
(
|
|
|
- Anchor&& anchor,
|
|
|
+ A&& anchor,
|
|
|
range<Size> i = range<Size>::limit()
|
|
|
) :
|
|
|
- anchor(std::forward<Anchor>(anchor)),
|
|
|
+ anchor(std::forward<A>(anchor)),
|
|
|
i(i)
|
|
|
{}
|
|
|
|
|
@@ -259,79 +261,6 @@ namespace simple::support
|
|
|
template <typename Size, typename Anchor>
|
|
|
offset_range(Anchor&&, range<Size>) -> offset_range<Size, Anchor>;
|
|
|
|
|
|
- // A bit unrealisitic to expect ::limit() for generic range, but oh well...
|
|
|
- template <template<typename...> typename Range, typename Size = void>
|
|
|
- class with_range
|
|
|
- {
|
|
|
- public:
|
|
|
- template <typename Container>
|
|
|
- class index
|
|
|
- {
|
|
|
- public:
|
|
|
- using container_type = Container;
|
|
|
- using size_type = std::conditional_t<
|
|
|
- std::is_same_v<Size,void>,
|
|
|
- typename container_type::size_type,
|
|
|
- Size
|
|
|
- >;
|
|
|
-
|
|
|
- constexpr index() = default;
|
|
|
-
|
|
|
- constexpr explicit index
|
|
|
- (
|
|
|
- Container container,
|
|
|
- Range<size_type> i = Range<size_type>::limit()
|
|
|
- ) :
|
|
|
- container(std::move(container)),
|
|
|
- i(i)
|
|
|
- {}
|
|
|
-
|
|
|
- constexpr auto begin() const
|
|
|
- { return iter_at(i.lower()); }
|
|
|
- constexpr auto end() const
|
|
|
- { return iter_at(i.upper()); }
|
|
|
-
|
|
|
- constexpr auto begin()
|
|
|
- { return iter_at(i.lower()); }
|
|
|
- constexpr auto end()
|
|
|
- { return iter_at(i.upper()); }
|
|
|
-
|
|
|
- private:
|
|
|
- Container container;
|
|
|
- Range<size_type> i;
|
|
|
-
|
|
|
- constexpr auto iter_at(size_type index) const
|
|
|
- {
|
|
|
- using std::begin;
|
|
|
- using std::end;
|
|
|
- using std::clamp;
|
|
|
-
|
|
|
- auto begin_ = begin(container);
|
|
|
- auto end_ = end(container);
|
|
|
-
|
|
|
- // TODO: use container.size() if available
|
|
|
- return begin_ + clamp(index, size_type{},
|
|
|
- static_cast<size_type>(end_ - begin_)); // good cast, since container can not have negative size
|
|
|
- }
|
|
|
-
|
|
|
- constexpr auto iter_at(size_type index)
|
|
|
- {
|
|
|
- using std::begin;
|
|
|
- using std::end;
|
|
|
- using std::clamp;
|
|
|
-
|
|
|
- auto begin_ = begin(container);
|
|
|
- auto end_ = end(container);
|
|
|
-
|
|
|
- // TODO: use container.size() if available
|
|
|
- return begin_ + clamp(index, size_type{},
|
|
|
- static_cast<size_type>(end_ - begin_)); // good cast, since container can not have negative size
|
|
|
- }
|
|
|
-
|
|
|
- };
|
|
|
-
|
|
|
- };
|
|
|
-
|
|
|
template <typename I>
|
|
|
[[nodiscard]] auto deref(I&& i) -> decltype(auto)
|
|
|
{
|