17 #ifndef OPENKALMAN_COMPATIBILITY_VIEWS_TRANSFORM_HPP 18 #define OPENKALMAN_COMPATIBILITY_VIEWS_TRANSFORM_HPP 29 #ifdef __cpp_lib_ranges 30 using std::ranges::transform_view;
33 using std::ranges::views::transform;
39 template<
typename V,
typename F>
44 static_assert(stdex::ranges::input_range<V>);
45 static_assert(std::is_move_constructible_v<F>);
46 static_assert(stdex::ranges::view<V>);
47 static_assert(std::is_object_v<F>);
48 static_assert(std::is_invocable_v<F&, stdex::ranges::range_reference_t<V>>);
50 template<
bool Const,
typename T>
51 using maybe_const = std::conditional_t<Const, const T, T>;
63 using Parent = maybe_const<Const, transform_view>;
64 using Base = maybe_const<Const, V>;
65 using MCF = maybe_const<Const, F>;
69 using iterator_concept = std::conditional_t<
70 stdex::ranges::random_access_range<Base>, std::random_access_iterator_tag,
71 std::conditional_t<stdex::ranges::bidirectional_range<Base>, std::bidirectional_iterator_tag,
72 std::conditional_t<stdex::ranges::forward_range<Base>, std::forward_iterator_tag, std::input_iterator_tag>>>;
74 using iterator_category = std::conditional_t<
75 not std::is_reference_v<std::invoke_result_t<MCF&, stdex::ranges::range_reference_t<Base>>>,
76 std::input_iterator_tag,
79 using reference = std::invoke_result_t<MCF&, stdex::ranges::range_reference_t<Base>>;
80 using value_type = stdex::remove_cvref_t<std::invoke_result_t<MCF&, stdex::ranges::range_reference_t<Base>>>;
81 using difference_type = stdex::ranges::range_difference_t<Base>;
84 template<
bool Enable = true, std::enable_if_t<Enable and stdex::default_initializable<stdex::ranges::iterator_t<Base>>,
int> = 0>
87 constexpr
iterator(Parent& parent, stdex::ranges::iterator_t<Base> current) : current_ {std::move(current)}, parent_ {std::addressof(parent)} {}
89 template<
bool Enable = Const, std::enable_if_t<Enable and stdex::convertible_to<stdex::ranges::iterator_t<V>, stdex::ranges::iterator_t<Base>>,
int> = 0>
90 constexpr iterator(
iterator<not Const> i) : current_ {std::move(i.current_)}, parent_ {std::move(i.parent_)} {}
92 constexpr
const stdex::ranges::iterator_t<Base>& base()
const & noexcept {
return current_; }
94 constexpr stdex::ranges::iterator_t<Base> base() && {
return std::move(current_); }
96 constexpr decltype(
auto) operator*()
const 98 return stdex::invoke(*parent_->fun_, *current_);
101 template<
bool Enable = true, std::enable_if_t<Enable and stdex::ranges::random_access_range<Base>,
int> = 0>
102 constexpr decltype(
auto) operator[](difference_type n)
const 104 return stdex::invoke(*parent_->fun_, current_[n]);
107 constexpr iterator& operator++() { ++current_;
return *
this; }
109 template<
bool Enable = true, std::enable_if_t<Enable and not stdex::ranges::forward_range<Base>,
int> = 0>
110 constexpr
void operator++(
int) { ++current_; }
112 template<
bool Enable = true, std::enable_if_t<Enable and stdex::ranges::forward_range<Base>,
int> = 0>
113 constexpr iterator operator++(
int) {
auto tmp = *
this; ++*
this;
return tmp; }
115 template<
bool Enable = true, std::enable_if_t<Enable and stdex::ranges::b
idirectional_range<Base>,
int> = 0>
116 constexpr iterator& operator--() { --current_;
return *
this; }
118 template<
bool Enable = true, std::enable_if_t<Enable and stdex::ranges::b
idirectional_range<Base>,
int> = 0>
119 constexpr iterator operator--(
int) {
auto tmp = *
this; --*
this;
return tmp; }
121 template<
bool Enable = true, std::enable_if_t<Enable and stdex::ranges::random_access_range<Base>,
int> = 0>
122 constexpr iterator& operator+=(
const difference_type& n) { current_ += n;
return *
this; }
124 template<
bool Enable = true, std::enable_if_t<Enable and stdex::ranges::random_access_range<Base>,
int> = 0>
125 constexpr iterator& operator-=(
const difference_type& n) { current_ -= n;
return *
this; }
127 friend constexpr
bool operator==(
const iterator& x,
const iterator& y) {
return x.current_ == y.current_; }
129 friend constexpr
bool operator!=(
const iterator& x,
const iterator& y) {
return not (x.current_ == y.current_); }
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 y < x; }
135 friend constexpr
bool operator<=(
const iterator& x,
const iterator& y) {
return not (y < x); }
137 friend constexpr
bool operator>=(
const iterator& x,
const iterator& y) {
return not (x < y); }
139 template<
bool Enable = true, std::enable_if_t<Enable and stdex::ranges::random_access_range<Base>,
int> = 0>
140 friend constexpr iterator operator+(
const iterator& i,
const difference_type& n) {
return iterator {*i.parent_, i.current_ + n}; }
142 template<
bool Enable = true, std::enable_if_t<Enable and stdex::ranges::random_access_range<Base>,
int> = 0>
143 friend constexpr iterator operator+(
const difference_type& n,
const iterator& i) {
return iterator {*i.parent_, i.current_ + n}; }
145 template<
bool Enable = true, std::enable_if_t<Enable and stdex::ranges::random_access_range<Base>,
int> = 0>
146 friend constexpr iterator operator-(
const iterator& i,
const difference_type& n) {
return iterator {*i.parent_, i.current_ - n}; }
148 template<
bool Enable = true, std::enable_if_t<Enable and stdex::ranges::random_access_range<Base>,
int> = 0>
149 friend constexpr difference_type operator-(
const iterator& x,
const iterator& y) {
return x.current_ - y.current_; }
151 template<
bool Enable = true, std::enable_if_t<Enable and stdex::ranges::random_access_range<Base>,
int> = 0>
152 friend constexpr decltype(
auto) iter_move(
const iterator& i) noexcept(noexcept(stdex::invoke(*i.parent_->fun_, *i.current_)))
154 if constexpr (std::is_lvalue_reference_v<decltype(*i)>)
return std::move(*i);
161 stdex::ranges::iterator_t<Base> current_;
171 using Parent = maybe_const<Const, transform_view>;
172 using Base = maybe_const<Const, V>;
173 using difference_type = stdex::ranges::range_difference_t<Base>;
179 constexpr
explicit sentinel(stdex::ranges::sentinel_t<Base> end) : end_ {end} {};
181 constexpr
const stdex::ranges::sentinel_t<Base>& base()
const {
return end_; }
191 template<
bool Enable =
true, std::enable_if_t<Enable and
192 stdex::convertible_to<decltype(std::declval<stdex::ranges::iterator_t<Base>>() - std::declval<stdex::ranges::sentinel_t<Base>>()), difference_type>,
int> = 0>
193 friend constexpr difference_type
operator-(
const iterator<Const>& x,
const sentinel& y)
194 {
return x.current_ - y.end_; }
196 template<
bool Enable =
true, std::enable_if_t<Enable and
197 stdex::convertible_to<decltype(-(std::declval<stdex::ranges::sentinel_t<Base>>() - std::declval<stdex::ranges::iterator_t<Base>>())), difference_type>,
int> = 0>
198 friend constexpr difference_type operator-(
const sentinel& y,
const iterator<Const>& x)
199 {
return y.end_ - x.current_; }
203 stdex::ranges::sentinel_t<Base> end_;
207 template<
bool Enable = true, std::enable_if_t<Enable and stdex::default_initializable<V> and stdex::default_initializable<F>,
int> = 0>
213 transform_view(V base, F fun) : base_ {std::move(base)}, fun_ {std::move(fun)} {}
216 template<
bool Enable = true, std::enable_if_t<Enable and stdex::copy_constructible<V>,
int> = 0>
218 base()
const& {
return base_; }
221 base() && {
return std::move(base_); }
225 begin() {
return iterator<false> {*
this, stdex::ranges::begin(base_)}; }
227 template<
bool Enable =
true, std::enable_if_t<Enable and
228 stdex::ranges::range<const V> and std::is_invocable_v<const F&, stdex::ranges::range_reference_t<const V>>,
int> = 0>
230 begin()
const {
return iterator<true> {*
this, stdex::ranges::begin(base_)}; }
233 template<
bool Enable = true, std::enable_if_t<Enable and not stdex::ranges::common_range<V>,
int> = 0>
237 template<
bool Enable = true, std::enable_if_t<Enable and stdex::ranges::common_range<V>,
int> = 0>
241 template<
bool Enable = true, std::enable_if_t<Enable and stdex::ranges::range<const V> and not stdex::ranges::common_range<const V> and
242 std::is_invocable_v<const F&, stdex::ranges::range_reference_t<const V>>,
int> = 0>
244 end()
const {
return sentinel<true> {stdex::ranges::end(base_)}; }
246 template<
bool Enable = true, std::enable_if_t<Enable and stdex::ranges::common_range<const V> and
247 std::is_invocable_v<const F&, stdex::ranges::range_reference_t<const V>>,
int> = 0>
249 end()
const {
return iterator<true> {*
this, stdex::ranges::end(base_)}; }
252 template<
bool Enable = true, std::enable_if_t<Enable and stdex::ranges::sized_range<V>,
int> = 0>
256 template<
bool Enable = true, std::enable_if_t<Enable and stdex::ranges::sized_range<const V>,
int> = 0>
268 template<
typename R,
typename F>
282 template<
typename R, std::enable_if_t<stdex::ranges::viewable_range<R>,
int> = 0>
284 operator() (R&& r)
const {
return transform_view {std::forward<R>(r), my_f}; }
295 operator() (F&& f)
const 301 template<
typename R,
typename F, std::enable_if_t<stdex::ranges::viewable_range<R>,
int> = 0>
303 operator() (R&& r, F&& f)
const
Definition: iterator.hpp:255
Definition: view_interface.hpp:32
Definitions relating to the availability of c++ language features.
Definition: common.hpp:200
constexpr bool size
T is either an index representing a size, or unbounded_size_t, which indicates that the size is unbou...
Definition: size.hpp:65
Definition: range_adaptor_closure.hpp:34
Definitions relating to a compatible replacement for std::invoke.