| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172 |
- //
- // projection_tuple.h
- // iterator
- //
- // Created by Sam Jaffe on 9/23/25.
- // Copyright © 2025 Sam Jaffe. All rights reserved.
- //
- #pragma once
- #include <functional>
- #include <tuple>
- #include <type_traits>
- #include <iterator/concepts.h>
- #include <iterator/detail/capture_fn.h>
- namespace iterator::detail {
- template <typename... Projs> class Projections {
- private:
- std::tuple<Projs...> fns_;
- public:
- Projections() = default;
- Projections(Projs... fns)
- requires(sizeof...(Projs) > 0)
- : fns_(fns...) {}
- Projections(std::tuple<Projs...> const & fns) : fns_(fns) {}
- template <size_t I, typename T>
- decltype(auto) operator()(T && arg,
- std::integral_constant<size_t, I> = {}) const {
- if constexpr (I >= sizeof...(Projs)) {
- return std::forward<T>(arg);
- } else if constexpr (Assoc<std::decay_t<T>>) {
- return std::tie(arg.first, std::invoke(std::get<I>(fns_),
- std::forward<T>(arg).second));
- } else {
- return std::invoke(std::get<I>(fns_), std::forward<T>(arg));
- }
- }
- };
- template <typename It, typename Projs, size_t I = 0> struct ProjectionExpander {
- using type = std::tuple<>;
- };
- template <typename It, typename... Projs, size_t I>
- requires(I < sizeof...(Projs))
- struct ProjectionExpander<It, Projections<Projs...>, I> {
- using Fn = std::tuple_element_t<I, std::tuple<Projs...>>;
- template <typename T> static decltype(auto) get(T && ref) {
- if constexpr (Assoc<std::decay_t<T>>) {
- return std::forward<T>(ref).second;
- } else {
- return std::forward<T>(ref);
- }
- }
- static std::iter_reference_t<It> _ref;
- using value_type = decltype(get(_ref));
- using result_type = std::invoke_result_t<Fn, value_type>;
- using type = tuple_cat_t<
- std::tuple<std::conditional_t<std::is_reference_v<result_type>, Fn,
- CaptureFn<Fn, value_type>>>,
- typename ProjectionExpander<iterator_t<result_type>,
- Projections<Projs...>, I + 1>::type>;
- };
- }
|