Horizon
Loading...
Searching...
No Matches
invoke.hpp
Go to the documentation of this file.
1
2// 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
25
26#include <range/v3/utility/static_const.hpp>
27
28#include <range/v3/detail/prologue.hpp>
29
30RANGES_DIAGNOSTIC_PUSH
31RANGES_DIAGNOSTIC_IGNORE_CXX17_COMPAT
32RANGES_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
42namespace 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
146 RANGES_INLINE_VARIABLE(invoke_fn, invoke)
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;
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
242RANGES_DIAGNOSTIC_POP
243
244#include <range/v3/detail/epilogue.hpp>
245
246#endif // RANGES_V3_FUNCTIONAL_INVOKE_HPP
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
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