6 Commits f454610f36 ... e71ac12592

Author SHA1 Message Date
  namark e71ac12592 allinclude 6 months ago
  namark c32a04ca81 Moved search algorithm into its own header and added search_prefix. 6 months ago
  namark d02c94c54c Moved ADL helpers for begin and end into their own header. 6 months ago
  namark 667a08e1ff Fixed iterator value_type difference_type confusion, 6 months ago
  namark 3849d65a5a Welp output iterators don't have to be comparable... 6 months ago
  namark 76c281bc88 Looks scary, but otherwise get a const iterator from non const container... 6 months ago

+ 2 - 0
source/simple/support/algorithm.hpp

@@ -1,4 +1,5 @@
 // this is an auto-generated allinclude
+#include "algorithm/adl_helper.hpp"
 #include "algorithm/advance_vector.hpp"
 #include "algorithm/find.hpp"
 #include "algorithm/mismatch.hpp"
@@ -6,6 +7,7 @@
 #include "algorithm/pick_unique.hpp"
 #include "algorithm/range_wrappers.hpp"
 #include "algorithm/reaches.hpp"
+#include "algorithm/search.hpp"
 #include "algorithm/set_ops.hpp"
 #include "algorithm/split.hpp"
 #include "algorithm/traits.hpp"

+ 37 - 0
source/simple/support/algorithm/adl_helper.hpp

@@ -0,0 +1,37 @@
+#ifndef SIMPLE_SUPPORT_ALGORITHM_ADL_HELPER_HPP
+#define SIMPLE_SUPPORT_ALGORITHM_ADL_HELPER_HPP
+
+#include <iterator> // std::begin std::end
+
+#include "traits.hpp" // is_range_v
+
+namespace simple::support
+{
+
+	namespace adl_helper
+	{
+		using std::begin;
+		using std::end;
+
+		// TODO: should these return decltype(auto)?
+		template <typename Range,
+			std::enable_if_t<is_range_v<Range>>* = nullptr>
+		constexpr auto adl_begin(Range&& range)
+		noexcept(noexcept(begin(std::forward<Range>(range))))
+		{
+			return begin(std::forward<Range>(range));
+		}
+
+		template <typename Range,
+			std::enable_if_t<is_range_v<Range>>* = nullptr>
+		constexpr auto adl_end(Range&& range)
+		noexcept(noexcept(end(std::forward<Range>(range))))
+		{
+			return end(std::forward<Range>(range));
+		}
+
+	} // namespace adl_helper
+
+} // namespace simple::support
+
+#endif /* end of include guard */

+ 1 - 1
source/simple/support/algorithm/numeric.hpp

@@ -124,7 +124,7 @@ namespace simple::support
 	template <typename Range,
 		std::enable_if_t<is_range_v<Range>>* = nullptr>
 	[[nodiscard]] constexpr
-	auto midpoint(const Range& r) noexcept
+	auto midpoint(Range&& r) noexcept
 	// TODO noexcept
 	{
 		using std::begin; using std::end;

+ 61 - 85
source/simple/support/algorithm/range_wrappers.hpp

@@ -5,37 +5,12 @@
 #include <algorithm>
 #include <string_view>
 
-#include "../algorithm/traits.hpp" // support::is_range_v
+#include "traits.hpp" // support::is_range_v
 #include "../function_utils.hpp" // support::invoke
+#include "adl_helper.hpp" // adl_helper::adl_begin adl_helper::adl_end
 
 namespace simple::support
 {
-	//TODO: all noexcepts bellow should account for return value construction
-
-	namespace detail // TODO: rename to adl_helper
-	{
-		using std::begin;
-		using std::end;
-
-		// TODO: should these return decltype(auto)?
-		template <typename Range,
-			std::enable_if_t<is_range_v<Range>>* = nullptr>
-		constexpr auto adl_begin(Range&& range)
-		noexcept(noexcept(begin(std::forward<Range>(range))))
-		{
-			return begin(std::forward<Range>(range));
-		}
-
-		template <typename Range,
-			std::enable_if_t<is_range_v<Range>>* = nullptr>
-		constexpr auto adl_end(Range&& range)
-		noexcept(noexcept(end(std::forward<Range>(range))))
-		{
-			return end(std::forward<Range>(range));
-		}
-
-	} // namespace detail
-
 
 	// TODO: check if string view has begin-end constructor(should since c++20) and replace this with a deprecated alias
 	class string_view : public std::string_view
@@ -47,77 +22,78 @@ namespace simple::support
 		{}
 	};
 
+	//TODO: all noexcepts bellow should account for return value construction
 
 	template <typename Range,
 		std::enable_if_t<is_range_v<Range>>* = nullptr>
 	constexpr auto min_element(Range& range)
-	noexcept(noexcept(std::min_element(detail::adl_begin(range), detail::adl_end(range))))
+	noexcept(noexcept(std::min_element(adl_helper::adl_begin(range), adl_helper::adl_end(range))))
 	{
-		return std::min_element(detail::adl_begin(range), detail::adl_end(range));
+		return std::min_element(adl_helper::adl_begin(range), adl_helper::adl_end(range));
 	}
 
 	template <typename Range,
 		std::enable_if_t<is_range_v<Range>>* = nullptr>
 	constexpr auto min_element(Range&& range)
-	noexcept(noexcept(std::min_element(detail::adl_begin(range), detail::adl_end(range))))
+	noexcept(noexcept(std::min_element(adl_helper::adl_begin(range), adl_helper::adl_end(range))))
 	{
-		return *std::min_element(detail::adl_begin(range), detail::adl_end(range));
+		return *std::min_element(adl_helper::adl_begin(range), adl_helper::adl_end(range));
 	}
 
 	template <typename Range,
 		std::enable_if_t<is_range_v<Range>>* = nullptr>
 	constexpr auto max_element(Range& range)
-	noexcept(noexcept(std::max_element(detail::adl_begin(range), detail::adl_end(range))))
+	noexcept(noexcept(std::max_element(adl_helper::adl_begin(range), adl_helper::adl_end(range))))
 	{
-		return std::max_element(detail::adl_begin(range), detail::adl_end(range));
+		return std::max_element(adl_helper::adl_begin(range), adl_helper::adl_end(range));
 	}
 
 	template <typename Range,
 		std::enable_if_t<is_range_v<Range>>* = nullptr>
 	constexpr auto max_element(Range&& range)
-	noexcept(noexcept(std::max_element(detail::adl_begin(range), detail::adl_end(range))))
+	noexcept(noexcept(std::max_element(adl_helper::adl_begin(range), adl_helper::adl_end(range))))
 	{
-		return *std::max_element(detail::adl_begin(range), detail::adl_end(range));
+		return *std::max_element(adl_helper::adl_begin(range), adl_helper::adl_end(range));
 	}
 
 	template <typename Range, typename Compare,
 		std::enable_if_t<is_range_v<Range>>* = nullptr>
 	constexpr auto min_element(Range& range, Compare comp)
-	noexcept(noexcept(std::min_element(detail::adl_begin(range), detail::adl_end(range), std::move(comp))))
+	noexcept(noexcept(std::min_element(adl_helper::adl_begin(range), adl_helper::adl_end(range), std::move(comp))))
 	{
-		return std::min_element(detail::adl_begin(range), detail::adl_end(range), std::move(comp));
+		return std::min_element(adl_helper::adl_begin(range), adl_helper::adl_end(range), std::move(comp));
 	}
 
 	template <typename Range, typename Compare,
 		std::enable_if_t<is_range_v<Range>>* = nullptr>
 	constexpr auto min_element(Range&& range, Compare comp)
-	noexcept(noexcept(std::min_element(detail::adl_begin(range), detail::adl_end(range), std::move(comp))))
+	noexcept(noexcept(std::min_element(adl_helper::adl_begin(range), adl_helper::adl_end(range), std::move(comp))))
 	{
-		return *std::min_element(detail::adl_begin(range), detail::adl_end(range), std::move(comp));
+		return *std::min_element(adl_helper::adl_begin(range), adl_helper::adl_end(range), std::move(comp));
 	}
 
 	template <typename Range, typename Compare,
 		std::enable_if_t<is_range_v<Range>>* = nullptr>
 	constexpr auto max_element(Range& range, Compare comp)
-	noexcept(noexcept(std::max_element(detail::adl_begin(range), detail::adl_end(range), std::move(comp))))
+	noexcept(noexcept(std::max_element(adl_helper::adl_begin(range), adl_helper::adl_end(range), std::move(comp))))
 	{
-		return std::max_element(detail::adl_begin(range), detail::adl_end(range), std::move(comp));
+		return std::max_element(adl_helper::adl_begin(range), adl_helper::adl_end(range), std::move(comp));
 	}
 
 	template <typename Range, typename Compare,
 		std::enable_if_t<is_range_v<Range>>* = nullptr>
 	constexpr auto max_element(Range&& range, Compare comp)
-	noexcept(noexcept(std::max_element(detail::adl_begin(range), detail::adl_end(range), std::move(comp))))
+	noexcept(noexcept(std::max_element(adl_helper::adl_begin(range), adl_helper::adl_end(range), std::move(comp))))
 	{
-		return *std::max_element(detail::adl_begin(range), detail::adl_end(range), std::move(comp));
+		return *std::max_element(adl_helper::adl_begin(range), adl_helper::adl_end(range), std::move(comp));
 	}
 
 	template <typename Range, typename UnaryPredicate,
 		std::enable_if_t<is_range_v<Range>>* = nullptr>
 	constexpr auto all_of(const Range& range, UnaryPredicate p)
-	noexcept(noexcept(std::all_of(detail::adl_begin(range), detail::adl_end(range), std::move(p))))
+	noexcept(noexcept(std::all_of(adl_helper::adl_begin(range), adl_helper::adl_end(range), std::move(p))))
 	{
-		return std::all_of(detail::adl_begin(range), detail::adl_end(range), std::move(p));
+		return std::all_of(adl_helper::adl_begin(range), adl_helper::adl_end(range), std::move(p));
 	}
 	template <typename ExecutionPolicy, typename Range, typename UnaryPredicate,
 		// TODO: use std::is_execution_policy_v when it stops depending on external tbb
@@ -125,18 +101,18 @@ namespace simple::support
 		std::enable_if_t<is_range_v<Range>>* = nullptr>
 	constexpr auto all_of(ExecutionPolicy&& policy, const Range& range, UnaryPredicate p)
 	noexcept(noexcept(std::all_of(std::forward<ExecutionPolicy>(policy),
-		detail::adl_begin(range), detail::adl_end(range), std::move(p))))
+		adl_helper::adl_begin(range), adl_helper::adl_end(range), std::move(p))))
 	{
 		return std::all_of(std::forward<ExecutionPolicy>(policy),
-			detail::adl_begin(range), detail::adl_end(range), std::move(p));
+			adl_helper::adl_begin(range), adl_helper::adl_end(range), std::move(p));
 	}
 
 	template <typename Range, typename UnaryPredicate,
 		std::enable_if_t<is_range_v<Range>>* = nullptr>
 	constexpr auto any_of(const Range& range, UnaryPredicate p)
-	noexcept(noexcept(std::any_of(detail::adl_begin(range), detail::adl_end(range), std::move(p))))
+	noexcept(noexcept(std::any_of(adl_helper::adl_begin(range), adl_helper::adl_end(range), std::move(p))))
 	{
-		return std::any_of(detail::adl_begin(range), detail::adl_end(range), std::move(p));
+		return std::any_of(adl_helper::adl_begin(range), adl_helper::adl_end(range), std::move(p));
 	}
 	template <typename ExecutionPolicy, typename Range, typename UnaryPredicate,
 		// TODO: use std::is_execution_policy_v when it stops depending on external tbb
@@ -144,18 +120,18 @@ namespace simple::support
 		std::enable_if_t<is_range_v<Range>>* = nullptr>
 	constexpr auto any_of(ExecutionPolicy&& policy, const Range& range, UnaryPredicate p)
 	noexcept(noexcept(std::any_of(std::forward<ExecutionPolicy>(policy),
-		detail::adl_begin(range), detail::adl_end(range), std::move(p))))
+		adl_helper::adl_begin(range), adl_helper::adl_end(range), std::move(p))))
 	{
 		return std::any_of(std::forward<ExecutionPolicy>(policy),
-			detail::adl_begin(range), detail::adl_end(range), std::move(p));
+			adl_helper::adl_begin(range), adl_helper::adl_end(range), std::move(p));
 	}
 
 	template <typename Range, typename UnaryPredicate,
 		std::enable_if_t<is_range_v<Range>>* = nullptr>
 	constexpr auto none_of(const Range& range, UnaryPredicate p)
-	noexcept(noexcept(std::none_of(detail::adl_begin(range), detail::adl_end(range), std::move(p))))
+	noexcept(noexcept(std::none_of(adl_helper::adl_begin(range), adl_helper::adl_end(range), std::move(p))))
 	{
-		return std::none_of(detail::adl_begin(range), detail::adl_end(range), std::move(p));
+		return std::none_of(adl_helper::adl_begin(range), adl_helper::adl_end(range), std::move(p));
 	}
 	template <typename ExecutionPolicy, typename Range, typename UnaryPredicate,
 		// TODO: use std::is_execution_policy_v when it stops depending on external tbb
@@ -163,10 +139,10 @@ namespace simple::support
 		std::enable_if_t<is_range_v<Range>>* = nullptr>
 	constexpr auto none_of(ExecutionPolicy&& policy, const Range& range, UnaryPredicate p)
 	noexcept(noexcept(std::none_of(std::forward<ExecutionPolicy>(policy),
-		detail::adl_begin(range), detail::adl_end(range), std::move(p))))
+		adl_helper::adl_begin(range), adl_helper::adl_end(range), std::move(p))))
 	{
 		return std::none_of(std::forward<ExecutionPolicy>(policy),
-			detail::adl_begin(range), detail::adl_end(range), std::move(p));
+			adl_helper::adl_begin(range), adl_helper::adl_end(range), std::move(p));
 	}
 
 	template <typename ExecutionPolicy, typename Range, typename OutIt, typename UnaryPredicate,
@@ -176,19 +152,19 @@ namespace simple::support
 	constexpr auto copy_if(ExecutionPolicy&& policy, const Range& range, UnaryPredicate p, OutIt out)
 	noexcept(noexcept(
 		std::copy_if(std::forward<ExecutionPolicy>(policy),
-			detail::adl_begin(range), detail::adl_end(range), out, std::move(p))
+			adl_helper::adl_begin(range), adl_helper::adl_end(range), out, std::move(p))
 	))
 	{
 		return std::copy_if(std::forward<ExecutionPolicy>(policy),
-			detail::adl_begin(range), detail::adl_end(range), out, std::move(p));
+			adl_helper::adl_begin(range), adl_helper::adl_end(range), out, std::move(p));
 	}
 
 	template <typename Range, typename OutIt, typename UnaryPredicate,
 		std::enable_if_t<is_range_v<Range>>* = nullptr>
 	constexpr auto copy_if(const Range& range, UnaryPredicate p, OutIt out)
-	noexcept(noexcept(std::copy_if(detail::adl_begin(range), detail::adl_end(range), out, std::move(p))))
+	noexcept(noexcept(std::copy_if(adl_helper::adl_begin(range), adl_helper::adl_end(range), out, std::move(p))))
 	{
-		return std::copy_if(detail::adl_begin(range), detail::adl_end(range), out, std::move(p));
+		return std::copy_if(adl_helper::adl_begin(range), adl_helper::adl_end(range), out, std::move(p));
 	}
 
 	template <typename ExecutionPolicy, typename Range, typename OutIt,
@@ -198,19 +174,19 @@ namespace simple::support
 	constexpr auto copy(ExecutionPolicy&& policy, const Range& range, OutIt out)
 	noexcept(noexcept(
 		std::copy(std::forward<ExecutionPolicy>(policy),
-			detail::adl_begin(range), detail::adl_end(range), out)
+			adl_helper::adl_begin(range), adl_helper::adl_end(range), out)
 	))
 	{
 		return std::copy(std::forward<ExecutionPolicy>(policy),
-			detail::adl_begin(range), detail::adl_end(range), out);
+			adl_helper::adl_begin(range), adl_helper::adl_end(range), out);
 	}
 
 	template <typename Range, typename OutIt,
 		std::enable_if_t<is_range_v<Range>>* = nullptr>
 	constexpr auto copy(const Range& range, OutIt out)
-	noexcept(noexcept(std::copy(detail::adl_begin(range), detail::adl_end(range), out)))
+	noexcept(noexcept(std::copy(adl_helper::adl_begin(range), adl_helper::adl_end(range), out)))
 	{
-		return std::copy(detail::adl_begin(range), detail::adl_end(range), out);
+		return std::copy(adl_helper::adl_begin(range), adl_helper::adl_end(range), out);
 	}
 
 	template <typename ExecutionPolicy, typename Range, typename It, typename OutIt, typename BinaryOperation,
@@ -220,12 +196,12 @@ namespace simple::support
 	constexpr auto transform(ExecutionPolicy&& policy, const Range& range, It it, BinaryOperation op, OutIt out)
 	noexcept(noexcept(
 		std::transform(std::forward<ExecutionPolicy>(policy),
-			detail::adl_begin(range), detail::adl_end(range),
+			adl_helper::adl_begin(range), adl_helper::adl_end(range),
 			it, out, std::move(op))
 	))
 	{
 		return std::transform(std::forward<ExecutionPolicy>(policy),
-			detail::adl_begin(range), detail::adl_end(range),
+			adl_helper::adl_begin(range), adl_helper::adl_end(range),
 			it, out, std::move(op));
 	}
 
@@ -233,11 +209,11 @@ namespace simple::support
 		std::enable_if_t<is_range_v<Range>>* = nullptr>
 	constexpr auto transform(const Range& range, It it, BinaryOperation op, OutIt out)
 	noexcept(noexcept(
-		std::transform(detail::adl_begin(range), detail::adl_end(range),
+		std::transform(adl_helper::adl_begin(range), adl_helper::adl_end(range),
 			it, out, std::move(op))
 	))
 	{
-		return std::transform(detail::adl_begin(range), detail::adl_end(range),
+		return std::transform(adl_helper::adl_begin(range), adl_helper::adl_end(range),
 			it, out, std::move(op));
 	}
 
@@ -248,12 +224,12 @@ namespace simple::support
 	constexpr auto transform(ExecutionPolicy&& policy, const Range& range, UnaryOperation op, OutIt out)
 	noexcept(noexcept(
 		std::transform(std::forward<ExecutionPolicy>(policy),
-			detail::adl_begin(range), detail::adl_end(range),
+			adl_helper::adl_begin(range), adl_helper::adl_end(range),
 			out, std::move(op))
 	))
 	{
 		return std::transform(std::forward<ExecutionPolicy>(policy),
-			detail::adl_begin(range), detail::adl_end(range),
+			adl_helper::adl_begin(range), adl_helper::adl_end(range),
 			out, std::move(op));
 	}
 
@@ -261,11 +237,11 @@ namespace simple::support
 		std::enable_if_t<is_range_v<Range>>* = nullptr>
 	constexpr auto transform(const Range& range, UnaryOperation op, OutIt out)
 	noexcept(noexcept(
-		std::transform(detail::adl_begin(range), detail::adl_end(range),
+		std::transform(adl_helper::adl_begin(range), adl_helper::adl_end(range),
 			out, std::move(op))
 	))
 	{
-		return std::transform(detail::adl_begin(range), detail::adl_end(range),
+		return std::transform(adl_helper::adl_begin(range), adl_helper::adl_end(range),
 			out, std::move(op));
 	}
 
@@ -278,21 +254,21 @@ namespace simple::support
 	constexpr auto find_if(ExecutionPolicy&& policy, const Range& range, UnaryPredicate p)
 	noexcept(noexcept(
 		std::find_if(std::forward<ExecutionPolicy>(policy),
-			detail::adl_begin(range), detail::adl_end(range), std::move(p))
+			adl_helper::adl_begin(range), adl_helper::adl_end(range), std::move(p))
 	))
 	{
 		return std::find_if(std::forward<ExecutionPolicy>(policy),
-			detail::adl_begin(range), detail::adl_end(range), std::move(p));
+			adl_helper::adl_begin(range), adl_helper::adl_end(range), std::move(p));
 	}
 
 	template <typename Range, typename UnaryPredicate,
 		std::enable_if_t<is_range_v<Range>>* = nullptr>
 	constexpr auto find_if(const Range& range, UnaryPredicate p)
 	noexcept(noexcept(
-		std::find_if(detail::adl_begin(range), detail::adl_end(range), std::move(p))
+		std::find_if(adl_helper::adl_begin(range), adl_helper::adl_end(range), std::move(p))
 	))
 	{
-		return std::find_if(detail::adl_begin(range), detail::adl_end(range), std::move(p));
+		return std::find_if(adl_helper::adl_begin(range), adl_helper::adl_end(range), std::move(p));
 	}
 
 	template <typename ExecutionPolicy, typename Range, typename Value,
@@ -302,21 +278,21 @@ namespace simple::support
 	constexpr auto find(ExecutionPolicy&& policy, const Range& range, const Value& value)
 	noexcept(noexcept(
 		std::find(std::forward<ExecutionPolicy>(policy),
-			detail::adl_begin(range), detail::adl_end(range), value)
+			adl_helper::adl_begin(range), adl_helper::adl_end(range), value)
 	))
 	{
 		return std::find(std::forward<ExecutionPolicy>(policy),
-			detail::adl_begin(range), detail::adl_end(range), value);
+			adl_helper::adl_begin(range), adl_helper::adl_end(range), value);
 	}
 
 	template <typename Range, typename Value,
 		std::enable_if_t<is_range_v<Range>>* = nullptr>
 	constexpr auto find(const Range& range, const Value& value)
 	noexcept(noexcept(
-		std::find(detail::adl_begin(range), detail::adl_end(range), value)
+		std::find(adl_helper::adl_begin(range), adl_helper::adl_end(range), value)
 	))
 	{
-		return std::find(detail::adl_begin(range), detail::adl_end(range), value);
+		return std::find(adl_helper::adl_begin(range), adl_helper::adl_end(range), value);
 	}
 
 	template <typename ExecutionPolicy, typename Range, typename Value, typename BinaryPredicate,
@@ -326,12 +302,12 @@ namespace simple::support
 	constexpr auto find(ExecutionPolicy&& policy, const Range& range, const Value& v, BinaryPredicate&& p)
 	noexcept(noexcept(
 		std::find(std::forward<ExecutionPolicy>(policy),
-			detail::adl_begin(range), detail::adl_end(range), v),
-		support::invoke(std::forward<BinaryPredicate>(p), *detail::adl_begin(range), v)
+			adl_helper::adl_begin(range), adl_helper::adl_end(range), v),
+		support::invoke(std::forward<BinaryPredicate>(p), *adl_helper::adl_begin(range), v)
 	))
 	{
 		return std::find_if(std::forward<ExecutionPolicy>(policy),
-			detail::adl_begin(range), detail::adl_end(range),
+			adl_helper::adl_begin(range), adl_helper::adl_end(range),
 			[&](auto&& x) { return support::invoke(std::forward<BinaryPredicate>(p), x, v); }
 		);
 	}
@@ -340,11 +316,11 @@ namespace simple::support
 		std::enable_if_t<is_range_v<Range>>* = nullptr>
 	constexpr auto find(const Range& range, const Value& v, BinaryPredicate&& p)
 	noexcept(noexcept(
-		std::find(detail::adl_begin(range), detail::adl_end(range), v),
-		support::invoke(std::forward<BinaryPredicate>(p), *detail::adl_begin(range), v)
+		std::find(adl_helper::adl_begin(range), adl_helper::adl_end(range), v),
+		support::invoke(std::forward<BinaryPredicate>(p), *adl_helper::adl_begin(range), v)
 	))
 	{
-		return std::find_if(detail::adl_begin(range), detail::adl_end(range),
+		return std::find_if(adl_helper::adl_begin(range), adl_helper::adl_end(range),
 			[&](auto&& x) { return support::invoke(std::forward<BinaryPredicate>(p), x, v); }
 		);
 	}

+ 65 - 0
source/simple/support/algorithm/search.hpp

@@ -0,0 +1,65 @@
+#ifndef SIMPLE_SUPPORT_ALGORITHM_SEARCH_HPP
+#define SIMPLE_SUPPORT_ALGORITHM_SEARCH_HPP
+
+#include "mismatch.hpp" // mismatch
+#include "../range.hpp" // range
+
+namespace simple::support
+{
+
+	// cause we don't get a proper standard search until c++20, and even then it depends on super experimental ranges library
+	// (how does stuff like that even get in i wonder -_-)
+	template <typename It, typename NeedleIt>
+	[[nodiscard]] constexpr
+	range<It> search(It begin, It end, NeedleIt nbegin, NeedleIt nend)
+	{
+		while(true)
+		{
+			auto [found_end, match_end] = support::mismatch(begin, end, nbegin, nend);
+			if(match_end == nend)
+				return {begin, found_end};
+			else if(found_end == end)
+				return {end, end};
+			++begin;
+		}
+		return {end,end}; // unreachable
+	}
+
+	// TODO: nearly identical to searche above
+	template <typename It, typename NeedleIt>
+	[[nodiscard]] constexpr
+	std::pair<range<It>, NeedleIt> search_prefix(It begin, It end, NeedleIt nbegin, NeedleIt nend)
+	{
+		while(true)
+		{
+			auto [found_end, match_end] = support::mismatch(begin, end, nbegin, nend);
+			if(match_end != nbegin) // we want any size match
+				return {{begin, found_end}, match_end};
+			else if(found_end == end)
+				return {{end, end}, nbegin};
+			++begin;
+		}
+		return {{end,end}, nend}; // unreachable
+	}
+
+	// TODO: nearly identical to search above
+	template <typename It, typename NeedleIt>
+	[[nodiscard]] constexpr
+	range<It> search(It begin, It end, NeedleIt nbegin) // assuming infinite needle
+	{
+		while(true)
+		{
+			auto [found_end, match_end] = support::mismatch(begin, end, nbegin);
+			if(match_end != nbegin) // we can't ever find all of it so we make due with some
+				return {begin, found_end};
+			else if(found_end == end)
+				return {end, end};
+			++begin;
+		}
+		return {end,end}; // unreachable
+	}
+
+
+} // namespace simple::support
+
+#endif /* end of include guard */

+ 1 - 36
source/simple/support/algorithm/split.hpp

@@ -4,45 +4,10 @@
 #include <iterator> // std::begin std::end
 
 #include "traits.hpp" // is_range_v is_iterable_v
-#include "mismatch.hpp" // mismatch
-#include "../range.hpp" // range
+#include "search.hpp" // search
 
 namespace simple::support
 {
-	// cause we don't get a proper standard search until c++20, and even then it depends on super experimental ranges library
-	// (how does stuff like that even get in i wonder -_-)
-	template <typename It, typename NeedleIt>
-	[[nodiscard]] constexpr
-	range<It> search(It begin, It end, NeedleIt nbegin, NeedleIt nend)
-	{
-		while(true)
-		{
-			auto [found_end, match_end] = support::mismatch(begin, end, nbegin, nend);
-			if(match_end == nend)
-				return {begin, found_end};
-			else if(found_end == end)
-				return {end, end};
-			++begin;
-		}
-		return {end,end}; // unreachable
-	}
-
-	// TODO: nearly identical to search above
-	template <typename It, typename NeedleIt>
-	[[nodiscard]] constexpr
-	range<It> search(It begin, It end, NeedleIt nbegin)
-	{
-		while(true)
-		{
-			auto [found_end, match_end] = support::mismatch(begin, end, nbegin);
-			if(match_end != nbegin) // we can't ever find all of it so we make due with some
-				return {begin, found_end};
-			else if(found_end == end)
-				return {end, end};
-			++begin;
-		}
-		return {end,end}; // unreachable
-	}
 
 	template <typename It, typename SepIt, typename OutIt>
 	constexpr

+ 1 - 1
source/simple/support/algorithm/traits.hpp

@@ -15,7 +15,7 @@ namespace simple::support
 	template<typename Type>
 	struct is_iterable<Type,
 	decltype(
-		not (std::declval<Type>() != std::declval<Type>()),
+		// not (std::declval<Type>() != std::declval<Type>()), // output iterators are not comparable
 		void(*std::declval<Type>()),
 		void(++(std::declval<Type&>())),
 		nullptr)>

+ 1 - 1
source/simple/support/iterator/offset.hpp

@@ -17,7 +17,7 @@ namespace simple::support
 		using iterator_type = typename std::remove_reference_t<Array>::iterator;
 
 		using value_type = typename std::iterator_traits<iterator_type>::value_type;
-		using difference_type = typename std::iterator_traits<iterator_type>::value_type;
+		using difference_type = typename std::iterator_traits<iterator_type>::difference_type;
 		using pointer = typename std::iterator_traits<iterator_type>::pointer;
 		using reference = typename std::iterator_traits<iterator_type>::reference;
 		using iterator_category = typename std::iterator_traits<iterator_type>::iterator_category;

+ 2 - 2
source/simple/support/iterator/offset_expander.hpp

@@ -9,7 +9,7 @@
 namespace simple::support
 {
 
-	// an offset based iterator to which you can assign one past the end to push_back
+	// an offset based iterator to which you can assign one past the end to emplace_back
 	template <typename Array>
 	struct offset_expander
 	{
@@ -17,7 +17,7 @@ namespace simple::support
 		using iterator_type = typename std::remove_reference_t<Array>::iterator;
 
 		using value_type = typename std::iterator_traits<iterator_type>::value_type;
-		using difference_type = typename std::iterator_traits<iterator_type>::value_type;
+		using difference_type = typename std::iterator_traits<iterator_type>::difference_type;
 		using pointer = typename std::iterator_traits<iterator_type>::pointer;
 		using reference = typename std::iterator_traits<iterator_type>::reference;
 		using iterator_category = typename std::iterator_traits<iterator_type>::iterator_category;

+ 0 - 0
source/simple/support/iterator/out_accumulate.hpp


Some files were not shown because too many files changed in this diff