OpenKalman
language-features.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) 2021-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 
16 #ifndef OPENKALMAN_LANGUAGE_FEATURES_HPP
17 #define OPENKALMAN_LANGUAGE_FEATURES_HPP
18 
19 #ifdef __clang__
20 # define OPENKALMAN_CPP_FEATURE_CONCEPTS true
21 # define OPENKALMAN_CPP_FEATURE_CONCEPTS_2 (__clang_major__ >= 15) // optimal value may be as low as > 10 (ver. 10.0.0)
22 #elif defined(__GNUC__)
23 # define OPENKALMAN_CPP_FEATURE_CONCEPTS (__GNUC__ >= 20) // optimal value may be as low as > 10 (ver. 10.1.0)
24 # define OPENKALMAN_CPP_FEATURE_CONCEPTS_2 (__GNUC__ >= 12) // optimal value may be as low as > 10 (ver. 10.1.0)
25 #else
26 # define OPENKALMAN_CPP_FEATURE_CONCEPTS true
27 # define OPENKALMAN_CPP_FEATURE_CONCEPTS_2 true
28 #endif
29 
30 
31 #include <cstddef>
32 #include <type_traits>
33 #include <functional>
34 #include <utility>
35 
36 #ifdef __cpp_lib_math_constants
37 #include <numbers>
38 #endif
39 
40 #ifdef __cpp_lib_concepts
41 #include <concepts>
42 #endif
43 
44 #include "common.hpp"
45 
46 namespace OpenKalman
47 {
48  // std::size_t literal similar and equivalent to "uz" literal defined in c++23 standard.
49  constexpr std::size_t operator ""_uz(unsigned long long x) { return x; };
50 
51 
52  namespace stdex
53  {
54  namespace numbers
55  {
56  #ifdef __cpp_lib_math_constants
57  using namespace std::numbers;
58  #else
59  template<typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0> inline constexpr T e_v = 2.718281828459045235360287471352662498L;
60  template<typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0> inline constexpr T log2e_v = 1.442695040888963407359924681001892137L;
61  template<typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0> inline constexpr T log10e_v = 0.434294481903251827651128918916605082L;
62  template<typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0> inline constexpr T pi_v = 3.141592653589793238462643383279502884L;
63  template<typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0> inline constexpr T inv_pi_v = 0.318309886183790671537767526745028724L;
64  template<typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0> inline constexpr T inv_sqrtpi_v = 0.564189583547756286948079451560772586L;
65  template<typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0> inline constexpr T ln2_v = 0.693147180559945309417232121458176568L;
66  template<typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0> inline constexpr T ln10_v = 2.302585092994045684017991454684364208L;
67  template<typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0> inline constexpr T sqrt2_v = 1.414213562373095048801688724209698079L;
68  template<typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0> inline constexpr T sqrt3_v = 1.732050807568877293527446341505872367L;
69  template<typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0> inline constexpr T inv_sqrt3_v = 0.577350269189625764509148780501957456L;
70  template<typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0> inline constexpr T egamma_v = 0.577215664901532860606512090082402431L;
71  template<typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0> inline constexpr T phi_v = 1.618033988749894848204586834365638118L;
72 
73  inline constexpr double e = e_v<double>;
74  inline constexpr double log2e = log2e_v<double>;
75  inline constexpr double log10e = log10e_v<double>;
76  inline constexpr double pi = pi_v<double>;
77  inline constexpr double inv_pi = inv_pi_v<double>;
78  inline constexpr double inv_sqrtpi = inv_sqrtpi_v<double>;
79  inline constexpr double ln2 = ln2_v<double>;
80  inline constexpr double ln10 = ln10_v<double>;
81  inline constexpr double sqrt2 = sqrt2_v<double>;
82  inline constexpr double sqrt3 = sqrt3_v<double>;
83  inline constexpr double inv_sqrt3 = inv_sqrt3_v<double>;
84  inline constexpr double egamma = egamma_v<double>;
85  inline constexpr double phi = phi_v<double>;
86  #endif
87  }
88 
89 
90 #ifdef __cpp_lib_remove_cvref
91  using std::remove_cvref;
92  using std::remove_cvref_t;
93 #else
94  template<typename T>
95  struct remove_cvref { using type = std::remove_cv_t<std::remove_reference_t<T>>; };
96 
97  template<typename T>
98  using remove_cvref_t = typename remove_cvref<T>::type;
99 #endif
100 
101 
102 #ifdef __cpp_lib_bounded_array_traits
103  using std::is_bounded_array;
104  using std::is_bounded_array_v;
105 #else
106  template<typename T>
107  struct is_bounded_array : std::false_type {};
108 
109  template<typename T, std::size_t N>
110  struct is_bounded_array<T[N]> : std::true_type {};
111 
112  template<typename T>
113  constexpr bool is_bounded_array_v = is_bounded_array<T>::value;
114 #endif
115 
116 
117 #if __cplusplus >= 202002L
118  using std::reference_wrapper;
119  using std::ref;
120  using std::cref;
121 #else
122 
126  namespace detail
127  {
128  template<typename T> constexpr T& reference_wrapper_FUN(T& t) noexcept { return t; }
129  template<typename T> void reference_wrapper_FUN(T&&) = delete;
130  }
131 
132 
133  template<typename T>
135  {
136  using type = T;
137 
138  template<typename U, typename = std::void_t<decltype(detail::reference_wrapper_FUN<T>(std::declval<U>()))>,
139  std::enable_if_t<not std::is_same_v<reference_wrapper, stdex::remove_cvref_t<U>>, int> = 0>
140  constexpr reference_wrapper(U&& u) noexcept(noexcept(detail::reference_wrapper_FUN<T>(std::forward<U>(u))))
141  : ptr(std::addressof(detail::reference_wrapper_FUN<T>(std::forward<U>(u)))) {}
142 
143 
144  reference_wrapper(const reference_wrapper&) noexcept = default;
145 
146 
147  reference_wrapper& operator=(const reference_wrapper& x) noexcept = default;
148 
149 
150  constexpr operator T& () const noexcept { return *ptr; }
151  constexpr T& get() const noexcept { return *ptr; }
152 
153 
154  template<typename... ArgTypes>
155  constexpr std::invoke_result_t<T&, ArgTypes...>
156  operator() (ArgTypes&&... args ) const noexcept(std::is_nothrow_invocable_v<T&, ArgTypes...>)
157  {
158  return get()(std::forward<ArgTypes>(args)...);
159  }
160 
161  private:
162 
163  T* ptr;
164 
165  };
166 
167  // deduction guides
168  template<typename T>
170 
171 
172  template<typename T>
173  constexpr std::reference_wrapper<T>
174  ref(T& t) noexcept { return {t}; };
175 
176  template<typename T>
177  constexpr std::reference_wrapper<T>
178  ref(std::reference_wrapper<T> t) noexcept { return std::move(t); };
179 
180  template<typename T>
181  void ref(const T&&) = delete;
182 
183  template<typename T>
184  constexpr std::reference_wrapper<const T>
185  cref(const T& t) noexcept { return {t}; };
186 
187  template<typename T>
188  constexpr std::reference_wrapper<const T>
189  cref(std::reference_wrapper<T> t) noexcept { return std::move(t); };
190 
191  template<typename T>
192  void cref(const T&&) = delete;
193 #endif
194 
195 
196 #ifdef __cpp_lib_unwrap_ref
197  using std::unwrap_reference;
198  using std::unwrap_reference_t;
199  using std::unwrap_ref_decay;
200  using std::unwrap_ref_decay_t;
201 #else
202  template<typename T>
203  struct unwrap_reference { using type = T; };
204 
205  template<typename U>
206  struct unwrap_reference<std::reference_wrapper<U>> { using type = U&; };
207 
208 #if __cplusplus < 202002L
209  template<typename U>
210  struct unwrap_reference<stdex::reference_wrapper<U>> { using type = U&; };
211 #endif
212 
213  template<typename T>
214  using unwrap_reference_t = typename unwrap_reference<T>::type;
215 
216 
217  template<typename T>
218  struct unwrap_ref_decay : unwrap_reference<std::decay_t<T>> {};
219 
220  template<typename T>
221  using unwrap_ref_decay_t = typename unwrap_ref_decay<T>::type;
222 #endif
223 
224 
225 #if __cplusplus >= 202002L
226  using std::identity;
227 #else
228  struct identity
229  {
230  template<typename T>
231  [[nodiscard]] constexpr T&& operator()(T&& t) const noexcept { return std::forward<T>(t); }
232 
233  struct is_transparent; // undefined
234  };
235 #endif
236 
237 
238 #ifdef __cpp_lib_type_identity
239  using std::type_identity;
240  using std::type_identity_t;
241 #else
242  template<typename T>
243  struct type_identity { using type = T; };
244 
245  template<typename T>
246  using type_identity_t = typename type_identity<T>::type;
247 #endif
248 
249  }
250 
251 }
252 
253 
254 #endif
Definition: language-features.hpp:218
Definition: language-features.hpp:95
Definition: language-features.hpp:228
Definition: language-features.hpp:107
The root namespace for OpenKalman.
Definition: basics.hpp:34
Definition: language-features.hpp:134
Definition: language-features.hpp:203
Definition: language-features.hpp:243