From 703a75b6711dd6fa417c7af1a05933530f6c9fea Mon Sep 17 00:00:00 2001 From: namark <namark@disroot.org> Date: Sat, 28 Aug 2021 16:30:47 +0400 Subject: [PATCH] indirect_range_referring_reference_t basically ranges::ref_view --- source/simple/support/misc.hpp | 55 +++++++++++++++++++++++++++------- unit_tests/misc.cpp | 5 +++- 2 files changed, 49 insertions(+), 11 deletions(-) diff --git a/source/simple/support/misc.hpp b/source/simple/support/misc.hpp index 1ac05d9..8f9fa53 100644 --- a/source/simple/support/misc.hpp +++ b/source/simple/support/misc.hpp @@ -136,31 +136,66 @@ namespace simple::support return {begin, static_cast<std::string_view::size_type>(end - begin)}; } - // NOTE: maybe put in algorithm range wrappers instead? + // NOTE: maybe put in algorithm/range_wrappers.hpp instead? + // problem is, range_wrappers.hpp doesn't depend on anything, + // so need to also parameterize the range type, to keep it that way. + // A bit unrealisitic to expect ::limit() or arithmetic for generic range. + // but really don't want the includeee template <typename Container, typename = std::enable_if_t<is_range_v<Container>>> - class index_range + class indirect_range_referring_reference_t { public: + using container_type = Container; + using size_type = typename container_type::size_type; + using iterator = typename container_type::iterator; + using const_iterator = typename container_type::const_iterator; + + explicit indirect_range_referring_reference_t + (Container& container) : container(&container) + {} + + auto begin() const + { + using std::begin; + return begin(*container); + } + + auto end() const + { + using std::end; + return end(*container); + } + private: + Container* container; + }; + + template <typename Container, + typename = std::enable_if_t<is_range_v<Container>>> + class index_range + { + public: using container_type = Container; using size_type = typename container_type::size_type; + explicit index_range ( - Container & container, + Container container, range<size_type> index = range<size_type>::limit() ) : - container(&container), + container(std::move(container)), index(index) {} explicit index_range ( - Container & container, + Container container, range<typename Container::const_iterator> iterator_range ) : - container(&container), - index(iterator_range - container.begin()) + container(std::move(container)), + // TODO: ADL the begin + index(iterator_range - this->container.begin()) {} auto begin() const @@ -169,7 +204,7 @@ namespace simple::support { return iter_at(index.upper()); } private: - Container* container; + Container container; range<size_type> index; auto iter_at(size_type index) const @@ -178,8 +213,8 @@ namespace simple::support using std::end; using std::clamp; - auto begin_ = begin(*container); - auto end_ = end(*container); + auto begin_ = begin(container); + auto end_ = end(container); // TODO: use container.size() if available return begin_ + clamp(index, size_type{}, diff --git a/unit_tests/misc.cpp b/unit_tests/misc.cpp index e295460..f7d82e3 100644 --- a/unit_tests/misc.cpp +++ b/unit_tests/misc.cpp @@ -115,7 +115,10 @@ void RangeReference() assert( std::equal(begin(temporef), end(temporef), begin(prefix), end(prefix)) ); - index_range permaref(stuff, {begin(stuff), end(stuff)}); + index_range permaref{ + indirect_range_referring_reference_t(stuff), + {begin(stuff), end(stuff)} + }; assert( std::equal(begin(permaref), end(permaref), begin(prefix), end(prefix)) ); -- GitLab