1#ifndef LIBSBX_UTILITY_ITERATOR_HPP_
2#define LIBSBX_UTILITY_ITERATOR_HPP_
11#include <range/v3/all.hpp>
13namespace sbx::utility {
15template<
typename Category,
typename Type,
typename Distance = std::ptrdiff_t,
typename Po
inter = Type*,
typename Reference = Type&>
17 using iterator_category = Category;
18 using value_type = Type;
19 using difference_type = Distance;
20 using pointer = Pointer;
21 using reference = Reference;
24template<
typename Type>
25concept iterable =
requires(Type t) {
26 { std::begin(t) } -> std::same_as<typename Type::iterator>;
27 { std::end(t) } -> std::same_as<typename Type::iterator>;
28} ||
requires(Type t) {
29 { std::begin(t) } -> std::same_as<typename Type::const_iterator>;
30 { std::end(t) } -> std::same_as<typename Type::const_iterator>;
31} || std::is_array_v<Type>;
33template<
template<
typename>
typename To, ranges::input_range Range, std::invocable<const ranges::range_value_t<Range>&> Fn>
34requires (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>&>>)
35auto map_to(Range&& range, Fn&& fn) -> To<std::invoke_result_t<Fn, const ranges::range_value_t<Range>&>> {
36 return std::forward<Range>(range) | ranges::views::transform(std::forward<Fn>(fn)) | ranges::to<To>();
49template<std::movable Type>
50auto append(std::vector<Type>& destination, std::vector<Type>&& source) ->
void {
51 destination.reserve(destination.size() + source.size());
52 std::move(std::make_move_iterator(source.begin()), std::make_move_iterator(source.end()), std::back_inserter(destination));
64template<std::copyable Type>
65auto append(std::vector<Type>& destination,
const std::vector<Type>& source) ->
void {
66 destination.reserve(destination.size() + source.size());
67 std::copy(source.begin(), source.end(), std::back_inserter(destination));
73template<
typename Type>
75 { descriptor.is_valid(size) } -> std::same_as<bool>;
76 { descriptor.start(size) } -> std::same_as<std::size_t>;
77 { descriptor.end(size) } -> std::same_as<std::size_t>;
88 constexpr auto is_valid(
const std::size_t size)
const ->
bool {
89 return offset <= size;
92 constexpr auto start([[maybe_unused]]
const std::size_t size)
const -> std::size_t {
96 constexpr auto end(
const std::size_t size)
const -> std::size_t {
97 return std::min(offset + count, size);
107 std::size_t begin_index;
108 std::size_t end_index;
110 constexpr auto is_valid(
const std::size_t size)
const ->
bool {
111 return begin_index <= end_index && end_index <= size;
114 constexpr auto start([[maybe_unused]]
const std::size_t size)
const -> std::size_t {
118 constexpr auto end(
const std::size_t size)
const -> std::size_t {
137template<std::movable Type, range_descriptor Range>
138auto subrange(std::vector<Type>&& vector,
const Range& range) -> std::vector<Type> {
139 const auto size = vector.size();
141 if (!range.is_valid(size)) {
145 const auto start = range.start(size);
146 const auto end = range.end(size);
148 auto result = std::vector<Type>{};
149 result.reserve(end - start);
151 std::move(std::make_move_iterator(vector.begin() + start), std::make_move_iterator(vector.begin() + end), std::back_inserter(result));
169template<std::copyable Type, range_descriptor Range>
170auto subrange(
const std::vector<Type>& vector,
const Range& range) -> std::vector<Type> {
171 const auto size = vector.size();
173 if (!range.is_valid(size)) {
177 const auto start = range.start(size);
178 const auto end = range.end(size);
180 auto result = std::vector<Type>{};
181 result.reserve(end - start);
183 std::copy(vector.begin() + start, vector.begin() + end, std::back_inserter(result));
Concept for a range descriptor that calculates a start/end subrange from a given size.
Definition: iterator.hpp:74
Definition: iterator.hpp:16
Range specified by an offset and a count.
Definition: iterator.hpp:83
Range specified by an explicit start and end index.
Definition: iterator.hpp:105