diff --git a/source/simple/support/misc.hpp b/source/simple/support/misc.hpp index 8f9fa53c3826b08ebc5265e5b41c016bebb72caa..b93fd0645678f3ece81cc928ebd68317df4da483 100644 --- a/source/simple/support/misc.hpp +++ b/source/simple/support/misc.hpp @@ -140,7 +140,9 @@ namespace simple::support // 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. + // also is_range_v :/ // but really don't want the includeee + template <typename Container, typename = std::enable_if_t<is_range_v<Container>>> class indirect_range_referring_reference_t @@ -151,17 +153,17 @@ namespace simple::support using iterator = typename container_type::iterator; using const_iterator = typename container_type::const_iterator; - explicit indirect_range_referring_reference_t + constexpr explicit indirect_range_referring_reference_t (Container& container) : container(&container) {} - auto begin() const + constexpr auto begin() const { using std::begin; return begin(*container); } - auto end() const + constexpr auto end() const { using std::end; return end(*container); @@ -171,55 +173,75 @@ namespace simple::support Container* container; }; - template <typename Container, - typename = std::enable_if_t<is_range_v<Container>>> - class index_range + template <template<typename...> typename Range, typename Size = void> + class with_range { public: - using container_type = Container; - using size_type = typename container_type::size_type; - - explicit index_range - ( - Container container, - range<size_type> index = range<size_type>::limit() - ) : - container(std::move(container)), - index(index) - {} + 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; - explicit index_range - ( - Container container, - range<typename Container::const_iterator> iterator_range - ) : - container(std::move(container)), - // TODO: ADL the begin - index(iterator_range - this->container.begin()) - {} + auto begin_ = begin(container); + auto end_ = end(container); - auto begin() const - { return iter_at(index.lower()); } - auto end() const - { return iter_at(index.upper()); } + // 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 + } - private: - Container container; - range<size_type> index; + constexpr auto iter_at(size_type index) + { + using std::begin; + using std::end; + using std::clamp; - auto iter_at(size_type index) const - { - using std::begin; - 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{}, + static_cast<size_type>(end_ - begin_)); // good cast, since container can not have negative size + } - // 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 - } + }; }; diff --git a/unit_tests/misc.cpp b/unit_tests/misc.cpp index f7d82e3477beaa5be2bbdbca106cfb45cce965f8..445e17c54cd00c326932229f6397d7762e25ba6a 100644 --- a/unit_tests/misc.cpp +++ b/unit_tests/misc.cpp @@ -115,9 +115,14 @@ void RangeReference() assert( std::equal(begin(temporef), end(temporef), begin(prefix), end(prefix)) ); - index_range permaref{ +#ifdef __clang__ // https://bugs.llvm.org/show_bug.cgi?id=33489 + using strrefrange = indirect_range_referring_reference_t<std::string>; + with_range<range>::index<strrefrange> permaref{ +#else + with_range<range>::index permaref{ +#endif indirect_range_referring_reference_t(stuff), - {begin(stuff), end(stuff)} + make_range(stuff) - begin(stuff) }; assert( std::equal(begin(permaref), end(permaref),