15#ifndef TLX_DELEGATE_HEADER
16#define TLX_DELEGATE_HEADER
27template <
typename T,
typename Allocator = std::allocator<
void> >
90template <
typename R,
typename... A,
typename Allocator>
113 template <R(*
const Function)(A...)>
115 return Delegate(function_caller<Function>,
nullptr);
124 explicit Delegate(R(*
const function_ptr)(A...)) noexcept
126 * reinterpret_cast<
void* const*>(&function_ptr)) { }
128 static_assert(
sizeof(
void*) ==
sizeof(
void (*)(void)),
129 "object pointer and function pointer sizes must equal");
142 template <
class C, R(C::* const Method)(A...)>
143 static
Delegate make(C* const object_ptr) noexcept {
144 return
Delegate(method_caller<C, Method>, object_ptr);
148 template <
class C, R(C::* const Method)(A...) const>
149 static
Delegate make(C const* const object_ptr) noexcept {
150 return
Delegate(const_method_caller<C, Method>,
151 const_cast<C*>(object_ptr));
156 template <
class C, R(C::* const Method)(A...)>
158 return
Delegate(method_caller<C, Method>, &object);
163 template <
class C, R(C::* const Method)(A...) const>
165 return
Delegate(const_method_caller<C, Method>,
166 const_cast<C*>(&object));
178 typename =
typename std::enable_if<
179 !std::is_same<Delegate, typename std::decay<T>::type>::value
185 typename
std::allocator_traits<Allocator>::template rebind_alloc<
186 typename
std::decay<T>::type>{ }.allocate(1),
187 store_deleter<typename std::decay<T>::type>, Allocator()) {
189 using Functor =
typename std::decay<T>::type;
190 using Rebind =
typename std::allocator_traits<Allocator>::template rebind_alloc<Functor>;
194 std::allocator_traits<Rebind>::construct(
195 rebind,
static_cast<Functor*
>(store_.get()), Functor(std::forward<T>(f)));
197 object_ptr_ = store_.get();
199 caller_ = functor_caller<Functor>;
204 template <
typename T>
206 return std::forward<T>(f);
211 Delegate(C*
const object_ptr, R(C::* const method_ptr)(A...))
216 Delegate(C*
const object_ptr, R(C::* const method_ptr)(A...) const)
221 Delegate(C&
object, R(C::* const method_ptr)(A...))
226 Delegate(C
const&
object, R(C::* const method_ptr)(A...) const)
232 R(C::* const method_ptr)(A...)) {
239 R(C::* const method_ptr)(A...) const) {
252 R(C::* const method_ptr)(A...) const) {
262 void reset() { caller_ =
nullptr; store_.reset(); }
270 bool operator == (
Delegate const& rhs)
const noexcept {
271 return (object_ptr_ == rhs.object_ptr_) && (caller_ == rhs.caller_);
275 bool operator != (
Delegate const& rhs)
const noexcept {
276 return !operator == (rhs);
280 bool operator < (
Delegate const& rhs)
const noexcept {
281 return (object_ptr_ < rhs.object_ptr_) ||
282 ((object_ptr_ == rhs.object_ptr_) && (
reinterpret_cast<const void*
>(caller_) <
reinterpret_cast<const void*
>(rhs.caller_)));
286 bool operator == (std::nullptr_t
const)
const noexcept {
287 return caller_ ==
nullptr;
291 bool operator != (std::nullptr_t
const)
const noexcept {
292 return caller_ !=
nullptr;
296 explicit operator bool () const noexcept {
return caller_ !=
nullptr; }
300 R operator () (A... args)
const {
302 return caller_(object_ptr_, std::forward<A>(args) ...);
323 void* object_ptr_ =
nullptr;
331 : caller_(m), object_ptr_(obj) { }
334 template <
typename T>
336 using Rebind =
typename std::allocator_traits<Allocator>::template rebind_alloc<T>;
339 std::allocator_traits<Rebind>::destroy(rebind,
static_cast<T*
>(ptr));
340 std::allocator_traits<Rebind>::deallocate(rebind,
static_cast<T*
>(ptr), 1);
347 template <R(*Function)(A...)>
349 return Function(std::forward<A>(args) ...);
354 return (*
reinterpret_cast<R(*const*)(A...)
>(&object_ptr))(args...);
358 template <
class C, R(C::* method_ptr)(A...)>
359 static R method_caller(void* const object_ptr, A&& ... args) {
360 return (
static_cast<C*
>(object_ptr)->*method_ptr)(
361 std::forward<A>(args) ...);
365 template <
class C, R(C::* method_ptr)(A...) const>
366 static R const_method_caller(void* const object_ptr, A&& ... args) {
367 return (
static_cast<C const*
>(object_ptr)->*method_ptr)(
368 std::forward<A>(args) ...);
380 std::pair<C*
const, R(C::* const)(A...)>;
386 std::pair<C
const*
const, R(C::* const)(A...) const>;
390 struct IsMemberPair : std::false_type { };
394 struct IsMemberPair<MemberPair<C> >: std::true_type { };
398 struct IsConstMemberPair : std::false_type { };
405 template <
typename T>
406 static typename std::enable_if<
407 !(IsMemberPair<T>::value || IsConstMemberPair<T>::value), R
410 return (*
static_cast<T*
>(object_ptr))(std::forward<A>(args) ...);
414 template <
typename T>
415 static typename std::enable_if<
416 (IsMemberPair<T>::value || IsConstMemberPair<T>::value), R
419 return (
static_cast<T*
>(object_ptr)->first->*
420 static_cast<T*
>(object_ptr)->second)(std::forward<A>(args) ...);
427template <
typename T,
typename Allocator = std::allocator<
void> >
431template <
class C,
typename R,
typename... A>
434 C*
const object_ptr, R(C::* const method_ptr)(A...)) noexcept {
435 return
Delegate<R(A...)>::template make<C>(object_ptr, method_ptr);
439template <
class C,
typename R,
typename... A>
440inline Delegate<R(A...)>
442 C*
const object_ptr, R(C::* const method_ptr)(A...) const) noexcept {
443 return Delegate<R(A...)>::template make<C>(object_ptr, method_ptr);
447template <
class C,
typename R,
typename... A>
448inline Delegate<R(A...)>
450 C& object_ptr, R(C::* const method_ptr)(A...)) noexcept {
451 return
Delegate<R(A...)>::template make<C>(object_ptr, method_ptr);
455template <
class C,
typename R,
typename... A>
456inline Delegate<R(A...)>
458 C
const& object_ptr, R(C::* const method_ptr)(A...) const) noexcept {
459 return
Delegate<R(A...)>::template make<C>(object_ptr, method_ptr);
Delegate(const Delegate &)=default
copy constructor
Delegate(Delegate &&)=default
move constructor
static R function_caller(void *const, A &&... args)
caller for an immediate function with no object or pointer.
Delegate()=default
default constructor
Delegate(T &&f)
constructor from any functor object T, which may be a lambda with capture or a MemberPair or ConstMem...
Delegate(R(*const function_ptr)(A...)) noexcept
constructor from a plain function pointer with no object.
static std::enable_if<(IsMemberPair< T >::value||IsConstMemberPair< T >::value), R >::type functor_caller(void *const object_ptr, A &&... args)
function caller for const functor class.
std::shared_ptr< void > store_
shared_ptr used to contain a memory object containing the callable, like lambdas with closures,...
static Delegate make(R(*const function_ptr)(A...)) noexcept
construction from a plain function pointer with no object.
Delegate(C &object, R(C::*const method_ptr)(A...))
constructor for wrapping a class::method with object reference.
static Delegate make(T &&f)
constructor from any functor object T, which may be a lambda with capture or a MemberPair or ConstMem...
Delegate(C *const object_ptr, R(C::*const method_ptr)(A...))
constructor for wrapping a class::method with object pointer.
R(*)(void *, A &&...) Caller
type of the function caller pointer.
Delegate(const Caller &m, void *const obj) noexcept
private constructor for plain
static void store_deleter(void *const ptr)
deleter for stored functor closures
static Delegate make(C *const object_ptr, R(C::*const method_ptr)(A...))
constructor for wrapping a class::method with object pointer.
static Delegate make() noexcept
construction from an immediate function with no object or pointer.
static Delegate make(C &object, R(C::*const method_ptr)(A...))
constructor for wrapping a class::method with object reference.
void reset()
reset delegate to invalid.
std::pair< C const *const, R(C::*const)(A...) const > ConstMemberPair
wrappers for indirect const class::method calls containing (object, const method_ptr)
void swap(Delegate &other) noexcept
swap delegates
void reset_caller() noexcept
Delegate(C const &object, R(C::*const method_ptr)(A...) const)
constructor for wrapping a const class::method with object reference.
std::pair< C *const, R(C::*const)(A...)> MemberPair
wrappers for indirect class::method calls containing (object, method_ptr)
static std::enable_if<!(IsMemberPair< T >::value||IsConstMemberPair< T >::value), R >::type functor_caller(void *const object_ptr, A &&... args)
function caller for functor class.
static Delegate make(C const *const object_ptr, R(C::*const method_ptr)(A...) const)
constructor for wrapping a const class::method with object pointer.
static R function_ptr_caller(void *const object_ptr, A &&... args)
caller for a plain function pointer.
static Delegate make(C const &object, R(C::*const method_ptr)(A...) const)
constructor for wrapping a const class::method with object reference.
Delegate(C *const object_ptr, R(C::*const method_ptr)(A...) const)
constructor for wrapping a const class::method with object pointer.
Delegate< R(A...)> make_delegate(C *const object_ptr, R(C::*const method_ptr)(A...)) noexcept
constructor for wrapping a class::method with object pointer.