OpenKalman
range_adaptor_closure.hpp
Go to the documentation of this file.
1 /* This file is part of OpenKalman, a header-only C++ library for
2  * Kalman filters and other recursive filters.
3  *
4  * Copyright (c) 2025 Christopher Lee Ogden <ogden@gatech.edu>
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
9  */
10 
17 #ifndef OPENKALMAN_COMPATIBILITY_VIEWS_RANGE_ADAPTOR_CLOSURE_HPP
18 #define OPENKALMAN_COMPATIBILITY_VIEWS_RANGE_ADAPTOR_CLOSURE_HPP
19 
20 #if __cpp_lib_ranges < 202202L
21 
22 #include <type_traits>
24 #include "view-concepts.hpp"
25 #include "ref_view.hpp"
26 #include "owning_view.hpp"
27 
28 namespace OpenKalman::ranges
29 {
30 #ifdef __cpp_concepts
31  template<typename D> requires std::is_object_v<D> && std::same_as<D, std::remove_cv_t<D>>
32 #else
33  template<typename D>
34 #endif
36 
37 
38  namespace detail
39  {
40 #ifdef __cpp_concepts
41  template<typename T, typename U> requires (not std::same_as<T, range_adaptor_closure<U>>)
42 #else
43  template<typename T, typename U, std::enable_if_t<not std::is_same_v<T, range_adaptor_closure<U>>, int> = 0>
44 #endif
45  void range_adaptor_closure_fn (const T&, const range_adaptor_closure<U>&);
46 
47 
48 #ifndef __cpp_concepts
49  template<typename T, typename = void>
50  struct is_range_adaptor_closure_impl : std::false_type {};
51 
52  template<typename T>
54  std::void_t<decltype(detail::range_adaptor_closure_fn(std::declval<T>(), std::declval<T>()))>> : std::true_type {};
55 #endif
56 
57 
58  template<typename T>
59 #ifdef __cpp_concepts
60  concept is_range_adaptor_closure = requires (T t) { detail::range_adaptor_closure_fn(t, t); };
61 #else
62  inline constexpr bool is_range_adaptor_closure = detail::is_range_adaptor_closure_impl<T>::value;
63 #endif
64 
65 
66 #ifndef __cpp_concepts
67  template<typename Lhs, typename Rhs, typename R, typename = void>
68  struct is_pipe_invocable : std::false_type {};
69 
70  template<typename Lhs, typename Rhs, typename R>
71  struct is_pipe_invocable<Lhs, Rhs, R, std::void_t<decltype(std::declval<Rhs>()(std::declval<Lhs>()(std::declval<R>())))>> : std::true_type {};
72 #endif
73 
74 
75  template<typename Lhs, typename Rhs, typename R>
76 #ifdef __cpp_concepts
77  concept __pipe_invocable = requires { std::declval<Rhs>()(std::declval<Lhs>()(std::declval<R>())); };
78 #else
79  inline constexpr bool pipe_invocable = is_pipe_invocable<Lhs, Rhs, R>::value;
80 #endif
81 
82  }
83 
84 
85  namespace internal
86  {
87  template<typename Lhs, typename Rhs>
88  struct Pipe : range_adaptor_closure<Pipe<Lhs, Rhs>>
89  {
90  template<typename T, typename U>
91  constexpr
92  Pipe(T&& lhs, U&& rhs) : my_lhs(std::forward<T>(lhs)), my_rhs(std::forward<U>(rhs)) {}
93 
94 
95 #if __cpp_explicit_this_parameter
96  template<typename Self, typename R>
97  requires pipe_invocable<decltype(std::forward_like<Self>(std::declval<Lhs>())), decltype(std::forward_like<Self>(std::declval<Rhs>())), R>
98  constexpr auto
99  operator()(this Self&& self, R&& r)
100  {
101  return (std::forward<Self>(self).my_rhs(std::forward<Self>(self).my_lhs(std::forward<R>(r))));
102  }
103 #else
104  template<typename R, std::enable_if_t<detail::pipe_invocable<const Lhs&, const Rhs&, R>, int> = 0>
105  constexpr auto
106  operator()(R&& r) const & { return my_rhs(my_lhs(std::forward<R>(r))); }
107 
108 
109  template<typename R, std::enable_if_t<detail::pipe_invocable<Lhs, Rhs, R>, int> = 0>
110  constexpr auto
111  operator()(R&& r) && { return std::move(my_rhs)(std::move(my_lhs)(std::forward<R>(r))); }
112 
113 
114  template<typename R>
115  constexpr auto
116  operator()(R&& r) const && = delete;
117 
118  private:
119 
120  [[no_unique_address]] Lhs my_lhs;
121  [[no_unique_address]] Rhs my_rhs;
122 #endif
123  };
124 
125  }
126 
127 
128 #ifdef __cpp_concepts
129  template<detail::is_range_adaptor_closure S, typename R> requires requires { std::declval<S>()(declval<R>()); }
130 #else
131  template<typename S, typename R, std::enable_if_t<detail::is_range_adaptor_closure<S> and not detail::is_range_adaptor_closure<R>, int> = 0>
132 #endif
133  constexpr auto
134  operator | (R&& r, S&& s)
135  {
136  return std::forward<S>(s)(std::forward<R>(r));
137  }
138 
139 
140 #ifdef __cpp_concepts
141  template<detail::is_range_adaptor_closure Lhs, detail::is_range_adaptor_closure Rhs>
142 #else
143  template<typename Lhs, typename Rhs, std::enable_if_t<detail::is_range_adaptor_closure<Lhs> and detail::is_range_adaptor_closure<Rhs>, int> = 0>
144 #endif
145  constexpr auto
146  operator | (Lhs&& lhs, Rhs&& rhs)
147  {
148  return internal::Pipe<std::decay_t<Lhs>, std::decay_t<Rhs>>{std::forward<Lhs>(lhs), std::forward<Rhs>(rhs)};
149  }
150 
151 }
152 
153 
154 #endif
155 
156 #endif //OPENKALMAN_COMPATIBILITY_VIEWS_RANGE_ADAPTOR_CLOSURE_HPP
Definition: tuple_reverse.hpp:103
Definition: range-access.hpp:25
Definitions relating to the availability of c++ language features.
Definition: range_adaptor_closure.hpp:88
Definition: range_adaptor_closure.hpp:35
Definition: range_adaptor_closure.hpp:68
Definition: range_adaptor_closure.hpp:50