5 #ifndef EASTL_FUNCTION_DETAIL_H
6 #define EASTL_FUNCTION_DETAIL_H
8 #if defined(EA_PRAGMA_ONCE_SUPPORTED)
12 #include <EABase/eabase.h>
13 #include <EABase/nullptr.h>
14 #include <EABase/config/eacompilertraits.h>
16 #include <EASTL/internal/config.h>
17 #include <EASTL/internal/functional_base.h>
18 #include <EASTL/internal/move_help.h>
19 #include <EASTL/internal/function_help.h>
21 #include <EASTL/type_traits.h>
22 #include <EASTL/utility.h>
23 #include <EASTL/allocator.h>
25 #if EASTL_RTTI_ENABLED
29 #if EASTL_EXCEPTIONS_ENABLED
30 EA_DISABLE_ALL_VC_WARNINGS()
33 EA_RESTORE_ALL_VC_WARNINGS()
38 #if EASTL_EXCEPTIONS_ENABLED
39 class bad_function_call :
public std::exception
42 bad_function_call() EA_NOEXCEPT = default;
44 const
char* what() const EA_NOEXCEPT EA_OVERRIDE
46 return "bad function_detail call";
57 void (*unused_func_ptr)(void);
62 template <
int SIZE_IN_BYTES>
65 static_assert(SIZE_IN_BYTES >= 0,
"local buffer storage cannot have a negative size!");
66 template <
typename Ret>
67 Ret& GetStorageTypeRef()
const
69 return *
reinterpret_cast<Ret*
>(
const_cast<char*
>(&storage[0]));
75 char storage[SIZE_IN_BYTES];
82 template <
typename Ret>
83 Ret& GetStorageTypeRef()
const
85 return *
reinterpret_cast<Ret*
>(
const_cast<char*
>(&storage[0]));
95 template <
typename Functor,
int SIZE_IN_BYTES>
98 static EA_CONSTEXPR
bool value =
100 (eastl::alignment_of_v<functor_storage<SIZE_IN_BYTES>> % eastl::alignment_of_v<Functor>) == 0;
106 template <
int SIZE_IN_BYTES>
113 enum ManagerOperations :
int
115 MGROPS_DESTRUCT_FUNCTOR = 0,
116 MGROPS_COPY_FUNCTOR = 1,
117 MGROPS_MOVE_FUNCTOR = 2,
118 #if EASTL_RTTI_ENABLED
119 MGROPS_GET_TYPE_INFO = 3,
120 MGROPS_GET_FUNC_PTR = 4,
125 template <
typename Functor,
typename =
void>
132 return &(storage.template GetStorageTypeRef<Functor>());
135 template <
typename T>
138 ::new (GetFunctorPtr(storage)) Functor(eastl::forward<T>(functor));
143 GetFunctorPtr(storage)->~Functor();
148 ::new (GetFunctorPtr(to)) Functor(*GetFunctorPtr(from));
153 ::new (GetFunctorPtr(to)) Functor(
eastl::move(*GetFunctorPtr(from)));
156 static void* Manager(
void* to,
void* from,
typename function_base_detail::ManagerOperations ops) EA_NOEXCEPT
160 case MGROPS_DESTRUCT_FUNCTOR:
165 case MGROPS_COPY_FUNCTOR:
171 case MGROPS_MOVE_FUNCTOR:
185 template <
typename Functor>
191 return storage.template GetStorageTypeRef<Functor*>();
196 return storage.template GetStorageTypeRef<Functor*>();
199 template <
typename T>
202 auto&
allocator = *EASTLAllocatorDefault();
203 Functor* func =
static_cast<Functor*
>(
allocator.allocate(
sizeof(Functor),
alignof(Functor), 0));
205 #if EASTL_EXCEPTIONS_ENABLED
208 throw std::bad_alloc();
211 EASTL_ASSERT_MSG(func !=
nullptr,
"Allocation failed!");
214 ::new (
static_cast<void*
>(func)) Functor(eastl::forward<T>(functor));
215 GetFunctorPtrRef(storage) = func;
220 Functor* func = GetFunctorPtr(storage);
223 auto&
allocator = *EASTLAllocatorDefault();
225 allocator.deallocate(
static_cast<void*
>(func),
sizeof(Functor));
231 auto&
allocator = *EASTLAllocatorDefault();
232 Functor* func =
static_cast<Functor*
>(
allocator.allocate(
sizeof(Functor),
alignof(Functor), 0));
233 #if EASTL_EXCEPTIONS_ENABLED
236 throw std::bad_alloc();
239 EASTL_ASSERT_MSG(func !=
nullptr,
"Allocation failed!");
241 ::new (
static_cast<void*
>(func)) Functor(*GetFunctorPtr(from));
242 GetFunctorPtrRef(to) = func;
247 Functor* func = GetFunctorPtr(from);
248 GetFunctorPtrRef(to) = func;
249 GetFunctorPtrRef(from) =
nullptr;
252 static void* Manager(
void* to,
void* from,
typename function_base_detail::ManagerOperations ops) EA_NOEXCEPT
256 case MGROPS_DESTRUCT_FUNCTOR:
261 case MGROPS_COPY_FUNCTOR:
267 case MGROPS_MOVE_FUNCTOR:
280 template <
typename Functor,
typename R,
typename... Args>
286 #if EASTL_RTTI_ENABLED
287 static void* GetTypeInfo() EA_NOEXCEPT
289 return reinterpret_cast<void*
>(
const_cast<std::type_info*
>(&
typeid(Functor)));
292 static void* Manager(
void* to,
void* from,
typename function_base_detail::ManagerOperations ops) EA_NOEXCEPT
296 case MGROPS_GET_TYPE_INFO:
298 return GetTypeInfo();
301 case MGROPS_GET_FUNC_PTR:
303 return static_cast<void*
>(Base::GetFunctorPtr(*
static_cast<FunctorStorageType*
>(to)));
308 return Base::Manager(to, from, ops);
396 return eastl::invoke(*Base::GetFunctorPtr(functor), eastl::forward<Args>(args)...);
404 #define EASTL_INTERNAL_FUNCTION_VALID_FUNCTION_ARGS(FUNCTOR, RET, ARGS, BASE, MYSELF) \
405 typename eastl::enable_if_t<eastl::is_invocable_r_v<RET, FUNCTOR, ARGS> && \
406 !eastl::is_base_of_v<BASE, eastl::decay_t<FUNCTOR>> && \
407 !eastl::is_same_v<eastl::decay_t<FUNCTOR>, MYSELF>>
409 #define EASTL_INTERNAL_FUNCTION_DETAIL_VALID_FUNCTION_ARGS(FUNCTOR, RET, ARGS, MYSELF) \
410 EASTL_INTERNAL_FUNCTION_VALID_FUNCTION_ARGS(FUNCTOR, RET, ARGS, MYSELF, MYSELF)
415 template <
int,
typename>
418 template <
int SIZE_IN_BYTES,
typename R,
typename... Args>
422 using result_type = R;
427 using Base::mStorage;
449 template <
typename Functor,
typename = EASTL_INTERNAL_FUNCTION_DETAIL_VALID_FUNCTION_ARGS(Functor, R, Args...,
function_detail)>
485 mMgrFuncPtr =
nullptr;
486 mInvokeFuncPtr = &DefaultInvoker;
491 template <
typename Functor,
typename = EASTL_INTERNAL_FUNCTION_DETAIL_VALID_FUNCTION_ARGS(Functor, R, Args...,
function_detail)>
495 CreateForwardFunctor(eastl::forward<Functor>(functor));
499 template <
typename Functor>
503 CreateForwardFunctor(f);
513 if (other.HaveManager())
515 (void)(*other.mMgrFuncPtr)(
static_cast<void*
>(&tempStorage),
static_cast<void*
>(&other.mStorage),
516 Base::ManagerOperations::MGROPS_MOVE_FUNCTOR);
521 (void)(*mMgrFuncPtr)(
static_cast<void*
>(&other.mStorage),
static_cast<void*
>(&mStorage),
522 Base::ManagerOperations::MGROPS_MOVE_FUNCTOR);
525 if (other.HaveManager())
527 (void)(*other.mMgrFuncPtr)(
static_cast<void*
>(&mStorage),
static_cast<void*
>(&tempStorage),
528 Base::ManagerOperations::MGROPS_MOVE_FUNCTOR);
531 eastl::swap(mMgrFuncPtr, other.mMgrFuncPtr);
532 eastl::swap(mInvokeFuncPtr, other.mInvokeFuncPtr);
535 explicit operator bool()
const EA_NOEXCEPT
537 return HaveManager();
540 EASTL_FORCE_INLINE R operator ()(Args... args)
const
542 return (*mInvokeFuncPtr)(eastl::forward<Args>(args)..., this->mStorage);
545 #if EASTL_RTTI_ENABLED
546 const std::type_info& target_type()
const EA_NOEXCEPT
550 void* ret = (*mMgrFuncPtr)(
nullptr,
nullptr, Base::ManagerOperations::MGROPS_GET_TYPE_INFO);
551 return *(
static_cast<const std::type_info*
>(ret));
556 template <
typename Functor>
557 Functor* target() EA_NOEXCEPT
559 if (HaveManager() && target_type() ==
typeid(Functor))
561 void* ret = (*mMgrFuncPtr)(
static_cast<void*
>(&mStorage),
nullptr,
562 Base::ManagerOperations::MGROPS_GET_FUNC_PTR);
563 return ret ?
static_cast<Functor*
>(ret) :
nullptr;
568 template <
typename Functor>
569 const Functor* target()
const EA_NOEXCEPT
571 if (HaveManager() && target_type() ==
typeid(Functor))
573 void* ret = (*mMgrFuncPtr)(
static_cast<void*
>(&mStorage),
nullptr,
574 Base::ManagerOperations::MGROPS_GET_FUNC_PTR);
575 return ret ?
static_cast<const Functor*
>(ret) :
nullptr;
582 bool HaveManager()
const EA_NOEXCEPT
584 return (mMgrFuncPtr !=
nullptr);
587 void Destroy() EA_NOEXCEPT
591 (void)(*mMgrFuncPtr)(
static_cast<void*
>(&mStorage),
nullptr,
592 Base::ManagerOperations::MGROPS_DESTRUCT_FUNCTOR);
598 if (other.HaveManager())
600 (void)(*other.mMgrFuncPtr)(
static_cast<void*
>(&mStorage),
601 const_cast<void*
>(
static_cast<const void*
>(&other.mStorage)),
602 Base::ManagerOperations::MGROPS_COPY_FUNCTOR);
605 mMgrFuncPtr = other.mMgrFuncPtr;
606 mInvokeFuncPtr = other.mInvokeFuncPtr;
611 if (other.HaveManager())
613 (void)(*other.mMgrFuncPtr)(
static_cast<void*
>(&mStorage),
static_cast<void*
>(&other.mStorage),
614 Base::ManagerOperations::MGROPS_MOVE_FUNCTOR);
617 mMgrFuncPtr = other.mMgrFuncPtr;
618 mInvokeFuncPtr = other.mInvokeFuncPtr;
619 other.mMgrFuncPtr =
nullptr;
620 other.mInvokeFuncPtr = &DefaultInvoker;
623 template <
typename Functor>
624 void CreateForwardFunctor(Functor&& functor)
627 using FunctionManagerType =
typename Base::template
function_manager<DecayedFunctorType, R, Args...>;
629 if (internal::is_null(functor))
631 mMgrFuncPtr =
nullptr;
632 mInvokeFuncPtr = &DefaultInvoker;
636 mMgrFuncPtr = &FunctionManagerType::Manager;
637 mInvokeFuncPtr = &FunctionManagerType::Invoker;
638 FunctionManagerType::CreateFunctor(mStorage, eastl::forward<Functor>(functor));
643 typedef void* (*ManagerFuncPtr)(
void*,
void*,
typename Base::ManagerOperations);
646 EA_DISABLE_GCC_WARNING(-Wreturn-type);
647 EA_DISABLE_CLANG_WARNING(-Wreturn-type);
648 EA_DISABLE_VC_WARNING(4716);
654 #if EASTL_EXCEPTIONS_ENABLED
655 throw eastl::bad_function_call();
657 EASTL_ASSERT_MSG(
false,
"function_detail call on an empty function_detail<R(Args..)>");
660 EA_RESTORE_VC_WARNING();
661 EA_RESTORE_CLANG_WARNING();
662 EA_RESTORE_GCC_WARNING();
665 ManagerFuncPtr mMgrFuncPtr =
nullptr;
666 InvokeFuncPtr mInvokeFuncPtr = &DefaultInvoker;
Definition: allocator.h:52
Definition: function_detail.h:127
Definition: function_detail.h:282
static R Invoker(Args... args, const FunctorStorageType &functor)
Definition: function_detail.h:394
Definition: function_detail.h:108
Definition: function_detail.h:416
Definition: function_detail.h:53
reference_wrapper
Definition: functional_base.h:221
EA Standard Template Library.
Definition: algorithm.h:288
OutputIterator move(InputIterator first, InputIterator last, OutputIterator result)
Definition: copy_help.h:170
Definition: type_traits.h:494
Definition: type_traits.h:442
Definition: function_detail.h:64
Definition: function_detail.h:97
Definition: function_detail.h:56