1 #ifndef ENTT_SIGNAL_DELEGATE_HPP
2 #define ENTT_SIGNAL_DELEGATE_HPP
10 #include "../config/config.h"
25 template<
typename Ret,
typename... Args>
26 auto function_pointer(Ret(*)(Args...)) -> Ret(*)(Args...);
29 template<
typename Ret,
typename Type,
typename... Args,
typename Other>
30 auto function_pointer(Ret(*)(Type, Args...), Other &&) -> Ret(*)(Args...);
33 template<
typename Class,
typename Ret,
typename... Args,
typename... Other>
34 auto function_pointer(Ret(Class:: *)(Args...), Other &&...) -> Ret(*)(Args...);
37 template<
typename Class,
typename Ret,
typename... Args,
typename... Other>
38 auto function_pointer(Ret(Class:: *)(Args...)
const, Other &&...) -> Ret(*)(Args...);
41 template<
typename Class,
typename Type,
typename... Other>
42 auto function_pointer(Type Class:: *, Other &&...) -> Type(*)();
45 template<
typename... Type>
46 using function_pointer_t = decltype(internal::function_pointer(std::declval<Type>()...));
49 template<
typename... Class,
typename Ret,
typename... Args>
50 [[nodiscard]] constexpr
auto index_sequence_for(Ret(*)(Args...)) {
51 return std::index_sequence_for<Class..., Args...>{};
96 template<
typename Ret,
typename... Args>
98 template<
auto Candidate, std::size_t... Index>
99 [[nodiscard]]
auto wrap(std::index_sequence<Index...>) ENTT_NOEXCEPT {
100 return [](
const void *, Args... args) -> Ret {
101 [[maybe_unused]]
const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
102 return Ret(std::invoke(Candidate, std::forward<std::tuple_element_t<Index, std::tuple<Args...>>>(std::get<Index>(arguments))...));
106 template<
auto Candidate,
typename Type, std::size_t... Index>
107 [[nodiscard]]
auto wrap(Type &, std::index_sequence<Index...>) ENTT_NOEXCEPT {
108 return [](
const void *payload, Args... args) -> Ret {
109 [[maybe_unused]]
const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
110 Type *curr =
static_cast<Type *
>(
const_cast<std::conditional_t<std::is_const_v<Type>,
const void *,
void *
>>(payload));
111 return Ret(std::invoke(Candidate, *curr, std::forward<std::tuple_element_t<Index, std::tuple<Args...>>>(std::get<Index>(arguments))...));
115 template<
auto Candidate,
typename Type, std::size_t... Index>
116 [[nodiscard]]
auto wrap(Type *, std::index_sequence<Index...>) ENTT_NOEXCEPT {
117 return [](
const void *payload, Args... args) -> Ret {
118 [[maybe_unused]]
const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...);
119 Type *curr =
static_cast<Type *
>(
const_cast<std::conditional_t<std::is_const_v<Type>,
const void *,
void *
>>(payload));
120 return Ret(std::invoke(Candidate, curr, std::forward<std::tuple_element_t<Index, std::tuple<Args...>>>(std::get<Index>(arguments))...));
134 : fn{
nullptr}, data{
nullptr}
142 template<auto Cand
idate>
144 connect<Candidate>();
154 template<auto Cand
idate,
typename Type>
156 connect<Candidate>(std::forward<Type>(value_or_instance));
166 connect(
function, payload);
173 template<auto Cand
idate>
177 if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Args...>) {
178 fn = [](
const void *, Args... args) -> Ret {
179 return Ret(std::invoke(Candidate, std::forward<Args>(args)...));
181 }
else if constexpr(std::is_member_pointer_v<decltype(Candidate)>) {
182 fn = wrap<Candidate>(internal::index_sequence_for<std::tuple_element_t<0, std::tuple<Args...>>>(internal::function_pointer_t<decltype(Candidate)>{}));
184 fn = wrap<Candidate>(internal::index_sequence_for(internal::function_pointer_t<decltype(Candidate)>{}));
203 template<auto Cand
idate,
typename Type>
204 void connect(Type &value_or_instance) ENTT_NOEXCEPT {
205 data = &value_or_instance;
207 if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Type &, Args...>) {
208 fn = [](
const void *payload, Args... args) -> Ret {
209 Type *curr =
static_cast<Type *
>(
const_cast<std::conditional_t<std::is_const_v<Type>,
const void *,
void *
>>(payload));
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>{}));
227 template<auto Cand
idate,
typename Type>
228 void connect(Type *value_or_instance) ENTT_NOEXCEPT {
229 data = value_or_instance;
231 if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Type *, Args...>) {
232 fn = [](
const void *payload, Args... args) -> Ret {
233 Type *curr =
static_cast<Type *
>(
const_cast<std::conditional_t<std::is_const_v<Type>,
const void *,
void *
>>(payload));
234 return Ret(std::invoke(Candidate, curr, std::forward<Args>(args)...));
237 fn = wrap<Candidate>(value_or_instance, internal::index_sequence_for(internal::function_pointer_t<decltype(Candidate), Type>{}));
273 [[nodiscard]]
const void *
instance() const ENTT_NOEXCEPT {
293 return fn(data, std::forward<Args>(args)...);
300 [[nodiscard]]
explicit operator bool() const ENTT_NOEXCEPT {
302 return !(fn ==
nullptr);
311 return fn == other.fn && data == other.data;
328 template<
typename Ret,
typename... Args>
330 return !(lhs == rhs);
338 template<auto Cand
idate>
340 ->
delegate<std::remove_pointer_t<internal::function_pointer_t<decltype(Candidate)>>>;
348 template<auto Cand
idate,
typename Type>
350 ->
delegate<std::remove_pointer_t<internal::function_pointer_t<decltype(Candidate), Type>>>;
354 template<typename Ret, typename... Args>
355 delegate(Ret(*)(const
void *, Args...), const
void * =
nullptr) ENTT_NOEXCEPT