1#ifndef ENTT_SIGNAL_DELEGATE_HPP
2#define ENTT_SIGNAL_DELEGATE_HPP
9#include "../config/config.h"
10#include "../core/type_traits.hpp"
18template<
typename Ret,
typename... Args>
19constexpr auto function_pointer(Ret (*)(Args...)) -> Ret (*)(Args...);
21template<
typename Ret,
typename Type,
typename... Args,
typename Other>
22constexpr auto function_pointer(Ret (*)(Type, Args...), Other &&) -> Ret (*)(Args...);
24template<
typename Class,
typename Ret,
typename... Args,
typename... Other>
25constexpr auto function_pointer(Ret (Class::*)(Args...), Other &&...) -> Ret (*)(Args...);
27template<
typename Class,
typename Ret,
typename... Args,
typename... Other>
28constexpr auto function_pointer(Ret (Class::*)(Args...) const, Other &&...) -> Ret (*)(Args...);
30template<
typename Class,
typename Type,
typename... Other>
31constexpr auto function_pointer(Type Class::*, Other &&...) -> Type (*)();
33template<
typename... Type>
34using function_pointer_t =
decltype(function_pointer(std::declval<Type>()...));
36template<
typename... Class,
typename Ret,
typename... Args>
37[[nodiscard]]
constexpr auto index_sequence_for(Ret (*)(Args...)) {
38 return std::index_sequence_for<Class..., Args...>{};
65template<
typename Ret,
typename... Args>
67 template<
auto Candidate, std::size_t... Index>
68 [[nodiscard]]
auto wrap(std::index_sequence<Index...>)
noexcept {
69 return [](
const void *, Args... args) -> Ret {
70 [[maybe_unused]]
const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
75 constexpr auto offset =
sizeof...(Args) -
sizeof...(Index);
81 template<
auto Candidate,
typename Type, std::size_t... Index>
82 [[nodiscard]]
auto wrap(Type &, std::index_sequence<Index...>)
noexcept {
83 return [](
const void *payload, Args... args) -> Ret {
84 [[maybe_unused]]
const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
90 constexpr auto offset =
sizeof...(Args) -
sizeof...(Index);
96 template<
auto Candidate,
typename Type, std::size_t... Index>
97 [[nodiscard]]
auto wrap(Type *, std::index_sequence<Index...>)
noexcept {
98 return [](
const void *payload, Args... args) -> Ret {
99 [[maybe_unused]]
const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
105 constexpr auto offset =
sizeof...(Args) -
sizeof...(Index);
130 template<
auto Candidate,
typename... Type>
132 connect<Candidate>(std::forward<Type>(value_or_instance)...);
142 connect(function, payload);
149 template<auto Cand
idate>
153 if constexpr(std::is_invocable_r_v<Ret,
decltype(Candidate), Args...>) {
154 fn = [](
const void *, Args... args) -> Ret {
155 return Ret(std::invoke(Candidate, std::forward<Args>(args)...));
157 }
else if constexpr(std::is_member_pointer_v<
decltype(Candidate)>) {
160 fn = wrap<Candidate>(internal::index_sequence_for(internal::function_pointer_t<
decltype(Candidate)>{}));
179 template<auto Cand
idate,
typename Type>
180 void connect(Type &value_or_instance)
noexcept {
181 instance = &value_or_instance;
183 if constexpr(std::is_invocable_r_v<Ret,
decltype(Candidate), Type &, Args...>) {
184 fn = [](
const void *payload, Args... args) -> Ret {
186 return Ret(std::invoke(Candidate, *curr, std::forward<Args>(args)...));
189 fn = wrap<Candidate>(value_or_instance, internal::index_sequence_for(internal::function_pointer_t<
decltype(Candidate), Type>{}));
203 template<auto Cand
idate,
typename Type>
204 void connect(Type *value_or_instance)
noexcept {
205 instance = value_or_instance;
207 if constexpr(std::is_invocable_r_v<Ret,
decltype(Candidate), Type *, Args...>) {
208 fn = [](
const void *payload, Args... args) -> Ret {
210 return Ret(std::invoke(Candidate, curr, std::forward<Args>(args)...));
213 fn = wrap<Candidate>(value_or_instance, internal::index_sequence_for(internal::function_pointer_t<
decltype(Candidate), Type>{}));
231 ENTT_ASSERT(function !=
nullptr,
"Uninitialized function pointer");
258 [[nodiscard]]
const void *
data() const noexcept {
275 ENTT_ASSERT(
static_cast<bool>(*
this),
"Uninitialized delegate");
276 return fn(instance, std::forward<Args>(args)...);
283 [[nodiscard]]
explicit operator bool() const noexcept {
285 return !(fn ==
nullptr);
294 return fn == other.fn && instance == other.instance;
298 const void *instance;
310template<
typename Ret,
typename... Args>
312 return !(lhs == rhs);
319template<auto Cand
idate>
327template<auto Cand
idate,
typename Type>
335template<
typename Ret,
typename... Args>
bool operator==(const delegate< Ret(Args...)> &other) const noexcept
Compares the contents of two delegates.
Ret operator()(Args... args) const
Triggers a delegate.
void reset() noexcept
Resets a delegate.
Ret(const void *, Args...) function_type
Function type of the contained target.
delegate() noexcept
Default constructor.
delegate(function_type *function, const void *payload=nullptr) noexcept
Constructs a delegate and connects an user defined function with optional payload.
void connect(Type &value_or_instance) noexcept
Connects a free function with payload or a bound member to a delegate.
delegate(connect_arg_t< Candidate >, Type &&...value_or_instance) noexcept
Constructs a delegate with a given object or payload, if any.
void connect(Type *value_or_instance) noexcept
Connects a free function with payload or a bound member to a delegate.
void connect() noexcept
Connects a free function or an unbound member to a delegate.
Ret result_type
Return type of the delegate.
const void * data() const noexcept
Returns the instance or the payload linked to a delegate, if any.
void connect(function_type *function, const void *payload=nullptr) noexcept
Connects an user defined function with optional payload to a delegate.
function_type * target() const noexcept
Returns a pointer to the stored callable function target, if any.
Ret(Args...) type
Function type of the delegate.
Basic delegate implementation.
typename constness_as< To, From >::type constness_as_t
Alias template to facilitate the transcription of the constness.
typename type_list_element< Index, List >::type type_list_element_t
Helper type.
constexpr bool operator!=(const basic_hashed_string< Char > &lhs, const basic_hashed_string< Char > &rhs) noexcept
Compares two hashed strings.
Disambiguation tag for constructors and the like.
A class to use to push around lists of types, nothing more.