61# if __has_builtin(__reference_converts_from_temporary)
62# define ARIA_DETAIL_HAS_REFERENCE_TEMPORARY_BUILTIN
68template<
class R,
class Fn,
class... Args>
69inline constexpr bool safely_invocable_r_v = [] {
70 if constexpr (!std::is_invocable_r_v<R, Fn, Args...>) {
72 }
else if constexpr (std::is_reference_v<R>) {
73 using Result = std::invoke_result_t<Fn, Args...>;
74#if defined(__cpp_lib_reference_from_temporary) && __cpp_lib_reference_from_temporary >= 202202L
75 return !std::reference_converts_from_temporary_v<R, Result>;
76#elifdef ARIA_DETAIL_HAS_REFERENCE_TEMPORARY_BUILTIN
79 return !__reference_converts_from_temporary(R, Result);
84 return std::is_reference_v<Result> &&
85 std::is_convertible_v<std::add_pointer_t<std::remove_reference_t<Result>>,
86 std::add_pointer_t<std::remove_reference_t<R>>>;
92#undef ARIA_DETAIL_HAS_REFERENCE_TEMPORARY_BUILTIN
98template<
class R,
class... Args>
111 : target_{.function =
reinterpret_cast<ErasedFunction
>(fp)},
112 invoke_(fp ? &invoke_function_pointer_<
decltype(fp)> :
nullptr) {}
118 std::enable_if_t<std::is_pointer_v<Fp> &&
119 std::is_function_v<std::remove_pointer_t<Fp>> &&
120 detail::safely_invocable_r_v<R, Fp, Args...>,
int> = 0>
122 : target_{.function =
reinterpret_cast<ErasedFunction
>(fp)},
123 invoke_(fp ? &invoke_function_pointer_<Fp> :
nullptr) {}
129 class = std::enable_if_t<
130 !std::is_same_v<std::remove_cvref_t<Fn>,
function_ref> &&
131 !std::is_pointer_v<std::remove_cvref_t<Fn>> &&
132 !std::is_function_v<std::remove_reference_t<Fn>> &&
133 !std::is_member_pointer_v<std::remove_cvref_t<Fn>> &&
134 detail::safely_invocable_r_v<R, Fn&, Args...>>>
136 : target_{.object =
static_cast<const void*
>(std::addressof(fn))},
137 invoke_(&invoke_callable_<std::remove_reference_t<Fn>>) {}
144 target_.object =
nullptr;
150 target_.function =
reinterpret_cast<ErasedFunction
>(fp);
151 invoke_ = fp ? &invoke_function_pointer_<
decltype(fp)> :
nullptr;
156 std::enable_if_t<std::is_pointer_v<Fp> &&
157 std::is_function_v<std::remove_pointer_t<Fp>> &&
158 detail::safely_invocable_r_v<R, Fp, Args...>,
int> = 0>
160 target_.function =
reinterpret_cast<ErasedFunction
>(fp);
161 invoke_ = fp ? &invoke_function_pointer_<Fp> :
nullptr;
166 class = std::enable_if_t<
167 !std::is_same_v<std::remove_cvref_t<Fn>,
function_ref> &&
168 !std::is_pointer_v<std::remove_cvref_t<Fn>> &&
169 !std::is_function_v<std::remove_reference_t<Fn>> &&
170 !std::is_member_pointer_v<std::remove_cvref_t<Fn>> &&
171 detail::safely_invocable_r_v<R, Fn&, Args...>>>
173 target_.object =
static_cast<const void*
>(std::addressof(fn));
174 invoke_ = &invoke_callable_<std::remove_reference_t<Fn>>;
179 explicit constexpr operator bool() const noexcept {
return invoke_ !=
nullptr; }
184 return invoke_(target_, std::forward<Args>(args)...);
188 return a.invoke_ ==
nullptr;
191 return a.invoke_ ==
nullptr;
194 return a.invoke_ !=
nullptr;
197 return a.invoke_ !=
nullptr;
201 using ErasedFunction = void (*)();
203 const void*
object =
nullptr;
204 ErasedFunction function;
206 using Invoker = R (*)(Target, Args...);
209 static R invoke_callable_(Target target, Args... args) {
211 auto* p =
const_cast<Fn*
>(
static_cast<const Fn*
>(target.object));
212 if constexpr (std::is_void_v<R>) {
213 std::invoke(*p, std::forward<Args>(args)...);
215 return std::invoke(*p, std::forward<Args>(args)...);
220 static R invoke_function_pointer_(Target target, Args... args) {
223 auto fp =
reinterpret_cast<Fp
>(target.function);
224 if constexpr (std::is_void_v<R>) {
225 std::invoke(fp, std::forward<Args>(args)...);
227 return std::invoke(fp, std::forward<Args>(args)...);
232 Invoker invoke_ =
nullptr;
237template<
class R,
class... Args>
function_ref & operator=(R(*fp)(Args...)) noexcept
Definition function_ref.hpp:149
function_ref(R(*fp)(Args...)) noexcept
Definition function_ref.hpp:110
constexpr function_ref(const function_ref &) noexcept=default
friend constexpr bool operator==(const function_ref &a, std::nullptr_t) noexcept
Definition function_ref.hpp:187
R result_type
Definition function_ref.hpp:101
friend constexpr bool operator!=(std::nullptr_t, const function_ref &a) noexcept
Definition function_ref.hpp:196
function_ref(Fp fp) noexcept
Definition function_ref.hpp:121
constexpr function_ref() noexcept=default
friend constexpr bool operator!=(const function_ref &a, std::nullptr_t) noexcept
Definition function_ref.hpp:193
constexpr function_ref & operator=(std::nullptr_t) noexcept
Definition function_ref.hpp:143
constexpr function_ref & operator=(const function_ref &) noexcept=default
function_ref(Fn &&fn) noexcept
Definition function_ref.hpp:135
friend constexpr bool operator==(std::nullptr_t, const function_ref &a) noexcept
Definition function_ref.hpp:190
function_ref & operator=(Fp fp) noexcept
Definition function_ref.hpp:159
function_ref & operator=(Fn &&fn) noexcept
Definition function_ref.hpp:172
R operator()(Args... args) const
Definition function_ref.hpp:181
Definition function_ref.hpp:96
function_ref(R(*)(Args...)) -> function_ref< R(Args...)>
Definition validation_key.hpp:110