|
|
@@ -25,16 +25,16 @@ template<typename Ret, typename... Args>
|
|
|
auto to_function_pointer(Ret(*)(Args...)) -> Ret(*)(Args...);
|
|
|
|
|
|
|
|
|
-template<typename Class, typename Ret, typename... Args>
|
|
|
-auto to_function_pointer(Ret(Class:: *)(Args...)) -> Ret(*)(Args...);
|
|
|
+template<typename Ret, typename... Args, typename Type, typename Value>
|
|
|
+auto to_function_pointer(Ret(*)(Type, Args...), Value) -> Ret(*)(Args...);
|
|
|
|
|
|
|
|
|
template<typename Class, typename Ret, typename... Args>
|
|
|
-auto to_function_pointer(Ret(Class:: *)(Args...) const) -> Ret(*)(Args...);
|
|
|
+auto to_function_pointer(Ret(Class:: *)(Args...), Class *) -> Ret(*)(Args...);
|
|
|
|
|
|
|
|
|
-template<auto Func>
|
|
|
-using function_type = std::remove_pointer_t<decltype(to_function_pointer(Func))>;
|
|
|
+template<typename Class, typename Ret, typename... Args>
|
|
|
+auto to_function_pointer(Ret(Class:: *)(Args...) const, Class *) -> Ret(*)(Args...);
|
|
|
|
|
|
|
|
|
}
|
|
|
@@ -80,7 +80,7 @@ class delegate;
|
|
|
* @tparam Args Types of arguments of a function type.
|
|
|
*/
|
|
|
template<typename Ret, typename... Args>
|
|
|
-class delegate<Ret(Args...)> final {
|
|
|
+class delegate<Ret(Args...)> {
|
|
|
using storage_type = std::aligned_storage_t<sizeof(void *), alignof(void *)>;
|
|
|
using proto_fn_type = Ret(storage_type &, Args...);
|
|
|
|
|
|
@@ -107,16 +107,32 @@ public:
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * @brief Constructs a delegate and connects a member function to it.
|
|
|
- * @tparam Member Member function to connect to the delegate.
|
|
|
- * @tparam Class Type of class to which the member function belongs.
|
|
|
- * @param instance A valid instance of type pointer to `Class`.
|
|
|
+ * @brief Constructs a delegate and connects a member function for a given
|
|
|
+ * instance or a curried free function to it.
|
|
|
+ * @tparam Candidate Member function or curried free function to connect to
|
|
|
+ * the delegate.
|
|
|
+ * @tparam Type Type of class to which the member function belongs or type
|
|
|
+ * of value used for currying.
|
|
|
+ * @param value_or_instance A valid pointer to an instance of class type or
|
|
|
+ * the value to use for currying.
|
|
|
*/
|
|
|
- template<auto Member, typename Class, typename = std::enable_if_t<std::is_member_function_pointer_v<decltype(Member)>>>
|
|
|
- delegate(connect_arg_t<Member>, Class *instance) ENTT_NOEXCEPT
|
|
|
+ template<auto Candidate, typename Type>
|
|
|
+ delegate(connect_arg_t<Candidate>, Type value_or_instance) ENTT_NOEXCEPT
|
|
|
+ : delegate{}
|
|
|
+ {
|
|
|
+ connect<Candidate>(value_or_instance);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @brief Constructs a delegate and connects a lambda or a functor to it.
|
|
|
+ * @tparam Invokable Type of lambda or functor to connect.
|
|
|
+ * @param invokable A valid instance of the given type.
|
|
|
+ */
|
|
|
+ template<typename Invokable>
|
|
|
+ delegate(Invokable invokable) ENTT_NOEXCEPT
|
|
|
: delegate{}
|
|
|
{
|
|
|
- connect<Member>(instance);
|
|
|
+ connect(std::move(invokable));
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -168,6 +184,25 @@ public:
|
|
|
};
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * @brief Connects a lambda or a functor to a delegate.
|
|
|
+ * @tparam Invokable Type of lambda or functor to connect.
|
|
|
+ * @param invokable A valid instance of the given type.
|
|
|
+ */
|
|
|
+ template<typename Invokable>
|
|
|
+ void connect(Invokable invokable) ENTT_NOEXCEPT {
|
|
|
+ static_assert(sizeof(Invokable) < sizeof(void *));
|
|
|
+ static_assert(std::is_class_v<Invokable>);
|
|
|
+ static_assert(std::is_trivially_destructible_v<Invokable>);
|
|
|
+ static_assert(std::is_invocable_r_v<Ret, Invokable, Args...>);
|
|
|
+ new (&storage) Invokable{std::move(invokable)};
|
|
|
+
|
|
|
+ fn = [](storage_type &storage, Args... args) -> Ret {
|
|
|
+ Invokable &invokable = *reinterpret_cast<Invokable *>(&storage);
|
|
|
+ return std::invoke(invokable, args...);
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* @brief Resets a delegate.
|
|
|
*
|
|
|
@@ -220,14 +255,17 @@ public:
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * @brief Checks if the contents of the two delegates are different.
|
|
|
+ * @brief Checks if the connected functions differ.
|
|
|
+ *
|
|
|
+ * In case of member functions, the instances connected to the delegate
|
|
|
+ * are not verified by this operator. Use the instance member function
|
|
|
+ * instead.
|
|
|
+ *
|
|
|
* @param other Delegate with which to compare.
|
|
|
- * @return True if the two delegates are identical, false otherwise.
|
|
|
+ * @return False if the connected functions differ, true otherwise.
|
|
|
*/
|
|
|
bool operator==(const delegate<Ret(Args...)> &other) const ENTT_NOEXCEPT {
|
|
|
- auto *lhs = reinterpret_cast<const unsigned char *>(&storage);
|
|
|
- auto *rhs = reinterpret_cast<const unsigned char *>(&other.storage);
|
|
|
- return fn == other.fn && std::equal(lhs, lhs + sizeof(storage_type), rhs);
|
|
|
+ return fn == other.fn;
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
@@ -237,12 +275,16 @@ private:
|
|
|
|
|
|
|
|
|
/**
|
|
|
- * @brief Checks if the contents of the two delegates are different.
|
|
|
+ * @brief Checks if the connected functions differ.
|
|
|
+ *
|
|
|
+ * In case of member functions, the instances connected to the delegate are not
|
|
|
+ * verified by this operator. Use the `instance` member function instead.
|
|
|
+ *
|
|
|
* @tparam Ret Return type of a function type.
|
|
|
* @tparam Args Types of arguments of a function type.
|
|
|
* @param lhs A valid delegate object.
|
|
|
* @param rhs A valid delegate object.
|
|
|
- * @return True if the two delegates are different, false otherwise.
|
|
|
+ * @return True if the connected functions differ, false otherwise.
|
|
|
*/
|
|
|
template<typename Ret, typename... Args>
|
|
|
bool operator!=(const delegate<Ret(Args...)> &lhs, const delegate<Ret(Args...)> &rhs) ENTT_NOEXCEPT {
|
|
|
@@ -253,27 +295,44 @@ bool operator!=(const delegate<Ret(Args...)> &lhs, const delegate<Ret(Args...)>
|
|
|
/**
|
|
|
* @brief Deduction guideline.
|
|
|
*
|
|
|
- * It allows to deduce the function type of the delegate directly from the
|
|
|
+ * It allows to deduce the function type of the delegate directly from a
|
|
|
* function provided to the constructor.
|
|
|
*
|
|
|
* @tparam Function A valid free function pointer.
|
|
|
*/
|
|
|
template<auto Function>
|
|
|
-delegate(connect_arg_t<Function>) ENTT_NOEXCEPT -> delegate<internal::function_type<Function>>;
|
|
|
+delegate(connect_arg_t<Function>) ENTT_NOEXCEPT
|
|
|
+-> delegate<std::remove_pointer_t<decltype(internal::to_function_pointer(Function))>>;
|
|
|
|
|
|
|
|
|
/**
|
|
|
+ * @brief Deduction guideline.
|
|
|
+ *
|
|
|
+ * It allows to deduce the function type of the delegate directly from a member
|
|
|
+ * function or a curried free function provided to the constructor.
|
|
|
+ *
|
|
|
+ * @tparam Candidate Member function or curried free function to connect to
|
|
|
+ * the delegate.
|
|
|
+ * @tparam Type Type of class to which the member function belongs or type
|
|
|
+ * of value used for currying.
|
|
|
+ */
|
|
|
+template<auto Candidate, typename Type>
|
|
|
+delegate(connect_arg_t<Candidate>, Type) ENTT_NOEXCEPT
|
|
|
+-> delegate<std::remove_pointer_t<decltype(internal::to_function_pointer(Candidate, std::declval<Type>()))>>;
|
|
|
|
|
|
+
|
|
|
+/**
|
|
|
* @brief Deduction guideline.
|
|
|
*
|
|
|
- * It allows to deduce the function type of the delegate directly from the
|
|
|
- * member function provided to the constructor.
|
|
|
+ * It allows to deduce the function type of the delegate directly from a lambda
|
|
|
+ * or a functor provided to the constructor.
|
|
|
*
|
|
|
- * @tparam Member Member function to connect to the delegate.
|
|
|
- * @tparam Class Type of class to which the member function belongs.
|
|
|
+ * @tparam Invokable Type of lambda or functor to connect.
|
|
|
+ * @param invokable A valid instance of the given type.
|
|
|
*/
|
|
|
-template<auto Member, typename Class>
|
|
|
-delegate(connect_arg_t<Member>, Class *) ENTT_NOEXCEPT -> delegate<internal::function_type<Member>>;
|
|
|
+template<typename Invokable>
|
|
|
+delegate(Invokable invokable) ENTT_NOEXCEPT
|
|
|
+-> delegate<std::remove_pointer_t<decltype(internal::to_function_pointer(&Invokable::operator(), &invokable))>>;
|
|
|
|
|
|
|
|
|
}
|