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 #include <type_traits>
22 #include "view-concepts.hpp"
23 
25 {
26 #if __cpp_lib_ranges >= 202202L
27  using std::ranges::range_adaptor_closure;
28 #else
29 #ifdef __cpp_concepts
30  template<typename D> requires std::is_object_v<D> && std::same_as<D, std::remove_cv_t<D>>
31 #else
32  template<typename D>
33 #endif
35 
36 
37  namespace detail
38  {
39 #ifdef __cpp_concepts
40  template<typename T, typename U> requires (not std::same_as<T, range_adaptor_closure<U>>)
41 #else
42  template<typename T, typename U, std::enable_if_t<not std::is_same_v<T, range_adaptor_closure<U>>, int> = 0>
43 #endif
44  void range_adaptor_closure_fn (const T&, const range_adaptor_closure<U>&);
45 
46 
47 #ifndef __cpp_concepts
48  template<typename T, typename = void>
49  struct is_range_adaptor_closure_impl : std::false_type {};
50 
51  template<typename T>
53  std::void_t<decltype(detail::range_adaptor_closure_fn(std::declval<T>(), std::declval<T>()))>> : std::true_type {};
54 #endif
55 
56 
57  template<typename T>
58 #ifdef __cpp_concepts
59  concept is_range_adaptor_closure = requires (T t) { detail::range_adaptor_closure_fn(t, t); };
60 #else
61  inline constexpr bool is_range_adaptor_closure = detail::is_range_adaptor_closure_impl<T>::value;
62 #endif
63 
64 
65 #ifndef __cpp_concepts
66  template<typename Lhs, typename Rhs, typename R, typename = void>
67  struct is_pipe_invocable : std::false_type {};
68 
69  template<typename Lhs, typename Rhs, typename R>
70  struct is_pipe_invocable<Lhs, Rhs, R, std::void_t<decltype(std::declval<Rhs>()(std::declval<Lhs>()(std::declval<R>())))>> : std::true_type {};
71 #endif
72 
73 
74  template<typename Lhs, typename Rhs, typename R>
75 #ifdef __cpp_concepts
76  concept __pipe_invocable = requires { std::declval<Rhs>()(std::declval<Lhs>()(std::declval<R>())); };
77 #else
78  inline constexpr bool pipe_invocable = is_pipe_invocable<Lhs, Rhs, R>::value;
79 #endif
80 
81  }
82 
83 
84  namespace internal
85  {
86  template<typename Lhs, typename Rhs>
87  struct Pipe : range_adaptor_closure<Pipe<Lhs, Rhs>>
88  {
89  template<typename T, typename U>
90  constexpr
91  Pipe(T&& lhs, U&& rhs) : my_lhs(std::forward<T>(lhs)), my_rhs(std::forward<U>(rhs)) {}
92 
93 
94 #if __cpp_explicit_this_parameter
95  template<typename Self, typename R>
96  requires pipe_invocable<decltype(std::forward_like<Self>(std::declval<Lhs>())), decltype(std::forward_like<Self>(std::declval<Rhs>())), R>
97  constexpr auto
98  operator()(this Self&& self, R&& r)
99  {
100  return (std::forward<Self>(self).my_rhs(std::forward<Self>(self).my_lhs(std::forward<R>(r))));
101  }
102 #else
103  template<typename R, std::enable_if_t<detail::pipe_invocable<const Lhs&, const Rhs&, R>, int> = 0>
104  constexpr auto
105  operator()(R&& r) const & { return my_rhs(my_lhs(std::forward<R>(r))); }
106 
107 
108  template<typename R, std::enable_if_t<detail::pipe_invocable<Lhs, Rhs, R>, int> = 0>
109  constexpr auto
110  operator()(R&& r) && { return std::move(my_rhs)(std::move(my_lhs)(std::forward<R>(r))); }
111 
112 
113  template<typename R>
114  constexpr auto
115  operator()(R&& r) const && = delete;
116 
117  private:
118 
119  [[no_unique_address]] Lhs my_lhs;
120  [[no_unique_address]] Rhs my_rhs;
121 #endif
122  };
123 
124  }
125 
126 
127 #ifdef __cpp_concepts
128  template<detail::is_range_adaptor_closure S, typename R> requires requires { std::declval<S>()(declval<R>()); }
129 #else
130  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>
131 #endif
132  constexpr auto
133  operator | (R&& r, S&& s)
134  {
135  return std::forward<S>(s)(std::forward<R>(r));
136  }
137 
138 
139 #ifdef __cpp_concepts
140  template<detail::is_range_adaptor_closure Lhs, detail::is_range_adaptor_closure Rhs>
141 #else
142  template<typename Lhs, typename Rhs, std::enable_if_t<detail::is_range_adaptor_closure<Lhs> and detail::is_range_adaptor_closure<Rhs>, int> = 0>
143 #endif
144  constexpr auto
145  operator | (Lhs&& lhs, Rhs&& rhs)
146  {
147  return internal::Pipe<std::decay_t<Lhs>, std::decay_t<Rhs>>{std::forward<Lhs>(lhs), std::forward<Rhs>(rhs)};
148  }
149 
150 #endif
151 }
152 
153 #endif
Definition: range_adaptor_closure.hpp:87
Definitions relating to the availability of c++ language features.
Definition: common.hpp:200
Definition: range_adaptor_closure.hpp:34
Definition: range_adaptor_closure.hpp:67