halcheck 1.0
Loading...
Searching...
No Matches
transform.hpp
1#ifndef HALCHECK_LIB_ITERATOR_TRANSFORM_HPP
2#define HALCHECK_LIB_ITERATOR_TRANSFORM_HPP
3
4// IWYU pragma: private, include <halcheck/lib/iterator.hpp>
5
6#include <halcheck/lib/functional.hpp>
7#include <halcheck/lib/iterator/base.hpp>
8#include <halcheck/lib/iterator/interface.hpp>
9#include <halcheck/lib/iterator/range.hpp>
10#include <halcheck/lib/iterator/type_traits.hpp>
11#include <halcheck/lib/optional.hpp>
12#include <halcheck/lib/pp.hpp>
13#include <halcheck/lib/type_traits.hpp>
14
15#include <iterator>
16#include <memory>
17#include <type_traits>
18
19namespace halcheck { namespace lib {
20
27template<typename I, typename F>
28class transform_iterator : public lib::iterator_interface<transform_iterator<I, F>> {
29private:
30 static_assert(lib::is_input_iterator<I>(), "I must be an input iterator");
31 static_assert(std::is_copy_constructible<F>(), "F must be copy constructible");
32 static_assert(std::is_object<F>(), "F must an object type");
33 static_assert(lib::is_invocable<const F &, lib::iter_reference_t<I>>(), "F must be invocable");
34
35 template<typename, typename>
36 friend class transform_iterator;
37
38public:
43
48
54
59
64
68 using pointer = void;
69
73 constexpr transform_iterator() = default;
74
80 constexpr transform_iterator(I current, F fun) : _base(std::move(current)), _func(std::move(fun)) {}
81
90 template<
91 typename J,
92 typename G,
96 : _base(std::move(other._base)), _func(std::move(*other._func)) {}
97
107 template<
108 typename J,
109 typename G,
113 explicit constexpr transform_iterator(transform_iterator<J, G> other) // NOLINT
114 : _base(std::move(other._base)), _func(*std::move(other._func)) {}
115
120 constexpr const I &base() const & noexcept { return _base; }
121
126 I base() && { return std::move(_base); }
127
133 noexcept(lib::is_nothrow_invocable<const F &, lib::iter_reference_t<I>>()) {
134 return lib::invoke(*_func, *_base);
135 }
136
142 ++_base;
143 return *this;
144 }
145
150 template<bool _ = true, HALCHECK_REQUIRE(lib::is_bidirectional_iterator<I>() && _)>
151 transform_iterator &operator--() {
152 --_base;
153 return *this;
154 }
155
161 template<bool _ = true, HALCHECK_REQUIRE(lib::is_random_access_iterator<I>() && _)>
163 _base += n;
164 return *this;
165 }
166
167private:
173 friend constexpr bool operator==(const transform_iterator &lhs, const transform_iterator &rhs) {
174 return lhs._base == rhs._base;
175 }
176
182 template<bool _ = true, HALCHECK_REQUIRE(lib::is_random_access_iterator<I>() && _)>
183 friend difference_type operator-(const transform_iterator &lhs, const transform_iterator &rhs) {
184 return lhs._base - rhs._base;
185 }
186
187 I _base;
188 lib::optional<F> _func;
189};
190
206 template<
207 typename I,
208 typename F,
213 lib::transform_iterator<I, F> operator()(I base, F func) const {
214 return lib::transform_iterator<I, F>(std::move(base), std::move(func));
215 }
217
224template<typename V, typename F>
225class transform_view : public lib::view_interface<transform_view<V, F>> {
226private:
227 static_assert(lib::is_input_range<V>(), "V must be an input range");
228 static_assert(std::is_move_constructible<F>(), "F must be move constructible");
229 static_assert(std::is_object<F>(), "F must be an object");
230 static_assert(lib::is_invocable<const F &, lib::range_reference_t<V>>(), "F must be invocable");
231
232 template<typename, typename>
233 friend class transform_view;
234
235 struct ref {
236 explicit ref(const F *base = nullptr) : base(base) {}
237 template<typename... Args>
238 lib::invoke_result_t<const F &, Args...> operator()(Args &&...args) const {
239 return lib::invoke(*base, std::forward<Args>(args)...);
240 }
241 const F *base;
242 };
243
244public:
248 constexpr transform_view() = default;
249
255 constexpr transform_view(V base, F func) : _base(std::move(base)), _func(std::move(func)) {}
256
265 template<
266 typename V2,
267 typename G,
270 constexpr transform_view(transform_view<V2, G> other) // NOLINT
271 : _base(std::move(other._base)), _func(std::move(*other._func)) {}
272
282 template<
283 typename V2,
284 typename G,
288 explicit constexpr transform_view(transform_view<V2, G> other) // NOLINT
289 : _base(std::move(other._base)), _func(*std::move(other._func)) {}
290
296 template<bool _ = true, HALCHECK_REQUIRE(std::is_copy_constructible<V>() && _)>
297 constexpr V base() const & {
298 return _base;
299 }
300
305 V base() && { return std::move(_base); }
306
312 return lib::make_transform_iterator(lib::begin(_base), ref{std::addressof(*_func)});
313 }
314
319 template<
320 typename U = V,
324 return lib::make_transform_iterator(lib::begin(_base), ref{std::addressof(*_func)});
325 }
326
332 return lib::make_transform_iterator(lib::end(_base), ref{std::addressof(*_func)});
333 }
334
339 template<
340 typename U = V,
344 return lib::make_transform_iterator(lib::end(_base), ref{std::addressof(*_func)});
345 }
346
351 template<typename U = V, HALCHECK_REQUIRE(lib::is_sized_range<U>())>
353 return lib::size(_base);
354 }
355
360 template<typename U = V, HALCHECK_REQUIRE(lib::is_sized_range<const U>())>
362 return lib::size(_base);
363 }
364
365private:
366 V _base;
367 lib::optional<F> _func;
368};
369
385 template<
386 typename V,
387 typename F,
392 lib::transform_view<V, F> operator()(V base, F func) const {
393 return lib::transform_view<V, F>(std::move(base), std::move(func));
394 }
396
397}} // namespace halcheck::lib
398
399#endif
T addressof(T... args)
A utility class for easily defining new iterators.
Definition interface.hpp:40
An implementation of std::optional.
Definition optional.hpp:338
constexpr lib::invoke_result_t< const F &, lib::iter_reference_t< I > > operator*() const noexcept(lib::is_nothrow_invocable< const F &, lib::iter_reference_t< I > >())
Dereferences the base iterator an applies the function.
Definition transform.hpp:132
friend constexpr bool operator==(const transform_iterator &lhs, const transform_iterator &rhs)
Compares two transform_iterators for equality.
Definition transform.hpp:173
transform_iterator & operator++()
Advances the base iterator.
Definition transform.hpp:141
lib::conditional_t<!std::is_reference< reference >(), std::input_iterator_tag, lib::iter_category_t< I > > iterator_category
Indicates the level of supported iterator operations this type provides.
Definition transform.hpp:52
constexpr transform_iterator(I current, F fun)
Constructs a transform_iterator with the given base iterator and function.
Definition transform.hpp:80
constexpr const I & base() const &noexcept
Get a reference to the base iterator of this transform_iterator.
Definition transform.hpp:120
constexpr transform_iterator(transform_iterator< J, G > other)
Performs a conversion on a transform_iterator with compatible type parameters.
Definition transform.hpp:95
I base() &&
Get the base iterator of this transform_iterator.
Definition transform.hpp:126
A transforming iterator adaptor.
Definition transform.hpp:28
void pointer
This type does not support operator->.
Definition transform.hpp:68
constexpr transform_iterator()=default
Constructs a default transform_iterator.
lib::iter_difference_t< I > difference_type
The type returned by operator- when given two transform_iterators.
Definition transform.hpp:63
lib::remove_cvref_t< lib::invoke_result_t< const F &, lib::iter_reference_t< I > > > value_type
The type of value pointed to by this iterator.
Definition transform.hpp:58
lib::invoke_result_t< const F &, lib::iter_reference_t< I > > reference
The type returned by operator*.
Definition transform.hpp:47
constexpr transform_view(transform_view< V2, G > other)
Performs a conversion on a transform_view with compatible type parameters.
Definition transform.hpp:270
lib::range_difference_t< const U > size() const
Computes the number of elements in this view.
Definition transform.hpp:361
lib::transform_iterator< lib::iterator_t< V >, ref > begin()
Gets an iterator pointing to the beginning of this view.
Definition transform.hpp:311
lib::transform_iterator< lib::iterator_t< const U >, ref > begin() const
Gets an iterator pointing to the beginning of this view.
Definition transform.hpp:323
constexpr V base() const &
Gets copy of the base range of this view.
Definition transform.hpp:297
constexpr transform_view(V base, F func)
Constructs a transform_view from the given base range and function.
Definition transform.hpp:255
V base() &&
Gets the base range of this view.
Definition transform.hpp:305
lib::range_difference_t< U > size()
Computes the number of elements in this view.
Definition transform.hpp:352
lib::transform_iterator< lib::iterator_t< V >, ref > end()
Gets an iterator pointing past the end of this view.
Definition transform.hpp:331
lib::transform_iterator< lib::iterator_t< const U >, ref > end() const
Gets an iterator pointing past the end of this view.
Definition transform.hpp:343
A transforming iterator adaptor.
Definition transform.hpp:225
constexpr transform_view()=default
Constructs a default transform_view.
An implementation of std::ranges::view_interface.
Definition interface.hpp:238
T forward(T... args)
HALCHECK_INLINE_CONSTEXPR struct halcheck::lib::@20 invoke
An implementation of std::invoke.
decltype(lib::invoke(std::declval< F >(), std::declval< Args >()...)) invoke_result_t
An implementation of std::invoke_result_t.
Definition invoke.hpp:42
HALCHECK_INLINE_CONSTEXPR struct halcheck::lib::@30 make_transform_iterator
Constructs a transform_iterator.
typename std::iterator_traits< I >::difference_type iter_difference_t
The return type of operator- for an iterator.
Definition base.hpp:32
typename std::iterator_traits< I >::reference iter_reference_t
The return type of operator* for an iterator.
Definition base.hpp:24
HALCHECK_INLINE_CONSTEXPR struct halcheck::lib::@25 size
Obtains the size of a range.
HALCHECK_INLINE_CONSTEXPR struct halcheck::lib::@31 transform
Constructs a transform_view.
typename std::iterator_traits< I >::iterator_category iter_category_t
A tag type indicating the level of supported iterator options a type provides.
Definition base.hpp:40
lib::iter_reference_t< lib::iterator_t< R > > range_reference_t
The type returned by operator* for a range type's iterators.
Definition range.hpp:340
lib::iter_difference_t< lib::iterator_t< R > > range_difference_t
The type of value returned by operator- for a range type's iterators.
Definition range.hpp:324
#define HALCHECK_INLINE_CONSTEXPR
A backwards-compatible substitute for inline constexpr.
Definition pp.hpp:70
typename std::remove_cv< typename std::remove_reference< T >::type >::type remove_cvref_t
An implementation of std::remove_cvref_t.
Definition type_traits.hpp:141
typename std::conditional< Cond, T, F >::type conditional_t
An implementation of std::conditional_t.
Definition type_traits.hpp:51
#define HALCHECK_REQUIRE(...)
Expands to a template argument that is only valid if the given argument evaluates to true.
Definition type_traits.hpp:24
STL namespace.
Determines whether a type satisfies the LegacyInputIterator concept.
Definition type_traits.hpp:54
Determines whether a type is a range whose iterators satisfy lib::is_input_iterator.
Definition range.hpp:183
An implementation of std::is_invocable.
Definition invoke.hpp:66
An implementation of std::is_nothrow_invocable.
Definition invoke.hpp:78
Determines whether the given type is a range.
Definition range.hpp:158