Horizon
invoke.hpp
Go to the documentation of this file.
1 // Range v3 library
3 //
4 // Copyright Eric Niebler 2013-present
5 // Copyright Casey Carter 2016
6 //
7 // Use, modification and distribution is subject to the
8 // Boost Software License, Version 1.0. (See accompanying
9 // file LICENSE_1_0.txt or copy at
10 // http://www.boost.org/LICENSE_1_0.txt)
11 //
12 // Project home: https://github.com/ericniebler/range-v3
13 //
14 #ifndef RANGES_V3_FUNCTIONAL_INVOKE_HPP
15 #define RANGES_V3_FUNCTIONAL_INVOKE_HPP
16 
17 #include <functional>
18 #include <type_traits>
19 
20 #include <meta/meta.hpp>
21 
22 #include <concepts/concepts.hpp>
23 
24 #include <range/v3/range_fwd.hpp>
25 
26 #include <range/v3/utility/static_const.hpp>
27 
28 #include <range/v3/detail/prologue.hpp>
29 
30 RANGES_DIAGNOSTIC_PUSH
31 RANGES_DIAGNOSTIC_IGNORE_CXX17_COMPAT
32 RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS
33 
34 #ifndef RANGES_CONSTEXPR_INVOKE
35 #ifdef RANGES_WORKAROUND_CLANG_23135
36 #define RANGES_CONSTEXPR_INVOKE 0
37 #else
38 #define RANGES_CONSTEXPR_INVOKE 1
39 #endif
40 #endif
41 
42 namespace ranges
43 {
46 
48  namespace detail
49  {
50  RANGES_DIAGNOSTIC_PUSH
51  RANGES_DIAGNOSTIC_IGNORE_VOID_PTR_DEREFERENCE
52 
53  template<typename U>
54  U & can_reference_(U &&);
55 
56  // clang-format off
59  template<typename T>
60  CPP_requires(dereferenceable_part_,
61  requires(T && t) //
62  (
63  detail::can_reference_(*(T &&) t)
64  ));
67  template<typename T>
68  CPP_concept dereferenceable_ = //
69  CPP_requires_ref(detail::dereferenceable_part_, T);
70  // clang-format on
71 
72  RANGES_DIAGNOSTIC_POP
73 
74  template<typename T>
75  RANGES_INLINE_VAR constexpr bool is_reference_wrapper_v =
78  } // namespace detail
80 
81  template<typename T>
82  RANGES_INLINE_VAR constexpr bool is_reference_wrapper_v =
83  detail::is_reference_wrapper_v<detail::decay_t<T>>;
84 
85  template<typename T>
86  using is_reference_wrapper = meta::bool_<is_reference_wrapper_v<T>>;
87 
89  template<typename T>
90  using is_reference_wrapper_t RANGES_DEPRECATED(
91  "is_reference_wrapper_t is deprecated.") = meta::_t<is_reference_wrapper<T>>;
93 
94  struct invoke_fn
95  {
96  private:
97  template(typename, typename T1)(
98  requires detail::dereferenceable_<T1>)
99  static constexpr decltype(auto) coerce(T1 && t1, long)
100  noexcept(noexcept(*static_cast<T1 &&>(t1)))
101  {
102  return *static_cast<T1 &&>(t1);
103  }
104 
105  template(typename T, typename T1)(
106  requires derived_from<detail::decay_t<T1>, T>)
107  static constexpr T1 && coerce(T1 && t1, int) noexcept
108  {
109  return static_cast<T1 &&>(t1);
110  }
111 
112  template(typename, typename T1)(
113  requires detail::is_reference_wrapper_v<detail::decay_t<T1>>)
114  static constexpr decltype(auto) coerce(T1 && t1, int) noexcept
115  {
116  return static_cast<T1 &&>(t1).get();
117  }
118 
119  public:
120  template<typename F, typename T, typename T1, typename... Args>
121  constexpr auto operator()(F T::*f, T1&& t1, Args&&... args) const
122  noexcept(noexcept((invoke_fn::coerce<T>((T1&&) t1, 0).*f)((Args&&) args...)))
123  -> decltype((invoke_fn::coerce<T>((T1&&) t1, 0).*f)((Args&&) args...))
124  {
125  return (invoke_fn::coerce<T>((T1&&) t1, 0).*f)((Args&&) args...);
126  }
127 
128  template<typename D, typename T, typename T1>
129  constexpr auto operator()(D T::*f, T1&& t1) const
130  noexcept(noexcept(invoke_fn::coerce<T>((T1&&) t1, 0).*f))
131  -> decltype(invoke_fn::coerce<T>((T1&&) t1, 0).*f)
132  {
133  return invoke_fn::coerce<T>((T1&&) t1, 0).*f;
134  }
135 
136  template<typename F, typename... Args>
137  CPP_PP_IIF(RANGES_CONSTEXPR_INVOKE)(CPP_PP_EXPAND, CPP_PP_EAT)(constexpr)
138  auto operator()(F&& f, Args&&... args) const
139  noexcept(noexcept(((F&&) f)((Args&&) args...)))
140  -> decltype(((F&&) f)((Args&&) args...))
141  {
142  return ((F&&) f)((Args&&) args...);
143  }
144  };
145 
147 
148 #ifdef RANGES_WORKAROUND_MSVC_701385
150  namespace detail
151  {
152  template<typename Void, typename Fun, typename... Args>
153  struct _invoke_result_
154  {};
155 
156  template<typename Fun, typename... Args>
157  struct _invoke_result_<
158  meta::void_<decltype(invoke(std::declval<Fun>(), std::declval<Args>()...))>,
159  Fun, Args...>
160  {
161  using type = decltype(invoke(std::declval<Fun>(), std::declval<Args>()...));
162  };
163  } // namespace detail
165 
166  template<typename Fun, typename... Args>
167  using invoke_result = detail::_invoke_result_<void, Fun, Args...>;
168 
169  template<typename Fun, typename... Args>
170  using invoke_result_t = meta::_t<invoke_result<Fun, Args...>>;
171 
172 #else // RANGES_WORKAROUND_MSVC_701385
173  template<typename Fun, typename... Args>
174  using invoke_result_t =
175  decltype(invoke(std::declval<Fun>(), std::declval<Args>()...));
176 
177  template<typename Fun, typename... Args>
178  struct invoke_result : meta::defer<invoke_result_t, Fun, Args...>
179  {};
180 #endif // RANGES_WORKAROUND_MSVC_701385
181 
183  namespace detail
184  {
185  template<bool IsInvocable>
186  struct is_nothrow_invocable_impl_
187  {
188  template<typename Fn, typename... Args>
189  static constexpr bool apply() noexcept
190  {
191  return false;
192  }
193  };
194  template<>
195  struct is_nothrow_invocable_impl_<true>
196  {
197  template<typename Fn, typename... Args>
198  static constexpr bool apply() noexcept
199  {
200  return noexcept(invoke(std::declval<Fn>(), std::declval<Args>()...));
201  }
202  };
203  } // namespace detail
205 
206  template<typename Fn, typename... Args>
207  RANGES_INLINE_VAR constexpr bool is_invocable_v =
208  meta::is_trait<invoke_result<Fn, Args...>>::value;
209 
210  template<typename Fn, typename... Args>
211  RANGES_INLINE_VAR constexpr bool is_nothrow_invocable_v =
212  detail::is_nothrow_invocable_impl_<is_invocable_v<Fn, Args...>>::template apply<
213  Fn, Args...>();
214 
216  template<typename Sig>
217  struct RANGES_DEPRECATED(
218  "ranges::result_of is deprecated. "
219  "Please use ranges::invoke_result") result_of
220  {};
221 
222  template<typename Fun, typename... Args>
223  struct RANGES_DEPRECATED(
224  "ranges::result_of is deprecated. "
225  "Please use ranges::invoke_result") result_of<Fun(Args...)>
226  : meta::defer<invoke_result_t, Fun, Args...>
227  {};
229 
230  namespace cpp20
231  {
232  using ranges::invoke;
233  using ranges::invoke_result;
234  using ranges::invoke_result_t;
235  using ranges::is_invocable_v;
236  using ranges::is_nothrow_invocable_v;
237  } // namespace cpp20
238 
240 } // namespace ranges
241 
242 RANGES_DIAGNOSTIC_POP
243 
244 #include <range/v3/detail/epilogue.hpp>
245 
246 #endif // RANGES_V3_FUNCTIONAL_INVOKE_HPP
template(typename ActionFn, typename Rng)(concept(invocable_action_closure_)(ActionFn
\concept invocable_action_closure_
RANGES_INLINE_VARIABLE(detail::to_container_fn< detail::from_range< std::vector >>, to_vector) template< template< typename... > class ContT > auto to(RANGES_HIDDEN_DETAIL(detail
For initializing a container of the specified type with the elements of an Range.
Definition: conversion.hpp:399
std::integral_constant< bool, B > bool_
An integral constant wrapper for bool.
Definition: meta.hpp:168
typename T::type _t
Type alias for T::type.
Definition: meta.hpp:141
_t< extension::apply< Fn, L > > apply
Applies the invocable Fn using the types in the type list L as arguments.
Definition: meta.hpp:1030
typename Fn::template invoke< Args... > invoke
Evaluate the invocable Fn with the arguments Args.
Definition: meta.hpp:541
_t< detail::is_< T, C > > is
is
Definition: meta.hpp:874
void void_
An alias for void.
Definition: meta.hpp:597
Tiny meta-programming library.
Tiny metaprogramming library.
Definition: meta.hpp:116
A wrapper that defers the instantiation of a template C with type parameters Ts in a lambda or let ex...
Definition: meta.hpp:787
Definition: arithmetic.hpp:78
Definition: invoke.hpp:95
Definition: invoke.hpp:179