diff --git a/source/simple/support/misc.hpp b/source/simple/support/misc.hpp index 1ac05d92b98f14672727295dfb070220c2e4bcd6..8f9fa53c3826b08ebc5265e5b41c016bebb72caa 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 e2954606c4fcda6bc0c19cbb2e83ec5a70a9ae1d..f7d82e3477beaa5be2bbdbca106cfb45cce965f8 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)) );