2#ifndef LIBSBX_UTILITY_ITERATOR_HPP_
3#define LIBSBX_UTILITY_ITERATOR_HPP_
12#include <range/v3/all.hpp>
14namespace sbx::utility {
16template<
typename Category,
typename Type,
typename Distance = std::ptrdiff_t,
typename Po
inter = Type*,
typename Reference = Type&>
18 using iterator_category = Category;
19 using value_type = Type;
20 using difference_type = Distance;
21 using pointer = Pointer;
22 using reference = Reference;
25template<
typename Type>
26concept iterable =
requires(Type t) {
27 { std::begin(t) } -> std::same_as<typename Type::iterator>;
28 { std::end(t) } -> std::same_as<typename Type::iterator>;
29} ||
requires(Type t) {
30 { std::begin(t) } -> std::same_as<typename Type::const_iterator>;
31 { std::end(t) } -> std::same_as<typename Type::const_iterator>;
32} || std::is_array_v<Type>;
34template<
template<
typename>
typename To, ranges::input_range Range, std::invocable<const ranges::range_value_t<Range>&> Fn>
35requires (ranges::output_range<To<std::invoke_result_t<Fn, const ranges::range_value_t<Range>&>>, std::invoke_result_t<Fn, const ranges::range_value_t<Range>&>>)
36auto map_to(Range&& range, Fn&& fn) -> To<std::invoke_result_t<Fn, const ranges::range_value_t<Range>&>> {
37 return std::forward<Range>(range) | ranges::views::transform(std::forward<Fn>(fn)) | ranges::to<To>();
40template<
typename Range>
41concept move_appendable = std::movable<typename Range::value_type> &&
requires(Range& destination, Range& source, std::size_t n) {
45 destination.reserve(n);
46 destination.insert(destination.end(), std::make_move_iterator(source.begin()), std::make_move_iterator(source.end()));
59template<move_appendable Range>
60auto append(Range& destination, Range&& source) ->
void {
61 destination.reserve(destination.size() + source.size());
62 std::move(std::make_move_iterator(source.begin()), std::make_move_iterator(source.end()), std::back_inserter(destination));
66template<
typename Range>
67concept copy_appendable = std::copyable<typename Range::value_type> &&
requires(Range& destination,
const Range& source, std::size_t n) {
70 destination.reserve(n);
71 destination.insert(destination.end(), source.begin(), source.end());
82template<copy_appendable Range>
83auto append(Range& destination,
const Range& source) ->
void {
84 destination.reserve(destination.size() + source.size());
85 std::copy(source.begin(), source.end(), std::back_inserter(destination));
91template<
typename Type>
93 { descriptor.is_valid(size) } -> std::same_as<bool>;
94 { descriptor.start(size) } -> std::same_as<std::size_t>;
95 { descriptor.end(size) } -> std::same_as<std::size_t>;
106 constexpr auto is_valid(
const std::size_t size)
const ->
bool {
107 return offset <= size;
110 constexpr auto start([[maybe_unused]]
const std::size_t size)
const -> std::size_t {
114 constexpr auto end(
const std::size_t size)
const -> std::size_t {
115 return std::min(offset + count, size);
125 std::size_t begin_index;
126 std::size_t end_index;
128 constexpr auto is_valid(
const std::size_t size)
const ->
bool {
129 return begin_index <= end_index && end_index <= size;
132 constexpr auto start([[maybe_unused]]
const std::size_t size)
const -> std::size_t {
136 constexpr auto end([[maybe_unused]]
const std::size_t size)
const -> std::size_t {
155template<std::movable Type, range_descriptor Range>
156auto subrange(std::vector<Type>&& vector,
const Range& range) -> std::vector<Type> {
157 const auto size = vector.size();
159 if (!range.is_valid(size)) {
163 const auto start = range.start(size);
164 const auto end = range.end(size);
166 auto result = std::vector<Type>{};
167 result.reserve(end - start);
169 std::move(std::make_move_iterator(vector.begin() + start), std::make_move_iterator(vector.begin() + end), std::back_inserter(result));
187template<std::copyable Type, range_descriptor Range>
188auto subrange(
const std::vector<Type>& vector,
const Range& range) -> std::vector<Type> {
189 const auto size = vector.size();
191 if (!range.is_valid(size)) {
195 const auto start = range.start(size);
196 const auto end = range.end(size);
198 auto result = std::vector<Type>{};
199 result.reserve(end - start);
201 std::copy(vector.begin() + start, vector.begin() + end, std::back_inserter(result));
206template<std::copyable Type>
207auto make_vector(
const std::size_t size,
const Type& value = Type{}) -> std::vector<Type> {
208 auto result = std::vector<Type>{};
210 result.resize(size, value);
215template<
typename Type>
216auto make_reserved_vector(
const std::size_t size) -> std::vector<Type> {
217 auto result = std::vector<Type>{};
219 result.reserve(size);
Concept for a range descriptor that calculates a start/end subrange from a given size.
Definition: iterator.hpp:92
Definition: iterator.hpp:17
Range specified by an offset and a count.
Definition: iterator.hpp:101
Range specified by an explicit start and end index.
Definition: iterator.hpp:123