20 #ifndef _UTIL_DELEGATE_H_
21 #define _UTIL_DELEGATE_H_
26 #include <type_traits>
37 template <
class R,
class... A>
class delegate<R(A...)> {
38 using stub_ptr_type = R (*)(
void*, A&&...);
40 delegate(
void*
const o, stub_ptr_type
const m) noexcept
51 delegate(::std::nullptr_t
const) noexcept
54 template <
class C,
typename =
typename ::std::enable_if<::std::is_
class<C>{}>::type>
55 explicit delegate(C
const*
const o) noexcept
56 : object_ptr_(
const_cast<C*
>(o)) {}
58 template <
class C,
typename =
typename ::std::enable_if<::std::is_
class<C>{}>::type>
59 explicit delegate(C
const& o) noexcept
60 : object_ptr_(
const_cast<C*
>(&o)) {}
62 template <
class C>
delegate(C*
const object_ptr, R (C::*
const method_ptr)(A...)) { *
this = from(object_ptr, method_ptr); }
64 template <
class C>
delegate(C*
const object_ptr, R (C::*
const method_ptr)(A...)
const) { *
this = from(object_ptr, method_ptr); }
66 template <
class C>
delegate(C&
object, R (C::*
const method_ptr)(A...)) { *
this = from(
object, method_ptr); }
68 template <
class C>
delegate(C
const&
object, R (C::*
const method_ptr)(A...)
const) { *
this = from(
object, method_ptr); }
70 template <typename T, typename = typename ::std::enable_if<!::std::is_same<delegate, typename ::std::decay<T>::type>{}>::type>
72 : store_(
operator new(
sizeof(typename ::std::decay<T>::type)), functor_deleter<typename ::std::decay<T>::type>)
73 , store_size_(
sizeof(typename ::std::decay<T>::type)) {
74 using functor_type = typename ::std::decay<T>::type;
76 new(store_.get()) functor_type(::std::forward<T>(f));
78 object_ptr_ = store_.get();
80 stub_ptr_ = functor_stub<functor_type>;
82 deleter_ = deleter_stub<functor_type>;
89 template <
class C>
delegate& operator=(R (C::*
const rhs)(A...)) {
return *
this = from(
static_cast<C*
>(object_ptr_), rhs); }
91 template <
class C>
delegate& operator=(R (C::*
const rhs)(A...)
const) {
return *
this = from(
static_cast<C const*
>(object_ptr_), rhs); }
93 template <typename T, typename = typename ::std::enable_if<!::std::is_same<delegate, typename ::std::decay<T>::type>{}>::type>
95 using functor_type = typename ::std::decay<T>::type;
97 if((
sizeof(functor_type) > store_size_) || !store_.unique()) {
98 store_.reset(
operator new(
sizeof(functor_type)), functor_deleter<functor_type>);
100 store_size_ =
sizeof(functor_type);
102 deleter_(store_.get());
105 new(store_.get()) functor_type(::std::forward<T>(f));
107 object_ptr_ = store_.get();
109 stub_ptr_ = functor_stub<functor_type>;
111 deleter_ = deleter_stub<functor_type>;
116 template <R (*
const function_ptr)(A...)>
static delegate from() noexcept {
return {
nullptr, function_stub<function_ptr>}; }
118 template <
class C, R (C::*
const method_ptr)(A...)>
static delegate from(C*
const object_ptr) noexcept {
119 return {object_ptr, method_stub<C, method_ptr>};
122 template <
class C, R (C::*
const method_ptr)(A...)
const>
static delegate from(C
const*
const object_ptr) noexcept {
123 return {
const_cast<C*
>(object_ptr), const_method_stub<C, method_ptr>};
126 template <
class C, R (C::*
const method_ptr)(A...)>
static delegate from(C&
object) noexcept {
127 return {&object, method_stub<C, method_ptr>};
130 template <
class C, R (C::*
const method_ptr)(A...)
const>
static delegate from(C
const&
object) noexcept {
131 return {
const_cast<C*
>(&object), const_method_stub<C, method_ptr>};
134 template <
typename T>
static delegate from(T&& f) { return ::std::forward<T>(f); }
136 static delegate from(R (*
const function_ptr)(A...)) {
return function_ptr; }
138 template <
class C>
using member_pair = ::std::pair<C*
const, R (C::*
const)(A...)>;
140 template <
class C>
using const_member_pair = ::std::pair<C
const*
const, R (C::*
const)(A...)
const>;
142 template <
class C>
static delegate from(C*
const object_ptr, R (C::*
const method_ptr)(A...)) {
143 return member_pair<C>(object_ptr, method_ptr);
146 template <
class C>
static delegate from(C
const*
const object_ptr, R (C::*
const method_ptr)(A...)
const) {
147 return const_member_pair<C>(object_ptr, method_ptr);
150 template <
class C>
static delegate from(C&
object, R (C::*
const method_ptr)(A...)) {
return member_pair<C>(&
object, method_ptr); }
152 template <
class C>
static delegate from(C
const&
object, R (C::*
const method_ptr)(A...)
const) {
153 return const_member_pair<C>(&
object, method_ptr);
161 void reset_stub() noexcept { stub_ptr_ =
nullptr; }
163 void swap(
delegate& other) noexcept { ::std::swap(*
this, other); }
165 bool operator==(
delegate const& rhs)
const noexcept {
return (object_ptr_ == rhs.object_ptr_) && (stub_ptr_ == rhs.stub_ptr_); }
167 bool operator!=(
delegate const& rhs)
const noexcept {
return !operator==(rhs); }
169 bool operator<(
delegate const& rhs)
const noexcept {
170 return (object_ptr_ < rhs.object_ptr_) || ((object_ptr_ == rhs.object_ptr_) && (stub_ptr_ < rhs.stub_ptr_));
173 bool operator==(::std::nullptr_t
const)
const noexcept {
return !stub_ptr_; }
175 bool operator!=(::std::nullptr_t
const)
const noexcept {
return stub_ptr_; }
177 explicit operator bool()
const noexcept {
return stub_ptr_; }
179 R operator()(A... args)
const {
181 return stub_ptr_(object_ptr_, ::std::forward<A>(args)...);
185 friend class ::std::hash<delegate>;
187 using deleter_type = void (*)(
void*);
190 stub_ptr_type stub_ptr_{};
192 deleter_type deleter_{};
194 ::std::shared_ptr<void> store_;
195 ::std::size_t store_size_{0};
197 template <
class T>
static void functor_deleter(
void*
const p) {
198 static_cast<T*
>(p)->~T();
203 template <
class T>
static void deleter_stub(
void*
const p) {
static_cast<T*
>(p)->~T(); }
205 template <R (*function_ptr)(A...)>
static R function_stub(
void*
const, A&&... args) {
return function_ptr(::std::forward<A>(args)...); }
207 template <
class C, R (C::*method_ptr)(A...)>
static R method_stub(
void*
const object_ptr, A&&... args) {
208 return (
static_cast<C*
>(object_ptr)->*method_ptr)(::std::forward<A>(args)...);
211 template <
class C, R (C::*method_ptr)(A...)
const>
static R const_method_stub(
void*
const object_ptr, A&&... args) {
212 return (
static_cast<C const*
>(object_ptr)->*method_ptr)(::std::forward<A>(args)...);
215 template <
typename>
class is_member_pair : std::false_type {};
217 template <
class C>
class is_member_pair<::std::pair<C* const, R (C::*const)(A...)>> : std::true_type {};
219 template <
typename>
class is_const_member_pair : std::false_type {};
221 template <
class C>
class is_const_member_pair<::std::pair<C const* const, R (C::*const)(A...) const>> : std::true_type {};
223 template <
typename T>
224 static typename ::std::enable_if<!(is_member_pair<T>{} || is_const_member_pair<T>{}), R>::type functor_stub(
void*
const object_ptr,
226 return (*
static_cast<T*
>(object_ptr))(::std::forward<A>(args)...);
229 template <
typename T>
230 static typename ::std::enable_if<is_member_pair<T>{} || is_const_member_pair<T>{}, R>::type functor_stub(
void*
const object_ptr,
232 return (
static_cast<T*
>(object_ptr)->first->*
static_cast<T*
>(object_ptr)->second)(::std::forward<A>(args)...);
240 template <
typename R,
typename... A>
class hash<
util::delegate<R(A...)>> {
242 size_t operator()(
util::delegate<R(A...)>
const& d)
const noexcept {
243 auto const seed(hash<void*>()(d.object_ptr_));
245 return hash<
typename util::delegate<R(A...)>::stub_ptr_type>()(d.stub_ptr_) + 0x9e3779b9 + (seed << 6) + (seed >> 2);