17 #ifndef OPENKALMAN_COMPATIBILITY_VIEWS_CONCAT_HPP 18 #define OPENKALMAN_COMPATIBILITY_VIEWS_CONCAT_HPP 20 #if __cpp_lib_ranges_concat < 202403L 22 #ifdef __cpp_lib_ranges 37 #ifdef __cpp_lib_ranges 38 template<std::ranges::random_access_range...Views> requires (... and std::ranges::view<Views>) and (
sizeof...(Views) > 0)
39 struct concat_view :
std::ranges::view_interface<concat_view<Views...>>
41 template<
typename...Views>
47 #if __cplusplus >= 202002L 48 template<
typename...Rs>
using concat_reference_t = std::common_reference_t<std::ranges::range_reference_t<Rs>...>;
49 template<
typename...Rs>
using concat_value_t = std::common_type_t<std::ranges::range_value_t<Rs>...>;
50 template<
typename...Rs>
using concat_rvalue_reference_t = std::common_reference_t<std::ranges::range_rvalue_reference_t<Rs>...>;
52 template<
typename...Rs>
using concat_reference_t = common_reference_t<ranges::range_reference_t<Rs>...>;
53 template<
typename...Rs>
using concat_value_t = std::common_type_t<ranges::range_value_t<Rs>...>;
54 template<
typename...Rs>
using concat_rvalue_reference_t = common_reference_t<ranges::range_rvalue_reference_t<Rs>...>;
57 template<
bool Const,
typename Rs>
58 using maybe_const = std::conditional_t<Const, const Rs, Rs>;
60 using ViewsTup = std::tuple<Views...>;
63 class concat_index_table
65 template<std::size_t...cs>
66 #ifdef __cpp_lib_constexpr_vector 71 make_index_table_range(
const ViewsTup& tup, std::index_sequence<cs...>)
73 std::vector<std::size_t> table;
74 auto it = std::back_inserter(table);
75 #ifdef __cpp_lib_ranges 78 (std::fill_n(it,
ranges::size(std::get<cs>(tup)), cs), ...);
85 make_index_table(
const ViewsTup& tup)
87 return make_index_table_range(tup, std::index_sequence_for<Views...>{});
92 explicit constexpr concat_index_table(
const ViewsTup& rs_tup) :
value {make_index_table(rs_tup)} {}
94 decltype(make_index_table(std::declval<const ViewsTup&>()))
value;
99 class concat_start_table
101 template<std::size_t i = 0,
typename...Locs>
102 static constexpr
auto 103 make_start_table(
const ViewsTup& tup, std::size_t currloc = 0_uz, Locs...locs)
105 if constexpr (i <
sizeof...(Views))
107 #ifdef __cpp_lib_ranges 110 std::size_t next_loc = currloc +
ranges::size(std::get<i>(tup));
112 return make_start_table<i + 1>(tup, next_loc, locs..., currloc);
116 return std::array {locs...};
122 explicit constexpr concat_start_table(
const ViewsTup& rs_tup) :
value {make_start_table(rs_tup)} {}
124 decltype(make_start_table(std::declval<const ViewsTup&>()))
value;
129 using IndexTable = decltype(concat_index_table(std::declval<ViewsTup>()).
value);
131 using StartTable = decltype(concat_start_table(std::declval<ViewsTup>()).
value);
138 using iterator_concept = std::random_access_iterator_tag;
139 using iterator_category = iterator_concept;
140 using value_type = concat_value_t<maybe_const<Const, Views>...>;
141 #if __cplusplus >= 202002L 142 using difference_type = std::common_type_t<std::ranges::range_difference_t<maybe_const<Const, Views>>...>;
144 using difference_type = std::common_type_t<ranges::range_difference_t<maybe_const<Const, Views>>...>;
146 using pointer = void;
147 using reference = concat_reference_t<maybe_const<Const, Views>...>;
151 using Tup = maybe_const<Const, ViewsTup>;
153 template<
typename = std::index_sequence_for<Views...>>
154 struct tuple_concat_iterator_call_table;
156 template<std::size_t...ix>
157 struct tuple_concat_iterator_call_table<std::index_sequence<ix...>>
159 template<std::
size_t i>
160 static constexpr value_type
161 call_table_get(Tup& tup, std::size_t local_i) noexcept
163 return std::get<i>(tup)[local_i];
166 static constexpr std::array
value {call_table_get<ix>...};
169 using table = tuple_concat_iterator_call_table<>;
173 #ifdef __cpp_lib_ranges 177 (... and std::convertible_to<std::ranges::iterator_t<Views>, std::ranges::iterator_t<const Views>>)
178 : parent(it.parent), current(it.current) {}
181 constexpr
explicit iterator(maybe_const<Const, concat_view>* parent, difference_type p)
183 : parent(parent), current(p) {}
185 constexpr iterator() : parent{
nullptr} {};
187 template<
bool C = Const, std::enable_if_t<C and
188 (... and std::is_convertible_v<ranges::iterator_t<Views>, ranges::iterator_t<const Views>>),
int> = 0>
189 constexpr iterator(
iterator<not C> it) : parent(it.parent), current(it.current) {}
192 constexpr
explicit iterator(maybe_const<Const, concat_view>* parent, difference_type p) : parent(parent), current(p) {}
195 constexpr iterator(
const iterator& other) =
default;
196 constexpr iterator(iterator&& other) noexcept =
default;
197 constexpr iterator& operator=(
const iterator& other) =
default;
198 constexpr iterator& operator=(iterator&& other) noexcept =
default;
199 explicit constexpr
operator std::size_t()
const noexcept {
return static_cast<std::size_t
>(current); }
201 constexpr decltype(
auto) operator*() noexcept
203 std::size_t c = (parent->index_table)[static_cast<std::size_t>(current)];
204 std::size_t local_i = current - parent->start_table[c];
207 constexpr decltype(
auto) operator*()
const noexcept
209 std::size_t c = (parent->index_table)[static_cast<std::size_t>(current)];
210 std::size_t local_i = current - parent->start_table[c];
213 constexpr decltype(
auto) operator[](difference_type offset) noexcept
215 auto i =
static_cast<std::size_t
>(current + offset);
216 std::size_t c = parent->index_table[i];
217 std::size_t local_i = i - parent->start_table[c];
220 constexpr decltype(
auto) operator[](difference_type offset)
const noexcept
222 auto i =
static_cast<std::size_t
>(current + offset);
223 std::size_t c = parent->index_table[i];
224 std::size_t local_i = i - parent->start_table[c];
227 constexpr
auto& operator++() noexcept { ++current;
return *
this; }
228 constexpr
auto operator++(
int) noexcept {
auto temp = *
this; ++*
this;
return temp; }
229 constexpr
auto& operator--() noexcept { --current;
return *
this; }
230 constexpr
auto operator--(
int) noexcept {
auto temp = *
this; --*
this;
return temp; }
231 constexpr
auto& operator+=(
const difference_type diff) noexcept { current += diff;
return *
this; }
232 constexpr
auto& operator-=(
const difference_type diff) noexcept { current -= diff;
return *
this; }
234 friend constexpr
auto operator+(
const iterator& it,
const difference_type diff) noexcept
236 return iterator {it.parent, it.current + diff};
238 friend constexpr
auto operator+(
const difference_type diff,
const iterator& it) noexcept
240 return iterator {it.parent, diff + it.current};
242 friend constexpr
auto operator-(
const iterator& it,
const difference_type diff) noexcept
244 return iterator {it.parent, it.current - diff};
246 friend constexpr difference_type operator-(
const iterator& it,
const iterator& other) noexcept
248 return it.current - other.current;
250 friend constexpr
bool operator==(
const iterator& it,
const iterator& other) noexcept
252 return it.current == other.current;
254 #ifdef __cpp_impl_three_way_comparison 255 constexpr
auto operator<=>(
const iterator& other)
const noexcept {
return current <=> other.current; }
257 constexpr
bool operator!=(
const iterator& other)
const noexcept {
return current != other.current; }
258 constexpr
bool operator<(
const iterator& other)
const noexcept {
return current < other.current; }
259 constexpr
bool operator>(
const iterator& other)
const noexcept {
return current > other.current; }
260 constexpr
bool operator<=(
const iterator& other)
const noexcept {
return current <= other.current; }
261 constexpr
bool operator>=(
const iterator& other)
const noexcept {
return current >= other.current; }
266 maybe_const<Const, concat_view>* parent;
267 difference_type current;
272 #ifdef __cpp_concepts 275 template<
typename aT =
void, std::enable_if_t<std::is_
void_v<aT> and (... and std::is_default_constructible_v<Views>),
int> = 0>
280 explicit constexpr
concat_view(Views...vs) : views_tup {std::move(vs)...} {}
291 begin()
const noexcept
307 return iterator<true> {
this,
static_cast<std::ptrdiff_t
>(size())};
312 template<
typename F,
typename Tuple>
313 static constexpr
auto tuple_transform(F&& f, Tuple&& tuple)
315 return std::apply([&f](
auto&&...args)
317 return std::tuple<std::invoke_result_t<F&, decltype(args)>...>(std::invoke(f, std::forward<decltype(args)>(args))...);
318 }, std::forward<Tuple>(tuple));
324 #ifdef __cpp_lib_ranges 325 constexpr
auto size()
const requires (... and std::ranges::sized_range<Views>)
327 template<
typename aT =
void, std::enable_if_t<std::is_
void_v<aT> and (... and ranges::sized_range<Views>),
int> = 0>
328 constexpr
auto size()
const 331 return std::apply([](
auto...sizes) {
return (... + static_cast<std::size_t>(sizes)); },
332 #ifdef __cpp_lib_ranges 343 IndexTable index_table = concat_index_table(views_tup).value;
345 StartTable start_table = concat_start_table(views_tup).value;
350 template<
typename...Rs>
351 #ifdef __cpp_lib_ranges 366 #ifdef __cpp_lib_ranges 367 template<std::ranges::viewable_range...Rs> requires (... and std::ranges::random_access_range<Rs>)
369 template<
typename...Rs, std::enable_if_t<(... and (ranges::viewable_range<Rs> and ranges::random_access_range<Rs>)),
int> = 0>
372 operator() (Rs&&...rs)
const 374 #ifdef __cpp_lib_ranges 379 if constexpr (
sizeof...(Rs) == 1 and (... and ns::ranges::input_range<Rs>))
380 return ns::ranges::views::all(std::forward<Rs>(rs)...);
382 return concat_view {ns::ranges::views::all(std::forward<Rs>(rs))...};
399 #endif //OPENKALMAN_COMPATIBILITY_VIEWS_CONCAT_HPP
constexpr detail::concat_adaptor concat
a std::ranges::range_adaptor_closure for a set of concatenated collection objects.
Definition: concat.hpp:173
Definition: concat.hpp:364
Definition: view_interface.hpp:32
Definition: tuple_reverse.hpp:103
constexpr bool value
T is numerical value or is reducible to a numerical value.
Definition: value.hpp:31
Definition: concat.hpp:42
The root namespace for OpenKalman.
Definition: basics.hpp:34
Definition: range-access.hpp:25
constexpr bool size
T is either an index representing a size, or void which represents that there is no size...
Definition: size.hpp:32
Definition: concat.hpp:136