17 #ifndef OPENKALMAN_COMPATIBILITY_VIEWS_TRANSFORM_HPP 18 #define OPENKALMAN_COMPATIBILITY_VIEWS_TRANSFORM_HPP 20 #ifndef __cpp_lib_ranges 23 #include "basics/compatibility/ranges/range-access.hpp" 34 template<
typename V,
typename F>
39 static_assert(ranges::input_range<V>);
40 static_assert(std::is_move_constructible_v<F>);
41 static_assert(ranges::view<V>);
42 static_assert(std::is_object_v<F>);
43 static_assert(std::is_invocable_v<F&, ranges::range_reference_t<V>>);
45 template<
bool Const,
typename T>
46 using maybe_const = std::conditional_t<Const, const T, T>;
58 using Parent = maybe_const<Const, transform_view>;
59 using Base = maybe_const<Const, V>;
63 using iterator_concept = std::conditional_t<
64 ranges::random_access_range<Base>, std::random_access_iterator_tag,
65 std::conditional_t<ranges::bidirectional_range<Base>, std::bidirectional_iterator_tag,
66 std::conditional_t<ranges::forward_range<Base>, std::forward_iterator_tag, std::input_iterator_tag>>>;
68 using reference = std::invoke_result_t<maybe_const<Const, F>&, ranges::range_reference_t<Base>>;
69 using value_type = remove_cvref_t<reference>;
70 using difference_type = ranges::range_difference_t<Base>;
73 using iterator_category = std::conditional_t<
74 not std::is_reference_v<reference>,
75 std::input_iterator_tag,
76 typename std::iterator_traits<ranges::iterator_t<Base>>::iterator_category>;
78 template<
bool Enable = true, std::enable_if_t<Enable and std::is_default_constructible_v<ranges::iterator_t<Base>>,
int> = 0>
81 constexpr
iterator(Parent& parent, ranges::iterator_t<Base> current) : current_ {std::move(current)}, parent_ {std::addressof(parent)} {}
83 template<
bool Enable = Const, std::enable_if_t<Enable and std::is_convertible_v<ranges::iterator_t<V>, ranges::iterator_t<Base>>,
int> = 0>
84 constexpr iterator(
iterator<not Const> i) : current_ {std::move(i.current_)}, parent_ {std::move(i.parent_)} {}
86 constexpr
const ranges::iterator_t<Base>& base()
const & noexcept {
return current_; }
88 constexpr ranges::iterator_t<Base> base() && {
return std::move(current_); }
90 constexpr decltype(
auto) operator*()
const 92 #if __cplusplus >= 202002L 97 return ns::invoke(std::get<0>(parent_->fun_), *current_);
100 template<
bool Enable = true, std::enable_if_t<Enable and ranges::random_access_range<Base>,
int> = 0>
101 constexpr decltype(
auto) operator[](difference_type n)
const 103 #if __cplusplus >= 202002L 108 return ns::invoke(std::get<0>(parent_->fun_), current_[n]);
111 constexpr iterator& operator++() { ++current_;
return *
this; }
113 template<
bool Enable = true, std::enable_if_t<Enable and not ranges::forward_range<Base>,
int> = 0>
114 constexpr
void operator++(
int) { ++current_; }
116 template<
bool Enable = true, std::enable_if_t<Enable and ranges::forward_range<Base>,
int> = 0>
117 constexpr iterator operator++(
int) {
auto tmp = *
this; ++*
this;
return tmp; }
119 template<
bool Enable = true, std::enable_if_t<Enable and ranges::b
idirectional_range<Base>,
int> = 0>
120 constexpr iterator& operator--() { --current_;
return *
this; }
122 template<
bool Enable = true, std::enable_if_t<Enable and ranges::b
idirectional_range<Base>,
int> = 0>
123 constexpr iterator operator--(
int) {
auto tmp = *
this; --*
this;
return tmp; }
125 template<
bool Enable = true, std::enable_if_t<Enable and ranges::random_access_range<Base>,
int> = 0>
126 constexpr iterator& operator+=(
const difference_type& n) { current_ += n;
return *
this; }
128 template<
bool Enable = true, std::enable_if_t<Enable and ranges::random_access_range<Base>,
int> = 0>
129 constexpr iterator& operator-=(
const difference_type& n) { current_ -= n;
return *
this; }
131 friend constexpr
bool operator==(
const iterator& x,
const iterator& y) {
return x.current_ == y.current_; }
133 friend constexpr
bool operator!=(
const iterator& x,
const iterator& y) {
return not (x.current_ == y.current_); }
135 friend constexpr
bool operator<(
const iterator& x,
const iterator& y) {
return x.current_ < y.current_; }
137 friend constexpr
bool operator>(
const iterator& x,
const iterator& y) {
return y < x; }
139 friend constexpr
bool operator<=(
const iterator& x,
const iterator& y) {
return not (y < x); }
141 friend constexpr
bool operator>=(
const iterator& x,
const iterator& y) {
return not (x < y); }
143 template<
bool Enable = true, std::enable_if_t<Enable and ranges::random_access_range<Base>,
int> = 0>
144 friend constexpr iterator operator+(
const iterator& i,
const difference_type& n) {
return iterator {*i.parent_, i.current_ + n}; }
146 template<
bool Enable = true, std::enable_if_t<Enable and ranges::random_access_range<Base>,
int> = 0>
147 friend constexpr iterator operator+(
const difference_type& n,
const iterator& i) {
return iterator {*i.parent_, i.current_ + n}; }
149 template<
bool Enable = true, std::enable_if_t<Enable and ranges::random_access_range<Base>,
int> = 0>
150 friend constexpr iterator operator-(
const iterator& i,
const difference_type& n) {
return iterator {*i.parent_, i.current_ - n}; }
152 template<
bool Enable = true, std::enable_if_t<Enable and ranges::random_access_range<Base>,
int> = 0>
153 friend constexpr difference_type operator-(
const iterator& x,
const iterator& y) {
return x.current_ - y.current_; }
155 template<
bool Enable = true, std::enable_if_t<Enable and ranges::random_access_range<Base>,
int> = 0>
156 friend constexpr decltype(
auto) iter_move(
const iterator& i) noexcept(noexcept(std::invoke(std::get<0>(i.parent_->fun_), *i.current_)))
158 if constexpr (std::is_lvalue_reference_v<decltype(*i)>)
return std::move(*i);
165 ranges::iterator_t<Base> current_;
175 using Parent = maybe_const<Const, transform_view>;
176 using Base = maybe_const<Const, V>;
177 using difference_type = ranges::range_difference_t<Base>;
183 constexpr
explicit sentinel(ranges::sentinel_t<Base> end) : end_ {end} {};
185 constexpr
const ranges::sentinel_t<Base>& base()
const {
return end_; }
195 template<
bool Enable =
true, std::enable_if_t<Enable and
196 std::is_convertible_v<decltype(std::declval<ranges::iterator_t<Base>>() - std::declval<ranges::sentinel_t<Base>>()), difference_type>,
int> = 0>
197 friend constexpr difference_type
operator-(
const iterator<Const>& x,
const sentinel& y)
198 {
return x.current_ - y.end_; }
200 template<
bool Enable =
true, std::enable_if_t<Enable and
201 std::is_convertible_v<decltype(-(std::declval<ranges::sentinel_t<Base>>() - std::declval<ranges::iterator_t<Base>>())), difference_type>,
int> = 0>
202 friend constexpr difference_type operator-(
const sentinel& y,
const iterator<Const>& x)
203 {
return y.end_ - x.current_; }
207 ranges::sentinel_t<Base> end_;
211 template<
bool Enable = true, std::enable_if_t<Enable and std::is_default_constructible_v<V> and std::is_default_constructible_v<F>,
int> = 0>
217 transform_view(V base, F fun) : base_ {std::move(base)}, fun_ {std::move(fun)} {}
220 template<
bool Enable = true, std::enable_if_t<Enable and std::is_copy_constructible_v<V>,
int> = 0>
222 base()
const& {
return base_; }
225 base() && {
return std::move(base_); }
231 template<
bool Enable =
true, std::enable_if_t<Enable and
232 ranges::range<const V> and std::is_invocable_v<const F&, ranges::range_reference_t<const V>>,
int> = 0>
234 begin()
const {
return iterator<true> {*
this, ranges::begin(base_)}; }
237 template<
bool Enable = true, std::enable_if_t<Enable and not ranges::common_range<V>,
int> = 0>
241 template<
bool Enable = true, std::enable_if_t<Enable and ranges::common_range<V>,
int> = 0>
245 template<
bool Enable = true, std::enable_if_t<Enable and ranges::range<const V> and not ranges::common_range<const V> and
246 std::is_invocable_v<const F&, ranges::range_reference_t<const V>>,
int> = 0>
250 template<
bool Enable = true, std::enable_if_t<Enable and ranges::common_range<const V> and
251 std::is_invocable_v<const F&, ranges::range_reference_t<const V>>,
int> = 0>
253 end()
const {
return iterator<true> {*
this, ranges::end(base_)}; }
256 template<
bool Enable = true, std::enable_if_t<Enable and ranges::sized_range<V>,
int> = 0>
260 template<
bool Enable = true, std::enable_if_t<Enable and ranges::sized_range<const V>,
int> = 0>
272 template<
typename R,
typename F>
288 template<
typename R, std::enable_if_t<ranges::viewable_range<R>,
int> = 0>
290 operator() (R&& r)
const {
return transform_view {std::forward<R>(r), my_f}; }
301 operator() (F&& f)
const 307 template<
typename R,
typename F, std::enable_if_t<ranges::viewable_range<R>,
int> = 0>
309 operator() (R&& r, F&& f)
const 331 #endif //OPENKALMAN_COMPATIBILITY_VIEWS_TRANSFORM_HPP
Definition: view_interface.hpp:32
Definition: tuple_reverse.hpp:103
The root namespace for OpenKalman.
Definition: basics.hpp:34
Definition: range-access.hpp:25
Definitions relating to the availability of c++ language features.
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: range_adaptor_closure.hpp:35