OpenKalman
invoke.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_COMPATIBILITY_INVOKE_HPP
17 #define OPENKALMAN_COMPATIBILITY_INVOKE_HPP
18 
19 namespace OpenKalman::stdex
20 {
21 #if __cplusplus >= 202002L
22  using std::invoke;
23 #else
24  namespace detail
25  {
26  template<typename> static constexpr bool is_reference_wrapper_v = false;
27  template<typename U> static constexpr bool is_reference_wrapper_v<std::reference_wrapper<U>> = true;
28  template<typename U> static constexpr bool is_reference_wrapper_v<stdex::reference_wrapper<U>> = true;
29 
30  template<typename C, typename Pointed, typename Object, typename...Args>
31  static constexpr decltype(auto)
32  invoke_memptr(Pointed C::* member, Object&& object, Args&&... args)
33  {
34  using object_t = remove_cvref_t<Object>;
35  constexpr bool is_member_function = std::is_function_v<Pointed>;
36  constexpr bool is_wrapped = is_reference_wrapper_v<object_t>;
37  constexpr bool is_derived_object = std::is_same_v<C, object_t> or std::is_base_of_v<C, object_t>;
38 
39  if constexpr (is_member_function)
40  {
41  if constexpr (is_derived_object)
42  return (std::forward<Object>(object) .* member) (std::forward<Args>(args)...);
43  else if constexpr (is_wrapped)
44  return (object.get() .* member)(std::forward<Args>(args)...);
45  else
46  return ((*std::forward<Object>(object)) .* member) (std::forward<Args>(args)...);
47  }
48  else
49  {
50  static_assert(std::is_object_v<Pointed> && sizeof...(args) == 0);
51  if constexpr (is_derived_object)
52  return std::forward<Object>(object) .* member;
53  else if constexpr (is_wrapped)
54  return object.get() .* member;
55  else
56  return (*std::forward<Object>(object)) .* member;
57  }
58  }
59  }
60 
61 
66  template<typename F, typename...Args>
67  static constexpr std::invoke_result_t<F, Args...>
68  invoke(F&& f, Args&&... args) noexcept(std::is_nothrow_invocable_v<F, Args...>)
69  {
70  if constexpr (std::is_member_pointer_v<stdex::remove_cvref_t<F>>)
71  return detail::invoke_memptr(f, std::forward<Args>(args)...);
72  else
73  return std::forward<F>(f)(std::forward<Args>(args)...);
74  }
75 #endif
76 
77 
78 #if __cplusplus >= 202302L
79  using std::invoke_r;
80 #else
81 
85 #ifdef __cpp_concepts
86  template<typename R, typename F, typename...Args> requires std::is_invocable_r_v<R, F, Args...>
87 #else
88  template<typename R, typename F, typename...Args, std::enable_if_t<std::is_invocable_r_v<R, F, Args...>, int> = 0>
89 #endif
90  constexpr R invoke_r(F&& f, Args&&... args) noexcept(std::is_nothrow_invocable_r_v<R, F, Args...>)
91  {
92  if constexpr (std::is_void_v<R>)
93  stdex::invoke(std::forward<F>(f), std::forward<Args>(args)...);
94  else
95  return stdex::invoke(std::forward<F>(f), std::forward<Args>(args)...);
96  }
97 #endif
98 
99 }
100 
101 
102 #endif
Definition: basics.hpp:55