16 #ifndef OPENKALMAN_COLLECTIONS_VIEWS_GENERATE_HPP 17 #define OPENKALMAN_COLLECTIONS_VIEWS_GENERATE_HPP 19 #include <type_traits> 21 #ifdef __cpp_lib_ranges 39 template<
typename F, values::size Size = std::unreachable_sentinel_t> requires std::same_as<Size, std::remove_reference_t<Size>> and
40 std::invocable<F, std::size_t> and std::invocable<F, std::integral_constant<std::size_t, 0>>
41 struct generate_view : std::ranges::view_interface<generate_view<F, Size>>
43 template<typename F, typename Size = unreachable_sentinel_t>
49 using Size_ = std::conditional_t<values::index<Size>, Size, std::monostate>;
53 #if __cplusplus >= 202002L 54 static constexpr
bool static_F = std::semiregular<F_box>;
56 static constexpr
bool static_F = semiregular<F_box>;
60 template<
bool Const,
typename T>
61 using maybe_const = std::conditional_t<Const, const T, T>;
73 using F_box_c = maybe_const<Const, F_box>;
75 using F_ref = std::conditional_t<static_F, F_box, F_box_c *>;
78 get_f()
const noexcept
80 if constexpr (static_F)
return const_cast<F_box&
>(f_ref);
81 else return const_cast<F_box&
>(*f_ref);
84 static constexpr F_ref
85 init_f_ref(F_box_c& f) noexcept
87 if constexpr (static_F)
return const_cast<F_ref&&
>(f);
88 else return std::addressof(f);
93 using iterator_concept = std::random_access_iterator_tag;
94 using iterator_category = std::random_access_iterator_tag;
95 using value_type = std::invoke_result_t<F_box&, std::size_t>;
96 using difference_type = std::ptrdiff_t;
97 using reference = value_type;
102 constexpr
iterator(F_box_c& f, std::size_t pos)
103 : f_ref {init_f_ref(f)}, current_ {
static_cast<difference_type
>(pos)} {};
105 constexpr iterator(
iterator<not Const> i) : f_ref {std::move(i.f_ref)}, current_ {std::move(i.current_)} {}
107 constexpr value_type operator*()
const 109 return get_f()(
static_cast<std::size_t
>(current_));
112 constexpr value_type operator[](difference_type offset)
const 114 return get_f()(
static_cast<std::size_t
>(current_ + offset));
117 constexpr
auto& operator++() noexcept { ++current_;
return *
this; }
118 constexpr
auto operator++(
int) noexcept {
auto temp = *
this; ++*
this;
return temp; }
119 constexpr
auto& operator--() noexcept { --current_;
return *
this; }
120 constexpr
auto operator--(
int) noexcept {
auto temp = *
this; --*
this;
return temp; }
121 constexpr
auto& operator+=(
const difference_type diff) noexcept { current_ += diff;
return *
this; }
122 constexpr
auto& operator-=(
const difference_type diff) noexcept { current_ -= diff;
return *
this; }
124 friend constexpr
auto operator+(
const iterator& it,
const difference_type diff)
125 {
return iterator {it.get_f(),
static_cast<std::size_t
>(it.current_ + diff)}; }
126 friend constexpr
auto operator+(
const difference_type diff,
const iterator& it)
127 {
return iterator {it.get_f(),
static_cast<std::size_t
>(diff + it.current_)}; }
128 friend constexpr
auto operator-(
const iterator& it,
const difference_type diff)
129 {
if (it.current_ < diff)
throw std::out_of_range{
"Iterator out of range"};
return iterator {it.get_f(),
static_cast<std::size_t
>(it.current_ - diff)}; }
130 friend constexpr difference_type operator-(
const iterator& it,
const iterator& other)
131 {
return it.current_ - other.current_; }
132 friend constexpr
bool operator==(
const iterator& it,
const iterator& other)
133 {
return it.current_ == other.current_; }
134 #ifdef __cpp_impl_three_way_comparison 135 constexpr
auto operator<=>(
const iterator& other)
const noexcept {
return current_ <=> other.current_; }
137 constexpr
bool operator!=(
const iterator& other)
const noexcept {
return current_ != other.current_; }
138 constexpr
bool operator<(
const iterator& other)
const noexcept {
return current_ < other.current_; }
139 constexpr
bool operator>(
const iterator& other)
const noexcept {
return current_ > other.current_; }
140 constexpr
bool operator<=(
const iterator& other)
const noexcept {
return current_ <= other.current_; }
141 constexpr
bool operator>=(
const iterator& other)
const noexcept {
return current_ >= other.current_; }
147 difference_type current_;
155 #ifdef __cpp_concepts 156 template<
typename Arg> requires std::constructible_from<const F, Arg&&> and values::index<Size>
160 template<
typename Arg, std::enable_if_t<std::is_constructible_v<const F, Arg&&> and values::index<Size>,
int> = 0>
164 : f_box {
const_cast<F&&
>(std::forward<Arg>(arg))}, size_ {std::move(size)} {}
170 #ifdef __cpp_concepts 172 generate_view(
const F&) noexcept requires static_F and (not values::index<Size>)
174 template<
bool Enable = true, std::enable_if_t<Enable and static_F and (not values::index<Size>),
int> = 0>
178 : f_box {F{}}, size_ {} {}
184 #ifdef __cpp_concepts 185 template<
typename Arg> requires std::constructible_from<const F, Arg&&> and (not static_F) and (not values::index<Size>)
189 template<
bool Enable =
true,
typename Arg, std::enable_if_t<Enable and
190 std::is_constructible_v<const F, Arg&&> and not static_F and (not values::index<Size>),
int> = 0>
194 : f_box {
const_cast<F&&
>(std::forward<Arg>(arg))}, size_ {} {}
200 #ifdef __cpp_concepts 202 generate_view(Size_ size) noexcept requires static_F and values::index<Size>
204 template<
bool Enable = true, std::enable_if_t<Enable and static_F and values::index<Size>,
int> = 0>
208 : f_box {F{}}, size_ {std::move(size)} {}
221 constexpr
auto begin() {
return iterator<false> {f_box, 0}; }
224 constexpr
auto begin()
const {
return iterator<true> {f_box, 0}; }
233 if constexpr (values::index<Size>)
234 return iterator<false> {f_box,
static_cast<std::size_t
>(size_)};
236 return unreachable_sentinel;
240 constexpr
auto end()
const 243 if constexpr (values::index<Size>)
244 return iterator<true> {f_box,
static_cast<std::size_t
>(size_)};
246 return unreachable_sentinel;
253 #ifdef __cpp_concepts 255 size()
const noexcept requires values::index<Size>
257 template<
bool Enable = true, std::enable_if_t<Enable and (values::index<Size>),
int> = 0>
258 constexpr
auto size() const noexcept
268 #ifdef __cpp_explicit_this_parameter 269 template<std::
size_t i>
270 constexpr decltype(
auto)
271 get(
this auto&&
self) noexcept
273 if constexpr (values::fixed<Size>) static_assert(i < values::fixed_number_of_v<Size>,
"Index out of range");
274 return std::forward<decltype(self)>(
self).f_box(std::integral_constant<std::size_t, i>{});
277 template<std::
size_t i>
278 constexpr decltype(
auto)
282 if constexpr (values::fixed<Size>) static_assert(i < values::fixed_number_of_v<Size>,
"Index out of range");
283 return f_box(std::integral_constant<std::size_t, i>{});
286 template<std::
size_t i>
287 constexpr decltype(
auto)
291 if constexpr (values::fixed<Size>) static_assert(i < values::fixed_number_of_v<Size>,
"Index out of range");
292 return f_box(std::integral_constant<std::size_t, i>{});
295 template<std::
size_t i>
296 constexpr decltype(
auto)
300 if constexpr (values::fixed<Size>) static_assert(i < values::fixed_number_of_v<Size>,
"Index out of range");
301 return std::move(*this).f_box(std::integral_constant<std::size_t, i>{});
304 template<std::
size_t i>
305 constexpr decltype(
auto)
306 get()
const && noexcept
309 if constexpr (values::fixed<Size>) static_assert(i < values::fixed_number_of_v<Size>,
"Index out of range");
310 return std::move(*this).f_box(std::integral_constant<std::size_t, i>{});
325 template<
typename F,
typename S>
336 #ifdef __cpp_lib_ranges 337 namespace std::ranges
342 template<
typename F,
typename S>
343 constexpr
bool enable_borrowed_range<OpenKalman::collections::generate_view<F, S>> = std::is_lvalue_reference_v<F> or
344 #if __cplusplus >= 202002L 345 std::semiregular<OpenKalman::collections::internal::movable_wrapper<F>>;
347 semiregular<OpenKalman::collections::internal::movable_wrapper<F>>;
354 template<
typename F,
typename S>
358 template<std::
size_t i,
typename F,
typename S>
361 using type = std::invoke_result_t<F, std::integral_constant<std::size_t, i>>;
376 #ifdef __cpp_concepts 377 template<
typename F, values::index Size> requires
378 std::invocable<F, std::size_t> and std::invocable<F, std::integral_constant<std::size_t, 0>>
380 template<
typename F,
typename Size, std::enable_if_t<values::index<Size> and
381 std::is_invocable_v<F, std::
size_t> and std::is_invocable_v<F, std::
integral_constant<std::
size_t, 0>>,
int> = 0>
384 operator() (F&& f, Size s)
const 393 #ifdef __cpp_concepts 394 template<
typename F> requires
395 std::invocable<F, std::size_t> and std::invocable<F, std::integral_constant<std::size_t, 0>>
397 template<
typename F, std::enable_if_t<std::is_invocable_v<F, std::
size_t> and
398 std::is_invocable_v<F, std::
integral_constant<std::
size_t, 0>>,
int> = 0>
401 operator() (F&& f)
const 420 #endif //OPENKALMAN_COLLECTIONS_VIEWS_GENERATE_HPP Namespace for collections.
Definition: collections.hpp:27
generate_view(F &&, const S &) -> generate_view< F, S >
Deduction guide.
constexpr auto size() const noexcept
The size of the resulting object.
Definition: generate.hpp:258
Definition for values::size.
Iterator for generate_view.
Definition: generate.hpp:69
Definition: view_interface.hpp:32
Definition: generate.hpp:371
constexpr generate_view(const F &) noexcept
Construct from a statically constructable callable object, if the view is unsized.
Definition: generate.hpp:176
constexpr generate_view(Arg &&arg) noexcept
Construct from a callable object, if the view is unsized.
Definition: generate.hpp:192
Definition: tuple_reverse.hpp:103
constexpr auto begin() const
Definition: generate.hpp:224
constexpr auto begin()
Definition: generate.hpp:221
constexpr generate_view(Size_ size) noexcept
Construct from a size if the function can be defined statically.
Definition: generate.hpp:206
A collection_view created by lazily generating elements based on an index.
Definition: generate.hpp:44
The root namespace for OpenKalman.
Definition: basics.hpp:34
Definitions relating to the availability of c++ language features.
The fixed number associated with a values::fixed.
Definition: fixed_number_of.hpp:45
decltype(auto) constexpr get() &
Get element i.
Definition: generate.hpp:279
Namespace for generalized views.
Definition: collections.hpp:33
constexpr detail::generate_adaptor generate
a collection_view generator associated with generate_view.
Definition: generate.hpp:416
Definitions implementing features of the c++ ranges library for compatibility.
constexpr generate_view()=default
Default constructor.
constexpr generate_view(Arg &&arg, Size_ size) noexcept
Construct from a callable object and a size.
Definition: generate.hpp:162
constexpr auto end()
Definition: generate.hpp:230
constexpr auto end() const
Definition: generate.hpp:240