1 #ifndef ENTT_SIGNAL_DELEGATE_HPP
2 #define ENTT_SIGNAL_DELEGATE_HPP
9 #include "../config/config.h"
10 #include "../core/type_traits.hpp"
22 template<
typename Ret,
typename... Args>
23 auto function_pointer(Ret (*)(Args...)) -> Ret (*)(Args...);
25 template<
typename Ret,
typename Type,
typename... Args,
typename Other>
26 auto function_pointer(Ret (*)(Type, Args...), Other &&) -> Ret (*)(Args...);
28 template<
typename Class,
typename Ret,
typename... Args,
typename... Other>
29 auto function_pointer(Ret (Class::*)(Args...), Other &&...) -> Ret (*)(Args...);
31 template<
typename Class,
typename Ret,
typename... Args,
typename... Other>
32 auto function_pointer(Ret (Class::*)(Args...)
const, Other &&...) -> Ret (*)(Args...);
34 template<
typename Class,
typename Type,
typename... Other>
35 auto function_pointer(Type Class::*, Other &&...) -> Type (*)();
37 template<
typename... Type>
38 using function_pointer_t = decltype(internal::function_pointer(std::declval<Type>()...));
40 template<
typename... Class,
typename Ret,
typename... Args>
41 [[nodiscard]] constexpr
auto index_sequence_for(Ret (*)(Args...)) {
42 return std::index_sequence_for<Class..., Args...>{};
81 template<
typename Ret,
typename... Args>
83 template<
auto Candidate, std::size_t... Index>
84 [[nodiscard]]
auto wrap(std::index_sequence<Index...>) ENTT_NOEXCEPT {
85 return [](
const void *, Args... args) -> Ret {
86 [[maybe_unused]]
const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
91 template<
auto Candidate,
typename Type, std::size_t... Index>
92 [[nodiscard]]
auto wrap(Type &, std::index_sequence<Index...>) ENTT_NOEXCEPT {
93 return [](
const void *payload, Args... args) -> Ret {
94 [[maybe_unused]]
const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
100 template<
auto Candidate,
typename Type, std::size_t... Index>
101 [[nodiscard]]
auto wrap(Type *, std::index_sequence<Index...>) ENTT_NOEXCEPT {
102 return [](
const void *payload, Args... args) -> Ret {
103 [[maybe_unused]]
const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
127 template<auto Cand
idate>
129 connect<Candidate>();
139 template<auto Cand
idate,
typename Type>
141 connect<Candidate>(std::forward<Type>(value_or_instance));
151 connect(
function, payload);
158 template<auto Cand
idate>
162 if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Args...>) {
163 fn = [](
const void *, Args... args) -> Ret {
164 return Ret(std::invoke(Candidate, std::forward<Args>(args)...));
166 }
else if constexpr(std::is_member_pointer_v<decltype(Candidate)>) {
169 fn = wrap<Candidate>(internal::index_sequence_for(internal::function_pointer_t<decltype(Candidate)>{}));
188 template<auto Cand
idate,
typename Type>
189 void connect(Type &value_or_instance) ENTT_NOEXCEPT {
190 instance = &value_or_instance;
192 if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Type &, Args...>) {
193 fn = [](
const void *payload, Args... args) -> Ret {
195 return Ret(std::invoke(Candidate, *curr, std::forward<Args>(args)...));
198 fn = wrap<Candidate>(value_or_instance, internal::index_sequence_for(internal::function_pointer_t<decltype(Candidate), Type>{}));
212 template<auto Cand
idate,
typename Type>
213 void connect(Type *value_or_instance) ENTT_NOEXCEPT {
214 instance = value_or_instance;
216 if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Type *, Args...>) {
217 fn = [](
const void *payload, Args... args) -> Ret {
219 return Ret(std::invoke(Candidate, curr, std::forward<Args>(args)...));
222 fn = wrap<Candidate>(value_or_instance, internal::index_sequence_for(internal::function_pointer_t<decltype(Candidate), Type>{}));
258 [[nodiscard]]
const void *
data() const ENTT_NOEXCEPT {
275 ENTT_ASSERT(
static_cast<bool>(*
this),
"Uninitialized delegate");
276 return fn(instance, std::forward<Args>(args)...);
283 [[nodiscard]]
explicit operator bool() const ENTT_NOEXCEPT {
285 return !(fn ==
nullptr);
294 return fn == other.fn && instance == other.instance;
298 const void *instance;
310 template<
typename Ret,
typename... Args>
312 return !(lhs == rhs);
319 template<auto Cand
idate>
327 template<auto Cand
idate,
typename Type>
335 template<
typename Ret,
typename... Args>
336 delegate(Ret (*)(
const void *, Args...),
const void * =
nullptr) ->
delegate<Ret(Args...)>;
Ret operator()(Args... args) const
Triggers a delegate.
Ret(const void *, Args...) function_type
Function type of the contained target.
void reset()
Resets a delegate.
delegate()
Default constructor.
delegate(connect_arg_t< Candidate >)
Constructs a delegate and connects a free function or an unbound member.
void connect(function_type *function, const void *payload=nullptr)
Connects an user defined function with optional payload to a delegate.
delegate(connect_arg_t< Candidate >, Type &&value_or_instance)
Constructs a delegate and connects a free function with payload or a bound member.
Ret result_type
Return type of the delegate.
void connect(Type *value_or_instance)
Connects a free function with payload or a bound member to a delegate.
bool operator==(const delegate< Ret(Args...)> &other) const
Compares the contents of two delegates.
const void * data() const
Returns the instance or the payload linked to a delegate, if any.
void connect()
Connects a free function or an unbound member to a delegate.
Ret(Args...) type
Function type of the delegate.
delegate(function_type *function, const void *payload=nullptr)
Constructs a delegate and connects an user defined function with optional payload.
void connect(Type &value_or_instance)
Connects a free function with payload or a bound member to a delegate.
Basic delegate implementation.
typename constness_as< To, From >::type constness_as_t
Alias template to facilitate the transcription of the constness.
delegate(connect_arg_t< Candidate >) -> delegate< std::remove_pointer_t< internal::function_pointer_t< decltype(Candidate)>>>
Deduction guide.
typename type_list_element< Index, List >::type type_list_element_t
Helper type.
bool operator!=(const basic_any< Len, Align > &lhs, const basic_any< Len, Align > &rhs)
Checks if two wrappers differ in their content.
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.
A class to use to push around lists of types, nothing more.