4#include "../Foundation/TypeTraits.h"
49template <
typename FuncType>
52template <
typename R,
typename... Args>
56 enum class FunctionErasedOperation
62 using StubFunction = R (*)(
const void*
const*,
typename TypeTraits::AddPointer<Args>::type...);
63 using OperationFunction = void (*)(FunctionErasedOperation operation,
const void** other,
const void*
const*);
65 static const int LAMBDA_SIZE =
sizeof(
void*) * 2;
67 StubFunction functionStub;
68 OperationFunction functionOperation;
72 const void* classInstance;
73 char lambdaMemory[LAMBDA_SIZE] = {0};
76 void executeOperation(FunctionErasedOperation operation,
const void** other)
const
78 if (functionOperation)
79 (*functionOperation)(operation, other, &classInstance);
82 Function(
const void* instance, StubFunction stub, OperationFunction operation)
83 : functionStub(stub), functionOperation(operation)
85 classInstance = instance;
87 using FreeFunction = R (*)(Args...);
93 static_assert(
sizeof(Function) ==
sizeof(
void*) * 4,
"Function Size");
94 functionStub =
nullptr;
95 functionOperation =
nullptr;
103 typename =
typename TypeTraits::EnableIf<
104 not TypeTraits::IsSame<typename TypeTraits::RemoveReference<Lambda>::type, Function>::value,
void>::type>
105 Function(Lambda&& lambda)
107 functionStub =
nullptr;
108 functionOperation =
nullptr;
109 bind(
forward<
typename TypeTraits::RemoveReference<Lambda>::type>(lambda));
113 ~Function() { executeOperation(FunctionErasedOperation::Destruct,
nullptr); }
117 Function(Function&& other)
119 functionStub = other.functionStub;
120 functionOperation = other.functionOperation;
121 classInstance = other.classInstance;
122 other.executeOperation(FunctionErasedOperation::MoveConstruct, &classInstance);
123 other.executeOperation(FunctionErasedOperation::Destruct,
nullptr);
124 other.functionStub =
nullptr;
125 other.functionOperation =
nullptr;
130 Function(
const Function& other)
132 functionStub = other.functionStub;
133 functionOperation = other.functionOperation;
134 other.executeOperation(FunctionErasedOperation::CopyConstruct, &classInstance);
139 Function& operator=(
const Function& other)
141 executeOperation(FunctionErasedOperation::Destruct,
nullptr);
142 functionStub = other.functionStub;
143 functionOperation = other.functionOperation;
144 other.executeOperation(FunctionErasedOperation::CopyConstruct, &classInstance);
150 Function& operator=(Function&& other)
noexcept
152 executeOperation(FunctionErasedOperation::Destruct,
nullptr);
153 functionStub = other.functionStub;
154 functionOperation = other.functionOperation;
155 other.executeOperation(FunctionErasedOperation::MoveConstruct, &classInstance);
156 other.executeOperation(FunctionErasedOperation::Destruct,
nullptr);
157 other.functionStub =
nullptr;
163 bool isValid()
const {
return functionStub !=
nullptr; }
165 bool operator==(
const Function& other)
const
167 return functionStub == other.functionStub and functionOperation == other.functionOperation and
168 classInstance == other.classInstance;
173 template <
typename Lambda>
174 void bind(Lambda&& lambda)
176 executeOperation(FunctionErasedOperation::Destruct,
nullptr);
177 functionStub =
nullptr;
178 functionOperation =
nullptr;
180 new (&classInstance, PlacementNew()) Lambda(forward<Lambda>(lambda));
181 static_assert(
sizeof(Lambda) <=
sizeof(lambdaMemory),
"Lambda is too big");
182 functionStub = [](
const void*
const* p,
typename TypeTraits::AddPointer<Args>::type... args) -> R
184 Lambda& lambda = *
reinterpret_cast<Lambda*
>(
const_cast<void**
>(p));
185 return lambda(*args...);
187 functionOperation = [](FunctionErasedOperation operation,
const void** other,
const void*
const* p)
189 Lambda& lambda = *
reinterpret_cast<Lambda*
>(
const_cast<void**
>(p));
190 if (operation == FunctionErasedOperation::Destruct)
192 else if (operation == FunctionErasedOperation::CopyConstruct)
193 new (other, PlacementNew()) Lambda(lambda);
194 else if (operation == FunctionErasedOperation::MoveConstruct)
195 new (other, PlacementNew()) Lambda(
move(lambda));
200 __builtin_unreachable();
207 template <R (*FreeFunction)(Args...)>
210 executeOperation(FunctionErasedOperation::Destruct,
nullptr);
211 classInstance =
nullptr;
212 functionStub = &FunctionWrapper<FreeFunction>;
213 functionOperation = &FunctionOperation;
220 template <
typename Class, R (Class::*MemberFunction)(Args...)
const>
221 void bind(
const Class& c)
223 executeOperation(FunctionErasedOperation::Destruct,
nullptr);
225 functionStub = &MemberWrapper<Class, MemberFunction>;
226 functionOperation = &MemberOperation;
233 template <
typename Class, R (Class::*MemberFunction)(Args...)>
236 executeOperation(FunctionErasedOperation::Destruct,
nullptr);
238 functionStub = &MemberWrapper<Class, MemberFunction>;
239 functionOperation = &MemberOperation;
247 template <
typename Class, R (Class::*MemberFunction)(Args...)>
248 static Function fromMember(Class& c)
250 return Function(&c, &MemberWrapper<Class, MemberFunction>, &MemberOperation);
258 template <
typename Class, R (Class::*MemberFunction)(Args...)
const>
259 static Function fromMember(
const Class& c)
261 return Function(&c, &MemberWrapper<Class, MemberFunction>, &MemberOperation);
266 [[nodiscard]] R operator()(Args... args)
const {
return (*functionStub)(&classInstance, &args...); }
269 static void MemberOperation(FunctionErasedOperation operation,
const void** other,
const void*
const* p)
271 if (operation == FunctionErasedOperation::CopyConstruct or operation == FunctionErasedOperation::MoveConstruct)
275 template <
typename Class, R (Class::*MemberFunction)(Args...)>
276 static R MemberWrapper(
const void*
const* p,
typename TypeTraits::RemoveReference<Args>::type*... args)
278 Class* cls =
const_cast<Class*
>(
static_cast<const Class*
>(*p));
279 return (cls->*MemberFunction)(*args...);
282 template <
typename Class, R (Class::*MemberFunction)(Args...)
const>
283 static R MemberWrapper(
const void*
const* p,
typename TypeTraits::RemoveReference<Args>::type*... args)
285 const Class* cls =
static_cast<const Class*
>(*p);
286 return (cls->*MemberFunction)(*args...);
289 template <R (*FreeFunction)(Args...)>
290 static R FunctionWrapper(
const void*
const* p,
typename TypeTraits::RemoveReference<Args>::type*... args)
293 return FreeFunction(*args...);
295 static void FunctionOperation(FunctionErasedOperation,
const void**,
const void*
const*) {}
299using Delegate = Function<void(T)>;
300using Action = Function<void()>;
#define SC_COMPILER_UNUSED(param)
Silence an unused variable or unused parameter warning.
Definition: Compiler.h:139
constexpr T && move(T &value)
Converts an lvalue to an rvalue reference.
Definition: Compiler.h:269
constexpr T && forward(typename TypeTraits::RemoveReference< T >::type &value)
Forwards an lvalue or an rvalue as an rvalue reference.
Definition: Compiler.h:272
Wraps function pointers, member functions and lambdas without ever allocating.
Definition: Function.h:50