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