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<Payload &, Type &>>>
31 auto to_function_pointer(Ret(*)(Type &, Args...), Payload &) -> Ret(*)(Args...);
34 template<
typename Class,
typename Ret,
typename... Args>
35 auto to_function_pointer(Ret(Class:: *)(Args...),
const Class &) -> Ret(*)(Args...);
38 template<
typename Class,
typename Ret,
typename... Args>
39 auto to_function_pointer(Ret(Class:: *)(Args...)
const,
const Class &) -> Ret(*)(Args...);
42 template<
typename Class,
typename Type>
43 auto to_function_pointer(Type Class:: *,
const Class &) -> Type(*)();
47 struct function_extent;
50 template<
typename Ret,
typename... Args>
51 struct function_extent<Ret(*)(Args...)> {
52 static constexpr
auto value =
sizeof...(Args);
56 template<
typename Func>
57 constexpr
auto function_extent_v = function_extent<Func>::value;
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 =
nullptr;
125 if constexpr(std::is_const_v<Type>) {
126 curr =
static_cast<Type *
>(payload);
128 curr =
static_cast<Type *
>(
const_cast<void *
>(payload));
132 return Ret(std::invoke(Candidate, *curr, std::forward<std::tuple_element_t<Index, std::tuple<Args...>>>(std::get<Index>(args))...));
142 : fn{
nullptr}, data{
nullptr}
149 template<auto Function>
163 template<auto Cand
idate,
typename Type>
167 connect<Candidate>(value_or_instance);
174 template<auto Function>
176 constexpr
auto extent = internal::function_extent_v<decltype(internal::to_function_pointer(std::declval<decltype(Function)>()))>;
177 connect<Function>(std::make_index_sequence<extent>{});
195 template<auto Cand
idate,
typename Type>
196 void connect(Type &value_or_instance) ENTT_NOEXCEPT {
197 constexpr
auto extent = internal::function_extent_v<decltype(internal::to_function_pointer(std::declval<decltype(Candidate)>(), value_or_instance))>;
198 connect<Candidate>(value_or_instance, std::make_index_sequence<extent>{});
235 return fn(data, std::forward_as_tuple(std::forward<Args>(args)...));
242 explicit operator bool() const ENTT_NOEXCEPT {
253 return fn == other.fn && data == other.data;
270 template<
typename Ret,
typename... Args>
272 return !(lhs == rhs);
284 template<auto Function>
299 template<auto Cand
idate,
typename Type>
307 #endif // ENTT_SIGNAL_DELEGATE_HPP 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.
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< Function >) ENTT_NOEXCEPT -> delegate< std::remove_pointer_t< decltype(internal::to_function_pointer(Function))>>
Deduction guide.
delegate() ENTT_NOEXCEPT
Default constructor.
bool operator==(const delegate< Ret(Args...)> &other) const ENTT_NOEXCEPT
Compares the contents of two delegates.