5#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_FUNCTIONAL_FUNCTION_REF_HPP_
6#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_FUNCTIONAL_FUNCTION_REF_HPP_
12#include "arene/base/array/array.hpp"
13#include "arene/base/byte/byte.hpp"
14#include "arene/base/constraints/constraints.hpp"
15#include "arene/base/contracts/contract.hpp"
16#include "arene/base/stdlib_choice/addressof.hpp"
17#include "arene/base/stdlib_choice/enable_if.hpp"
18#include "arene/base/stdlib_choice/forward.hpp"
19#include "arene/base/stdlib_choice/ignore.hpp"
20#include "arene/base/stdlib_choice/is_function.hpp"
21#include "arene/base/stdlib_choice/is_fundamental.hpp"
22#include "arene/base/stdlib_choice/is_same.hpp"
23#include "arene/base/stdlib_choice/is_trivially_copyable.hpp"
24#include "arene/base/stdlib_choice/is_void.hpp"
25#include "arene/base/stdlib_choice/max_value_overload.hpp"
26#include "arene/base/stdlib_choice/memcpy.hpp"
27#include "arene/base/stdlib_choice/remove_cv.hpp"
28#include "arene/base/stdlib_choice/remove_reference.hpp"
29#include "arene/base/type_traits/conditional.hpp"
30#include "arene/base/type_traits/is_invocable.hpp"
31#include "arene/base/type_traits/remove_cvref.hpp"
32#include "arene/base/type_traits/type_identity.hpp"
46template <
typename Signature,
bool IsNoexcept =
false>
51template <
typename Signature>
52using noexcept_function_ref = function_ref<Signature,
true>;
54namespace function_ref_detail {
60template <
typename Func>
61auto checked_deref(Func* ptr)
noexcept -> Func& {
62 ARENE_PRECONDITION(ptr !=
nullptr);
71using arg_passing_type = conditional_t<
72 std::is_fundamental<T>::value || (std::is_trivially_copyable<T>::value &&
sizeof(T) <=
sizeof(
void*)),
82template <
bool IsConst,
bool IsNoexcept,
typename R,
typename... Args>
83class function_ref_base {
86 using storage_buffer = arene::base::array<byte, std::max(
sizeof(
void*),
sizeof(
void (*)()))>;
89 using call_type = R (*)(storage_buffer, arg_passing_type<Args>...);
91 static_assert(
sizeof(call_type) ==
sizeof(
void (*)()),
"Function pointers must have the same size");
96 using func_type = conditional_t<IsConst, F
const, F>;
108 typename ReturnType = R,
109 constraints<std::enable_if_t<!std::is_void<ReturnType>::value>> =
nullptr>
110 static auto invoke_wrapped_callable(storage_buffer buffer, arg_passing_type<Args>... args) -> R {
114 std::ignore = std::memcpy(&local_f, buffer.data(),
sizeof(local_f));
116 return static_cast<R>((*local_f)(
static_cast<Args&&>(args)...));
128 typename ReturnType = R,
129 constraints<std::enable_if_t<std::is_void<ReturnType>::value>> =
nullptr>
130 static void invoke_wrapped_callable(storage_buffer buffer, arg_passing_type<Args>... args) {
134 std::ignore = std::memcpy(&local_f, buffer.data(),
sizeof(local_f));
135 static_cast<
void>((*local_f)(
static_cast<Args&&>(args)...));
142 template <
typename PointeeType,
typename CallType>
143 function_ref_base(PointeeType
const& f_ref, type_identity<CallType>)
noexcept
144 : call_(&invoke_wrapped_callable<CallType>) {
146 PointeeType
const* f_pointer{std::addressof(f_ref)};
148 std::ignore = std::memcpy(buffer_.data(), &f_pointer,
sizeof(f_pointer));
155 template <
typename F>
156 static constexpr bool
157 is_invocable_n_r_v{IsNoexcept ? ::arene::base::is_nothrow_invocable_r_v<R, F, Args...> : ::arene::base::is_invocable_r_v<R, F, Args...>};
164 auto operator()(Args... args)
const noexcept(IsNoexcept) -> R {
166 return call_(buffer_, args...);
183 std::enable_if_t<!std::is_same<function_ref_base, remove_cvref_t<F>>::value>,
184 std::enable_if_t<!std::is_function<std::remove_reference_t<F>>::value>,
185 std::enable_if_t<is_invocable_n_r_v<F>>> =
nullptr>
191 function_ref_base(F&& func)
noexcept
192 : function_ref_base(std::forward<F>(func), type_identity<func_type<std::remove_reference_t<F>>>{}) {}
207 constraints<std::enable_if_t<std::is_function<F>::value>, std::enable_if_t<is_invocable_n_r_v<F>>> =
nullptr>
213 function_ref_base(F* func)
noexcept
214 : function_ref_base(function_ref_detail::checked_deref(func), type_identity<F>{}) {}
219 function_ref_base(function_ref_base
const& other) =
default;
222 function_ref_base(function_ref_base&& other) =
default;
226 ~function_ref_base() =
default;
230 auto operator=(function_ref_base
const& other) -> function_ref_base& =
default;
233 auto operator=(function_ref_base&& other) -> function_ref_base& =
default;
237 alignas(
void*)
alignas(call_type) storage_buffer buffer_{};
251template <
typename R,
typename... Args,
bool IsNoexcept>
252class function_ref<R(Args...), IsNoexcept> : function_ref_detail::function_ref_base<
false, IsNoexcept, R, Args...> {
254 using base_class = function_ref_detail::function_ref_base<
false, IsNoexcept, R, Args...>;
258 using base_class::base_class;
260 using base_class::operator();
269template <
typename R,
typename... Args,
bool IsNoexcept>
270class function_ref<R(Args...)
const, IsNoexcept>
271 : function_ref_detail::function_ref_base<
true, IsNoexcept, R, Args...> {
273 using base_class = function_ref_detail::function_ref_base<
true, IsNoexcept, R, Args...>;
277 using base_class::base_class;
279 using base_class::operator();
Definition array_exceptions_disabled.cpp:11
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10