From 61e5bcef2629e2d68b805a956a96fff264d4f74d Mon Sep 17 00:00:00 2001 From: untodesu Date: Sat, 28 Jun 2025 01:59:49 +0500 Subject: Restructure dependencies and update to C++20 - Nuked static_assert from almost everywhere in the project - Nuked binary dependency support. Might add one later though - Separated dependency headers into a separate include subdirectory - Grafted a thirdpartylegalnotices.txt generator from RITEG - Pushed development snapshot version to 2126 (26th week of 2025) --- deps/include/entt/signal/delegate.hpp | 323 ---------------------- deps/include/entt/signal/dispatcher.hpp | 397 --------------------------- deps/include/entt/signal/emitter.hpp | 182 ------------ deps/include/entt/signal/fwd.hpp | 46 ---- deps/include/entt/signal/sigh.hpp | 471 -------------------------------- 5 files changed, 1419 deletions(-) delete mode 100644 deps/include/entt/signal/delegate.hpp delete mode 100644 deps/include/entt/signal/dispatcher.hpp delete mode 100644 deps/include/entt/signal/emitter.hpp delete mode 100644 deps/include/entt/signal/fwd.hpp delete mode 100644 deps/include/entt/signal/sigh.hpp (limited to 'deps/include/entt/signal') diff --git a/deps/include/entt/signal/delegate.hpp b/deps/include/entt/signal/delegate.hpp deleted file mode 100644 index e8b3299..0000000 --- a/deps/include/entt/signal/delegate.hpp +++ /dev/null @@ -1,323 +0,0 @@ -#ifndef ENTT_SIGNAL_DELEGATE_HPP -#define ENTT_SIGNAL_DELEGATE_HPP - -#include -#include -#include -#include -#include -#include "../config/config.h" -#include "../core/type_traits.hpp" -#include "fwd.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template -constexpr auto function_pointer(Ret (*)(Args...)) -> Ret (*)(Args...); - -template -constexpr auto function_pointer(Ret (*)(Type, Args...), Other &&) -> Ret (*)(Args...); - -template -constexpr auto function_pointer(Ret (Class::*)(Args...), Other &&...) -> Ret (*)(Args...); - -template -constexpr auto function_pointer(Ret (Class::*)(Args...) const, Other &&...) -> Ret (*)(Args...); - -template -constexpr auto function_pointer(Type Class::*, Other &&...) -> Type (*)(); - -template -using function_pointer_t = decltype(function_pointer(std::declval()...)); - -template -[[nodiscard]] constexpr auto index_sequence_for(Ret (*)(Args...)) { - return std::index_sequence_for{}; -} - -} // namespace internal -/*! @endcond */ - -/** - * @brief Basic delegate implementation. - * - * Primary template isn't defined on purpose. All the specializations give a - * compile-time error unless the template parameter is a function type. - */ -template -class delegate; - -/** - * @brief Utility class to use to send around functions and members. - * - * Unmanaged delegate for function pointers and members. Users of this class are - * in charge of disconnecting instances before deleting them. - * - * A delegate can be used as a general purpose invoker without memory overhead - * for free functions possibly with payloads and bound or unbound members. - * - * @tparam Ret Return type of a function type. - * @tparam Args Types of arguments of a function type. - */ -template -class delegate { - template - [[nodiscard]] auto wrap(std::index_sequence) noexcept { - return [](const void *, Args... args) -> Ret { - [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward(args)...); - [[maybe_unused]] constexpr auto offset = !std::is_invocable_r_v>...> * (sizeof...(Args) - sizeof...(Index)); - return static_cast(std::invoke(Candidate, std::forward>>(std::get(arguments))...)); - }; - } - - template - [[nodiscard]] auto wrap(Type &, std::index_sequence) noexcept { - return [](const void *payload, Args... args) -> Ret { - Type *curr = static_cast(const_cast *>(payload)); - [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward(args)...); - [[maybe_unused]] constexpr auto offset = !std::is_invocable_r_v>...> * (sizeof...(Args) - sizeof...(Index)); - return static_cast(std::invoke(Candidate, *curr, std::forward>>(std::get(arguments))...)); - }; - } - - template - [[nodiscard]] auto wrap(Type *, std::index_sequence) noexcept { - return [](const void *payload, Args... args) -> Ret { - Type *curr = static_cast(const_cast *>(payload)); - [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward(args)...); - [[maybe_unused]] constexpr auto offset = !std::is_invocable_r_v>...> * (sizeof...(Args) - sizeof...(Index)); - return static_cast(std::invoke(Candidate, curr, std::forward>>(std::get(arguments))...)); - }; - } - -public: - /*! @brief Function type of the contained target. */ - using function_type = Ret(const void *, Args...); - /*! @brief Function type of the delegate. */ - using type = Ret(Args...); - /*! @brief Return type of the delegate. */ - using result_type = Ret; - - /*! @brief Default constructor. */ - delegate() noexcept = default; - - /** - * @brief Constructs a delegate with a given object or payload, if any. - * @tparam Candidate Function or member to connect to the delegate. - * @tparam Type Type of class or type of payload, if any. - * @param value_or_instance Optional valid object that fits the purpose. - */ - template - delegate(connect_arg_t, Type &&...value_or_instance) noexcept { - connect(std::forward(value_or_instance)...); - } - - /** - * @brief Constructs a delegate and connects an user defined function with - * optional payload. - * @param function Function to connect to the delegate. - * @param payload User defined arbitrary data. - */ - delegate(function_type *function, const void *payload = nullptr) noexcept { - connect(function, payload); - } - - /** - * @brief Connects a free function or an unbound member to a delegate. - * @tparam Candidate Function or member to connect to the delegate. - */ - template - void connect() noexcept { - instance = nullptr; - - if constexpr(std::is_invocable_r_v) { - fn = [](const void *, Args... args) -> Ret { - return Ret(std::invoke(Candidate, std::forward(args)...)); - }; - } else if constexpr(std::is_member_pointer_v) { - fn = wrap(internal::index_sequence_for>>(internal::function_pointer_t{})); - } else { - fn = wrap(internal::index_sequence_for(internal::function_pointer_t{})); - } - } - - /** - * @brief Connects a free function with payload or a bound member to a - * delegate. - * - * The delegate isn't responsible for the connected object or the payload. - * Users must always guarantee that the lifetime of the instance overcomes - * the one of the delegate.
- * When used to connect a free function with payload, its signature must be - * such that the instance is the first argument before the ones used to - * define the delegate itself. - * - * @tparam Candidate Function or member to connect to the delegate. - * @tparam Type Type of class or type of payload. - * @param value_or_instance A valid reference that fits the purpose. - */ - template - void connect(Type &value_or_instance) noexcept { - instance = &value_or_instance; - - if constexpr(std::is_invocable_r_v) { - fn = [](const void *payload, Args... args) -> Ret { - Type *curr = static_cast(const_cast *>(payload)); - return Ret(std::invoke(Candidate, *curr, std::forward(args)...)); - }; - } else { - fn = wrap(value_or_instance, internal::index_sequence_for(internal::function_pointer_t{})); - } - } - - /** - * @brief Connects a free function with payload or a bound member to a - * delegate. - * - * @sa connect(Type &) - * - * @tparam Candidate Function or member to connect to the delegate. - * @tparam Type Type of class or type of payload. - * @param value_or_instance A valid pointer that fits the purpose. - */ - template - void connect(Type *value_or_instance) noexcept { - instance = value_or_instance; - - if constexpr(std::is_invocable_r_v) { - fn = [](const void *payload, Args... args) -> Ret { - Type *curr = static_cast(const_cast *>(payload)); - return Ret(std::invoke(Candidate, curr, std::forward(args)...)); - }; - } else { - fn = wrap(value_or_instance, internal::index_sequence_for(internal::function_pointer_t{})); - } - } - - /** - * @brief Connects an user defined function with optional payload to a - * delegate. - * - * The delegate isn't responsible for the connected object or the payload. - * Users must always guarantee that the lifetime of an instance overcomes - * the one of the delegate.
- * The payload is returned as the first argument to the target function in - * all cases. - * - * @param function Function to connect to the delegate. - * @param payload User defined arbitrary data. - */ - void connect(function_type *function, const void *payload = nullptr) noexcept { - ENTT_ASSERT(function != nullptr, "Uninitialized function pointer"); - instance = payload; - fn = function; - } - - /** - * @brief Resets a delegate. - * - * After a reset, a delegate cannot be invoked anymore. - */ - void reset() noexcept { - instance = nullptr; - fn = nullptr; - } - - /** - * @brief Returns a pointer to the stored callable function target, if any. - * @return An opaque pointer to the stored callable function target. - */ - [[nodiscard]] function_type *target() const noexcept { - return fn; - } - - /** - * @brief Returns the instance or the payload linked to a delegate, if any. - * @return An opaque pointer to the underlying data. - */ - [[nodiscard]] const void *data() const noexcept { - return instance; - } - - /** - * @brief Triggers a delegate. - * - * The delegate invokes the underlying function and returns the result. - * - * @warning - * Attempting to trigger an invalid delegate results in undefined - * behavior. - * - * @param args Arguments to use to invoke the underlying function. - * @return The value returned by the underlying function. - */ - Ret operator()(Args... args) const { - ENTT_ASSERT(static_cast(*this), "Uninitialized delegate"); - return fn(instance, std::forward(args)...); - } - - /** - * @brief Checks whether a delegate actually stores a listener. - * @return False if the delegate is empty, true otherwise. - */ - [[nodiscard]] explicit operator bool() const noexcept { - // no need to also test instance - return !(fn == nullptr); - } - - /** - * @brief Compares the contents of two delegates. - * @param other Delegate with which to compare. - * @return False if the two contents differ, true otherwise. - */ - [[nodiscard]] bool operator==(const delegate &other) const noexcept { - return fn == other.fn && instance == other.instance; - } - -private: - const void *instance{}; - function_type *fn{}; -}; - -/** - * @brief Compares the contents of two delegates. - * @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 contents differ, false otherwise. - */ -template -[[nodiscard]] bool operator!=(const delegate &lhs, const delegate &rhs) noexcept { - return !(lhs == rhs); -} - -/** - * @brief Deduction guide. - * @tparam Candidate Function or member to connect to the delegate. - */ -template -delegate(connect_arg_t) -> delegate>>; - -/** - * @brief Deduction guide. - * @tparam Candidate Function or member to connect to the delegate. - * @tparam Type Type of class or type of payload. - */ -template -delegate(connect_arg_t, Type &&) -> delegate>>; - -/** - * @brief Deduction guide. - * @tparam Ret Return type of a function type. - * @tparam Args Types of arguments of a function type. - */ -template -delegate(Ret (*)(const void *, Args...), const void * = nullptr) -> delegate; - -} // namespace entt - -#endif diff --git a/deps/include/entt/signal/dispatcher.hpp b/deps/include/entt/signal/dispatcher.hpp deleted file mode 100644 index fd0287d..0000000 --- a/deps/include/entt/signal/dispatcher.hpp +++ /dev/null @@ -1,397 +0,0 @@ -#ifndef ENTT_SIGNAL_DISPATCHER_HPP -#define ENTT_SIGNAL_DISPATCHER_HPP - -#include -#include -#include -#include -#include -#include -#include "../container/dense_map.hpp" -#include "../core/compressed_pair.hpp" -#include "../core/fwd.hpp" -#include "../core/type_info.hpp" -#include "../core/utility.hpp" -#include "fwd.hpp" -#include "sigh.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -struct basic_dispatcher_handler { - virtual ~basic_dispatcher_handler() noexcept = default; - virtual void publish() = 0; - virtual void disconnect(void *) = 0; - virtual void clear() noexcept = 0; - [[nodiscard]] virtual std::size_t size() const noexcept = 0; -}; - -template -class dispatcher_handler final: public basic_dispatcher_handler { - static_assert(std::is_same_v>, "Invalid type"); - - using alloc_traits = std::allocator_traits; - using signal_type = sigh; - using container_type = std::vector>; - -public: - using allocator_type = Allocator; - - dispatcher_handler(const allocator_type &allocator) - : signal{allocator}, - events{allocator} {} - - void publish() override { - const auto length = events.size(); - - for(std::size_t pos{}; pos < length; ++pos) { - signal.publish(events[pos]); - } - - events.erase(events.cbegin(), events.cbegin() + length); - } - - void disconnect(void *instance) override { - bucket().disconnect(instance); - } - - void clear() noexcept override { - events.clear(); - } - - [[nodiscard]] auto bucket() noexcept { - return typename signal_type::sink_type{signal}; - } - - void trigger(Type event) { - signal.publish(event); - } - - template - void enqueue(Args &&...args) { - if constexpr(std::is_aggregate_v && (sizeof...(Args) != 0u || !std::is_default_constructible_v)) { - events.push_back(Type{std::forward(args)...}); - } else { - events.emplace_back(std::forward(args)...); - } - } - - [[nodiscard]] std::size_t size() const noexcept override { - return events.size(); - } - -private: - signal_type signal; - container_type events; -}; - -} // namespace internal -/*! @endcond */ - -/** - * @brief Basic dispatcher implementation. - * - * A dispatcher can be used either to trigger an immediate event or to enqueue - * events to be published all together once per tick.
- * Listeners are provided in the form of member functions. For each event of - * type `Type`, listeners are such that they can be invoked with an argument of - * type `Type &`, no matter what the return type is. - * - * The dispatcher creates instances of the `sigh` class internally. Refer to the - * documentation of the latter for more details. - * - * @tparam Allocator Type of allocator used to manage memory and elements. - */ -template -class basic_dispatcher { - template - using handler_type = internal::dispatcher_handler; - - using key_type = id_type; - // std::shared_ptr because of its type erased allocator which is useful here - using mapped_type = std::shared_ptr; - - using alloc_traits = std::allocator_traits; - using container_allocator = typename alloc_traits::template rebind_alloc>; - using container_type = dense_map, container_allocator>; - - template - [[nodiscard]] handler_type &assure(const id_type id) { - static_assert(std::is_same_v>, "Non-decayed types not allowed"); - auto &&ptr = pools.first()[id]; - - if(!ptr) { - const auto &allocator = get_allocator(); - ptr = std::allocate_shared>(allocator, allocator); - } - - return static_cast &>(*ptr); - } - - template - [[nodiscard]] const handler_type *assure(const id_type id) const { - static_assert(std::is_same_v>, "Non-decayed types not allowed"); - - if(auto it = pools.first().find(id); it != pools.first().cend()) { - return static_cast *>(it->second.get()); - } - - return nullptr; - } - -public: - /*! @brief Allocator type. */ - using allocator_type = Allocator; - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - - /*! @brief Default constructor. */ - basic_dispatcher() - : basic_dispatcher{allocator_type{}} {} - - /** - * @brief Constructs a dispatcher with a given allocator. - * @param allocator The allocator to use. - */ - explicit basic_dispatcher(const allocator_type &allocator) - : pools{allocator, allocator} {} - - /*! @brief Default copy constructor, deleted on purpose. */ - basic_dispatcher(const basic_dispatcher &) = delete; - - /** - * @brief Move constructor. - * @param other The instance to move from. - */ - basic_dispatcher(basic_dispatcher &&other) noexcept - : pools{std::move(other.pools)} {} - - /** - * @brief Allocator-extended move constructor. - * @param other The instance to move from. - * @param allocator The allocator to use. - */ - basic_dispatcher(basic_dispatcher &&other, const allocator_type &allocator) - : pools{container_type{std::move(other.pools.first()), allocator}, allocator} { - ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a dispatcher is not allowed"); - } - - /*! @brief Default destructor. */ - ~basic_dispatcher() noexcept = default; - - /** - * @brief Default copy assignment operator, deleted on purpose. - * @return This dispatcher. - */ - basic_dispatcher &operator=(const basic_dispatcher &) = delete; - - /** - * @brief Move assignment operator. - * @param other The instance to move from. - * @return This dispatcher. - */ - basic_dispatcher &operator=(basic_dispatcher &&other) noexcept { - ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a dispatcher is not allowed"); - pools = std::move(other.pools); - return *this; - } - - /** - * @brief Exchanges the contents with those of a given dispatcher. - * @param other Dispatcher to exchange the content with. - */ - void swap(basic_dispatcher &other) { - using std::swap; - swap(pools, other.pools); - } - - /** - * @brief Returns the associated allocator. - * @return The associated allocator. - */ - [[nodiscard]] constexpr allocator_type get_allocator() const noexcept { - return pools.second(); - } - - /** - * @brief Returns the number of pending events for a given type. - * @tparam Type Type of event for which to return the count. - * @param id Name used to map the event queue within the dispatcher. - * @return The number of pending events for the given type. - */ - template - [[nodiscard]] size_type size(const id_type id = type_hash::value()) const noexcept { - const auto *cpool = assure>(id); - return cpool ? cpool->size() : 0u; - } - - /** - * @brief Returns the total number of pending events. - * @return The total number of pending events. - */ - [[nodiscard]] size_type size() const noexcept { - size_type count{}; - - for(auto &&cpool: pools.first()) { - count += cpool.second->size(); - } - - return count; - } - - /** - * @brief Returns a sink object for the given event and queue. - * - * A sink is an opaque object used to connect listeners to events. - * - * The function type for a listener is _compatible_ with: - * - * @code{.cpp} - * void(Type &); - * @endcode - * - * The order of invocation of the listeners isn't guaranteed. - * - * @sa sink - * - * @tparam Type Type of event of which to get the sink. - * @param id Name used to map the event queue within the dispatcher. - * @return A temporary sink object. - */ - template - [[nodiscard]] auto sink(const id_type id = type_hash::value()) { - return assure(id).bucket(); - } - - /** - * @brief Triggers an immediate event of a given type. - * @tparam Type Type of event to trigger. - * @param value An instance of the given type of event. - */ - template - void trigger(Type &&value = {}) { - trigger(type_hash>::value(), std::forward(value)); - } - - /** - * @brief Triggers an immediate event on a queue of a given type. - * @tparam Type Type of event to trigger. - * @param value An instance of the given type of event. - * @param id Name used to map the event queue within the dispatcher. - */ - template - void trigger(const id_type id, Type &&value = {}) { - assure>(id).trigger(std::forward(value)); - } - - /** - * @brief Enqueues an event of the given type. - * @tparam Type Type of event to enqueue. - * @tparam Args Types of arguments to use to construct the event. - * @param args Arguments to use to construct the event. - */ - template - void enqueue(Args &&...args) { - enqueue_hint(type_hash::value(), std::forward(args)...); - } - - /** - * @brief Enqueues an event of the given type. - * @tparam Type Type of event to enqueue. - * @param value An instance of the given type of event. - */ - template - void enqueue(Type &&value) { - enqueue_hint(type_hash>::value(), std::forward(value)); - } - - /** - * @brief Enqueues an event of the given type. - * @tparam Type Type of event to enqueue. - * @tparam Args Types of arguments to use to construct the event. - * @param id Name used to map the event queue within the dispatcher. - * @param args Arguments to use to construct the event. - */ - template - void enqueue_hint(const id_type id, Args &&...args) { - assure(id).enqueue(std::forward(args)...); - } - - /** - * @brief Enqueues an event of the given type. - * @tparam Type Type of event to enqueue. - * @param id Name used to map the event queue within the dispatcher. - * @param value An instance of the given type of event. - */ - template - void enqueue_hint(const id_type id, Type &&value) { - assure>(id).enqueue(std::forward(value)); - } - - /** - * @brief Utility function to disconnect everything related to a given value - * or instance from a dispatcher. - * @tparam Type Type of class or type of payload. - * @param value_or_instance A valid object that fits the purpose. - */ - template - void disconnect(Type &value_or_instance) { - disconnect(&value_or_instance); - } - - /** - * @brief Utility function to disconnect everything related to a given value - * or instance from a dispatcher. - * @tparam Type Type of class or type of payload. - * @param value_or_instance A valid object that fits the purpose. - */ - template - void disconnect(Type *value_or_instance) { - for(auto &&cpool: pools.first()) { - cpool.second->disconnect(value_or_instance); - } - } - - /** - * @brief Discards all the events stored so far in a given queue. - * @tparam Type Type of event to discard. - * @param id Name used to map the event queue within the dispatcher. - */ - template - void clear(const id_type id = type_hash::value()) { - assure(id).clear(); - } - - /*! @brief Discards all the events queued so far. */ - void clear() noexcept { - for(auto &&cpool: pools.first()) { - cpool.second->clear(); - } - } - - /** - * @brief Delivers all the pending events of a given queue. - * @tparam Type Type of event to send. - * @param id Name used to map the event queue within the dispatcher. - */ - template - void update(const id_type id = type_hash::value()) { - assure(id).publish(); - } - - /*! @brief Delivers all the pending events. */ - void update() const { - for(auto &&cpool: pools.first()) { - cpool.second->publish(); - } - } - -private: - compressed_pair pools; -}; - -} // namespace entt - -#endif diff --git a/deps/include/entt/signal/emitter.hpp b/deps/include/entt/signal/emitter.hpp deleted file mode 100644 index a35e0d1..0000000 --- a/deps/include/entt/signal/emitter.hpp +++ /dev/null @@ -1,182 +0,0 @@ -#ifndef ENTT_SIGNAL_EMITTER_HPP -#define ENTT_SIGNAL_EMITTER_HPP - -#include -#include -#include -#include "../container/dense_map.hpp" -#include "../core/compressed_pair.hpp" -#include "../core/fwd.hpp" -#include "../core/type_info.hpp" -#include "../core/utility.hpp" -#include "fwd.hpp" - -namespace entt { - -/** - * @brief General purpose event emitter. - * - * To create an emitter type, derived classes must inherit from the base as: - * - * @code{.cpp} - * struct my_emitter: emitter { - * // ... - * } - * @endcode - * - * Handlers for the different events are created internally on the fly. It's not - * required to specify in advance the full list of accepted events.
- * Moreover, whenever an event is published, an emitter also passes a reference - * to itself to its listeners. - * - * @tparam Derived Emitter type. - * @tparam Allocator Type of allocator used to manage memory and elements. - */ -template -class emitter { - using key_type = id_type; - using mapped_type = std::function; - - using alloc_traits = std::allocator_traits; - using container_allocator = typename alloc_traits::template rebind_alloc>; - using container_type = dense_map, container_allocator>; - -public: - /*! @brief Allocator type. */ - using allocator_type = Allocator; - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - - /*! @brief Default constructor. */ - emitter() - : emitter{allocator_type{}} {} - - /** - * @brief Constructs an emitter with a given allocator. - * @param allocator The allocator to use. - */ - explicit emitter(const allocator_type &allocator) - : handlers{allocator, allocator} {} - - /*! @brief Default copy constructor, deleted on purpose. */ - emitter(const emitter &) = delete; - - /** - * @brief Move constructor. - * @param other The instance to move from. - */ - emitter(emitter &&other) noexcept - : handlers{std::move(other.handlers)} {} - - /** - * @brief Allocator-extended move constructor. - * @param other The instance to move from. - * @param allocator The allocator to use. - */ - emitter(emitter &&other, const allocator_type &allocator) - : handlers{container_type{std::move(other.handlers.first()), allocator}, allocator} { - ENTT_ASSERT(alloc_traits::is_always_equal::value || handlers.second() == other.handlers.second(), "Copying an emitter is not allowed"); - } - - /*! @brief Default destructor. */ - virtual ~emitter() noexcept { - static_assert(std::is_base_of_v, Derived>, "Invalid emitter type"); - } - - /** - * @brief Default copy assignment operator, deleted on purpose. - * @return This emitter. - */ - emitter &operator=(const emitter &) = delete; - - /** - * @brief Move assignment operator. - * @param other The instance to move from. - * @return This emitter. - */ - emitter &operator=(emitter &&other) noexcept { - ENTT_ASSERT(alloc_traits::is_always_equal::value || handlers.second() == other.handlers.second(), "Copying an emitter is not allowed"); - handlers = std::move(other.handlers); - return *this; - } - - /** - * @brief Exchanges the contents with those of a given emitter. - * @param other Emitter to exchange the content with. - */ - void swap(emitter &other) { - using std::swap; - swap(handlers, other.handlers); - } - - /** - * @brief Returns the associated allocator. - * @return The associated allocator. - */ - [[nodiscard]] constexpr allocator_type get_allocator() const noexcept { - return handlers.second(); - } - - /** - * @brief Publishes a given event. - * @tparam Type Type of event to trigger. - * @param value An instance of the given type of event. - */ - template - void publish(Type &&value) { - if(const auto id = type_id().hash(); handlers.first().contains(id)) { - handlers.first()[id](&value); - } - } - - /** - * @brief Registers a listener with the event emitter. - * @tparam Type Type of event to which to connect the listener. - * @param func The listener to register. - */ - template - void on(std::function func) { - handlers.first().insert_or_assign(type_id().hash(), [func = std::move(func), this](void *value) { - func(*static_cast(value), static_cast(*this)); - }); - } - - /** - * @brief Disconnects a listener from the event emitter. - * @tparam Type Type of event of the listener. - */ - template - void erase() { - handlers.first().erase(type_hash>>::value()); - } - - /*! @brief Disconnects all the listeners. */ - void clear() noexcept { - handlers.first().clear(); - } - - /** - * @brief Checks if there are listeners registered for the specific event. - * @tparam Type Type of event to test. - * @return True if there are no listeners registered, false otherwise. - */ - template - [[nodiscard]] bool contains() const { - return handlers.first().contains(type_hash>>::value()); - } - - /** - * @brief Checks if there are listeners registered with the event emitter. - * @return True if there are no listeners registered, false otherwise. - */ - [[nodiscard]] bool empty() const noexcept { - return handlers.first().empty(); - } - -private: - compressed_pair handlers; -}; - -} // namespace entt - -#endif diff --git a/deps/include/entt/signal/fwd.hpp b/deps/include/entt/signal/fwd.hpp deleted file mode 100644 index d195312..0000000 --- a/deps/include/entt/signal/fwd.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef ENTT_SIGNAL_FWD_HPP -#define ENTT_SIGNAL_FWD_HPP - -#include - -namespace entt { - -template -class delegate; - -template> -class basic_dispatcher; - -template> -class emitter; - -class connection; - -struct scoped_connection; - -template -class sink; - -template> -class sigh; - -/*! @brief Alias declaration for the most common use case. */ -using dispatcher = basic_dispatcher<>; - -/*! @brief Disambiguation tag for constructors and the like. */ -template -struct connect_arg_t { - /*! @brief Default constructor. */ - explicit connect_arg_t() = default; -}; - -/** - * @brief Constant of type connect_arg_t used to disambiguate calls. - * @tparam Candidate Element to connect (likely a free or member function). - */ -template -inline constexpr connect_arg_t connect_arg{}; - -} // namespace entt - -#endif diff --git a/deps/include/entt/signal/sigh.hpp b/deps/include/entt/signal/sigh.hpp deleted file mode 100644 index 93c96ea..0000000 --- a/deps/include/entt/signal/sigh.hpp +++ /dev/null @@ -1,471 +0,0 @@ -#ifndef ENTT_SIGNAL_SIGH_HPP -#define ENTT_SIGNAL_SIGH_HPP - -#include -#include -#include -#include -#include -#include "delegate.hpp" -#include "fwd.hpp" - -namespace entt { - -/** - * @brief Sink class. - * - * Primary template isn't defined on purpose. All the specializations give a - * compile-time error unless the template parameter is a function type. - * - * @tparam Type A valid signal handler type. - */ -template -class sink; - -/** - * @brief Unmanaged signal handler. - * - * Primary template isn't defined on purpose. All the specializations give a - * compile-time error unless the template parameter is a function type. - * - * @tparam Type A valid function type. - * @tparam Allocator Type of allocator used to manage memory and elements. - */ -template -class sigh; - -/** - * @brief Unmanaged signal handler. - * - * It works directly with references to classes and pointers to member functions - * as well as pointers to free functions. Users of this class are in charge of - * disconnecting instances before deleting them. - * - * This class serves mainly two purposes: - * - * * Creating signals to use later to notify a bunch of listeners. - * * Collecting results from a set of functions like in a voting system. - * - * @tparam Ret Return type of a function type. - * @tparam Args Types of arguments of a function type. - * @tparam Allocator Type of allocator used to manage memory and elements. - */ -template -class sigh { - friend class sink>; - - using alloc_traits = std::allocator_traits; - using delegate_type = delegate; - using container_type = std::vector>; - -public: - /*! @brief Allocator type. */ - using allocator_type = Allocator; - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - /*! @brief Sink type. */ - using sink_type = sink>; - - /*! @brief Default constructor. */ - sigh() noexcept(std::is_nothrow_default_constructible_v && std::is_nothrow_constructible_v) - : sigh{allocator_type{}} {} - - /** - * @brief Constructs a signal handler with a given allocator. - * @param allocator The allocator to use. - */ - explicit sigh(const allocator_type &allocator) noexcept(std::is_nothrow_constructible_v) - : calls{allocator} {} - - /** - * @brief Copy constructor. - * @param other The instance to copy from. - */ - sigh(const sigh &other) noexcept(std::is_nothrow_copy_constructible_v) - : calls{other.calls} {} - - /** - * @brief Allocator-extended copy constructor. - * @param other The instance to copy from. - * @param allocator The allocator to use. - */ - sigh(const sigh &other, const allocator_type &allocator) noexcept(std::is_nothrow_constructible_v) - : calls{other.calls, allocator} {} - - /** - * @brief Move constructor. - * @param other The instance to move from. - */ - sigh(sigh &&other) noexcept(std::is_nothrow_move_constructible_v) - : calls{std::move(other.calls)} {} - - /** - * @brief Allocator-extended move constructor. - * @param other The instance to move from. - * @param allocator The allocator to use. - */ - sigh(sigh &&other, const allocator_type &allocator) noexcept(std::is_nothrow_constructible_v) - : calls{std::move(other.calls), allocator} {} - - /*! @brief Default destructor. */ - ~sigh() noexcept = default; - - /** - * @brief Copy assignment operator. - * @param other The instance to copy from. - * @return This signal handler. - */ - sigh &operator=(const sigh &other) noexcept(std::is_nothrow_copy_assignable_v) { - calls = other.calls; - return *this; - } - - /** - * @brief Move assignment operator. - * @param other The instance to move from. - * @return This signal handler. - */ - sigh &operator=(sigh &&other) noexcept(std::is_nothrow_move_assignable_v) { - calls = std::move(other.calls); - return *this; - } - - /** - * @brief Exchanges the contents with those of a given signal handler. - * @param other Signal handler to exchange the content with. - */ - void swap(sigh &other) noexcept(std::is_nothrow_swappable_v) { - using std::swap; - swap(calls, other.calls); - } - - /** - * @brief Returns the associated allocator. - * @return The associated allocator. - */ - [[nodiscard]] constexpr allocator_type get_allocator() const noexcept { - return calls.get_allocator(); - } - - /** - * @brief Number of listeners connected to the signal. - * @return Number of listeners currently connected. - */ - [[nodiscard]] size_type size() const noexcept { - return calls.size(); - } - - /** - * @brief Returns false if at least a listener is connected to the signal. - * @return True if the signal has no listeners connected, false otherwise. - */ - [[nodiscard]] bool empty() const noexcept { - return calls.empty(); - } - - /** - * @brief Triggers a signal. - * - * All the listeners are notified. Order isn't guaranteed. - * - * @param args Arguments to use to invoke listeners. - */ - void publish(Args... args) const { - for(auto pos = calls.size(); pos; --pos) { - calls[pos - 1u](args...); - } - } - - /** - * @brief Collects return values from the listeners. - * - * The collector must expose a call operator with the following properties: - * - * * The return type is either `void` or such that it's convertible to - * `bool`. In the second case, a true value will stop the iteration. - * * The list of parameters is empty if `Ret` is `void`, otherwise it - * contains a single element such that `Ret` is convertible to it. - * - * @tparam Func Type of collector to use, if any. - * @param func A valid function object. - * @param args Arguments to use to invoke listeners. - */ - template - void collect(Func func, Args... args) const { - for(auto pos = calls.size(); pos; --pos) { - if constexpr(std::is_void_v || !std::is_invocable_v) { - calls[pos - 1u](args...); - - if constexpr(std::is_invocable_r_v) { - if(func()) { - break; - } - } else { - func(); - } - } else { - if constexpr(std::is_invocable_r_v) { - if(func(calls[pos - 1u](args...))) { - break; - } - } else { - func(calls[pos - 1u](args...)); - } - } - } - } - -private: - container_type calls; -}; - -/** - * @brief Connection class. - * - * Opaque object the aim of which is to allow users to release an already - * estabilished connection without having to keep a reference to the signal or - * the sink that generated it. - */ -class connection { - template - friend class sink; - - connection(delegate fn, void *ref) - : disconnect{fn}, signal{ref} {} - -public: - /*! @brief Default constructor. */ - connection() - : disconnect{}, - signal{} {} - - /** - * @brief Checks whether a connection is properly initialized. - * @return True if the connection is properly initialized, false otherwise. - */ - [[nodiscard]] explicit operator bool() const noexcept { - return static_cast(disconnect); - } - - /*! @brief Breaks the connection. */ - void release() { - if(disconnect) { - disconnect(signal); - disconnect.reset(); - } - } - -private: - delegate disconnect; - void *signal; -}; - -/** - * @brief Scoped connection class. - * - * Opaque object the aim of which is to allow users to release an already - * estabilished connection without having to keep a reference to the signal or - * the sink that generated it.
- * A scoped connection automatically breaks the link between the two objects - * when it goes out of scope. - */ -struct scoped_connection { - /*! @brief Default constructor. */ - scoped_connection() = default; - - /** - * @brief Constructs a scoped connection from a basic connection. - * @param other A valid connection object. - */ - scoped_connection(const connection &other) - : conn{other} {} - - /*! @brief Default copy constructor, deleted on purpose. */ - scoped_connection(const scoped_connection &) = delete; - - /** - * @brief Move constructor. - * @param other The scoped connection to move from. - */ - scoped_connection(scoped_connection &&other) noexcept - : conn{std::exchange(other.conn, {})} {} - - /*! @brief Automatically breaks the link on destruction. */ - ~scoped_connection() noexcept { - conn.release(); - } - - /** - * @brief Default copy assignment operator, deleted on purpose. - * @return This scoped connection. - */ - scoped_connection &operator=(const scoped_connection &) = delete; - - /** - * @brief Move assignment operator. - * @param other The scoped connection to move from. - * @return This scoped connection. - */ - scoped_connection &operator=(scoped_connection &&other) noexcept { - conn = std::exchange(other.conn, {}); - return *this; - } - - /** - * @brief Acquires a connection. - * @param other The connection object to acquire. - * @return This scoped connection. - */ - scoped_connection &operator=(connection other) { - conn = other; - return *this; - } - - /** - * @brief Checks whether a scoped connection is properly initialized. - * @return True if the connection is properly initialized, false otherwise. - */ - [[nodiscard]] explicit operator bool() const noexcept { - return static_cast(conn); - } - - /*! @brief Breaks the connection. */ - void release() { - conn.release(); - } - -private: - connection conn; -}; - -/** - * @brief Sink class. - * - * A sink is used to connect listeners to signals and to disconnect them.
- * The function type for a listener is the one of the signal to which it - * belongs. - * - * The clear separation between a signal and a sink permits to store the former - * as private data member without exposing the publish functionality to the - * users of the class. - * - * @warning - * Lifetime of a sink must not overcome that of the signal to which it refers. - * In any other case, attempting to use a sink results in undefined behavior. - * - * @tparam Ret Return type of a function type. - * @tparam Args Types of arguments of a function type. - * @tparam Allocator Type of allocator used to manage memory and elements. - */ -template -class sink> { - using signal_type = sigh; - using delegate_type = typename signal_type::delegate_type; - using difference_type = typename signal_type::container_type::difference_type; - - template - static void release(Type value_or_instance, void *signal) { - sink{*static_cast(signal)}.disconnect(value_or_instance); - } - - template - static void release(void *signal) { - sink{*static_cast(signal)}.disconnect(); - } - - template - void disconnect_if(Func callback) { - for(auto pos = signal->calls.size(); pos; --pos) { - if(auto &elem = signal->calls[pos - 1u]; callback(elem)) { - elem = std::move(signal->calls.back()); - signal->calls.pop_back(); - } - } - } - -public: - /** - * @brief Constructs a sink that is allowed to modify a given signal. - * @param ref A valid reference to a signal object. - */ - sink(sigh &ref) noexcept - : signal{&ref} {} - - /** - * @brief Returns false if at least a listener is connected to the sink. - * @return True if the sink has no listeners connected, false otherwise. - */ - [[nodiscard]] bool empty() const noexcept { - return signal->calls.empty(); - } - - /** - * @brief Connects a free function (with or without payload), a bound or an - * unbound member to a signal. - * @tparam Candidate Function or member to connect to the signal. - * @tparam Type Type of class or type of payload, if any. - * @param value_or_instance A valid object that fits the purpose, if any. - * @return A properly initialized connection object. - */ - template - connection connect(Type &&...value_or_instance) { - disconnect(value_or_instance...); - - delegate_type call{}; - call.template connect(value_or_instance...); - signal->calls.push_back(std::move(call)); - - delegate conn{}; - conn.template connect<&release>(value_or_instance...); - return {conn, signal}; - } - - /** - * @brief Disconnects a free function (with or without payload), a bound or - * an unbound member from a signal. - * @tparam Candidate Function or member to disconnect from the signal. - * @tparam Type Type of class or type of payload, if any. - * @param value_or_instance A valid object that fits the purpose, if any. - */ - template - void disconnect(Type &&...value_or_instance) { - delegate_type call{}; - call.template connect(value_or_instance...); - disconnect_if([&call](const auto &elem) { return elem == call; }); - } - - /** - * @brief Disconnects free functions with payload or bound members from a - * signal. - * @param value_or_instance A valid object that fits the purpose. - */ - void disconnect(const void *value_or_instance) { - ENTT_ASSERT(value_or_instance != nullptr, "Invalid value or instance"); - disconnect_if([value_or_instance](const auto &elem) { return elem.data() == value_or_instance; }); - } - - /*! @brief Disconnects all the listeners from a signal. */ - void disconnect() { - signal->calls.clear(); - } - -private: - signal_type *signal; -}; - -/** - * @brief Deduction guide. - * - * It allows to deduce the signal handler type of a sink directly from the - * signal it refers to. - * - * @tparam Ret Return type of a function type. - * @tparam Args Types of arguments of a function type. - * @tparam Allocator Type of allocator used to manage memory and elements. - */ -template -sink(sigh &) -> sink>; - -} // namespace entt - -#endif -- cgit