1 #ifndef ENTT_SIGNAL_DELEGATE_HPP 2 #define ENTT_SIGNAL_DELEGATE_HPP 10 #include <type_traits> 11 #include "../config/config.h" 26 template<
typename Ret,
typename... Args>
27 auto to_function_pointer(Ret(*)(Args...)) -> Ret(*)(Args...);
30 template<
typename Ret,
typename... Args,
typename Type,
typename Payload,
typename = std::enable_if_t<std::is_convertible_v<const Payload *, const Type *>>>
31 auto to_function_pointer(Ret(*)(Type &, Args...),
const Payload *) -> Ret(*)(Args...);
34 template<
typename Ret,
typename... Args,
typename Type,
typename Payload,
typename = std::enable_if_t<std::is_convertible_v<const Payload *, const Type *>>>
35 auto to_function_pointer(Ret(*)(Type *, Args...),
const Payload *) -> Ret(*)(Args...);
38 template<
typename Class,
typename Ret,
typename... Args>
39 auto to_function_pointer(Ret(Class:: *)(Args...),
const Class *) -> Ret(*)(Args...);
42 template<
typename Class,
typename Ret,
typename... Args>
43 auto to_function_pointer(Ret(Class:: *)(Args...)
const,
const Class *) -> Ret(*)(Args...);
46 template<
typename Class,
typename Type>
47 auto to_function_pointer(Type Class:: *,
const Class *) -> Type(*)();
50 template<
typename... Type>
51 using to_function_pointer_t = decltype(internal::to_function_pointer(std::declval<Type>()...));
54 template<
typename Ret,
typename... Args>
55 constexpr
auto index_sequence_for(Ret(*)(Args...)) {
56 return std::index_sequence_for<Args...>{};
102 template<
typename Ret,
typename... Args>
104 using proto_fn_type = Ret(
const void *, std::tuple<Args &&...>);
106 template<
auto Function, std::size_t... Index>
107 void connect(std::index_sequence<Index...>) ENTT_NOEXCEPT {
108 static_assert(std::is_invocable_r_v<Ret, decltype(Function), std::tuple_element_t<Index, std::tuple<Args...>>...>);
111 fn = [](
const void *, std::tuple<Args &&...> args) -> Ret {
113 return Ret(std::invoke(Function, std::forward<std::tuple_element_t<Index, std::tuple<Args...>>>(std::get<Index>(args))...));
117 template<
auto Candidate,
typename Type, std::size_t... Index>
118 void connect(Type &value_or_instance, std::index_sequence<Index...>) ENTT_NOEXCEPT {
119 static_assert(std::is_invocable_r_v<Ret, decltype(Candidate), Type &, std::tuple_element_t<Index, std::tuple<Args...>>...>);
120 data = &value_or_instance;
122 fn = [](
const void *payload, std::tuple<Args &&...> args) -> Ret {
123 Type *curr =
static_cast<Type *
>(
const_cast<std::conditional_t<std::is_const_v<Type>,
const void *,
void *
>>(payload));
125 return Ret(std::invoke(Candidate, *curr, std::forward<std::tuple_element_t<Index, std::tuple<Args...>>>(std::get<Index>(args))...));
129 template<
auto Candidate,
typename Type, std::size_t... Index>
130 void connect(Type *value_or_instance, std::index_sequence<Index...>) ENTT_NOEXCEPT {
131 static_assert(std::is_invocable_r_v<Ret, decltype(Candidate), Type *, std::tuple_element_t<Index, std::tuple<Args...>>...>);
132 data = value_or_instance;
134 fn = [](
const void *payload, std::tuple<Args &&...> args) -> Ret {
135 Type *curr =
static_cast<Type *
>(
const_cast<std::conditional_t<std::is_const_v<Type>,
const void *,
void *
>>(payload));
137 return Ret(std::invoke(Candidate, curr, std::forward<std::tuple_element_t<Index, std::tuple<Args...>>>(std::get<Index>(args))...));
147 : fn{
nullptr}, data{
nullptr}
154 template<auto Function>
168 template<auto Cand
idate,
typename Type>
172 connect<Candidate>(value_or_instance);
182 template<auto Cand
idate,
typename Type>
186 connect<Candidate>(value_or_instance);
193 template<auto Function>
195 connect<Function>(internal::index_sequence_for(internal::to_function_pointer_t<decltype(Function)>{}));
213 template<auto Cand
idate,
typename Type>
214 void connect(Type &value_or_instance) ENTT_NOEXCEPT {
215 connect<Candidate>(value_or_instance, internal::index_sequence_for(internal::to_function_pointer_t<decltype(Candidate), Type *>{}));
233 template<auto Cand
idate,
typename Type>
234 void connect(Type *value_or_instance) ENTT_NOEXCEPT {
235 connect<Candidate>(value_or_instance, internal::index_sequence_for(internal::to_function_pointer_t<decltype(Candidate), Type *>{}));
272 return fn(data, std::forward_as_tuple(std::forward<Args>(args)...));
279 explicit operator bool() const ENTT_NOEXCEPT {
290 return fn == other.fn && data == other.data;
307 template<
typename Ret,
typename... Args>
309 return !(lhs == rhs);
321 template<auto Function>
335 template<auto Cand
idate,
typename Type>
349 template<auto Cand
idate,
typename Type>
357 #endif // ENTT_SIGNAL_DELEGATE_HPP delegate(connect_arg_t< Function >) ENTT_NOEXCEPT -> delegate< std::remove_pointer_t< internal::to_function_pointer_t< decltype(Function)>>>
Deduction guide.
delegate(connect_arg_t< Candidate >, Type &value_or_instance) ENTT_NOEXCEPT
Constructs a delegate and connects a member for a given instance or a free function with payload...
constexpr connect_arg_t< Func > connect_arg
Constant of type connect_arg_t used to disambiguate calls.
Used to wrap a function or a member of a specified type.
constexpr bool operator!=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) ENTT_NOEXCEPT
Compares two hashed strings.
void connect() ENTT_NOEXCEPT
Connects a free function to a delegate.
void connect(Type *value_or_instance) ENTT_NOEXCEPT
Connects a member function for a given instance or a free function with payload to a delegate...
Basic delegate implementation.
void connect(Type &value_or_instance) ENTT_NOEXCEPT
Connects a member function for a given instance or a free function with payload to a delegate...
const void * instance() const ENTT_NOEXCEPT
Returns the instance or the payload linked to a delegate, if any.
Ret operator()(Args... args) const
Triggers a delegate.
Ret(Args...) function_type
Function type of the delegate.
void reset() ENTT_NOEXCEPT
Resets a delegate.
delegate(connect_arg_t< Function >) ENTT_NOEXCEPT
Constructs a delegate and connects a free function to it.
delegate(connect_arg_t< Candidate >, Type *value_or_instance) ENTT_NOEXCEPT
Constructs a delegate and connects a member for a given instance or a free function with payload...
delegate() ENTT_NOEXCEPT
Default constructor.
bool operator==(const delegate< Ret(Args...)> &other) const ENTT_NOEXCEPT
Compares the contents of two delegates.