diff options
Diffstat (limited to 'deps/entt/include')
78 files changed, 0 insertions, 24084 deletions
diff --git a/deps/entt/include/entt/config/config.h b/deps/entt/include/entt/config/config.h deleted file mode 100644 index 80a3305..0000000 --- a/deps/entt/include/entt/config/config.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef ENTT_CONFIG_CONFIG_H -#define ENTT_CONFIG_CONFIG_H - -#include "version.h" - -// NOLINTBEGIN(cppcoreguidelines-macro-usage) - -#if defined(__cpp_exceptions) && !defined(ENTT_NOEXCEPTION) -# define ENTT_CONSTEXPR -# define ENTT_THROW throw -# define ENTT_TRY try -# define ENTT_CATCH catch(...) -#else -# define ENTT_CONSTEXPR constexpr // use only with throwing functions (waiting for C++20) -# define ENTT_THROW -# define ENTT_TRY if(true) -# define ENTT_CATCH if(false) -#endif - -#ifdef ENTT_USE_ATOMIC -# include <atomic> -# define ENTT_MAYBE_ATOMIC(Type) std::atomic<Type> -#else -# define ENTT_MAYBE_ATOMIC(Type) Type -#endif - -#ifndef ENTT_ID_TYPE -# include <cstdint> -# define ENTT_ID_TYPE std::uint32_t -#else -# include <cstdint> // provides coverage for types in the std namespace -#endif - -#ifndef ENTT_SPARSE_PAGE -# define ENTT_SPARSE_PAGE 4096 -#endif - -#ifndef ENTT_PACKED_PAGE -# define ENTT_PACKED_PAGE 1024 -#endif - -#ifdef ENTT_DISABLE_ASSERT -# undef ENTT_ASSERT -# define ENTT_ASSERT(condition, msg) (void(0)) -#elif !defined ENTT_ASSERT -# include <cassert> -# define ENTT_ASSERT(condition, msg) assert(condition) -#endif - -#ifdef ENTT_DISABLE_ASSERT -# undef ENTT_ASSERT_CONSTEXPR -# define ENTT_ASSERT_CONSTEXPR(condition, msg) (void(0)) -#elif !defined ENTT_ASSERT_CONSTEXPR -# define ENTT_ASSERT_CONSTEXPR(condition, msg) ENTT_ASSERT(condition, msg) -#endif - -#define ENTT_FAIL(msg) ENTT_ASSERT(false, msg); - -#ifdef ENTT_NO_ETO -# define ENTT_ETO_TYPE(Type) void -#else -# define ENTT_ETO_TYPE(Type) Type -#endif - -#ifdef ENTT_NO_MIXIN -# define ENTT_STORAGE(Mixin, ...) __VA_ARGS__ -#else -# define ENTT_STORAGE(Mixin, ...) Mixin<__VA_ARGS__> -#endif - -#ifdef ENTT_STANDARD_CPP -# define ENTT_NONSTD false -#else -# define ENTT_NONSTD true -# if defined __clang__ || defined __GNUC__ -# define ENTT_PRETTY_FUNCTION __PRETTY_FUNCTION__ -# define ENTT_PRETTY_FUNCTION_PREFIX '=' -# define ENTT_PRETTY_FUNCTION_SUFFIX ']' -# elif defined _MSC_VER -# define ENTT_PRETTY_FUNCTION __FUNCSIG__ -# define ENTT_PRETTY_FUNCTION_PREFIX '<' -# define ENTT_PRETTY_FUNCTION_SUFFIX '>' -# endif -#endif - -#if defined _MSC_VER -# pragma detect_mismatch("entt.version", ENTT_VERSION) -# pragma detect_mismatch("entt.noexcept", ENTT_XSTR(ENTT_TRY)) -# pragma detect_mismatch("entt.id", ENTT_XSTR(ENTT_ID_TYPE)) -# pragma detect_mismatch("entt.nonstd", ENTT_XSTR(ENTT_NONSTD)) -#endif - -// NOLINTEND(cppcoreguidelines-macro-usage) - -#endif diff --git a/deps/entt/include/entt/config/macro.h b/deps/entt/include/entt/config/macro.h deleted file mode 100644 index b7b2323..0000000 --- a/deps/entt/include/entt/config/macro.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef ENTT_CONFIG_MACRO_H -#define ENTT_CONFIG_MACRO_H - -// NOLINTBEGIN(cppcoreguidelines-macro-usage) - -#define ENTT_STR(arg) #arg -#define ENTT_XSTR(arg) ENTT_STR(arg) - -// NOLINTEND(cppcoreguidelines-macro-usage) - -#endif diff --git a/deps/entt/include/entt/config/version.h b/deps/entt/include/entt/config/version.h deleted file mode 100644 index 843443f..0000000 --- a/deps/entt/include/entt/config/version.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef ENTT_CONFIG_VERSION_H -#define ENTT_CONFIG_VERSION_H - -#include "macro.h" - -// NOLINTBEGIN(cppcoreguidelines-macro-usage) - -#define ENTT_VERSION_MAJOR 3 -#define ENTT_VERSION_MINOR 14 -#define ENTT_VERSION_PATCH 0 - -#define ENTT_VERSION \ - ENTT_XSTR(ENTT_VERSION_MAJOR) \ - "." ENTT_XSTR(ENTT_VERSION_MINOR) "." ENTT_XSTR(ENTT_VERSION_PATCH) - -// NOLINTEND(cppcoreguidelines-macro-usage) - -#endif diff --git a/deps/entt/include/entt/container/dense_map.hpp b/deps/entt/include/entt/container/dense_map.hpp deleted file mode 100644 index 6bf7238..0000000 --- a/deps/entt/include/entt/container/dense_map.hpp +++ /dev/null @@ -1,1043 +0,0 @@ -#ifndef ENTT_CONTAINER_DENSE_MAP_HPP -#define ENTT_CONTAINER_DENSE_MAP_HPP - -#include <cmath> -#include <cstddef> -#include <functional> -#include <iterator> -#include <limits> -#include <memory> -#include <tuple> -#include <type_traits> -#include <utility> -#include <vector> -#include "../config/config.h" -#include "../core/compressed_pair.hpp" -#include "../core/iterator.hpp" -#include "../core/memory.hpp" -#include "../core/bit.hpp" -#include "../core/type_traits.hpp" -#include "fwd.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename Key, typename Type> -struct dense_map_node final { - using value_type = std::pair<Key, Type>; - - template<typename... Args> - dense_map_node(const std::size_t pos, Args &&...args) - : next{pos}, - element{std::forward<Args>(args)...} {} - - template<typename Allocator, typename... Args> - dense_map_node(std::allocator_arg_t, const Allocator &allocator, const std::size_t pos, Args &&...args) - : next{pos}, - element{entt::make_obj_using_allocator<value_type>(allocator, std::forward<Args>(args)...)} {} - - template<typename Allocator> - dense_map_node(std::allocator_arg_t, const Allocator &allocator, const dense_map_node &other) - : next{other.next}, - element{entt::make_obj_using_allocator<value_type>(allocator, other.element)} {} - - template<typename Allocator> - dense_map_node(std::allocator_arg_t, const Allocator &allocator, dense_map_node &&other) - : next{other.next}, - element{entt::make_obj_using_allocator<value_type>(allocator, std::move(other.element))} {} - - std::size_t next; - value_type element; -}; - -template<typename It> -class dense_map_iterator final { - template<typename> - friend class dense_map_iterator; - - using first_type = decltype(std::as_const(std::declval<It>()->element.first)); - using second_type = decltype((std::declval<It>()->element.second)); - -public: - using value_type = std::pair<first_type, second_type>; - using pointer = input_iterator_pointer<value_type>; - using reference = value_type; - using difference_type = std::ptrdiff_t; - using iterator_category = std::input_iterator_tag; - using iterator_concept = std::random_access_iterator_tag; - - constexpr dense_map_iterator() noexcept - : it{} {} - - constexpr dense_map_iterator(const It iter) noexcept - : it{iter} {} - - template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>> - constexpr dense_map_iterator(const dense_map_iterator<Other> &other) noexcept - : it{other.it} {} - - constexpr dense_map_iterator &operator++() noexcept { - return ++it, *this; - } - - constexpr dense_map_iterator operator++(int) noexcept { - dense_map_iterator orig = *this; - return ++(*this), orig; - } - - constexpr dense_map_iterator &operator--() noexcept { - return --it, *this; - } - - constexpr dense_map_iterator operator--(int) noexcept { - dense_map_iterator orig = *this; - return operator--(), orig; - } - - constexpr dense_map_iterator &operator+=(const difference_type value) noexcept { - it += value; - return *this; - } - - constexpr dense_map_iterator operator+(const difference_type value) const noexcept { - dense_map_iterator copy = *this; - return (copy += value); - } - - constexpr dense_map_iterator &operator-=(const difference_type value) noexcept { - return (*this += -value); - } - - constexpr dense_map_iterator operator-(const difference_type value) const noexcept { - return (*this + -value); - } - - [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept { - return {it[value].element.first, it[value].element.second}; - } - - [[nodiscard]] constexpr pointer operator->() const noexcept { - return operator*(); - } - - [[nodiscard]] constexpr reference operator*() const noexcept { - return operator[](0); - } - - template<typename Lhs, typename Rhs> - friend constexpr std::ptrdiff_t operator-(const dense_map_iterator<Lhs> &, const dense_map_iterator<Rhs> &) noexcept; - - template<typename Lhs, typename Rhs> - friend constexpr bool operator==(const dense_map_iterator<Lhs> &, const dense_map_iterator<Rhs> &) noexcept; - - template<typename Lhs, typename Rhs> - friend constexpr bool operator<(const dense_map_iterator<Lhs> &, const dense_map_iterator<Rhs> &) noexcept; - -private: - It it; -}; - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr std::ptrdiff_t operator-(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept { - return lhs.it - rhs.it; -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator==(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept { - return lhs.it == rhs.it; -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator!=(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept { - return !(lhs == rhs); -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator<(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept { - return lhs.it < rhs.it; -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator>(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept { - return rhs < lhs; -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator<=(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept { - return !(lhs > rhs); -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator>=(const dense_map_iterator<Lhs> &lhs, const dense_map_iterator<Rhs> &rhs) noexcept { - return !(lhs < rhs); -} - -template<typename It> -class dense_map_local_iterator final { - template<typename> - friend class dense_map_local_iterator; - - using first_type = decltype(std::as_const(std::declval<It>()->element.first)); - using second_type = decltype((std::declval<It>()->element.second)); - -public: - using value_type = std::pair<first_type, second_type>; - using pointer = input_iterator_pointer<value_type>; - using reference = value_type; - using difference_type = std::ptrdiff_t; - using iterator_category = std::input_iterator_tag; - using iterator_concept = std::forward_iterator_tag; - - constexpr dense_map_local_iterator() noexcept - : it{}, - offset{} {} - - constexpr dense_map_local_iterator(It iter, const std::size_t pos) noexcept - : it{iter}, - offset{pos} {} - - template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>> - constexpr dense_map_local_iterator(const dense_map_local_iterator<Other> &other) noexcept - : it{other.it}, - offset{other.offset} {} - - constexpr dense_map_local_iterator &operator++() noexcept { - return offset = it[offset].next, *this; - } - - constexpr dense_map_local_iterator operator++(int) noexcept { - dense_map_local_iterator orig = *this; - return ++(*this), orig; - } - - [[nodiscard]] constexpr pointer operator->() const noexcept { - return operator*(); - } - - [[nodiscard]] constexpr reference operator*() const noexcept { - return {it[offset].element.first, it[offset].element.second}; - } - - [[nodiscard]] constexpr std::size_t index() const noexcept { - return offset; - } - -private: - It it; - std::size_t offset; -}; - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator==(const dense_map_local_iterator<Lhs> &lhs, const dense_map_local_iterator<Rhs> &rhs) noexcept { - return lhs.index() == rhs.index(); -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator!=(const dense_map_local_iterator<Lhs> &lhs, const dense_map_local_iterator<Rhs> &rhs) noexcept { - return !(lhs == rhs); -} - -} // namespace internal -/*! @endcond */ - -/** - * @brief Associative container for key-value pairs with unique keys. - * - * Internally, elements are organized into buckets. Which bucket an element is - * placed into depends entirely on the hash of its key. Keys with the same hash - * code appear in the same bucket. - * - * @tparam Key Key type of the associative container. - * @tparam Type Mapped type of the associative container. - * @tparam Hash Type of function to use to hash the keys. - * @tparam KeyEqual Type of function to use to compare the keys for equality. - * @tparam Allocator Type of allocator used to manage memory and elements. - */ -template<typename Key, typename Type, typename Hash, typename KeyEqual, typename Allocator> -class dense_map { - static constexpr float default_threshold = 0.875f; - static constexpr std::size_t minimum_capacity = 8u; - - using node_type = internal::dense_map_node<Key, Type>; - using alloc_traits = std::allocator_traits<Allocator>; - static_assert(std::is_same_v<typename alloc_traits::value_type, std::pair<const Key, Type>>, "Invalid value type"); - using sparse_container_type = std::vector<std::size_t, typename alloc_traits::template rebind_alloc<std::size_t>>; - using packed_container_type = std::vector<node_type, typename alloc_traits::template rebind_alloc<node_type>>; - - template<typename Other> - [[nodiscard]] std::size_t key_to_bucket(const Other &key) const noexcept { - return fast_mod(static_cast<size_type>(sparse.second()(key)), bucket_count()); - } - - template<typename Other> - [[nodiscard]] auto constrained_find(const Other &key, std::size_t bucket) { - for(auto it = begin(bucket), last = end(bucket); it != last; ++it) { - if(packed.second()(it->first, key)) { - return begin() + static_cast<typename iterator::difference_type>(it.index()); - } - } - - return end(); - } - - template<typename Other> - [[nodiscard]] auto constrained_find(const Other &key, std::size_t bucket) const { - for(auto it = cbegin(bucket), last = cend(bucket); it != last; ++it) { - if(packed.second()(it->first, key)) { - return cbegin() + static_cast<typename iterator::difference_type>(it.index()); - } - } - - return cend(); - } - - template<typename Other, typename... Args> - [[nodiscard]] auto insert_or_do_nothing(Other &&key, Args &&...args) { - const auto index = key_to_bucket(key); - - if(auto it = constrained_find(key, index); it != end()) { - return std::make_pair(it, false); - } - - packed.first().emplace_back(sparse.first()[index], std::piecewise_construct, std::forward_as_tuple(std::forward<Other>(key)), std::forward_as_tuple(std::forward<Args>(args)...)); - sparse.first()[index] = packed.first().size() - 1u; - rehash_if_required(); - - return std::make_pair(--end(), true); - } - - template<typename Other, typename Arg> - [[nodiscard]] auto insert_or_overwrite(Other &&key, Arg &&value) { - const auto index = key_to_bucket(key); - - if(auto it = constrained_find(key, index); it != end()) { - it->second = std::forward<Arg>(value); - return std::make_pair(it, false); - } - - packed.first().emplace_back(sparse.first()[index], std::forward<Other>(key), std::forward<Arg>(value)); - sparse.first()[index] = packed.first().size() - 1u; - rehash_if_required(); - - return std::make_pair(--end(), true); - } - - void move_and_pop(const std::size_t pos) { - if(const auto last = size() - 1u; pos != last) { - size_type *curr = &sparse.first()[key_to_bucket(packed.first().back().element.first)]; - packed.first()[pos] = std::move(packed.first().back()); - for(; *curr != last; curr = &packed.first()[*curr].next) {} - *curr = pos; - } - - packed.first().pop_back(); - } - - void rehash_if_required() { - if(size() > (bucket_count() * max_load_factor())) { - rehash(bucket_count() * 2u); - } - } - -public: - /*! @brief Allocator type. */ - using allocator_type = Allocator; - /*! @brief Key type of the container. */ - using key_type = Key; - /*! @brief Mapped type of the container. */ - using mapped_type = Type; - /*! @brief Key-value type of the container. */ - using value_type = std::pair<const Key, Type>; - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - /*! @brief Type of function to use to hash the keys. */ - using hasher = Hash; - /*! @brief Type of function to use to compare the keys for equality. */ - using key_equal = KeyEqual; - /*! @brief Input iterator type. */ - using iterator = internal::dense_map_iterator<typename packed_container_type::iterator>; - /*! @brief Constant input iterator type. */ - using const_iterator = internal::dense_map_iterator<typename packed_container_type::const_iterator>; - /*! @brief Input iterator type. */ - using local_iterator = internal::dense_map_local_iterator<typename packed_container_type::iterator>; - /*! @brief Constant input iterator type. */ - using const_local_iterator = internal::dense_map_local_iterator<typename packed_container_type::const_iterator>; - - /*! @brief Default constructor. */ - dense_map() - : dense_map{minimum_capacity} {} - - /** - * @brief Constructs an empty container with a given allocator. - * @param allocator The allocator to use. - */ - explicit dense_map(const allocator_type &allocator) - : dense_map{minimum_capacity, hasher{}, key_equal{}, allocator} {} - - /** - * @brief Constructs an empty container with a given allocator and user - * supplied minimal number of buckets. - * @param cnt Minimal number of buckets. - * @param allocator The allocator to use. - */ - dense_map(const size_type cnt, const allocator_type &allocator) - : dense_map{cnt, hasher{}, key_equal{}, allocator} {} - - /** - * @brief Constructs an empty container with a given allocator, hash - * function and user supplied minimal number of buckets. - * @param cnt Minimal number of buckets. - * @param hash Hash function to use. - * @param allocator The allocator to use. - */ - dense_map(const size_type cnt, const hasher &hash, const allocator_type &allocator) - : dense_map{cnt, hash, key_equal{}, allocator} {} - - /** - * @brief Constructs an empty container with a given allocator, hash - * function, compare function and user supplied minimal number of buckets. - * @param cnt Minimal number of buckets. - * @param hash Hash function to use. - * @param equal Compare function to use. - * @param allocator The allocator to use. - */ - explicit dense_map(const size_type cnt, const hasher &hash = hasher{}, const key_equal &equal = key_equal{}, const allocator_type &allocator = allocator_type{}) - : sparse{allocator, hash}, - packed{allocator, equal} { - rehash(cnt); - } - - /*! @brief Default copy constructor. */ - dense_map(const dense_map &) = default; - - /** - * @brief Allocator-extended copy constructor. - * @param other The instance to copy from. - * @param allocator The allocator to use. - */ - dense_map(const dense_map &other, const allocator_type &allocator) - : sparse{std::piecewise_construct, std::forward_as_tuple(other.sparse.first(), allocator), std::forward_as_tuple(other.sparse.second())}, - packed{std::piecewise_construct, std::forward_as_tuple(other.packed.first(), allocator), std::forward_as_tuple(other.packed.second())}, - threshold{other.threshold} {} - - /*! @brief Default move constructor. */ - dense_map(dense_map &&) noexcept(std::is_nothrow_move_constructible_v<compressed_pair<sparse_container_type, hasher>> && std::is_nothrow_move_constructible_v<compressed_pair<packed_container_type, key_equal>>) = default; - - /** - * @brief Allocator-extended move constructor. - * @param other The instance to move from. - * @param allocator The allocator to use. - */ - dense_map(dense_map &&other, const allocator_type &allocator) - : sparse{std::piecewise_construct, std::forward_as_tuple(std::move(other.sparse.first()), allocator), std::forward_as_tuple(std::move(other.sparse.second()))}, - packed{std::piecewise_construct, std::forward_as_tuple(std::move(other.packed.first()), allocator), std::forward_as_tuple(std::move(other.packed.second()))}, - threshold{other.threshold} {} - - /*! @brief Default destructor. */ - ~dense_map() noexcept = default; - - /** - * @brief Default copy assignment operator. - * @return This container. - */ - dense_map &operator=(const dense_map &) = default; - - /** - * @brief Default move assignment operator. - * @return This container. - */ - dense_map &operator=(dense_map &&) noexcept(std::is_nothrow_move_assignable_v<compressed_pair<sparse_container_type, hasher>> && std::is_nothrow_move_assignable_v<compressed_pair<packed_container_type, key_equal>>) = default; - - /** - * @brief Returns the associated allocator. - * @return The associated allocator. - */ - [[nodiscard]] constexpr allocator_type get_allocator() const noexcept { - return sparse.first().get_allocator(); - } - - /** - * @brief Returns an iterator to the beginning. - * - * If the array is empty, the returned iterator will be equal to `end()`. - * - * @return An iterator to the first instance of the internal array. - */ - [[nodiscard]] const_iterator cbegin() const noexcept { - return packed.first().begin(); - } - - /*! @copydoc cbegin */ - [[nodiscard]] const_iterator begin() const noexcept { - return cbegin(); - } - - /*! @copydoc begin */ - [[nodiscard]] iterator begin() noexcept { - return packed.first().begin(); - } - - /** - * @brief Returns an iterator to the end. - * @return An iterator to the element following the last instance of the - * internal array. - */ - [[nodiscard]] const_iterator cend() const noexcept { - return packed.first().end(); - } - - /*! @copydoc cend */ - [[nodiscard]] const_iterator end() const noexcept { - return cend(); - } - - /*! @copydoc end */ - [[nodiscard]] iterator end() noexcept { - return packed.first().end(); - } - - /** - * @brief Checks whether a container is empty. - * @return True if the container is empty, false otherwise. - */ - [[nodiscard]] bool empty() const noexcept { - return packed.first().empty(); - } - - /** - * @brief Returns the number of elements in a container. - * @return Number of elements in a container. - */ - [[nodiscard]] size_type size() const noexcept { - return packed.first().size(); - } - - /** - * @brief Returns the maximum possible number of elements. - * @return Maximum possible number of elements. - */ - [[nodiscard]] size_type max_size() const noexcept { - return packed.first().max_size(); - } - - /*! @brief Clears the container. */ - void clear() noexcept { - sparse.first().clear(); - packed.first().clear(); - rehash(0u); - } - - /** - * @brief Inserts an element into the container, if the key does not exist. - * @param value A key-value pair eventually convertible to the value type. - * @return A pair consisting of an iterator to the inserted element (or to - * the element that prevented the insertion) and a bool denoting whether the - * insertion took place. - */ - std::pair<iterator, bool> insert(const value_type &value) { - return insert_or_do_nothing(value.first, value.second); - } - - /*! @copydoc insert */ - std::pair<iterator, bool> insert(value_type &&value) { - return insert_or_do_nothing(std::move(value.first), std::move(value.second)); - } - - /** - * @copydoc insert - * @tparam Arg Type of the key-value pair to insert into the container. - */ - template<typename Arg> - std::enable_if_t<std::is_constructible_v<value_type, Arg &&>, std::pair<iterator, bool>> - insert(Arg &&value) { - return insert_or_do_nothing(std::forward<Arg>(value).first, std::forward<Arg>(value).second); - } - - /** - * @brief Inserts elements into the container, if their keys do not exist. - * @tparam It Type of input iterator. - * @param first An iterator to the first element of the range of elements. - * @param last An iterator past the last element of the range of elements. - */ - template<typename It> - void insert(It first, It last) { - for(; first != last; ++first) { - insert(*first); - } - } - - /** - * @brief Inserts an element into the container or assigns to the current - * element if the key already exists. - * @tparam Arg Type of the value to insert or assign. - * @param key A key used both to look up and to insert if not found. - * @param value A value to insert or assign. - * @return A pair consisting of an iterator to the element and a bool - * denoting whether the insertion took place. - */ - template<typename Arg> - std::pair<iterator, bool> insert_or_assign(const key_type &key, Arg &&value) { - return insert_or_overwrite(key, std::forward<Arg>(value)); - } - - /*! @copydoc insert_or_assign */ - template<typename Arg> - std::pair<iterator, bool> insert_or_assign(key_type &&key, Arg &&value) { - return insert_or_overwrite(std::move(key), std::forward<Arg>(value)); - } - - /** - * @brief Constructs an element in-place, if the key does not exist. - * - * The element is also constructed when the container already has the key, - * in which case the newly constructed object is destroyed immediately. - * - * @tparam Args Types of arguments to forward to the constructor of the - * element. - * @param args Arguments to forward to the constructor of the element. - * @return A pair consisting of an iterator to the inserted element (or to - * the element that prevented the insertion) and a bool denoting whether the - * insertion took place. - */ - template<typename... Args> - std::pair<iterator, bool> emplace([[maybe_unused]] Args &&...args) { - if constexpr(sizeof...(Args) == 0u) { - return insert_or_do_nothing(key_type{}); - } else if constexpr(sizeof...(Args) == 1u) { - return insert_or_do_nothing(std::forward<Args>(args).first..., std::forward<Args>(args).second...); - } else if constexpr(sizeof...(Args) == 2u) { - return insert_or_do_nothing(std::forward<Args>(args)...); - } else { - auto &node = packed.first().emplace_back(packed.first().size(), std::forward<Args>(args)...); - const auto index = key_to_bucket(node.element.first); - - if(auto it = constrained_find(node.element.first, index); it != end()) { - packed.first().pop_back(); - return std::make_pair(it, false); - } - - std::swap(node.next, sparse.first()[index]); - rehash_if_required(); - - return std::make_pair(--end(), true); - } - } - - /** - * @brief Inserts in-place if the key does not exist, does nothing if the - * key exists. - * @tparam Args Types of arguments to forward to the constructor of the - * element. - * @param key A key used both to look up and to insert if not found. - * @param args Arguments to forward to the constructor of the element. - * @return A pair consisting of an iterator to the inserted element (or to - * the element that prevented the insertion) and a bool denoting whether the - * insertion took place. - */ - template<typename... Args> - std::pair<iterator, bool> try_emplace(const key_type &key, Args &&...args) { - return insert_or_do_nothing(key, std::forward<Args>(args)...); - } - - /*! @copydoc try_emplace */ - template<typename... Args> - std::pair<iterator, bool> try_emplace(key_type &&key, Args &&...args) { - return insert_or_do_nothing(std::move(key), std::forward<Args>(args)...); - } - - /** - * @brief Removes an element from a given position. - * @param pos An iterator to the element to remove. - * @return An iterator following the removed element. - */ - iterator erase(const_iterator pos) { - const auto diff = pos - cbegin(); - erase(pos->first); - return begin() + diff; - } - - /** - * @brief Removes the given elements from a container. - * @param first An iterator to the first element of the range of elements. - * @param last An iterator past the last element of the range of elements. - * @return An iterator following the last removed element. - */ - iterator erase(const_iterator first, const_iterator last) { - const auto dist = first - cbegin(); - - for(auto from = last - cbegin(); from != dist; --from) { - erase(packed.first()[from - 1u].element.first); - } - - return (begin() + dist); - } - - /** - * @brief Removes the element associated with a given key. - * @param key A key value of an element to remove. - * @return Number of elements removed (either 0 or 1). - */ - size_type erase(const key_type &key) { - for(size_type *curr = &sparse.first()[key_to_bucket(key)]; *curr != (std::numeric_limits<size_type>::max)(); curr = &packed.first()[*curr].next) { - if(packed.second()(packed.first()[*curr].element.first, key)) { - const auto index = *curr; - *curr = packed.first()[*curr].next; - move_and_pop(index); - return 1u; - } - } - - return 0u; - } - - /** - * @brief Exchanges the contents with those of a given container. - * @param other Container to exchange the content with. - */ - void swap(dense_map &other) { - using std::swap; - swap(sparse, other.sparse); - swap(packed, other.packed); - swap(threshold, other.threshold); - } - - /** - * @brief Accesses a given element with bounds checking. - * @param key A key of an element to find. - * @return A reference to the mapped value of the requested element. - */ - [[nodiscard]] mapped_type &at(const key_type &key) { - auto it = find(key); - ENTT_ASSERT(it != end(), "Invalid key"); - return it->second; - } - - /*! @copydoc at */ - [[nodiscard]] const mapped_type &at(const key_type &key) const { - auto it = find(key); - ENTT_ASSERT(it != cend(), "Invalid key"); - return it->second; - } - - /** - * @brief Accesses or inserts a given element. - * @param key A key of an element to find or insert. - * @return A reference to the mapped value of the requested element. - */ - [[nodiscard]] mapped_type &operator[](const key_type &key) { - return insert_or_do_nothing(key).first->second; - } - - /** - * @brief Accesses or inserts a given element. - * @param key A key of an element to find or insert. - * @return A reference to the mapped value of the requested element. - */ - [[nodiscard]] mapped_type &operator[](key_type &&key) { - return insert_or_do_nothing(std::move(key)).first->second; - } - - /** - * @brief Returns the number of elements matching a key (either 1 or 0). - * @param key Key value of an element to search for. - * @return Number of elements matching the key (either 1 or 0). - */ - [[nodiscard]] size_type count(const key_type &key) const { - return find(key) != end(); - } - - /** - * @brief Returns the number of elements matching a key (either 1 or 0). - * @tparam Other Type of the key value of an element to search for. - * @param key Key value of an element to search for. - * @return Number of elements matching the key (either 1 or 0). - */ - template<typename Other> - [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, size_type>> - count(const Other &key) const { - return find(key) != end(); - } - - /** - * @brief Finds an element with a given key. - * @param key Key value of an element to search for. - * @return An iterator to an element with the given key. If no such element - * is found, a past-the-end iterator is returned. - */ - [[nodiscard]] iterator find(const key_type &key) { - return constrained_find(key, key_to_bucket(key)); - } - - /*! @copydoc find */ - [[nodiscard]] const_iterator find(const key_type &key) const { - return constrained_find(key, key_to_bucket(key)); - } - - /** - * @brief Finds an element with a key that compares _equivalent_ to a given - * key. - * @tparam Other Type of the key value of an element to search for. - * @param key Key value of an element to search for. - * @return An iterator to an element with the given key. If no such element - * is found, a past-the-end iterator is returned. - */ - template<typename Other> - [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, iterator>> - find(const Other &key) { - return constrained_find(key, key_to_bucket(key)); - } - - /*! @copydoc find */ - template<typename Other> - [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, const_iterator>> - find(const Other &key) const { - return constrained_find(key, key_to_bucket(key)); - } - - /** - * @brief Returns a range containing all elements with a given key. - * @param key Key value of an element to search for. - * @return A pair of iterators pointing to the first element and past the - * last element of the range. - */ - [[nodiscard]] std::pair<iterator, iterator> equal_range(const key_type &key) { - const auto it = find(key); - return {it, it + !(it == end())}; - } - - /*! @copydoc equal_range */ - [[nodiscard]] std::pair<const_iterator, const_iterator> equal_range(const key_type &key) const { - const auto it = find(key); - return {it, it + !(it == cend())}; - } - - /** - * @brief Returns a range containing all elements that compare _equivalent_ - * to a given key. - * @tparam Other Type of an element to search for. - * @param key Key value of an element to search for. - * @return A pair of iterators pointing to the first element and past the - * last element of the range. - */ - template<typename Other> - [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<iterator, iterator>>> - equal_range(const Other &key) { - const auto it = find(key); - return {it, it + !(it == end())}; - } - - /*! @copydoc equal_range */ - template<typename Other> - [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<const_iterator, const_iterator>>> - equal_range(const Other &key) const { - const auto it = find(key); - return {it, it + !(it == cend())}; - } - - /** - * @brief Checks if the container contains an element with a given key. - * @param key Key value of an element to search for. - * @return True if there is such an element, false otherwise. - */ - [[nodiscard]] bool contains(const key_type &key) const { - return (find(key) != cend()); - } - - /** - * @brief Checks if the container contains an element with a key that - * compares _equivalent_ to a given value. - * @tparam Other Type of the key value of an element to search for. - * @param key Key value of an element to search for. - * @return True if there is such an element, false otherwise. - */ - template<typename Other> - [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, bool>> - contains(const Other &key) const { - return (find(key) != cend()); - } - - /** - * @brief Returns an iterator to the beginning of a given bucket. - * @param index An index of a bucket to access. - * @return An iterator to the beginning of the given bucket. - */ - [[nodiscard]] const_local_iterator cbegin(const size_type index) const { - return {packed.first().begin(), sparse.first()[index]}; - } - - /** - * @brief Returns an iterator to the beginning of a given bucket. - * @param index An index of a bucket to access. - * @return An iterator to the beginning of the given bucket. - */ - [[nodiscard]] const_local_iterator begin(const size_type index) const { - return cbegin(index); - } - - /** - * @brief Returns an iterator to the beginning of a given bucket. - * @param index An index of a bucket to access. - * @return An iterator to the beginning of the given bucket. - */ - [[nodiscard]] local_iterator begin(const size_type index) { - return {packed.first().begin(), sparse.first()[index]}; - } - - /** - * @brief Returns an iterator to the end of a given bucket. - * @param index An index of a bucket to access. - * @return An iterator to the end of the given bucket. - */ - [[nodiscard]] const_local_iterator cend([[maybe_unused]] const size_type index) const { - return {packed.first().begin(), (std::numeric_limits<size_type>::max)()}; - } - - /** - * @brief Returns an iterator to the end of a given bucket. - * @param index An index of a bucket to access. - * @return An iterator to the end of the given bucket. - */ - [[nodiscard]] const_local_iterator end(const size_type index) const { - return cend(index); - } - - /** - * @brief Returns an iterator to the end of a given bucket. - * @param index An index of a bucket to access. - * @return An iterator to the end of the given bucket. - */ - [[nodiscard]] local_iterator end([[maybe_unused]] const size_type index) { - return {packed.first().begin(), (std::numeric_limits<size_type>::max)()}; - } - - /** - * @brief Returns the number of buckets. - * @return The number of buckets. - */ - [[nodiscard]] size_type bucket_count() const { - return sparse.first().size(); - } - - /** - * @brief Returns the maximum number of buckets. - * @return The maximum number of buckets. - */ - [[nodiscard]] size_type max_bucket_count() const { - return sparse.first().max_size(); - } - - /** - * @brief Returns the number of elements in a given bucket. - * @param index The index of the bucket to examine. - * @return The number of elements in the given bucket. - */ - [[nodiscard]] size_type bucket_size(const size_type index) const { - return static_cast<size_type>(std::distance(begin(index), end(index))); - } - - /** - * @brief Returns the bucket for a given key. - * @param key The value of the key to examine. - * @return The bucket for the given key. - */ - [[nodiscard]] size_type bucket(const key_type &key) const { - return key_to_bucket(key); - } - - /** - * @brief Returns the average number of elements per bucket. - * @return The average number of elements per bucket. - */ - [[nodiscard]] float load_factor() const { - return size() / static_cast<float>(bucket_count()); - } - - /** - * @brief Returns the maximum average number of elements per bucket. - * @return The maximum average number of elements per bucket. - */ - [[nodiscard]] float max_load_factor() const { - return threshold; - } - - /** - * @brief Sets the desired maximum average number of elements per bucket. - * @param value A desired maximum average number of elements per bucket. - */ - void max_load_factor(const float value) { - ENTT_ASSERT(value > 0.f, "Invalid load factor"); - threshold = value; - rehash(0u); - } - - /** - * @brief Reserves at least the specified number of buckets and regenerates - * the hash table. - * @param cnt New number of buckets. - */ - void rehash(const size_type cnt) { - auto value = cnt > minimum_capacity ? cnt : minimum_capacity; - const auto cap = static_cast<size_type>(size() / max_load_factor()); - value = value > cap ? value : cap; - - if(const auto sz = next_power_of_two(value); sz != bucket_count()) { - sparse.first().resize(sz); - - for(auto &&elem: sparse.first()) { - elem = (std::numeric_limits<size_type>::max)(); - } - - for(size_type pos{}, last = size(); pos < last; ++pos) { - const auto index = key_to_bucket(packed.first()[pos].element.first); - packed.first()[pos].next = std::exchange(sparse.first()[index], pos); - } - } - } - - /** - * @brief Reserves space for at least the specified number of elements and - * regenerates the hash table. - * @param cnt New number of elements. - */ - void reserve(const size_type cnt) { - packed.first().reserve(cnt); - rehash(static_cast<size_type>(std::ceil(cnt / max_load_factor()))); - } - - /** - * @brief Returns the function used to hash the keys. - * @return The function used to hash the keys. - */ - [[nodiscard]] hasher hash_function() const { - return sparse.second(); - } - - /** - * @brief Returns the function used to compare keys for equality. - * @return The function used to compare keys for equality. - */ - [[nodiscard]] key_equal key_eq() const { - return packed.second(); - } - -private: - compressed_pair<sparse_container_type, hasher> sparse; - compressed_pair<packed_container_type, key_equal> packed; - float threshold{default_threshold}; -}; - -} // namespace entt - -/*! @cond TURN_OFF_DOXYGEN */ -namespace std { - -template<typename Key, typename Value, typename Allocator> -struct uses_allocator<entt::internal::dense_map_node<Key, Value>, Allocator> - : std::true_type {}; - -} // namespace std -/*! @endcond */ - -#endif diff --git a/deps/entt/include/entt/container/dense_set.hpp b/deps/entt/include/entt/container/dense_set.hpp deleted file mode 100644 index 1ad5057..0000000 --- a/deps/entt/include/entt/container/dense_set.hpp +++ /dev/null @@ -1,927 +0,0 @@ -#ifndef ENTT_CONTAINER_DENSE_SET_HPP -#define ENTT_CONTAINER_DENSE_SET_HPP - -#include <cmath> -#include <cstddef> -#include <functional> -#include <iterator> -#include <limits> -#include <memory> -#include <tuple> -#include <type_traits> -#include <utility> -#include <vector> -#include "../config/config.h" -#include "../core/bit.hpp" -#include "../core/compressed_pair.hpp" -#include "../core/type_traits.hpp" -#include "fwd.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename It> -class dense_set_iterator final { - template<typename> - friend class dense_set_iterator; - -public: - using value_type = typename It::value_type::second_type; - using pointer = const value_type *; - using reference = const value_type &; - using difference_type = std::ptrdiff_t; - using iterator_category = std::random_access_iterator_tag; - - constexpr dense_set_iterator() noexcept - : it{} {} - - constexpr dense_set_iterator(const It iter) noexcept - : it{iter} {} - - template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>> - constexpr dense_set_iterator(const dense_set_iterator<Other> &other) noexcept - : it{other.it} {} - - constexpr dense_set_iterator &operator++() noexcept { - return ++it, *this; - } - - constexpr dense_set_iterator operator++(int) noexcept { - dense_set_iterator orig = *this; - return ++(*this), orig; - } - - constexpr dense_set_iterator &operator--() noexcept { - return --it, *this; - } - - constexpr dense_set_iterator operator--(int) noexcept { - dense_set_iterator orig = *this; - return operator--(), orig; - } - - constexpr dense_set_iterator &operator+=(const difference_type value) noexcept { - it += value; - return *this; - } - - constexpr dense_set_iterator operator+(const difference_type value) const noexcept { - dense_set_iterator copy = *this; - return (copy += value); - } - - constexpr dense_set_iterator &operator-=(const difference_type value) noexcept { - return (*this += -value); - } - - constexpr dense_set_iterator operator-(const difference_type value) const noexcept { - return (*this + -value); - } - - [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept { - return it[value].second; - } - - [[nodiscard]] constexpr pointer operator->() const noexcept { - return std::addressof(operator[](0)); - } - - [[nodiscard]] constexpr reference operator*() const noexcept { - return operator[](0); - } - - template<typename Lhs, typename Rhs> - friend constexpr std::ptrdiff_t operator-(const dense_set_iterator<Lhs> &, const dense_set_iterator<Rhs> &) noexcept; - - template<typename Lhs, typename Rhs> - friend constexpr bool operator==(const dense_set_iterator<Lhs> &, const dense_set_iterator<Rhs> &) noexcept; - - template<typename Lhs, typename Rhs> - friend constexpr bool operator<(const dense_set_iterator<Lhs> &, const dense_set_iterator<Rhs> &) noexcept; - -private: - It it; -}; - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr std::ptrdiff_t operator-(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept { - return lhs.it - rhs.it; -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator==(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept { - return lhs.it == rhs.it; -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator!=(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept { - return !(lhs == rhs); -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator<(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept { - return lhs.it < rhs.it; -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator>(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept { - return rhs < lhs; -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator<=(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept { - return !(lhs > rhs); -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator>=(const dense_set_iterator<Lhs> &lhs, const dense_set_iterator<Rhs> &rhs) noexcept { - return !(lhs < rhs); -} - -template<typename It> -class dense_set_local_iterator final { - template<typename> - friend class dense_set_local_iterator; - -public: - using value_type = typename It::value_type::second_type; - using pointer = const value_type *; - using reference = const value_type &; - using difference_type = std::ptrdiff_t; - using iterator_category = std::forward_iterator_tag; - - constexpr dense_set_local_iterator() noexcept - : it{}, - offset{} {} - - constexpr dense_set_local_iterator(It iter, const std::size_t pos) noexcept - : it{iter}, - offset{pos} {} - - template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>> - constexpr dense_set_local_iterator(const dense_set_local_iterator<Other> &other) noexcept - : it{other.it}, - offset{other.offset} {} - - constexpr dense_set_local_iterator &operator++() noexcept { - return offset = it[offset].first, *this; - } - - constexpr dense_set_local_iterator operator++(int) noexcept { - dense_set_local_iterator orig = *this; - return ++(*this), orig; - } - - [[nodiscard]] constexpr pointer operator->() const noexcept { - return std::addressof(it[offset].second); - } - - [[nodiscard]] constexpr reference operator*() const noexcept { - return *operator->(); - } - - [[nodiscard]] constexpr std::size_t index() const noexcept { - return offset; - } - -private: - It it; - std::size_t offset; -}; - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator==(const dense_set_local_iterator<Lhs> &lhs, const dense_set_local_iterator<Rhs> &rhs) noexcept { - return lhs.index() == rhs.index(); -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator!=(const dense_set_local_iterator<Lhs> &lhs, const dense_set_local_iterator<Rhs> &rhs) noexcept { - return !(lhs == rhs); -} - -} // namespace internal -/*! @endcond */ - -/** - * @brief Associative container for unique objects of a given type. - * - * Internally, elements are organized into buckets. Which bucket an element is - * placed into depends entirely on its hash. Elements with the same hash code - * appear in the same bucket. - * - * @tparam Type Value type of the associative container. - * @tparam Hash Type of function to use to hash the values. - * @tparam KeyEqual Type of function to use to compare the values for equality. - * @tparam Allocator Type of allocator used to manage memory and elements. - */ -template<typename Type, typename Hash, typename KeyEqual, typename Allocator> -class dense_set { - static constexpr float default_threshold = 0.875f; - static constexpr std::size_t minimum_capacity = 8u; - - using node_type = std::pair<std::size_t, Type>; - using alloc_traits = std::allocator_traits<Allocator>; - static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type"); - using sparse_container_type = std::vector<std::size_t, typename alloc_traits::template rebind_alloc<std::size_t>>; - using packed_container_type = std::vector<node_type, typename alloc_traits::template rebind_alloc<node_type>>; - - template<typename Other> - [[nodiscard]] std::size_t value_to_bucket(const Other &value) const noexcept { - return fast_mod(static_cast<size_type>(sparse.second()(value)), bucket_count()); - } - - template<typename Other> - [[nodiscard]] auto constrained_find(const Other &value, std::size_t bucket) { - for(auto it = begin(bucket), last = end(bucket); it != last; ++it) { - if(packed.second()(*it, value)) { - return begin() + static_cast<typename iterator::difference_type>(it.index()); - } - } - - return end(); - } - - template<typename Other> - [[nodiscard]] auto constrained_find(const Other &value, std::size_t bucket) const { - for(auto it = cbegin(bucket), last = cend(bucket); it != last; ++it) { - if(packed.second()(*it, value)) { - return cbegin() + static_cast<typename iterator::difference_type>(it.index()); - } - } - - return cend(); - } - - template<typename Other> - [[nodiscard]] auto insert_or_do_nothing(Other &&value) { - const auto index = value_to_bucket(value); - - if(auto it = constrained_find(value, index); it != end()) { - return std::make_pair(it, false); - } - - packed.first().emplace_back(sparse.first()[index], std::forward<Other>(value)); - sparse.first()[index] = packed.first().size() - 1u; - rehash_if_required(); - - return std::make_pair(--end(), true); - } - - void move_and_pop(const std::size_t pos) { - if(const auto last = size() - 1u; pos != last) { - size_type *curr = &sparse.first()[value_to_bucket(packed.first().back().second)]; - packed.first()[pos] = std::move(packed.first().back()); - for(; *curr != last; curr = &packed.first()[*curr].first) {} - *curr = pos; - } - - packed.first().pop_back(); - } - - void rehash_if_required() { - if(size() > (bucket_count() * max_load_factor())) { - rehash(bucket_count() * 2u); - } - } - -public: - /*! @brief Allocator type. */ - using allocator_type = Allocator; - /*! @brief Key type of the container. */ - using key_type = Type; - /*! @brief Value type of the container. */ - using value_type = Type; - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - /*! @brief Type of function to use to hash the elements. */ - using hasher = Hash; - /*! @brief Type of function to use to compare the elements for equality. */ - using key_equal = KeyEqual; - /*! @brief Random access iterator type. */ - using iterator = internal::dense_set_iterator<typename packed_container_type::iterator>; - /*! @brief Constant random access iterator type. */ - using const_iterator = internal::dense_set_iterator<typename packed_container_type::const_iterator>; - /*! @brief Reverse iterator type. */ - using reverse_iterator = std::reverse_iterator<iterator>; - /*! @brief Constant reverse iterator type. */ - using const_reverse_iterator = std::reverse_iterator<const_iterator>; - /*! @brief Forward iterator type. */ - using local_iterator = internal::dense_set_local_iterator<typename packed_container_type::iterator>; - /*! @brief Constant forward iterator type. */ - using const_local_iterator = internal::dense_set_local_iterator<typename packed_container_type::const_iterator>; - - /*! @brief Default constructor. */ - dense_set() - : dense_set{minimum_capacity} {} - - /** - * @brief Constructs an empty container with a given allocator. - * @param allocator The allocator to use. - */ - explicit dense_set(const allocator_type &allocator) - : dense_set{minimum_capacity, hasher{}, key_equal{}, allocator} {} - - /** - * @brief Constructs an empty container with a given allocator and user - * supplied minimal number of buckets. - * @param cnt Minimal number of buckets. - * @param allocator The allocator to use. - */ - dense_set(const size_type cnt, const allocator_type &allocator) - : dense_set{cnt, hasher{}, key_equal{}, allocator} {} - - /** - * @brief Constructs an empty container with a given allocator, hash - * function and user supplied minimal number of buckets. - * @param cnt Minimal number of buckets. - * @param hash Hash function to use. - * @param allocator The allocator to use. - */ - dense_set(const size_type cnt, const hasher &hash, const allocator_type &allocator) - : dense_set{cnt, hash, key_equal{}, allocator} {} - - /** - * @brief Constructs an empty container with a given allocator, hash - * function, compare function and user supplied minimal number of buckets. - * @param cnt Minimal number of buckets. - * @param hash Hash function to use. - * @param equal Compare function to use. - * @param allocator The allocator to use. - */ - explicit dense_set(const size_type cnt, const hasher &hash = hasher{}, const key_equal &equal = key_equal{}, const allocator_type &allocator = allocator_type{}) - : sparse{allocator, hash}, - packed{allocator, equal} { - rehash(cnt); - } - - /*! @brief Default copy constructor. */ - dense_set(const dense_set &) = default; - - /** - * @brief Allocator-extended copy constructor. - * @param other The instance to copy from. - * @param allocator The allocator to use. - */ - dense_set(const dense_set &other, const allocator_type &allocator) - : sparse{std::piecewise_construct, std::forward_as_tuple(other.sparse.first(), allocator), std::forward_as_tuple(other.sparse.second())}, - packed{std::piecewise_construct, std::forward_as_tuple(other.packed.first(), allocator), std::forward_as_tuple(other.packed.second())}, - threshold{other.threshold} {} - - /*! @brief Default move constructor. */ - dense_set(dense_set &&) noexcept(std::is_nothrow_move_constructible_v<compressed_pair<sparse_container_type, hasher>> && std::is_nothrow_move_constructible_v<compressed_pair<packed_container_type, key_equal>>) = default; - - /** - * @brief Allocator-extended move constructor. - * @param other The instance to move from. - * @param allocator The allocator to use. - */ - dense_set(dense_set &&other, const allocator_type &allocator) - : sparse{std::piecewise_construct, std::forward_as_tuple(std::move(other.sparse.first()), allocator), std::forward_as_tuple(std::move(other.sparse.second()))}, - packed{std::piecewise_construct, std::forward_as_tuple(std::move(other.packed.first()), allocator), std::forward_as_tuple(std::move(other.packed.second()))}, - threshold{other.threshold} {} - - /*! @brief Default destructor. */ - ~dense_set() noexcept = default; - - /** - * @brief Default copy assignment operator. - * @return This container. - */ - dense_set &operator=(const dense_set &) = default; - - /** - * @brief Default move assignment operator. - * @return This container. - */ - dense_set &operator=(dense_set &&) noexcept(std::is_nothrow_move_assignable_v<compressed_pair<sparse_container_type, hasher>> && std::is_nothrow_move_assignable_v<compressed_pair<packed_container_type, key_equal>>) = default; - - /** - * @brief Returns the associated allocator. - * @return The associated allocator. - */ - [[nodiscard]] constexpr allocator_type get_allocator() const noexcept { - return sparse.first().get_allocator(); - } - - /** - * @brief Returns an iterator to the beginning. - * - * If the array is empty, the returned iterator will be equal to `end()`. - * - * @return An iterator to the first instance of the internal array. - */ - [[nodiscard]] const_iterator cbegin() const noexcept { - return packed.first().begin(); - } - - /*! @copydoc cbegin */ - [[nodiscard]] const_iterator begin() const noexcept { - return cbegin(); - } - - /*! @copydoc begin */ - [[nodiscard]] iterator begin() noexcept { - return packed.first().begin(); - } - - /** - * @brief Returns an iterator to the end. - * @return An iterator to the element following the last instance of the - * internal array. - */ - [[nodiscard]] const_iterator cend() const noexcept { - return packed.first().end(); - } - - /*! @copydoc cend */ - [[nodiscard]] const_iterator end() const noexcept { - return cend(); - } - - /*! @copydoc end */ - [[nodiscard]] iterator end() noexcept { - return packed.first().end(); - } - - /** - * @brief Returns a reverse iterator to the beginning. - * - * If the array is empty, the returned iterator will be equal to `rend()`. - * - * @return An iterator to the first instance of the reversed internal array. - */ - [[nodiscard]] const_reverse_iterator crbegin() const noexcept { - return std::make_reverse_iterator(cend()); - } - - /*! @copydoc crbegin */ - [[nodiscard]] const_reverse_iterator rbegin() const noexcept { - return crbegin(); - } - - /*! @copydoc rbegin */ - [[nodiscard]] reverse_iterator rbegin() noexcept { - return std::make_reverse_iterator(end()); - } - - /** - * @brief Returns a reverse iterator to the end. - * @return An iterator to the element following the last instance of the - * reversed internal array. - */ - [[nodiscard]] const_reverse_iterator crend() const noexcept { - return std::make_reverse_iterator(cbegin()); - } - - /*! @copydoc crend */ - [[nodiscard]] const_reverse_iterator rend() const noexcept { - return crend(); - } - - /*! @copydoc rend */ - [[nodiscard]] reverse_iterator rend() noexcept { - return std::make_reverse_iterator(begin()); - } - - /** - * @brief Checks whether a container is empty. - * @return True if the container is empty, false otherwise. - */ - [[nodiscard]] bool empty() const noexcept { - return packed.first().empty(); - } - - /** - * @brief Returns the number of elements in a container. - * @return Number of elements in a container. - */ - [[nodiscard]] size_type size() const noexcept { - return packed.first().size(); - } - - /** - * @brief Returns the maximum possible number of elements. - * @return Maximum possible number of elements. - */ - [[nodiscard]] size_type max_size() const noexcept { - return packed.first().max_size(); - } - - /*! @brief Clears the container. */ - void clear() noexcept { - sparse.first().clear(); - packed.first().clear(); - rehash(0u); - } - - /** - * @brief Inserts an element into the container, if it does not exist. - * @param value An element to insert into the container. - * @return A pair consisting of an iterator to the inserted element (or to - * the element that prevented the insertion) and a bool denoting whether the - * insertion took place. - */ - std::pair<iterator, bool> insert(const value_type &value) { - return insert_or_do_nothing(value); - } - - /*! @copydoc insert */ - std::pair<iterator, bool> insert(value_type &&value) { - return insert_or_do_nothing(std::move(value)); - } - - /** - * @brief Inserts elements into the container, if they do not exist. - * @tparam It Type of input iterator. - * @param first An iterator to the first element of the range of elements. - * @param last An iterator past the last element of the range of elements. - */ - template<typename It> - void insert(It first, It last) { - for(; first != last; ++first) { - insert(*first); - } - } - - /** - * @brief Constructs an element in-place, if it does not exist. - * - * The element is also constructed when the container already has the key, - * in which case the newly constructed object is destroyed immediately. - * - * @tparam Args Types of arguments to forward to the constructor of the - * element. - * @param args Arguments to forward to the constructor of the element. - * @return A pair consisting of an iterator to the inserted element (or to - * the element that prevented the insertion) and a bool denoting whether the - * insertion took place. - */ - template<typename... Args> - std::pair<iterator, bool> emplace(Args &&...args) { - if constexpr(((sizeof...(Args) == 1u) && ... && std::is_same_v<std::decay_t<Args>, value_type>)) { - return insert_or_do_nothing(std::forward<Args>(args)...); - } else { - auto &node = packed.first().emplace_back(std::piecewise_construct, std::make_tuple(packed.first().size()), std::forward_as_tuple(std::forward<Args>(args)...)); - const auto index = value_to_bucket(node.second); - - if(auto it = constrained_find(node.second, index); it != end()) { - packed.first().pop_back(); - return std::make_pair(it, false); - } - - std::swap(node.first, sparse.first()[index]); - rehash_if_required(); - - return std::make_pair(--end(), true); - } - } - - /** - * @brief Removes an element from a given position. - * @param pos An iterator to the element to remove. - * @return An iterator following the removed element. - */ - iterator erase(const_iterator pos) { - const auto diff = pos - cbegin(); - erase(*pos); - return begin() + diff; - } - - /** - * @brief Removes the given elements from a container. - * @param first An iterator to the first element of the range of elements. - * @param last An iterator past the last element of the range of elements. - * @return An iterator following the last removed element. - */ - iterator erase(const_iterator first, const_iterator last) { - const auto dist = first - cbegin(); - - for(auto from = last - cbegin(); from != dist; --from) { - erase(packed.first()[from - 1u].second); - } - - return (begin() + dist); - } - - /** - * @brief Removes the element associated with a given value. - * @param value Value of an element to remove. - * @return Number of elements removed (either 0 or 1). - */ - size_type erase(const value_type &value) { - for(size_type *curr = &sparse.first()[value_to_bucket(value)]; *curr != (std::numeric_limits<size_type>::max)(); curr = &packed.first()[*curr].first) { - if(packed.second()(packed.first()[*curr].second, value)) { - const auto index = *curr; - *curr = packed.first()[*curr].first; - move_and_pop(index); - return 1u; - } - } - - return 0u; - } - - /** - * @brief Exchanges the contents with those of a given container. - * @param other Container to exchange the content with. - */ - void swap(dense_set &other) { - using std::swap; - swap(sparse, other.sparse); - swap(packed, other.packed); - swap(threshold, other.threshold); - } - - /** - * @brief Returns the number of elements matching a value (either 1 or 0). - * @param key Key value of an element to search for. - * @return Number of elements matching the key (either 1 or 0). - */ - [[nodiscard]] size_type count(const value_type &key) const { - return find(key) != end(); - } - - /** - * @brief Returns the number of elements matching a key (either 1 or 0). - * @tparam Other Type of the key value of an element to search for. - * @param key Key value of an element to search for. - * @return Number of elements matching the key (either 1 or 0). - */ - template<typename Other> - [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, size_type>> - count(const Other &key) const { - return find(key) != end(); - } - - /** - * @brief Finds an element with a given value. - * @param value Value of an element to search for. - * @return An iterator to an element with the given value. If no such - * element is found, a past-the-end iterator is returned. - */ - [[nodiscard]] iterator find(const value_type &value) { - return constrained_find(value, value_to_bucket(value)); - } - - /*! @copydoc find */ - [[nodiscard]] const_iterator find(const value_type &value) const { - return constrained_find(value, value_to_bucket(value)); - } - - /** - * @brief Finds an element that compares _equivalent_ to a given value. - * @tparam Other Type of an element to search for. - * @param value Value of an element to search for. - * @return An iterator to an element with the given value. If no such - * element is found, a past-the-end iterator is returned. - */ - template<typename Other> - [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, iterator>> - find(const Other &value) { - return constrained_find(value, value_to_bucket(value)); - } - - /*! @copydoc find */ - template<typename Other> - [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, const_iterator>> - find(const Other &value) const { - return constrained_find(value, value_to_bucket(value)); - } - - /** - * @brief Returns a range containing all elements with a given value. - * @param value Value of an element to search for. - * @return A pair of iterators pointing to the first element and past the - * last element of the range. - */ - [[nodiscard]] std::pair<iterator, iterator> equal_range(const value_type &value) { - const auto it = find(value); - return {it, it + !(it == end())}; - } - - /*! @copydoc equal_range */ - [[nodiscard]] std::pair<const_iterator, const_iterator> equal_range(const value_type &value) const { - const auto it = find(value); - return {it, it + !(it == cend())}; - } - - /** - * @brief Returns a range containing all elements that compare _equivalent_ - * to a given value. - * @tparam Other Type of an element to search for. - * @param value Value of an element to search for. - * @return A pair of iterators pointing to the first element and past the - * last element of the range. - */ - template<typename Other> - [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<iterator, iterator>>> - equal_range(const Other &value) { - const auto it = find(value); - return {it, it + !(it == end())}; - } - - /*! @copydoc equal_range */ - template<typename Other> - [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, std::pair<const_iterator, const_iterator>>> - equal_range(const Other &value) const { - const auto it = find(value); - return {it, it + !(it == cend())}; - } - - /** - * @brief Checks if the container contains an element with a given value. - * @param value Value of an element to search for. - * @return True if there is such an element, false otherwise. - */ - [[nodiscard]] bool contains(const value_type &value) const { - return (find(value) != cend()); - } - - /** - * @brief Checks if the container contains an element that compares - * _equivalent_ to a given value. - * @tparam Other Type of an element to search for. - * @param value Value of an element to search for. - * @return True if there is such an element, false otherwise. - */ - template<typename Other> - [[nodiscard]] std::enable_if_t<is_transparent_v<hasher> && is_transparent_v<key_equal>, std::conditional_t<false, Other, bool>> - contains(const Other &value) const { - return (find(value) != cend()); - } - - /** - * @brief Returns an iterator to the beginning of a given bucket. - * @param index An index of a bucket to access. - * @return An iterator to the beginning of the given bucket. - */ - [[nodiscard]] const_local_iterator cbegin(const size_type index) const { - return {packed.first().begin(), sparse.first()[index]}; - } - - /** - * @brief Returns an iterator to the beginning of a given bucket. - * @param index An index of a bucket to access. - * @return An iterator to the beginning of the given bucket. - */ - [[nodiscard]] const_local_iterator begin(const size_type index) const { - return cbegin(index); - } - - /** - * @brief Returns an iterator to the beginning of a given bucket. - * @param index An index of a bucket to access. - * @return An iterator to the beginning of the given bucket. - */ - [[nodiscard]] local_iterator begin(const size_type index) { - return {packed.first().begin(), sparse.first()[index]}; - } - - /** - * @brief Returns an iterator to the end of a given bucket. - * @param index An index of a bucket to access. - * @return An iterator to the end of the given bucket. - */ - [[nodiscard]] const_local_iterator cend([[maybe_unused]] const size_type index) const { - return {packed.first().begin(), (std::numeric_limits<size_type>::max)()}; - } - - /** - * @brief Returns an iterator to the end of a given bucket. - * @param index An index of a bucket to access. - * @return An iterator to the end of the given bucket. - */ - [[nodiscard]] const_local_iterator end(const size_type index) const { - return cend(index); - } - - /** - * @brief Returns an iterator to the end of a given bucket. - * @param index An index of a bucket to access. - * @return An iterator to the end of the given bucket. - */ - [[nodiscard]] local_iterator end([[maybe_unused]] const size_type index) { - return {packed.first().begin(), (std::numeric_limits<size_type>::max)()}; - } - - /** - * @brief Returns the number of buckets. - * @return The number of buckets. - */ - [[nodiscard]] size_type bucket_count() const { - return sparse.first().size(); - } - - /** - * @brief Returns the maximum number of buckets. - * @return The maximum number of buckets. - */ - [[nodiscard]] size_type max_bucket_count() const { - return sparse.first().max_size(); - } - - /** - * @brief Returns the number of elements in a given bucket. - * @param index The index of the bucket to examine. - * @return The number of elements in the given bucket. - */ - [[nodiscard]] size_type bucket_size(const size_type index) const { - return static_cast<size_type>(std::distance(begin(index), end(index))); - } - - /** - * @brief Returns the bucket for a given element. - * @param value The value of the element to examine. - * @return The bucket for the given element. - */ - [[nodiscard]] size_type bucket(const value_type &value) const { - return value_to_bucket(value); - } - - /** - * @brief Returns the average number of elements per bucket. - * @return The average number of elements per bucket. - */ - [[nodiscard]] float load_factor() const { - return size() / static_cast<float>(bucket_count()); - } - - /** - * @brief Returns the maximum average number of elements per bucket. - * @return The maximum average number of elements per bucket. - */ - [[nodiscard]] float max_load_factor() const { - return threshold; - } - - /** - * @brief Sets the desired maximum average number of elements per bucket. - * @param value A desired maximum average number of elements per bucket. - */ - void max_load_factor(const float value) { - ENTT_ASSERT(value > 0.f, "Invalid load factor"); - threshold = value; - rehash(0u); - } - - /** - * @brief Reserves at least the specified number of buckets and regenerates - * the hash table. - * @param cnt New number of buckets. - */ - void rehash(const size_type cnt) { - auto value = cnt > minimum_capacity ? cnt : minimum_capacity; - const auto cap = static_cast<size_type>(size() / max_load_factor()); - value = value > cap ? value : cap; - - if(const auto sz = next_power_of_two(value); sz != bucket_count()) { - sparse.first().resize(sz); - - for(auto &&elem: sparse.first()) { - elem = (std::numeric_limits<size_type>::max)(); - } - - for(size_type pos{}, last = size(); pos < last; ++pos) { - const auto index = value_to_bucket(packed.first()[pos].second); - packed.first()[pos].first = std::exchange(sparse.first()[index], pos); - } - } - } - - /** - * @brief Reserves space for at least the specified number of elements and - * regenerates the hash table. - * @param cnt New number of elements. - */ - void reserve(const size_type cnt) { - packed.first().reserve(cnt); - rehash(static_cast<size_type>(std::ceil(cnt / max_load_factor()))); - } - - /** - * @brief Returns the function used to hash the elements. - * @return The function used to hash the elements. - */ - [[nodiscard]] hasher hash_function() const { - return sparse.second(); - } - - /** - * @brief Returns the function used to compare elements for equality. - * @return The function used to compare elements for equality. - */ - [[nodiscard]] key_equal key_eq() const { - return packed.second(); - } - -private: - compressed_pair<sparse_container_type, hasher> sparse; - compressed_pair<packed_container_type, key_equal> packed; - float threshold{default_threshold}; -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/container/fwd.hpp b/deps/entt/include/entt/container/fwd.hpp deleted file mode 100644 index 4622263..0000000 --- a/deps/entt/include/entt/container/fwd.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef ENTT_CONTAINER_FWD_HPP -#define ENTT_CONTAINER_FWD_HPP - -#include <functional> -#include <memory> -#include <utility> -#include <vector> - -namespace entt { - -template< - typename Key, - typename Type, - typename = std::hash<Key>, - typename = std::equal_to<>, - typename = std::allocator<std::pair<const Key, Type>>> -class dense_map; - -template< - typename Type, - typename = std::hash<Type>, - typename = std::equal_to<>, - typename = std::allocator<Type>> -class dense_set; - -template<typename...> -class basic_table; - -/** - * @brief Alias declaration for the most common use case. - * @tparam Type Element types. - */ -template<typename... Type> -using table = basic_table<std::vector<Type>...>; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/container/table.hpp b/deps/entt/include/entt/container/table.hpp deleted file mode 100644 index f69e221..0000000 --- a/deps/entt/include/entt/container/table.hpp +++ /dev/null @@ -1,460 +0,0 @@ -#ifndef ENTT_CONTAINER_TABLE_HPP -#define ENTT_CONTAINER_TABLE_HPP - -#include <cstddef> -#include <iterator> -#include <tuple> -#include <type_traits> -#include <utility> -#include "../config/config.h" -#include "../core/iterator.hpp" -#include "fwd.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename... It> -class table_iterator { - template<typename...> - friend class table_iterator; - -public: - using value_type = decltype(std::forward_as_tuple(*std::declval<It>()...)); - using pointer = input_iterator_pointer<value_type>; - using reference = value_type; - using difference_type = std::ptrdiff_t; - using iterator_category = std::input_iterator_tag; - using iterator_concept = std::random_access_iterator_tag; - - constexpr table_iterator() noexcept - : it{} {} - - constexpr table_iterator(It... from) noexcept - : it{from...} {} - - template<typename... Other, typename = std::enable_if_t<(std::is_constructible_v<It, Other> && ...)>> - constexpr table_iterator(const table_iterator<Other...> &other) noexcept - : table_iterator{std::get<Other>(other.it)...} {} - - constexpr table_iterator &operator++() noexcept { - return (++std::get<It>(it), ...), *this; - } - - constexpr table_iterator operator++(int) noexcept { - table_iterator orig = *this; - return ++(*this), orig; - } - - constexpr table_iterator &operator--() noexcept { - return (--std::get<It>(it), ...), *this; - } - - constexpr table_iterator operator--(int) noexcept { - table_iterator orig = *this; - return operator--(), orig; - } - - constexpr table_iterator &operator+=(const difference_type value) noexcept { - return ((std::get<It>(it) += value), ...), *this; - } - - constexpr table_iterator operator+(const difference_type value) const noexcept { - table_iterator copy = *this; - return (copy += value); - } - - constexpr table_iterator &operator-=(const difference_type value) noexcept { - return (*this += -value); - } - - constexpr table_iterator operator-(const difference_type value) const noexcept { - return (*this + -value); - } - - [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept { - return std::forward_as_tuple(std::get<It>(it)[value]...); - } - - [[nodiscard]] constexpr pointer operator->() const noexcept { - return {operator[](0)}; - } - - [[nodiscard]] constexpr reference operator*() const noexcept { - return operator[](0); - } - - template<typename... Lhs, typename... Rhs> - friend constexpr std::ptrdiff_t operator-(const table_iterator<Lhs...> &, const table_iterator<Rhs...> &) noexcept; - - template<typename... Lhs, typename... Rhs> - friend constexpr bool operator==(const table_iterator<Lhs...> &, const table_iterator<Rhs...> &) noexcept; - - template<typename... Lhs, typename... Rhs> - friend constexpr bool operator<(const table_iterator<Lhs...> &, const table_iterator<Rhs...> &) noexcept; - -private: - std::tuple<It...> it; -}; - -template<typename... Lhs, typename... Rhs> -[[nodiscard]] constexpr std::ptrdiff_t operator-(const table_iterator<Lhs...> &lhs, const table_iterator<Rhs...> &rhs) noexcept { - return std::get<0>(lhs.it) - std::get<0>(rhs.it); -} - -template<typename... Lhs, typename... Rhs> -[[nodiscard]] constexpr bool operator==(const table_iterator<Lhs...> &lhs, const table_iterator<Rhs...> &rhs) noexcept { - return std::get<0>(lhs.it) == std::get<0>(rhs.it); -} - -template<typename... Lhs, typename... Rhs> -[[nodiscard]] constexpr bool operator!=(const table_iterator<Lhs...> &lhs, const table_iterator<Rhs...> &rhs) noexcept { - return !(lhs == rhs); -} - -template<typename... Lhs, typename... Rhs> -[[nodiscard]] constexpr bool operator<(const table_iterator<Lhs...> &lhs, const table_iterator<Rhs...> &rhs) noexcept { - return std::get<0>(lhs.it) < std::get<0>(rhs.it); -} - -template<typename... Lhs, typename... Rhs> -[[nodiscard]] constexpr bool operator>(const table_iterator<Lhs...> &lhs, const table_iterator<Rhs...> &rhs) noexcept { - return rhs < lhs; -} - -template<typename... Lhs, typename... Rhs> -[[nodiscard]] constexpr bool operator<=(const table_iterator<Lhs...> &lhs, const table_iterator<Rhs...> &rhs) noexcept { - return !(lhs > rhs); -} - -template<typename... Lhs, typename... Rhs> -[[nodiscard]] constexpr bool operator>=(const table_iterator<Lhs...> &lhs, const table_iterator<Rhs...> &rhs) noexcept { - return !(lhs < rhs); -} - -} // namespace internal -/*! @endcond */ - -/** - * @brief Basic table implementation. - * - * Internal data structures arrange elements to maximize performance. There are - * no guarantees that objects are returned in the insertion order when iterate - * a table. Do not make assumption on the order in any case. - * - * @tparam Container Sequence container row types. - */ -template<typename... Container> -class basic_table { - using container_type = std::tuple<Container...>; - -public: - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - /*! @brief Input iterator type. */ - using iterator = internal::table_iterator<typename Container::iterator...>; - /*! @brief Constant input iterator type. */ - using const_iterator = internal::table_iterator<typename Container::const_iterator...>; - /*! @brief Reverse iterator type. */ - using reverse_iterator = internal::table_iterator<typename Container::reverse_iterator...>; - /*! @brief Constant reverse iterator type. */ - using const_reverse_iterator = internal::table_iterator<typename Container::const_reverse_iterator...>; - - /*! @brief Default constructor. */ - basic_table() - : payload{} { - } - - /** - * @brief Copy constructs the underlying containers. - * @param container The containers to copy from. - */ - explicit basic_table(const Container &...container) noexcept - : payload{container...} { - ENTT_ASSERT((((std::get<Container>(payload).size() * sizeof...(Container)) == (std::get<Container>(payload).size() + ...)) && ...), "Unexpected container size"); - } - - /** - * @brief Move constructs the underlying containers. - * @param container The containers to move from. - */ - explicit basic_table(Container &&...container) noexcept - : payload{std::move(container)...} { - ENTT_ASSERT((((std::get<Container>(payload).size() * sizeof...(Container)) == (std::get<Container>(payload).size() + ...)) && ...), "Unexpected container size"); - } - - /*! @brief Default copy constructor, deleted on purpose. */ - basic_table(const basic_table &) = delete; - - /** - * @brief Move constructor. - * @param other The instance to move from. - */ - basic_table(basic_table &&other) noexcept - : payload{std::move(other.payload)} {} - - /** - * @brief Constructs the underlying containers using a given allocator. - * @tparam Allocator Type of allocator. - * @param allocator A valid allocator. - */ - template<typename Allocator> - explicit basic_table(const Allocator &allocator) - : payload{Container{allocator}...} {} - - /** - * @brief Copy constructs the underlying containers using a given allocator. - * @tparam Allocator Type of allocator. - * @param container The containers to copy from. - * @param allocator A valid allocator. - */ - template<class Allocator> - basic_table(const Container &...container, const Allocator &allocator) noexcept - : payload{Container{container, allocator}...} { - ENTT_ASSERT((((std::get<Container>(payload).size() * sizeof...(Container)) == (std::get<Container>(payload).size() + ...)) && ...), "Unexpected container size"); - } - - /** - * @brief Move constructs the underlying containers using a given allocator. - * @tparam Allocator Type of allocator. - * @param container The containers to move from. - * @param allocator A valid allocator. - */ - template<class Allocator> - basic_table(Container &&...container, const Allocator &allocator) noexcept - : payload{Container{std::move(container), allocator}...} { - ENTT_ASSERT((((std::get<Container>(payload).size() * sizeof...(Container)) == (std::get<Container>(payload).size() + ...)) && ...), "Unexpected container size"); - } - - /** - * @brief Allocator-extended move constructor. - * @tparam Allocator Type of allocator. - * @param other The instance to move from. - * @param allocator The allocator to use. - */ - template<class Allocator> - basic_table(basic_table &&other, const Allocator &allocator) - : payload{Container{std::move(std::get<Container>(other.payload)), allocator}...} {} - - /*! @brief Default destructor. */ - ~basic_table() noexcept = default; - - /** - * @brief Default copy assignment operator, deleted on purpose. - * @return This container. - */ - basic_table &operator=(const basic_table &) = delete; - - /** - * @brief Move assignment operator. - * @param other The instance to move from. - * @return This container. - */ - basic_table &operator=(basic_table &&other) noexcept { - payload = std::move(other.payload); - return *this; - } - - /** - * @brief Exchanges the contents with those of a given table. - * @param other Table to exchange the content with. - */ - void swap(basic_table &other) { - using std::swap; - swap(payload, other.payload); - } - - /** - * @brief Increases the capacity of a table. - * - * If the new capacity is greater than the current capacity, new storage is - * allocated, otherwise the method does nothing. - * - * @param cap Desired capacity. - */ - void reserve(const size_type cap) { - (std::get<Container>(payload).reserve(cap), ...); - } - - /** - * @brief Returns the number of rows that a table has currently allocated - * space for. - * @return Capacity of the table. - */ - [[nodiscard]] size_type capacity() const noexcept { - return std::get<0>(payload).capacity(); - } - - /*! @brief Requests the removal of unused capacity. */ - void shrink_to_fit() { - (std::get<Container>(payload).shrink_to_fit(), ...); - } - - /** - * @brief Returns the number of rows in a table. - * @return Number of rows. - */ - [[nodiscard]] size_type size() const noexcept { - return std::get<0>(payload).size(); - } - - /** - * @brief Checks whether a table is empty. - * @return True if the table is empty, false otherwise. - */ - [[nodiscard]] bool empty() const noexcept { - return std::get<0>(payload).empty(); - } - - /** - * @brief Returns an iterator to the beginning. - * - * If the table is empty, the returned iterator will be equal to `end()`. - * - * @return An iterator to the first row of the table. - */ - [[nodiscard]] const_iterator cbegin() const noexcept { - return {std::get<Container>(payload).cbegin()...}; - } - - /*! @copydoc cbegin */ - [[nodiscard]] const_iterator begin() const noexcept { - return cbegin(); - } - - /*! @copydoc begin */ - [[nodiscard]] iterator begin() noexcept { - return {std::get<Container>(payload).begin()...}; - } - - /** - * @brief Returns an iterator to the end. - * @return An iterator to the element following the last row of the table. - */ - [[nodiscard]] const_iterator cend() const noexcept { - return {std::get<Container>(payload).cend()...}; - } - - /*! @copydoc cend */ - [[nodiscard]] const_iterator end() const noexcept { - return cend(); - } - - /*! @copydoc end */ - [[nodiscard]] iterator end() noexcept { - return {std::get<Container>(payload).end()...}; - } - - /** - * @brief Returns a reverse iterator to the beginning. - * - * If the table is empty, the returned iterator will be equal to `rend()`. - * - * @return An iterator to the first row of the reversed table. - */ - [[nodiscard]] const_reverse_iterator crbegin() const noexcept { - return {std::get<Container>(payload).crbegin()...}; - } - - /*! @copydoc crbegin */ - [[nodiscard]] const_reverse_iterator rbegin() const noexcept { - return crbegin(); - } - - /*! @copydoc rbegin */ - [[nodiscard]] reverse_iterator rbegin() noexcept { - return {std::get<Container>(payload).rbegin()...}; - } - - /** - * @brief Returns a reverse iterator to the end. - * @return An iterator to the element following the last row of the reversed - * table. - */ - [[nodiscard]] const_reverse_iterator crend() const noexcept { - return {std::get<Container>(payload).crend()...}; - } - - /*! @copydoc crend */ - [[nodiscard]] const_reverse_iterator rend() const noexcept { - return crend(); - } - - /*! @copydoc rend */ - [[nodiscard]] reverse_iterator rend() noexcept { - return {std::get<Container>(payload).rend()...}; - } - - /** - * @brief Appends a row to the end of a table. - * @tparam Args Types of arguments to use to construct the row data. - * @param args Parameters to use to construct the row data. - * @return A reference to the newly created row data. - */ - template<typename... Args> - std::tuple<typename Container::value_type &...> emplace(Args &&...args) { - if constexpr(sizeof...(Args) == 0u) { - return std::forward_as_tuple(std::get<Container>(payload).emplace_back()...); - } else { - return std::forward_as_tuple(std::get<Container>(payload).emplace_back(std::forward<Args>(args))...); - } - } - - /** - * @brief Removes a row from a table. - * @param pos An iterator to the row to remove. - * @return An iterator following the removed row. - */ - iterator erase(const_iterator pos) { - const auto diff = pos - begin(); - return {std::get<Container>(payload).erase(std::get<Container>(payload).begin() + diff)...}; - } - - /** - * @brief Removes a row from a table. - * @param pos Index of the row to remove. - */ - void erase(const size_type pos) { - ENTT_ASSERT(pos < size(), "Index out of bounds"); - erase(begin() + static_cast<typename const_iterator::difference_type>(pos)); - } - - /** - * @brief Returns the row data at specified location. - * @param pos The row for which to return the data. - * @return The row data at specified location. - */ - [[nodiscard]] std::tuple<const typename Container::value_type &...> operator[](const size_type pos) const { - ENTT_ASSERT(pos < size(), "Index out of bounds"); - return std::forward_as_tuple(std::get<Container>(payload)[pos]...); - } - - /*! @copydoc operator[] */ - [[nodiscard]] std::tuple<typename Container::value_type &...> operator[](const size_type pos) { - ENTT_ASSERT(pos < size(), "Index out of bounds"); - return std::forward_as_tuple(std::get<Container>(payload)[pos]...); - } - - /*! @brief Clears a table. */ - void clear() { - (std::get<Container>(payload).clear(), ...); - } - -private: - container_type payload; -}; - -} // namespace entt - -/*! @cond TURN_OFF_DOXYGEN */ -namespace std { - -template<typename... Container, typename Allocator> -struct uses_allocator<entt::basic_table<Container...>, Allocator> - : std::bool_constant<(std::uses_allocator_v<Container, Allocator> && ...)> {}; - -} // namespace std -/*! @endcond */ - -#endif diff --git a/deps/entt/include/entt/core/algorithm.hpp b/deps/entt/include/entt/core/algorithm.hpp deleted file mode 100644 index c3c6354..0000000 --- a/deps/entt/include/entt/core/algorithm.hpp +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef ENTT_CORE_ALGORITHM_HPP -#define ENTT_CORE_ALGORITHM_HPP - -#include <algorithm> -#include <functional> -#include <iterator> -#include <utility> -#include <vector> -#include "utility.hpp" - -namespace entt { - -/** - * @brief Function object to wrap `std::sort` in a class type. - * - * Unfortunately, `std::sort` cannot be passed as template argument to a class - * template or a function template.<br/> - * This class fills the gap by wrapping some flavors of `std::sort` in a - * function object. - */ -struct std_sort { - /** - * @brief Sorts the elements in a range. - * - * Sorts the elements in a range using the given binary comparison function. - * - * @tparam It Type of random access iterator. - * @tparam Compare Type of comparison function object. - * @tparam Args Types of arguments to forward to the sort function. - * @param first An iterator to the first element of the range to sort. - * @param last An iterator past the last element of the range to sort. - * @param compare A valid comparison function object. - * @param args Arguments to forward to the sort function, if any. - */ - template<typename It, typename Compare = std::less<>, typename... Args> - void operator()(It first, It last, Compare compare = Compare{}, Args &&...args) const { - std::sort(std::forward<Args>(args)..., std::move(first), std::move(last), std::move(compare)); - } -}; - -/*! @brief Function object for performing insertion sort. */ -struct insertion_sort { - /** - * @brief Sorts the elements in a range. - * - * Sorts the elements in a range using the given binary comparison function. - * - * @tparam It Type of random access iterator. - * @tparam Compare Type of comparison function object. - * @param first An iterator to the first element of the range to sort. - * @param last An iterator past the last element of the range to sort. - * @param compare A valid comparison function object. - */ - template<typename It, typename Compare = std::less<>> - void operator()(It first, It last, Compare compare = Compare{}) const { - if(first < last) { - for(auto it = first + 1; it < last; ++it) { - auto value = std::move(*it); - auto pre = it; - - // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) - for(; pre > first && compare(value, *(pre - 1)); --pre) { - *pre = std::move(*(pre - 1)); - } - // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic) - - *pre = std::move(value); - } - } - } -}; - -/** - * @brief Function object for performing LSD radix sort. - * @tparam Bit Number of bits processed per pass. - * @tparam N Maximum number of bits to sort. - */ -template<std::size_t Bit, std::size_t N> -struct radix_sort { - static_assert((N % Bit) == 0, "The maximum number of bits to sort must be a multiple of the number of bits processed per pass"); - - /** - * @brief Sorts the elements in a range. - * - * Sorts the elements in a range using the given _getter_ to access the - * actual data to be sorted. - * - * This implementation is inspired by the online book - * [Physically Based Rendering](http://www.pbr-book.org/3ed-2018/Primitives_and_Intersection_Acceleration/Bounding_Volume_Hierarchies.html#RadixSort). - * - * @tparam It Type of random access iterator. - * @tparam Getter Type of _getter_ function object. - * @param first An iterator to the first element of the range to sort. - * @param last An iterator past the last element of the range to sort. - * @param getter A valid _getter_ function object. - */ - template<typename It, typename Getter = identity> - void operator()(It first, It last, Getter getter = Getter{}) const { - if(first < last) { - constexpr auto passes = N / Bit; - - using value_type = typename std::iterator_traits<It>::value_type; - std::vector<value_type> aux(std::distance(first, last)); - - auto part = [getter = std::move(getter)](auto from, auto to, auto out, auto start) { - constexpr auto mask = (1 << Bit) - 1; - constexpr auto buckets = 1 << Bit; - - // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays) - std::size_t count[buckets]{}; - - for(auto it = from; it != to; ++it) { - ++count[(getter(*it) >> start) & mask]; - } - - // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays) - std::size_t index[buckets]{}; - - for(std::size_t pos{}, end = buckets - 1u; pos < end; ++pos) { - index[pos + 1u] = index[pos] + count[pos]; - } - - for(auto it = from; it != to; ++it) { - out[index[(getter(*it) >> start) & mask]++] = std::move(*it); - } - }; - - for(std::size_t pass = 0; pass < (passes & ~1); pass += 2) { - part(first, last, aux.begin(), pass * Bit); - part(aux.begin(), aux.end(), first, (pass + 1) * Bit); - } - - if constexpr(passes & 1) { - part(first, last, aux.begin(), (passes - 1) * Bit); - std::move(aux.begin(), aux.end(), first); - } - } - } -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/core/any.hpp b/deps/entt/include/entt/core/any.hpp deleted file mode 100644 index 65d8736..0000000 --- a/deps/entt/include/entt/core/any.hpp +++ /dev/null @@ -1,513 +0,0 @@ -#ifndef ENTT_CORE_ANY_HPP -#define ENTT_CORE_ANY_HPP - -#include <cstddef> -#include <memory> -#include <type_traits> -#include <utility> -#include "../config/config.h" -#include "../core/utility.hpp" -#include "fwd.hpp" -#include "type_info.hpp" -#include "type_traits.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -enum class any_operation : std::uint8_t { - copy, - move, - transfer, - assign, - destroy, - compare, - get -}; - -} // namespace internal -/*! @endcond */ - -/*! @brief Possible modes of an any object. */ -enum class any_policy : std::uint8_t { - /*! @brief Default mode, the object owns the contained element. */ - owner, - /*! @brief Aliasing mode, the object _points_ to a non-const element. */ - ref, - /*! @brief Const aliasing mode, the object _points_ to a const element. */ - cref -}; - -/** - * @brief A SBO friendly, type-safe container for single values of any type. - * @tparam Len Size of the storage reserved for the small buffer optimization. - * @tparam Align Optional alignment requirement. - */ -template<std::size_t Len, std::size_t Align> -class basic_any { - using operation = internal::any_operation; - using vtable_type = const void *(const operation, const basic_any &, const void *); - - struct storage_type { - // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays) - alignas(Align) std::byte data[Len + !Len]; - }; - - template<typename Type> - static constexpr bool in_situ = Len && alignof(Type) <= Align && sizeof(Type) <= Len && std::is_nothrow_move_constructible_v<Type>; - - template<typename Type> - static const void *basic_vtable(const operation op, const basic_any &value, const void *other) { - static_assert(!std::is_void_v<Type> && std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, Type>, "Invalid type"); - const Type *elem = nullptr; - - if constexpr(in_situ<Type>) { - elem = (value.mode == any_policy::owner) ? reinterpret_cast<const Type *>(&value.storage) : static_cast<const Type *>(value.instance); - } else { - elem = static_cast<const Type *>(value.instance); - } - - switch(op) { - case operation::copy: - if constexpr(std::is_copy_constructible_v<Type>) { - static_cast<basic_any *>(const_cast<void *>(other))->initialize<Type>(*elem); - } - break; - case operation::move: - if constexpr(in_situ<Type>) { - if(value.mode == any_policy::owner) { - return ::new(&static_cast<basic_any *>(const_cast<void *>(other))->storage) Type{std::move(*const_cast<Type *>(elem))}; - } - } - - return (static_cast<basic_any *>(const_cast<void *>(other))->instance = std::exchange(const_cast<basic_any &>(value).instance, nullptr)); - case operation::transfer: - if constexpr(std::is_move_assignable_v<Type>) { - *const_cast<Type *>(elem) = std::move(*static_cast<Type *>(const_cast<void *>(other))); - return other; - } - [[fallthrough]]; - case operation::assign: - if constexpr(std::is_copy_assignable_v<Type>) { - *const_cast<Type *>(elem) = *static_cast<const Type *>(other); - return other; - } - break; - case operation::destroy: - if constexpr(in_situ<Type>) { - elem->~Type(); - } else if constexpr(std::is_array_v<Type>) { - delete[] elem; - } else { - delete elem; - } - break; - case operation::compare: - if constexpr(!std::is_function_v<Type> && !std::is_array_v<Type> && is_equality_comparable_v<Type>) { - return *elem == *static_cast<const Type *>(other) ? other : nullptr; - } else { - return (elem == other) ? other : nullptr; - } - case operation::get: - return elem; - } - - return nullptr; - } - - template<typename Type, typename... Args> - void initialize([[maybe_unused]] Args &&...args) { - using plain_type = std::remove_cv_t<std::remove_reference_t<Type>>; - info = &type_id<plain_type>(); - - if constexpr(!std::is_void_v<Type>) { - vtable = basic_vtable<plain_type>; - - if constexpr(std::is_lvalue_reference_v<Type>) { - static_assert((std::is_lvalue_reference_v<Args> && ...) && (sizeof...(Args) == 1u), "Invalid arguments"); - mode = std::is_const_v<std::remove_reference_t<Type>> ? any_policy::cref : any_policy::ref; - instance = (std::addressof(args), ...); - } else if constexpr(in_situ<plain_type>) { - if constexpr(std::is_aggregate_v<plain_type> && (sizeof...(Args) != 0u || !std::is_default_constructible_v<plain_type>)) { - ::new(&storage) plain_type{std::forward<Args>(args)...}; - } else { - ::new(&storage) plain_type(std::forward<Args>(args)...); - } - } else { - if constexpr(std::is_aggregate_v<plain_type> && (sizeof...(Args) != 0u || !std::is_default_constructible_v<plain_type>)) { - instance = new plain_type{std::forward<Args>(args)...}; - } else if constexpr(std::is_array_v<plain_type>) { - static_assert(sizeof...(Args) == 0u, "Invalid arguments"); - instance = new plain_type[std::extent_v<plain_type>](); - } else { - instance = new plain_type(std::forward<Args>(args)...); - } - } - } - } - - basic_any(const basic_any &other, const any_policy pol) noexcept - : instance{other.data()}, - info{other.info}, - vtable{other.vtable}, - mode{pol} {} - -public: - /*! @brief Size of the internal storage. */ - static constexpr auto length = Len; - /*! @brief Alignment requirement. */ - static constexpr auto alignment = Align; - - /*! @brief Default constructor. */ - constexpr basic_any() noexcept - : basic_any{std::in_place_type<void>} {} - - /** - * @brief Constructs a wrapper by directly initializing the new object. - * @tparam Type Type of object to use to initialize the wrapper. - * @tparam Args Types of arguments to use to construct the new instance. - * @param args Parameters to use to construct the instance. - */ - template<typename Type, typename... Args> - explicit basic_any(std::in_place_type_t<Type>, Args &&...args) - : instance{}, - info{}, - vtable{}, - mode{any_policy::owner} { - initialize<Type>(std::forward<Args>(args)...); - } - - /** - * @brief Constructs a wrapper from a given value. - * @tparam Type Type of object to use to initialize the wrapper. - * @param value An instance of an object to use to initialize the wrapper. - */ - template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, basic_any>>> - basic_any(Type &&value) - : basic_any{std::in_place_type<std::decay_t<Type>>, std::forward<Type>(value)} {} - - /** - * @brief Copy constructor. - * @param other The instance to copy from. - */ - basic_any(const basic_any &other) - : basic_any{} { - if(other.vtable) { - other.vtable(operation::copy, other, this); - } - } - - /** - * @brief Move constructor. - * @param other The instance to move from. - */ - basic_any(basic_any &&other) noexcept - : instance{}, - info{other.info}, - vtable{other.vtable}, - mode{other.mode} { - if(other.vtable) { - other.vtable(operation::move, other, this); - } - } - - /*! @brief Frees the internal storage, whatever it means. */ - ~basic_any() noexcept { - if(vtable && (mode == any_policy::owner)) { - vtable(operation::destroy, *this, nullptr); - } - } - - /** - * @brief Copy assignment operator. - * @param other The instance to copy from. - * @return This any object. - */ - basic_any &operator=(const basic_any &other) { - if(this != &other) { - reset(); - - if(other.vtable) { - other.vtable(operation::copy, other, this); - } - } - - return *this; - } - - /** - * @brief Move assignment operator. - * @param other The instance to move from. - * @return This any object. - */ - basic_any &operator=(basic_any &&other) noexcept { - ENTT_ASSERT(this != &other, "Self move assignment"); - - reset(); - - if(other.vtable) { - other.vtable(operation::move, other, this); - info = other.info; - vtable = other.vtable; - mode = other.mode; - } - - return *this; - } - - /** - * @brief Value assignment operator. - * @tparam Type Type of object to use to initialize the wrapper. - * @param value An instance of an object to use to initialize the wrapper. - * @return This any object. - */ - template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, basic_any>>> - basic_any &operator=(Type &&value) { - emplace<std::decay_t<Type>>(std::forward<Type>(value)); - return *this; - } - - /** - * @brief Returns the object type if any, `type_id<void>()` otherwise. - * @return The object type if any, `type_id<void>()` otherwise. - */ - [[nodiscard]] const type_info &type() const noexcept { - return *info; - } - - /** - * @brief Returns an opaque pointer to the contained instance. - * @return An opaque pointer the contained instance, if any. - */ - [[nodiscard]] const void *data() const noexcept { - return vtable ? vtable(operation::get, *this, nullptr) : nullptr; - } - - /** - * @brief Returns an opaque pointer to the contained instance. - * @param req Expected type. - * @return An opaque pointer the contained instance, if any. - */ - [[nodiscard]] const void *data(const type_info &req) const noexcept { - return *info == req ? data() : nullptr; - } - - /** - * @brief Returns an opaque pointer to the contained instance. - * @return An opaque pointer the contained instance, if any. - */ - [[nodiscard]] void *data() noexcept { - return mode == any_policy::cref ? nullptr : const_cast<void *>(std::as_const(*this).data()); - } - - /** - * @brief Returns an opaque pointer to the contained instance. - * @param req Expected type. - * @return An opaque pointer the contained instance, if any. - */ - [[nodiscard]] void *data(const type_info &req) noexcept { - return mode == any_policy::cref ? nullptr : const_cast<void *>(std::as_const(*this).data(req)); - } - - /** - * @brief Replaces the contained object by creating a new instance directly. - * @tparam Type Type of object to use to initialize the wrapper. - * @tparam Args Types of arguments to use to construct the new instance. - * @param args Parameters to use to construct the instance. - */ - template<typename Type, typename... Args> - void emplace(Args &&...args) { - reset(); - initialize<Type>(std::forward<Args>(args)...); - } - - /** - * @brief Assigns a value to the contained object without replacing it. - * @param other The value to assign to the contained object. - * @return True in case of success, false otherwise. - */ - bool assign(const basic_any &other) { - if(vtable && mode != any_policy::cref && *info == *other.info) { - return (vtable(operation::assign, *this, other.data()) != nullptr); - } - - return false; - } - - /*! @copydoc assign */ - bool assign(basic_any &&other) { - if(vtable && mode != any_policy::cref && *info == *other.info) { - if(auto *val = other.data(); val) { - return (vtable(operation::transfer, *this, val) != nullptr); - } else { - return (vtable(operation::assign, *this, std::as_const(other).data()) != nullptr); - } - } - - return false; - } - - /*! @brief Destroys contained object */ - void reset() { - if(vtable && (mode == any_policy::owner)) { - vtable(operation::destroy, *this, nullptr); - } - - // unnecessary but it helps to detect nasty bugs - ENTT_ASSERT((instance = nullptr) == nullptr, ""); - info = &type_id<void>(); - vtable = nullptr; - mode = any_policy::owner; - } - - /** - * @brief Returns false if a wrapper is empty, true otherwise. - * @return False if the wrapper is empty, true otherwise. - */ - [[nodiscard]] explicit operator bool() const noexcept { - return vtable != nullptr; - } - - /** - * @brief Checks if two wrappers differ in their content. - * @param other Wrapper with which to compare. - * @return False if the two objects differ in their content, true otherwise. - */ - [[nodiscard]] bool operator==(const basic_any &other) const noexcept { - if(vtable && *info == *other.info) { - return (vtable(operation::compare, *this, other.data()) != nullptr); - } - - return (!vtable && !other.vtable); - } - - /** - * @brief Checks if two wrappers differ in their content. - * @param other Wrapper with which to compare. - * @return True if the two objects differ in their content, false otherwise. - */ - [[nodiscard]] bool operator!=(const basic_any &other) const noexcept { - return !(*this == other); - } - - /** - * @brief Aliasing constructor. - * @return A wrapper that shares a reference to an unmanaged object. - */ - [[nodiscard]] basic_any as_ref() noexcept { - return basic_any{*this, (mode == any_policy::cref ? any_policy::cref : any_policy::ref)}; - } - - /*! @copydoc as_ref */ - [[nodiscard]] basic_any as_ref() const noexcept { - return basic_any{*this, any_policy::cref}; - } - - /** - * @brief Returns the current mode of an any object. - * @return The current mode of the any object. - */ - [[nodiscard]] any_policy policy() const noexcept { - return mode; - } - -private: - union { - const void *instance; - storage_type storage; - }; - const type_info *info; - vtable_type *vtable; - any_policy mode; -}; - -/** - * @brief Performs type-safe access to the contained object. - * @tparam Type Type to which conversion is required. - * @tparam Len Size of the storage reserved for the small buffer optimization. - * @tparam Align Alignment requirement. - * @param data Target any object. - * @return The element converted to the requested type. - */ -template<typename Type, std::size_t Len, std::size_t Align> -[[nodiscard]] Type any_cast(const basic_any<Len, Align> &data) noexcept { - const auto *const instance = any_cast<std::remove_reference_t<Type>>(&data); - ENTT_ASSERT(instance, "Invalid instance"); - return static_cast<Type>(*instance); -} - -/*! @copydoc any_cast */ -template<typename Type, std::size_t Len, std::size_t Align> -[[nodiscard]] Type any_cast(basic_any<Len, Align> &data) noexcept { - // forces const on non-reference types to make them work also with wrappers for const references - auto *const instance = any_cast<std::remove_reference_t<const Type>>(&data); - ENTT_ASSERT(instance, "Invalid instance"); - return static_cast<Type>(*instance); -} - -/*! @copydoc any_cast */ -template<typename Type, std::size_t Len, std::size_t Align> -[[nodiscard]] Type any_cast(basic_any<Len, Align> &&data) noexcept { - if constexpr(std::is_copy_constructible_v<std::remove_cv_t<std::remove_reference_t<Type>>>) { - if(auto *const instance = any_cast<std::remove_reference_t<Type>>(&data); instance) { - return static_cast<Type>(std::move(*instance)); - } else { - return any_cast<Type>(data); - } - } else { - auto *const instance = any_cast<std::remove_reference_t<Type>>(&data); - ENTT_ASSERT(instance, "Invalid instance"); - return static_cast<Type>(std::move(*instance)); - } -} - -/*! @copydoc any_cast */ -template<typename Type, std::size_t Len, std::size_t Align> -[[nodiscard]] const Type *any_cast(const basic_any<Len, Align> *data) noexcept { - const auto &info = type_id<std::remove_cv_t<Type>>(); - return static_cast<const Type *>(data->data(info)); -} - -/*! @copydoc any_cast */ -template<typename Type, std::size_t Len, std::size_t Align> -[[nodiscard]] Type *any_cast(basic_any<Len, Align> *data) noexcept { - if constexpr(std::is_const_v<Type>) { - // last attempt to make wrappers for const references return their values - return any_cast<Type>(&std::as_const(*data)); - } else { - const auto &info = type_id<std::remove_cv_t<Type>>(); - return static_cast<Type *>(data->data(info)); - } -} - -/** - * @brief Constructs a wrapper from a given type, passing it all arguments. - * @tparam Type Type of object to use to initialize the wrapper. - * @tparam Len Size of the storage reserved for the small buffer optimization. - * @tparam Align Optional alignment requirement. - * @tparam Args Types of arguments to use to construct the new instance. - * @param args Parameters to use to construct the instance. - * @return A properly initialized wrapper for an object of the given type. - */ -template<typename Type, std::size_t Len = basic_any<>::length, std::size_t Align = basic_any<Len>::alignment, typename... Args> -[[nodiscard]] basic_any<Len, Align> make_any(Args &&...args) { - return basic_any<Len, Align>{std::in_place_type<Type>, std::forward<Args>(args)...}; -} - -/** - * @brief Forwards its argument and avoids copies for lvalue references. - * @tparam Len Size of the storage reserved for the small buffer optimization. - * @tparam Align Optional alignment requirement. - * @tparam Type Type of argument to use to construct the new instance. - * @param value Parameter to use to construct the instance. - * @return A properly initialized and not necessarily owning wrapper. - */ -template<std::size_t Len = basic_any<>::length, std::size_t Align = basic_any<Len>::alignment, typename Type> -[[nodiscard]] basic_any<Len, Align> forward_as_any(Type &&value) { - return basic_any<Len, Align>{std::in_place_type<Type &&>, std::forward<Type>(value)}; -} - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/core/attribute.h b/deps/entt/include/entt/core/attribute.h deleted file mode 100644 index b1d0503..0000000 --- a/deps/entt/include/entt/core/attribute.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef ENTT_CORE_ATTRIBUTE_H -#define ENTT_CORE_ATTRIBUTE_H - -#ifndef ENTT_EXPORT -# if defined _WIN32 || defined __CYGWIN__ || defined _MSC_VER -# define ENTT_EXPORT __declspec(dllexport) -# define ENTT_IMPORT __declspec(dllimport) -# define ENTT_HIDDEN -# elif defined __GNUC__ && __GNUC__ >= 4 -# define ENTT_EXPORT __attribute__((visibility("default"))) -# define ENTT_IMPORT __attribute__((visibility("default"))) -# define ENTT_HIDDEN __attribute__((visibility("hidden"))) -# else /* Unsupported compiler */ -# define ENTT_EXPORT -# define ENTT_IMPORT -# define ENTT_HIDDEN -# endif -#endif - -#ifndef ENTT_API -# if defined ENTT_API_EXPORT -# define ENTT_API ENTT_EXPORT -# elif defined ENTT_API_IMPORT -# define ENTT_API ENTT_IMPORT -# else /* No API */ -# define ENTT_API -# endif -#endif - -#endif diff --git a/deps/entt/include/entt/core/bit.hpp b/deps/entt/include/entt/core/bit.hpp deleted file mode 100644 index 6622bd6..0000000 --- a/deps/entt/include/entt/core/bit.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef ENTT_CORE_BIT_HPP -#define ENTT_CORE_BIT_HPP - -#include <cstddef> -#include <limits> -#include <type_traits> -#include "../config/config.h" - -namespace entt { - -/** - * @brief Returns the number of set bits in a value (waiting for C++20 and - * `std::popcount`). - * @tparam Type Unsigned integer type. - * @param value A value of unsigned integer type. - * @return The number of set bits in the value. - */ -template<typename Type> -[[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, int> popcount(const Type value) noexcept { - return value ? (int(value & 1) + popcount(static_cast<Type>(value >> 1))) : 0; -} - -/** - * @brief Checks whether a value is a power of two or not (waiting for C++20 and - * `std::has_single_bit`). - * @tparam Type Unsigned integer type. - * @param value A value of unsigned integer type. - * @return True if the value is a power of two, false otherwise. - */ -template<typename Type> -[[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, bool> has_single_bit(const Type value) noexcept { - return value && ((value & (value - 1)) == 0); -} - -/** - * @brief Computes the smallest power of two greater than or equal to a value - * (waiting for C++20 and `std::bit_ceil`). - * @tparam Type Unsigned integer type. - * @param value A value of unsigned integer type. - * @return The smallest power of two greater than or equal to the given value. - */ -template<typename Type> -[[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, Type> next_power_of_two(const Type value) noexcept { - ENTT_ASSERT_CONSTEXPR(value < (Type{1u} << (std::numeric_limits<Type>::digits - 1)), "Numeric limits exceeded"); - Type curr = value - (value != 0u); - - for(int next = 1; next < std::numeric_limits<Type>::digits; next = next * 2) { - curr |= (curr >> next); - } - - return ++curr; -} - -/** - * @brief Fast module utility function (powers of two only). - * @tparam Type Unsigned integer type. - * @param value A value of unsigned integer type. - * @param mod _Modulus_, it must be a power of two. - * @return The common remainder. - */ -template<typename Type> -[[nodiscard]] constexpr std::enable_if_t<std::is_unsigned_v<Type>, Type> fast_mod(const Type value, const std::size_t mod) noexcept { - ENTT_ASSERT_CONSTEXPR(has_single_bit(mod), "Value must be a power of two"); - return value & (mod - 1u); -} - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/core/compressed_pair.hpp b/deps/entt/include/entt/core/compressed_pair.hpp deleted file mode 100644 index f1bea5a..0000000 --- a/deps/entt/include/entt/core/compressed_pair.hpp +++ /dev/null @@ -1,272 +0,0 @@ -#ifndef ENTT_CORE_COMPRESSED_PAIR_HPP -#define ENTT_CORE_COMPRESSED_PAIR_HPP - -#include <cstddef> -#include <tuple> -#include <type_traits> -#include <utility> -#include "fwd.hpp" -#include "type_traits.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename Type, std::size_t, typename = void> -struct compressed_pair_element { - using reference = Type &; - using const_reference = const Type &; - - template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>> - // NOLINTNEXTLINE(modernize-use-equals-default) - constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<Type>) {} - - template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Arg>>, compressed_pair_element>>> - constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<Type, Arg>) - : value{std::forward<Arg>(arg)} {} - - template<typename... Args, std::size_t... Index> - constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<Type, Args...>) - : value{std::forward<Args>(std::get<Index>(args))...} {} - - [[nodiscard]] constexpr reference get() noexcept { - return value; - } - - [[nodiscard]] constexpr const_reference get() const noexcept { - return value; - } - -private: - Type value{}; -}; - -template<typename Type, std::size_t Tag> -struct compressed_pair_element<Type, Tag, std::enable_if_t<is_ebco_eligible_v<Type>>>: Type { - using reference = Type &; - using const_reference = const Type &; - using base_type = Type; - - template<typename Dummy = Type, typename = std::enable_if_t<std::is_default_constructible_v<Dummy>>> - constexpr compressed_pair_element() noexcept(std::is_nothrow_default_constructible_v<base_type>) - : base_type{} {} - - template<typename Arg, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Arg>>, compressed_pair_element>>> - constexpr compressed_pair_element(Arg &&arg) noexcept(std::is_nothrow_constructible_v<base_type, Arg>) - : base_type{std::forward<Arg>(arg)} {} - - template<typename... Args, std::size_t... Index> - constexpr compressed_pair_element(std::tuple<Args...> args, std::index_sequence<Index...>) noexcept(std::is_nothrow_constructible_v<base_type, Args...>) - : base_type{std::forward<Args>(std::get<Index>(args))...} {} - - [[nodiscard]] constexpr reference get() noexcept { - return *this; - } - - [[nodiscard]] constexpr const_reference get() const noexcept { - return *this; - } -}; - -} // namespace internal -/*! @endcond */ - -/** - * @brief A compressed pair. - * - * A pair that exploits the _Empty Base Class Optimization_ (or _EBCO_) to - * reduce its final size to a minimum. - * - * @tparam First The type of the first element that the pair stores. - * @tparam Second The type of the second element that the pair stores. - */ -template<typename First, typename Second> -class compressed_pair final - : internal::compressed_pair_element<First, 0u>, - internal::compressed_pair_element<Second, 1u> { - using first_base = internal::compressed_pair_element<First, 0u>; - using second_base = internal::compressed_pair_element<Second, 1u>; - -public: - /*! @brief The type of the first element that the pair stores. */ - using first_type = First; - /*! @brief The type of the second element that the pair stores. */ - using second_type = Second; - - /** - * @brief Default constructor, conditionally enabled. - * - * This constructor is only available when the types that the pair stores - * are both at least default constructible. - * - * @tparam Dummy Dummy template parameter used for internal purposes. - */ - template<bool Dummy = true, typename = std::enable_if_t<Dummy && std::is_default_constructible_v<first_type> && std::is_default_constructible_v<second_type>>> - constexpr compressed_pair() noexcept(std::is_nothrow_default_constructible_v<first_base> && std::is_nothrow_default_constructible_v<second_base>) - : first_base{}, - second_base{} {} - - /** - * @brief Copy constructor. - * @param other The instance to copy from. - */ - constexpr compressed_pair(const compressed_pair &other) noexcept(std::is_nothrow_copy_constructible_v<first_base> && std::is_nothrow_copy_constructible_v<second_base>) = default; - - /** - * @brief Move constructor. - * @param other The instance to move from. - */ - constexpr compressed_pair(compressed_pair &&other) noexcept(std::is_nothrow_move_constructible_v<first_base> && std::is_nothrow_move_constructible_v<second_base>) = default; - - /** - * @brief Constructs a pair from its values. - * @tparam Arg Type of value to use to initialize the first element. - * @tparam Other Type of value to use to initialize the second element. - * @param arg Value to use to initialize the first element. - * @param other Value to use to initialize the second element. - */ - template<typename Arg, typename Other> - constexpr compressed_pair(Arg &&arg, Other &&other) noexcept(std::is_nothrow_constructible_v<first_base, Arg> && std::is_nothrow_constructible_v<second_base, Other>) - : first_base{std::forward<Arg>(arg)}, - second_base{std::forward<Other>(other)} {} - - /** - * @brief Constructs a pair by forwarding the arguments to its parts. - * @tparam Args Types of arguments to use to initialize the first element. - * @tparam Other Types of arguments to use to initialize the second element. - * @param args Arguments to use to initialize the first element. - * @param other Arguments to use to initialize the second element. - */ - template<typename... Args, typename... Other> - constexpr compressed_pair(std::piecewise_construct_t, std::tuple<Args...> args, std::tuple<Other...> other) noexcept(std::is_nothrow_constructible_v<first_base, Args...> && std::is_nothrow_constructible_v<second_base, Other...>) - : first_base{std::move(args), std::index_sequence_for<Args...>{}}, - second_base{std::move(other), std::index_sequence_for<Other...>{}} {} - - /*! @brief Default destructor. */ - ~compressed_pair() noexcept(std::is_nothrow_destructible_v<First> && std::is_nothrow_destructible_v<Second>) = default; - - /** - * @brief Copy assignment operator. - * @param other The instance to copy from. - * @return This compressed pair object. - */ - constexpr compressed_pair &operator=(const compressed_pair &other) noexcept(std::is_nothrow_copy_assignable_v<first_base> && std::is_nothrow_copy_assignable_v<second_base>) = default; - - /** - * @brief Move assignment operator. - * @param other The instance to move from. - * @return This compressed pair object. - */ - constexpr compressed_pair &operator=(compressed_pair &&other) noexcept(std::is_nothrow_move_assignable_v<first_base> && std::is_nothrow_move_assignable_v<second_base>) = default; - - /** - * @brief Returns the first element that a pair stores. - * @return The first element that a pair stores. - */ - [[nodiscard]] constexpr first_type &first() noexcept { - return static_cast<first_base &>(*this).get(); - } - - /*! @copydoc first */ - [[nodiscard]] constexpr const first_type &first() const noexcept { - return static_cast<const first_base &>(*this).get(); - } - - /** - * @brief Returns the second element that a pair stores. - * @return The second element that a pair stores. - */ - [[nodiscard]] constexpr second_type &second() noexcept { - return static_cast<second_base &>(*this).get(); - } - - /*! @copydoc second */ - [[nodiscard]] constexpr const second_type &second() const noexcept { - return static_cast<const second_base &>(*this).get(); - } - - /** - * @brief Swaps two compressed pair objects. - * @param other The compressed pair to swap with. - */ - constexpr void swap(compressed_pair &other) noexcept(std::is_nothrow_swappable_v<first_type> && std::is_nothrow_swappable_v<second_type>) { - using std::swap; - swap(first(), other.first()); - swap(second(), other.second()); - } - - /** - * @brief Extracts an element from the compressed pair. - * @tparam Index An integer value that is either 0 or 1. - * @return Returns a reference to the first element if `Index` is 0 and a - * reference to the second element if `Index` is 1. - */ - template<std::size_t Index> - [[nodiscard]] constexpr decltype(auto) get() noexcept { - if constexpr(Index == 0u) { - return first(); - } else { - static_assert(Index == 1u, "Index out of bounds"); - return second(); - } - } - - /*! @copydoc get */ - template<std::size_t Index> - [[nodiscard]] constexpr decltype(auto) get() const noexcept { - if constexpr(Index == 0u) { - return first(); - } else { - static_assert(Index == 1u, "Index out of bounds"); - return second(); - } - } -}; - -/** - * @brief Deduction guide. - * @tparam Type Type of value to use to initialize the first element. - * @tparam Other Type of value to use to initialize the second element. - */ -template<typename Type, typename Other> -compressed_pair(Type &&, Other &&) -> compressed_pair<std::decay_t<Type>, std::decay_t<Other>>; - -/** - * @brief Swaps two compressed pair objects. - * @tparam First The type of the first element that the pairs store. - * @tparam Second The type of the second element that the pairs store. - * @param lhs A valid compressed pair object. - * @param rhs A valid compressed pair object. - */ -template<typename First, typename Second> -inline constexpr void swap(compressed_pair<First, Second> &lhs, compressed_pair<First, Second> &rhs) { - lhs.swap(rhs); -} - -} // namespace entt - -namespace std { - -/** - * @brief `std::tuple_size` specialization for `compressed_pair`s. - * @tparam First The type of the first element that the pair stores. - * @tparam Second The type of the second element that the pair stores. - */ -template<typename First, typename Second> -struct tuple_size<entt::compressed_pair<First, Second>>: integral_constant<size_t, 2u> {}; - -/** - * @brief `std::tuple_element` specialization for `compressed_pair`s. - * @tparam Index The index of the type to return. - * @tparam First The type of the first element that the pair stores. - * @tparam Second The type of the second element that the pair stores. - */ -template<size_t Index, typename First, typename Second> -struct tuple_element<Index, entt::compressed_pair<First, Second>>: conditional<Index == 0u, First, Second> { - static_assert(Index < 2u, "Index out of bounds"); -}; - -} // namespace std - -#endif diff --git a/deps/entt/include/entt/core/enum.hpp b/deps/entt/include/entt/core/enum.hpp deleted file mode 100644 index 5922c2f..0000000 --- a/deps/entt/include/entt/core/enum.hpp +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef ENTT_CORE_ENUM_HPP -#define ENTT_CORE_ENUM_HPP - -#include <type_traits> - -namespace entt { - -/** - * @brief Enable bitmask support for enum classes. - * @tparam Type The enum type for which to enable bitmask support. - */ -template<typename Type, typename = void> -struct enum_as_bitmask: std::false_type {}; - -/*! @copydoc enum_as_bitmask */ -template<typename Type> -struct enum_as_bitmask<Type, std::void_t<decltype(Type::_entt_enum_as_bitmask)>>: std::is_enum<Type> {}; - -/** - * @brief Helper variable template. - * @tparam Type The enum class type for which to enable bitmask support. - */ -template<typename Type> -inline constexpr bool enum_as_bitmask_v = enum_as_bitmask<Type>::value; - -} // namespace entt - -/** - * @brief Operator available for enums for which bitmask support is enabled. - * @tparam Type Enum class type. - * @param lhs The first value to use. - * @param rhs The second value to use. - * @return The result of invoking the operator on the underlying types of the - * two values provided. - */ -template<typename Type> -[[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type> -operator|(const Type lhs, const Type rhs) noexcept { - return static_cast<Type>(static_cast<std::underlying_type_t<Type>>(lhs) | static_cast<std::underlying_type_t<Type>>(rhs)); -} - -/*! @copydoc operator| */ -template<typename Type> -[[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type> -operator&(const Type lhs, const Type rhs) noexcept { - return static_cast<Type>(static_cast<std::underlying_type_t<Type>>(lhs) & static_cast<std::underlying_type_t<Type>>(rhs)); -} - -/*! @copydoc operator| */ -template<typename Type> -[[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type> -operator^(const Type lhs, const Type rhs) noexcept { - return static_cast<Type>(static_cast<std::underlying_type_t<Type>>(lhs) ^ static_cast<std::underlying_type_t<Type>>(rhs)); -} - -/** - * @brief Operator available for enums for which bitmask support is enabled. - * @tparam Type Enum class type. - * @param value The value to use. - * @return The result of invoking the operator on the underlying types of the - * value provided. - */ -template<typename Type> -[[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type> -operator~(const Type value) noexcept { - return static_cast<Type>(~static_cast<std::underlying_type_t<Type>>(value)); -} - -/*! @copydoc operator~ */ -template<typename Type> -[[nodiscard]] constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, bool> -operator!(const Type value) noexcept { - return !static_cast<std::underlying_type_t<Type>>(value); -} - -/*! @copydoc operator| */ -template<typename Type> -constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type &> -operator|=(Type &lhs, const Type rhs) noexcept { - return (lhs = (lhs | rhs)); -} - -/*! @copydoc operator| */ -template<typename Type> -constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type &> -operator&=(Type &lhs, const Type rhs) noexcept { - return (lhs = (lhs & rhs)); -} - -/*! @copydoc operator| */ -template<typename Type> -constexpr std::enable_if_t<entt::enum_as_bitmask_v<Type>, Type &> -operator^=(Type &lhs, const Type rhs) noexcept { - return (lhs = (lhs ^ rhs)); -} - -#endif diff --git a/deps/entt/include/entt/core/family.hpp b/deps/entt/include/entt/core/family.hpp deleted file mode 100644 index 3a83b88..0000000 --- a/deps/entt/include/entt/core/family.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef ENTT_CORE_FAMILY_HPP -#define ENTT_CORE_FAMILY_HPP - -#include "../config/config.h" -#include "fwd.hpp" - -namespace entt { - -/** - * @brief Dynamic identifier generator. - * - * Utility class template that can be used to assign unique identifiers to types - * at runtime. Use different specializations to create separate sets of - * identifiers. - */ -template<typename...> -class family { - // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - inline static ENTT_MAYBE_ATOMIC(id_type) identifier{}; - -public: - /*! @brief Unsigned integer type. */ - using value_type = id_type; - - /*! @brief Statically generated unique identifier for the given type. */ - template<typename... Type> - // at the time I'm writing, clang crashes during compilation if auto is used instead of family_type - inline static const value_type value = identifier++; -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/core/fwd.hpp b/deps/entt/include/entt/core/fwd.hpp deleted file mode 100644 index bdd0b23..0000000 --- a/deps/entt/include/entt/core/fwd.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef ENTT_CORE_FWD_HPP -#define ENTT_CORE_FWD_HPP - -#include <cstddef> -#include "../config/config.h" - -namespace entt { - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays) -template<std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])> -class basic_any; - -/*! @brief Alias declaration for type identifiers. */ -using id_type = ENTT_ID_TYPE; - -/*! @brief Alias declaration for the most common use case. */ -using any = basic_any<>; - -template<typename, typename> -class compressed_pair; - -template<typename> -class basic_hashed_string; - -/*! @brief Aliases for common character types. */ -using hashed_string = basic_hashed_string<char>; - -/*! @brief Aliases for common character types. */ -using hashed_wstring = basic_hashed_string<wchar_t>; - -// NOLINTNEXTLINE(bugprone-forward-declaration-namespace) -struct type_info; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/core/hashed_string.hpp b/deps/entt/include/entt/core/hashed_string.hpp deleted file mode 100644 index df3e964..0000000 --- a/deps/entt/include/entt/core/hashed_string.hpp +++ /dev/null @@ -1,311 +0,0 @@ -#ifndef ENTT_CORE_HASHED_STRING_HPP -#define ENTT_CORE_HASHED_STRING_HPP - -#include <cstddef> -#include <cstdint> -#include <string_view> -#include "fwd.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename = id_type> -struct fnv_1a_params; - -template<> -struct fnv_1a_params<std::uint32_t> { - static constexpr auto offset = 2166136261; - static constexpr auto prime = 16777619; -}; - -template<> -struct fnv_1a_params<std::uint64_t> { - static constexpr auto offset = 14695981039346656037ull; - static constexpr auto prime = 1099511628211ull; -}; - -template<typename Char> -struct basic_hashed_string { - using value_type = Char; - using size_type = std::size_t; - using hash_type = id_type; - - const value_type *repr; - size_type length; - hash_type hash; -}; - -} // namespace internal -/*! @endcond */ - -/** - * @brief Zero overhead unique identifier. - * - * A hashed string is a compile-time tool that allows users to use - * human-readable identifiers in the codebase while using their numeric - * counterparts at runtime.<br/> - * Because of that, a hashed string can also be used in constant expressions if - * required. - * - * @warning - * This class doesn't take ownership of user-supplied strings nor does it make a - * copy of them. - * - * @tparam Char Character type. - */ -template<typename Char> -class basic_hashed_string: internal::basic_hashed_string<Char> { - using base_type = internal::basic_hashed_string<Char>; - using params = internal::fnv_1a_params<>; - - struct const_wrapper { - // non-explicit constructor on purpose - constexpr const_wrapper(const Char *str) noexcept - : repr{str} {} - - const Char *repr; - }; - - // Fowler–Noll–Vo hash function v. 1a - the good - [[nodiscard]] static constexpr auto helper(const std::basic_string_view<Char> view) noexcept { - base_type base{view.data(), view.size(), params::offset}; - - for(auto &&curr: view) { - base.hash = (base.hash ^ static_cast<id_type>(curr)) * params::prime; - } - - return base; - } - -public: - /*! @brief Character type. */ - using value_type = typename base_type::value_type; - /*! @brief Unsigned integer type. */ - using size_type = typename base_type::size_type; - /*! @brief Unsigned integer type. */ - using hash_type = typename base_type::hash_type; - - /** - * @brief Returns directly the numeric representation of a string view. - * @param str Human-readable identifier. - * @param len Length of the string to hash. - * @return The numeric representation of the string. - */ - [[nodiscard]] static constexpr hash_type value(const value_type *str, const size_type len) noexcept { - return basic_hashed_string{str, len}; - } - - /** - * @brief Returns directly the numeric representation of a string. - * @tparam N Number of characters of the identifier. - * @param str Human-readable identifier. - * @return The numeric representation of the string. - */ - template<std::size_t N> - // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays) - [[nodiscard]] static constexpr hash_type value(const value_type (&str)[N]) noexcept { - return basic_hashed_string{str}; - } - - /** - * @brief Returns directly the numeric representation of a string. - * @param wrapper Helps achieving the purpose by relying on overloading. - * @return The numeric representation of the string. - */ - [[nodiscard]] static constexpr hash_type value(const_wrapper wrapper) noexcept { - return basic_hashed_string{wrapper}; - } - - /*! @brief Constructs an empty hashed string. */ - constexpr basic_hashed_string() noexcept - : basic_hashed_string{nullptr, 0u} {} - - /** - * @brief Constructs a hashed string from a string view. - * @param str Human-readable identifier. - * @param len Length of the string to hash. - */ - constexpr basic_hashed_string(const value_type *str, const size_type len) noexcept - : base_type{helper({str, len})} {} - - /** - * @brief Constructs a hashed string from an array of const characters. - * @tparam N Number of characters of the identifier. - * @param str Human-readable identifier. - */ - template<std::size_t N> - // NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays) - constexpr basic_hashed_string(const value_type (&str)[N]) noexcept - : base_type{helper({static_cast<const value_type *>(str)})} {} - - /** - * @brief Explicit constructor on purpose to avoid constructing a hashed - * string directly from a `const value_type *`. - * - * @warning - * The lifetime of the string is not extended nor is it copied. - * - * @param wrapper Helps achieving the purpose by relying on overloading. - */ - explicit constexpr basic_hashed_string(const_wrapper wrapper) noexcept - : base_type{helper({wrapper.repr})} {} - - /** - * @brief Returns the size a hashed string. - * @return The size of the hashed string. - */ - [[nodiscard]] constexpr size_type size() const noexcept { - return base_type::length; - } - - /** - * @brief Returns the human-readable representation of a hashed string. - * @return The string used to initialize the hashed string. - */ - [[nodiscard]] constexpr const value_type *data() const noexcept { - return base_type::repr; - } - - /** - * @brief Returns the numeric representation of a hashed string. - * @return The numeric representation of the hashed string. - */ - [[nodiscard]] constexpr hash_type value() const noexcept { - return base_type::hash; - } - - /*! @copydoc data */ - [[nodiscard]] constexpr operator const value_type *() const noexcept { - return data(); - } - - /** - * @brief Returns the numeric representation of a hashed string. - * @return The numeric representation of the hashed string. - */ - [[nodiscard]] constexpr operator hash_type() const noexcept { - return value(); - } -}; - -/** - * @brief Deduction guide. - * @tparam Char Character type. - * @param str Human-readable identifier. - * @param len Length of the string to hash. - */ -template<typename Char> -basic_hashed_string(const Char *str, const std::size_t len) -> basic_hashed_string<Char>; - -/** - * @brief Deduction guide. - * @tparam Char Character type. - * @tparam N Number of characters of the identifier. - * @param str Human-readable identifier. - */ -template<typename Char, std::size_t N> -// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays) -basic_hashed_string(const Char (&str)[N]) -> basic_hashed_string<Char>; - -/** - * @brief Compares two hashed strings. - * @tparam Char Character type. - * @param lhs A valid hashed string. - * @param rhs A valid hashed string. - * @return True if the two hashed strings are identical, false otherwise. - */ -template<typename Char> -[[nodiscard]] constexpr bool operator==(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept { - return lhs.value() == rhs.value(); -} - -/** - * @brief Compares two hashed strings. - * @tparam Char Character type. - * @param lhs A valid hashed string. - * @param rhs A valid hashed string. - * @return True if the two hashed strings differ, false otherwise. - */ -template<typename Char> -[[nodiscard]] constexpr bool operator!=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept { - return !(lhs == rhs); -} - -/** - * @brief Compares two hashed strings. - * @tparam Char Character type. - * @param lhs A valid hashed string. - * @param rhs A valid hashed string. - * @return True if the first element is less than the second, false otherwise. - */ -template<typename Char> -[[nodiscard]] constexpr bool operator<(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept { - return lhs.value() < rhs.value(); -} - -/** - * @brief Compares two hashed strings. - * @tparam Char Character type. - * @param lhs A valid hashed string. - * @param rhs A valid hashed string. - * @return True if the first element is less than or equal to the second, false - * otherwise. - */ -template<typename Char> -[[nodiscard]] constexpr bool operator<=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept { - return !(rhs < lhs); -} - -/** - * @brief Compares two hashed strings. - * @tparam Char Character type. - * @param lhs A valid hashed string. - * @param rhs A valid hashed string. - * @return True if the first element is greater than the second, false - * otherwise. - */ -template<typename Char> -[[nodiscard]] constexpr bool operator>(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept { - return rhs < lhs; -} - -/** - * @brief Compares two hashed strings. - * @tparam Char Character type. - * @param lhs A valid hashed string. - * @param rhs A valid hashed string. - * @return True if the first element is greater than or equal to the second, - * false otherwise. - */ -template<typename Char> -[[nodiscard]] constexpr bool operator>=(const basic_hashed_string<Char> &lhs, const basic_hashed_string<Char> &rhs) noexcept { - return !(lhs < rhs); -} - -inline namespace literals { - -/** - * @brief User defined literal for hashed strings. - * @param str The literal without its suffix. - * @return A properly initialized hashed string. - */ -[[nodiscard]] constexpr hashed_string operator"" _hs(const char *str, std::size_t) noexcept { - return hashed_string{str}; -} - -/** - * @brief User defined literal for hashed wstrings. - * @param str The literal without its suffix. - * @return A properly initialized hashed wstring. - */ -[[nodiscard]] constexpr hashed_wstring operator"" _hws(const wchar_t *str, std::size_t) noexcept { - return hashed_wstring{str}; -} - -} // namespace literals - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/core/ident.hpp b/deps/entt/include/entt/core/ident.hpp deleted file mode 100644 index 2ff6026..0000000 --- a/deps/entt/include/entt/core/ident.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef ENTT_CORE_IDENT_HPP -#define ENTT_CORE_IDENT_HPP - -#include <cstddef> -#include <type_traits> -#include <utility> -#include "fwd.hpp" -#include "type_traits.hpp" - -namespace entt { - -/** - * @brief Type integral identifiers. - * @tparam Type List of types for which to generate identifiers. - */ -template<typename... Type> -class ident { - template<typename Curr, std::size_t... Index> - [[nodiscard]] static constexpr id_type get(std::index_sequence<Index...>) noexcept { - static_assert((std::is_same_v<Curr, Type> || ...), "Invalid type"); - return (0 + ... + (std::is_same_v<Curr, type_list_element_t<Index, type_list<std::decay_t<Type>...>>> ? id_type{Index} : id_type{})); - } - -public: - /*! @brief Unsigned integer type. */ - using value_type = id_type; - - /*! @brief Statically generated unique identifier for the given type. */ - template<typename Curr> - static constexpr value_type value = get<std::decay_t<Curr>>(std::index_sequence_for<Type...>{}); -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/core/iterator.hpp b/deps/entt/include/entt/core/iterator.hpp deleted file mode 100644 index 42db97e..0000000 --- a/deps/entt/include/entt/core/iterator.hpp +++ /dev/null @@ -1,197 +0,0 @@ -#ifndef ENTT_CORE_ITERATOR_HPP -#define ENTT_CORE_ITERATOR_HPP - -#include <iterator> -#include <memory> -#include <type_traits> -#include <utility> - -namespace entt { - -/** - * @brief Helper type to use as pointer with input iterators. - * @tparam Type of wrapped value. - */ -template<typename Type> -struct input_iterator_pointer final { - /*! @brief Value type. */ - using value_type = Type; - /*! @brief Pointer type. */ - using pointer = Type *; - /*! @brief Reference type. */ - using reference = Type &; - - /** - * @brief Constructs a proxy object by move. - * @param val Value to use to initialize the proxy object. - */ - constexpr input_iterator_pointer(value_type &&val) noexcept(std::is_nothrow_move_constructible_v<value_type>) - : value{std::move(val)} {} - - /** - * @brief Access operator for accessing wrapped values. - * @return A pointer to the wrapped value. - */ - [[nodiscard]] constexpr pointer operator->() noexcept { - return std::addressof(value); - } - - /** - * @brief Dereference operator for accessing wrapped values. - * @return A reference to the wrapped value. - */ - [[nodiscard]] constexpr reference operator*() noexcept { - return value; - } - -private: - Type value; -}; - -/** - * @brief Plain iota iterator (waiting for C++20). - * @tparam Type Value type. - */ -template<typename Type> -class iota_iterator final { - static_assert(std::is_integral_v<Type>, "Not an integral type"); - -public: - /*! @brief Value type, likely an integral one. */ - using value_type = Type; - /*! @brief Invalid pointer type. */ - using pointer = void; - /*! @brief Non-reference type, same as value type. */ - using reference = value_type; - /*! @brief Difference type. */ - using difference_type = std::ptrdiff_t; - /*! @brief Iterator category. */ - using iterator_category = std::input_iterator_tag; - - /*! @brief Default constructor. */ - constexpr iota_iterator() noexcept - : current{} {} - - /** - * @brief Constructs an iota iterator from a given value. - * @param init The initial value assigned to the iota iterator. - */ - constexpr iota_iterator(const value_type init) noexcept - : current{init} {} - - /** - * @brief Pre-increment operator. - * @return This iota iterator. - */ - constexpr iota_iterator &operator++() noexcept { - return ++current, *this; - } - - /** - * @brief Post-increment operator. - * @return This iota iterator. - */ - constexpr iota_iterator operator++(int) noexcept { - iota_iterator orig = *this; - return ++(*this), orig; - } - - /** - * @brief Dereference operator. - * @return The underlying value. - */ - [[nodiscard]] constexpr reference operator*() const noexcept { - return current; - } - -private: - value_type current; -}; - -/** - * @brief Comparison operator. - * @tparam Type Value type of the iota iterator. - * @param lhs A properly initialized iota iterator. - * @param rhs A properly initialized iota iterator. - * @return True if the two iterators are identical, false otherwise. - */ -template<typename Type> -[[nodiscard]] constexpr bool operator==(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept { - return *lhs == *rhs; -} - -/** - * @brief Comparison operator. - * @tparam Type Value type of the iota iterator. - * @param lhs A properly initialized iota iterator. - * @param rhs A properly initialized iota iterator. - * @return True if the two iterators differ, false otherwise. - */ -template<typename Type> -[[nodiscard]] constexpr bool operator!=(const iota_iterator<Type> &lhs, const iota_iterator<Type> &rhs) noexcept { - return !(lhs == rhs); -} - -/** - * @brief Utility class to create an iterable object from a pair of iterators. - * @tparam It Type of iterator. - * @tparam Sentinel Type of sentinel. - */ -template<typename It, typename Sentinel = It> -struct iterable_adaptor final { - /*! @brief Value type. */ - using value_type = typename std::iterator_traits<It>::value_type; - /*! @brief Iterator type. */ - using iterator = It; - /*! @brief Sentinel type. */ - using sentinel = Sentinel; - - /*! @brief Default constructor. */ - constexpr iterable_adaptor() noexcept(std::is_nothrow_default_constructible_v<iterator> &&std::is_nothrow_default_constructible_v<sentinel>) - : first{}, - last{} {} - - /** - * @brief Creates an iterable object from a pair of iterators. - * @param from Begin iterator. - * @param to End iterator. - */ - constexpr iterable_adaptor(iterator from, sentinel to) noexcept(std::is_nothrow_move_constructible_v<iterator> &&std::is_nothrow_move_constructible_v<sentinel>) - : first{std::move(from)}, - last{std::move(to)} {} - - /** - * @brief Returns an iterator to the beginning. - * @return An iterator to the first element of the range. - */ - [[nodiscard]] constexpr iterator begin() const noexcept { - return first; - } - - /** - * @brief Returns an iterator to the end. - * @return An iterator to the element following the last element of the - * range. - */ - [[nodiscard]] constexpr sentinel end() const noexcept { - return last; - } - - /*! @copydoc begin */ - [[nodiscard]] constexpr iterator cbegin() const noexcept { - return begin(); - } - - /*! @copydoc end */ - [[nodiscard]] constexpr sentinel cend() const noexcept { - return end(); - } - -private: - It first; - Sentinel last; -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/core/memory.hpp b/deps/entt/include/entt/core/memory.hpp deleted file mode 100644 index 8f6f34b..0000000 --- a/deps/entt/include/entt/core/memory.hpp +++ /dev/null @@ -1,244 +0,0 @@ -#ifndef ENTT_CORE_MEMORY_HPP -#define ENTT_CORE_MEMORY_HPP - -#include <cstddef> -#include <memory> -#include <tuple> -#include <type_traits> -#include <utility> -#include "../config/config.h" - -namespace entt { - -/** - * @brief Unwraps fancy pointers, does nothing otherwise (waiting for C++20). - * @tparam Type Pointer type. - * @param ptr Fancy or raw pointer. - * @return A raw pointer that represents the address of the original pointer. - */ -template<typename Type> -[[nodiscard]] constexpr auto to_address(Type &&ptr) noexcept { - if constexpr(std::is_pointer_v<std::decay_t<Type>>) { - return ptr; - } else { - return to_address(std::forward<Type>(ptr).operator->()); - } -} - -/** - * @brief Utility function to design allocation-aware containers. - * @tparam Allocator Type of allocator. - * @param lhs A valid allocator. - * @param rhs Another valid allocator. - */ -template<typename Allocator> -constexpr void propagate_on_container_copy_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept { - if constexpr(std::allocator_traits<Allocator>::propagate_on_container_copy_assignment::value) { - lhs = rhs; - } -} - -/** - * @brief Utility function to design allocation-aware containers. - * @tparam Allocator Type of allocator. - * @param lhs A valid allocator. - * @param rhs Another valid allocator. - */ -template<typename Allocator> -constexpr void propagate_on_container_move_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept { - if constexpr(std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) { - lhs = std::move(rhs); - } -} - -/** - * @brief Utility function to design allocation-aware containers. - * @tparam Allocator Type of allocator. - * @param lhs A valid allocator. - * @param rhs Another valid allocator. - */ -template<typename Allocator> -constexpr void propagate_on_container_swap([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) noexcept { - if constexpr(std::allocator_traits<Allocator>::propagate_on_container_swap::value) { - using std::swap; - swap(lhs, rhs); - } else { - ENTT_ASSERT_CONSTEXPR(lhs == rhs, "Cannot swap the containers"); - } -} - -/** - * @brief Deleter for allocator-aware unique pointers (waiting for C++20). - * @tparam Allocator Type of allocator used to manage memory and elements. - */ -template<typename Allocator> -struct allocation_deleter: private Allocator { - /*! @brief Allocator type. */ - using allocator_type = Allocator; - /*! @brief Pointer type. */ - using pointer = typename std::allocator_traits<Allocator>::pointer; - - /** - * @brief Inherited constructors. - * @param alloc The allocator to use. - */ - constexpr allocation_deleter(const allocator_type &alloc) noexcept(std::is_nothrow_copy_constructible_v<allocator_type>) - : Allocator{alloc} {} - - /** - * @brief Destroys the pointed object and deallocates its memory. - * @param ptr A valid pointer to an object of the given type. - */ - constexpr void operator()(pointer ptr) noexcept(std::is_nothrow_destructible_v<typename allocator_type::value_type>) { - using alloc_traits = std::allocator_traits<Allocator>; - alloc_traits::destroy(*this, to_address(ptr)); - alloc_traits::deallocate(*this, ptr, 1u); - } -}; - -/** - * @brief Allows `std::unique_ptr` to use allocators (waiting for C++20). - * @tparam Type Type of object to allocate for and to construct. - * @tparam Allocator Type of allocator used to manage memory and elements. - * @tparam Args Types of arguments to use to construct the object. - * @param allocator The allocator to use. - * @param args Parameters to use to construct the object. - * @return A properly initialized unique pointer with a custom deleter. - */ -template<typename Type, typename Allocator, typename... Args> -ENTT_CONSTEXPR auto allocate_unique(Allocator &allocator, Args &&...args) { - static_assert(!std::is_array_v<Type>, "Array types are not supported"); - - using alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<Type>; - using allocator_type = typename alloc_traits::allocator_type; - - allocator_type alloc{allocator}; - auto ptr = alloc_traits::allocate(alloc, 1u); - - ENTT_TRY { - alloc_traits::construct(alloc, to_address(ptr), std::forward<Args>(args)...); - } - ENTT_CATCH { - alloc_traits::deallocate(alloc, ptr, 1u); - ENTT_THROW; - } - - return std::unique_ptr<Type, allocation_deleter<allocator_type>>{ptr, alloc}; -} - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename Type> -struct uses_allocator_construction { - template<typename Allocator, typename... Params> - static constexpr auto args([[maybe_unused]] const Allocator &allocator, Params &&...params) noexcept { - if constexpr(!std::uses_allocator_v<Type, Allocator> && std::is_constructible_v<Type, Params...>) { - return std::forward_as_tuple(std::forward<Params>(params)...); - } else { - static_assert(std::uses_allocator_v<Type, Allocator>, "Ill-formed request"); - - if constexpr(std::is_constructible_v<Type, std::allocator_arg_t, const Allocator &, Params...>) { - return std::tuple<std::allocator_arg_t, const Allocator &, Params &&...>{std::allocator_arg, allocator, std::forward<Params>(params)...}; - } else { - static_assert(std::is_constructible_v<Type, Params..., const Allocator &>, "Ill-formed request"); - return std::forward_as_tuple(std::forward<Params>(params)..., allocator); - } - } - } -}; - -template<typename Type, typename Other> -struct uses_allocator_construction<std::pair<Type, Other>> { - using type = std::pair<Type, Other>; - - template<typename Allocator, typename First, typename Second> - static constexpr auto args(const Allocator &allocator, std::piecewise_construct_t, First &&first, Second &&second) noexcept { - return std::make_tuple( - std::piecewise_construct, - std::apply([&allocator](auto &&...curr) { return uses_allocator_construction<Type>::args(allocator, std::forward<decltype(curr)>(curr)...); }, std::forward<First>(first)), - std::apply([&allocator](auto &&...curr) { return uses_allocator_construction<Other>::args(allocator, std::forward<decltype(curr)>(curr)...); }, std::forward<Second>(second))); - } - - template<typename Allocator> - static constexpr auto args(const Allocator &allocator) noexcept { - return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::tuple<>{}, std::tuple<>{}); - } - - template<typename Allocator, typename First, typename Second> - static constexpr auto args(const Allocator &allocator, First &&first, Second &&second) noexcept { - return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::forward<First>(first)), std::forward_as_tuple(std::forward<Second>(second))); - } - - template<typename Allocator, typename First, typename Second> - static constexpr auto args(const Allocator &allocator, const std::pair<First, Second> &value) noexcept { - return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(value.first), std::forward_as_tuple(value.second)); - } - - template<typename Allocator, typename First, typename Second> - static constexpr auto args(const Allocator &allocator, std::pair<First, Second> &&value) noexcept { - return uses_allocator_construction<type>::args(allocator, std::piecewise_construct, std::forward_as_tuple(std::move(value.first)), std::forward_as_tuple(std::move(value.second))); - } -}; - -} // namespace internal -/*! @endcond */ - -/** - * @brief Uses-allocator construction utility (waiting for C++20). - * - * Primarily intended for internal use. Prepares the argument list needed to - * create an object of a given type by means of uses-allocator construction. - * - * @tparam Type Type to return arguments for. - * @tparam Allocator Type of allocator used to manage memory and elements. - * @tparam Args Types of arguments to use to construct the object. - * @param allocator The allocator to use. - * @param args Parameters to use to construct the object. - * @return The arguments needed to create an object of the given type. - */ -template<typename Type, typename Allocator, typename... Args> -constexpr auto uses_allocator_construction_args(const Allocator &allocator, Args &&...args) noexcept { - return internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...); -} - -/** - * @brief Uses-allocator construction utility (waiting for C++20). - * - * Primarily intended for internal use. Creates an object of a given type by - * means of uses-allocator construction. - * - * @tparam Type Type of object to create. - * @tparam Allocator Type of allocator used to manage memory and elements. - * @tparam Args Types of arguments to use to construct the object. - * @param allocator The allocator to use. - * @param args Parameters to use to construct the object. - * @return A newly created object of the given type. - */ -template<typename Type, typename Allocator, typename... Args> -constexpr Type make_obj_using_allocator(const Allocator &allocator, Args &&...args) { - return std::make_from_tuple<Type>(internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...)); -} - -/** - * @brief Uses-allocator construction utility (waiting for C++20). - * - * Primarily intended for internal use. Creates an object of a given type by - * means of uses-allocator construction at an uninitialized memory location. - * - * @tparam Type Type of object to create. - * @tparam Allocator Type of allocator used to manage memory and elements. - * @tparam Args Types of arguments to use to construct the object. - * @param value Memory location in which to place the object. - * @param allocator The allocator to use. - * @param args Parameters to use to construct the object. - * @return A pointer to the newly created object of the given type. - */ -template<typename Type, typename Allocator, typename... Args> -constexpr Type *uninitialized_construct_using_allocator(Type *value, const Allocator &allocator, Args &&...args) { - return std::apply([value](auto &&...curr) { return ::new(value) Type(std::forward<decltype(curr)>(curr)...); }, internal::uses_allocator_construction<Type>::args(allocator, std::forward<Args>(args)...)); -} - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/core/monostate.hpp b/deps/entt/include/entt/core/monostate.hpp deleted file mode 100644 index 4116bda..0000000 --- a/deps/entt/include/entt/core/monostate.hpp +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef ENTT_CORE_MONOSTATE_HPP -#define ENTT_CORE_MONOSTATE_HPP - -#include "../config/config.h" -#include "fwd.hpp" - -namespace entt { - -/** - * @brief Minimal implementation of the monostate pattern. - * - * A minimal, yet complete configuration system built on top of the monostate - * pattern. Thread safe by design, it works only with basic types like `int`s or - * `bool`s.<br/> - * Multiple types and therefore more than one value can be associated with a - * single key. Because of this, users must pay attention to use the same type - * both during an assignment and when they try to read back their data. - * Otherwise, they can incur in unexpected results. - */ -template<id_type> -struct monostate { - /** - * @brief Assigns a value of a specific type to a given key. - * @tparam Type Type of the value to assign. - * @param val User data to assign to the given key. - * @return This monostate object. - */ - template<typename Type> - monostate &operator=(Type val) noexcept { - value<Type> = val; - return *this; - } - - /** - * @brief Gets a value of a specific type for a given key. - * @tparam Type Type of the value to get. - * @return Stored value, if any. - */ - template<typename Type> - operator Type() const noexcept { - return value<Type>; - } - -private: - template<typename Type> - // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - inline static ENTT_MAYBE_ATOMIC(Type) value{}; -}; - -/** - * @brief Helper variable template. - * @tparam Value Value used to differentiate between different variables. - */ -template<id_type Value> -// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) -inline monostate<Value> monostate_v{}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/core/ranges.hpp b/deps/entt/include/entt/core/ranges.hpp deleted file mode 100644 index c1d062c..0000000 --- a/deps/entt/include/entt/core/ranges.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef ENTT_CORE_RANGES_HPP -#define ENTT_CORE_RANGES_HPP - -#if __has_include(<version>) -# include <version> -# -# if defined(__cpp_lib_ranges) -# include <ranges> -# include "iterator.hpp" - -template<class... Args> -inline constexpr bool std::ranges::enable_borrowed_range<entt::iterable_adaptor<Args...>>{true}; - -template<class... Args> -inline constexpr bool std::ranges::enable_view<entt::iterable_adaptor<Args...>>{true}; - -# endif -#endif - -#endif
\ No newline at end of file diff --git a/deps/entt/include/entt/core/tuple.hpp b/deps/entt/include/entt/core/tuple.hpp deleted file mode 100644 index 1a2dc4e..0000000 --- a/deps/entt/include/entt/core/tuple.hpp +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef ENTT_CORE_TUPLE_HPP -#define ENTT_CORE_TUPLE_HPP - -#include <tuple> -#include <type_traits> -#include <utility> - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename> -struct is_tuple_impl: std::false_type {}; - -template<typename... Args> -struct is_tuple_impl<std::tuple<Args...>>: std::true_type {}; - -} // namespace internal -/*! @endcond */ - -/** - * @brief Provides the member constant `value` to true if a given type is a - * tuple, false otherwise. - * @tparam Type The type to test. - */ -template<typename Type> -struct is_tuple: internal::is_tuple_impl<std::remove_cv_t<Type>> {}; - -/** - * @brief Helper variable template. - * @tparam Type The type to test. - */ -template<typename Type> -inline constexpr bool is_tuple_v = is_tuple<Type>::value; - -/** - * @brief Utility function to unwrap tuples of a single element. - * @tparam Type Tuple type of any sizes. - * @param value A tuple object of the given type. - * @return The tuple itself if it contains more than one element, the first - * element otherwise. - */ -template<typename Type> -constexpr decltype(auto) unwrap_tuple(Type &&value) noexcept { - if constexpr(std::tuple_size_v<std::remove_reference_t<Type>> == 1u) { - return std::get<0>(std::forward<Type>(value)); - } else { - return std::forward<Type>(value); - } -} - -/** - * @brief Utility class to forward-and-apply tuple objects. - * @tparam Func Type of underlying invocable object. - */ -template<typename Func> -struct forward_apply: private Func { - /** - * @brief Constructs a forward-and-apply object. - * @tparam Args Types of arguments to use to construct the new instance. - * @param args Parameters to use to construct the instance. - */ - template<typename... Args> - constexpr forward_apply(Args &&...args) noexcept(std::is_nothrow_constructible_v<Func, Args...>) - : Func{std::forward<Args>(args)...} {} - - /** - * @brief Forwards and applies the arguments with the underlying function. - * @tparam Type Tuple-like type to forward to the underlying function. - * @param args Parameters to forward to the underlying function. - * @return Return value of the underlying function, if any. - */ - template<typename Type> - constexpr decltype(auto) operator()(Type &&args) noexcept(noexcept(std::apply(std::declval<Func &>(), args))) { - return std::apply(static_cast<Func &>(*this), std::forward<Type>(args)); - } - - /*! @copydoc operator()() */ - template<typename Type> - constexpr decltype(auto) operator()(Type &&args) const noexcept(noexcept(std::apply(std::declval<const Func &>(), args))) { - return std::apply(static_cast<const Func &>(*this), std::forward<Type>(args)); - } -}; - -/** - * @brief Deduction guide. - * @tparam Func Type of underlying invocable object. - */ -template<typename Func> -forward_apply(Func) -> forward_apply<std::remove_reference_t<std::remove_cv_t<Func>>>; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/core/type_info.hpp b/deps/entt/include/entt/core/type_info.hpp deleted file mode 100644 index 1937506..0000000 --- a/deps/entt/include/entt/core/type_info.hpp +++ /dev/null @@ -1,268 +0,0 @@ -#ifndef ENTT_CORE_TYPE_INFO_HPP -#define ENTT_CORE_TYPE_INFO_HPP - -#include <string_view> -#include <type_traits> -#include <utility> -#include "../config/config.h" -#include "../core/attribute.h" -#include "fwd.hpp" -#include "hashed_string.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -struct ENTT_API type_index final { - [[nodiscard]] static id_type next() noexcept { - static ENTT_MAYBE_ATOMIC(id_type) value{}; - return value++; - } -}; - -template<typename Type> -[[nodiscard]] constexpr auto stripped_type_name() noexcept { -#if defined ENTT_PRETTY_FUNCTION - std::string_view pretty_function{static_cast<const char *>(ENTT_PRETTY_FUNCTION)}; - auto first = pretty_function.find_first_not_of(' ', pretty_function.find_first_of(ENTT_PRETTY_FUNCTION_PREFIX) + 1); - auto value = pretty_function.substr(first, pretty_function.find_last_of(ENTT_PRETTY_FUNCTION_SUFFIX) - first); - return value; -#else - return std::string_view{""}; -#endif -} - -template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')> -[[nodiscard]] constexpr std::string_view type_name(int) noexcept { - constexpr auto value = stripped_type_name<Type>(); - return value; -} - -template<typename Type> -[[nodiscard]] std::string_view type_name(char) noexcept { - static const auto value = stripped_type_name<Type>(); - return value; -} - -template<typename Type, auto = stripped_type_name<Type>().find_first_of('.')> -[[nodiscard]] constexpr id_type type_hash(int) noexcept { - constexpr auto stripped = stripped_type_name<Type>(); - constexpr auto value = hashed_string::value(stripped.data(), stripped.size()); - return value; -} - -template<typename Type> -[[nodiscard]] id_type type_hash(char) noexcept { - static const auto value = [](const auto stripped) { - return hashed_string::value(stripped.data(), stripped.size()); - }(stripped_type_name<Type>()); - return value; -} - -} // namespace internal -/*! @endcond */ - -/** - * @brief Type sequential identifier. - * @tparam Type Type for which to generate a sequential identifier. - */ -template<typename Type, typename = void> -struct ENTT_API type_index final { - /** - * @brief Returns the sequential identifier of a given type. - * @return The sequential identifier of a given type. - */ - [[nodiscard]] static id_type value() noexcept { - static const id_type value = internal::type_index::next(); - return value; - } - - /*! @copydoc value */ - [[nodiscard]] constexpr operator id_type() const noexcept { - return value(); - } -}; - -/** - * @brief Type hash. - * @tparam Type Type for which to generate a hash value. - */ -template<typename Type, typename = void> -struct type_hash final { - /** - * @brief Returns the numeric representation of a given type. - * @return The numeric representation of the given type. - */ -#if defined ENTT_PRETTY_FUNCTION - [[nodiscard]] static constexpr id_type value() noexcept { - return internal::type_hash<Type>(0); -#else - [[nodiscard]] static constexpr id_type value() noexcept { - return type_index<Type>::value(); -#endif - } - - /*! @copydoc value */ - [[nodiscard]] constexpr operator id_type() const noexcept { - return value(); - } -}; - -/** - * @brief Type name. - * @tparam Type Type for which to generate a name. - */ -template<typename Type, typename = void> -struct type_name final { - /** - * @brief Returns the name of a given type. - * @return The name of the given type. - */ - [[nodiscard]] static constexpr std::string_view value() noexcept { - return internal::type_name<Type>(0); - } - - /*! @copydoc value */ - [[nodiscard]] constexpr operator std::string_view() const noexcept { - return value(); - } -}; - -/*! @brief Implementation specific information about a type. */ -struct type_info final { - /** - * @brief Constructs a type info object for a given type. - * @tparam Type Type for which to construct a type info object. - */ - template<typename Type> - // NOLINTBEGIN(modernize-use-transparent-functors) - constexpr type_info(std::in_place_type_t<Type>) noexcept - : seq{type_index<std::remove_cv_t<std::remove_reference_t<Type>>>::value()}, - identifier{type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::value()}, - alias{type_name<std::remove_cv_t<std::remove_reference_t<Type>>>::value()} {} - // NOLINTEND(modernize-use-transparent-functors) - - /** - * @brief Type index. - * @return Type index. - */ - [[nodiscard]] constexpr id_type index() const noexcept { - return seq; - } - - /** - * @brief Type hash. - * @return Type hash. - */ - [[nodiscard]] constexpr id_type hash() const noexcept { - return identifier; - } - - /** - * @brief Type name. - * @return Type name. - */ - [[nodiscard]] constexpr std::string_view name() const noexcept { - return alias; - } - -private: - id_type seq; - id_type identifier; - std::string_view alias; -}; - -/** - * @brief Compares the contents of two type info objects. - * @param lhs A type info object. - * @param rhs A type info object. - * @return True if the two type info objects are identical, false otherwise. - */ -[[nodiscard]] inline constexpr bool operator==(const type_info &lhs, const type_info &rhs) noexcept { - return lhs.hash() == rhs.hash(); -} - -/** - * @brief Compares the contents of two type info objects. - * @param lhs A type info object. - * @param rhs A type info object. - * @return True if the two type info objects differ, false otherwise. - */ -[[nodiscard]] inline constexpr bool operator!=(const type_info &lhs, const type_info &rhs) noexcept { - return !(lhs == rhs); -} - -/** - * @brief Compares two type info objects. - * @param lhs A valid type info object. - * @param rhs A valid type info object. - * @return True if the first element is less than the second, false otherwise. - */ -[[nodiscard]] inline constexpr bool operator<(const type_info &lhs, const type_info &rhs) noexcept { - return lhs.index() < rhs.index(); -} - -/** - * @brief Compares two type info objects. - * @param lhs A valid type info object. - * @param rhs A valid type info object. - * @return True if the first element is less than or equal to the second, false - * otherwise. - */ -[[nodiscard]] inline constexpr bool operator<=(const type_info &lhs, const type_info &rhs) noexcept { - return !(rhs < lhs); -} - -/** - * @brief Compares two type info objects. - * @param lhs A valid type info object. - * @param rhs A valid type info object. - * @return True if the first element is greater than the second, false - * otherwise. - */ -[[nodiscard]] inline constexpr bool operator>(const type_info &lhs, const type_info &rhs) noexcept { - return rhs < lhs; -} - -/** - * @brief Compares two type info objects. - * @param lhs A valid type info object. - * @param rhs A valid type info object. - * @return True if the first element is greater than or equal to the second, - * false otherwise. - */ -[[nodiscard]] inline constexpr bool operator>=(const type_info &lhs, const type_info &rhs) noexcept { - return !(lhs < rhs); -} - -/** - * @brief Returns the type info object associated to a given type. - * - * The returned element refers to an object with static storage duration.<br/> - * The type doesn't need to be a complete type. If the type is a reference, the - * result refers to the referenced type. In all cases, top-level cv-qualifiers - * are ignored. - * - * @tparam Type Type for which to generate a type info object. - * @return A reference to a properly initialized type info object. - */ -template<typename Type> -[[nodiscard]] const type_info &type_id() noexcept { - if constexpr(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>) { - static type_info instance{std::in_place_type<Type>}; - return instance; - } else { - return type_id<std::remove_cv_t<std::remove_reference_t<Type>>>(); - } -} - -/*! @copydoc type_id */ -template<typename Type> -[[nodiscard]] const type_info &type_id(Type &&) noexcept { - return type_id<std::remove_cv_t<std::remove_reference_t<Type>>>(); -} - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/core/type_traits.hpp b/deps/entt/include/entt/core/type_traits.hpp deleted file mode 100644 index f6a9ea9..0000000 --- a/deps/entt/include/entt/core/type_traits.hpp +++ /dev/null @@ -1,919 +0,0 @@ -#ifndef ENTT_CORE_TYPE_TRAITS_HPP -#define ENTT_CORE_TYPE_TRAITS_HPP - -#include <cstddef> -#include <iterator> -#include <tuple> -#include <type_traits> -#include <utility> -#include "../config/config.h" -#include "fwd.hpp" - -namespace entt { - -/** - * @brief Utility class to disambiguate overloaded functions. - * @tparam N Number of choices available. - */ -template<std::size_t N> -struct choice_t - // unfortunately, doxygen cannot parse such a construct - : /*! @cond TURN_OFF_DOXYGEN */ choice_t<N - 1> /*! @endcond */ -{}; - -/*! @copybrief choice_t */ -template<> -struct choice_t<0> {}; - -/** - * @brief Variable template for the choice trick. - * @tparam N Number of choices available. - */ -template<std::size_t N> -inline constexpr choice_t<N> choice{}; - -/** - * @brief Identity type trait. - * - * Useful to establish non-deduced contexts in template argument deduction - * (waiting for C++20) or to provide types through function arguments. - * - * @tparam Type A type. - */ -template<typename Type> -struct type_identity { - /*! @brief Identity type. */ - using type = Type; -}; - -/** - * @brief Helper type. - * @tparam Type A type. - */ -template<typename Type> -using type_identity_t = typename type_identity<Type>::type; - -/** - * @brief A type-only `sizeof` wrapper that returns 0 where `sizeof` complains. - * @tparam Type The type of which to return the size. - */ -template<typename Type, typename = void> -struct size_of: std::integral_constant<std::size_t, 0u> {}; - -/*! @copydoc size_of */ -template<typename Type> -struct size_of<Type, std::void_t<decltype(sizeof(Type))>> - : std::integral_constant<std::size_t, sizeof(Type)> {}; - -/** - * @brief Helper variable template. - * @tparam Type The type of which to return the size. - */ -template<typename Type> -inline constexpr std::size_t size_of_v = size_of<Type>::value; - -/** - * @brief Using declaration to be used to _repeat_ the same type a number of - * times equal to the size of a given parameter pack. - * @tparam Type A type to repeat. - */ -template<typename Type, typename> -using unpack_as_type = Type; - -/** - * @brief Helper variable template to be used to _repeat_ the same value a - * number of times equal to the size of a given parameter pack. - * @tparam Value A value to repeat. - */ -template<auto Value, typename> -inline constexpr auto unpack_as_value = Value; - -/** - * @brief Wraps a static constant. - * @tparam Value A static constant. - */ -template<auto Value> -using integral_constant = std::integral_constant<decltype(Value), Value>; - -/** - * @brief Alias template to facilitate the creation of named values. - * @tparam Value A constant value at least convertible to `id_type`. - */ -template<id_type Value> -using tag = integral_constant<Value>; - -/** - * @brief A class to use to push around lists of types, nothing more. - * @tparam Type Types provided by the type list. - */ -template<typename... Type> -struct type_list { - /*! @brief Type list type. */ - using type = type_list; - /*! @brief Compile-time number of elements in the type list. */ - static constexpr auto size = sizeof...(Type); -}; - -/*! @brief Primary template isn't defined on purpose. */ -template<std::size_t, typename> -struct type_list_element; - -/** - * @brief Provides compile-time indexed access to the types of a type list. - * @tparam Index Index of the type to return. - * @tparam First First type provided by the type list. - * @tparam Other Other types provided by the type list. - */ -template<std::size_t Index, typename First, typename... Other> -struct type_list_element<Index, type_list<First, Other...>> - : type_list_element<Index - 1u, type_list<Other...>> {}; - -/** - * @brief Provides compile-time indexed access to the types of a type list. - * @tparam First First type provided by the type list. - * @tparam Other Other types provided by the type list. - */ -template<typename First, typename... Other> -struct type_list_element<0u, type_list<First, Other...>> { - /*! @brief Searched type. */ - using type = First; -}; - -/** - * @brief Helper type. - * @tparam Index Index of the type to return. - * @tparam List Type list to search into. - */ -template<std::size_t Index, typename List> -using type_list_element_t = typename type_list_element<Index, List>::type; - -/*! @brief Primary template isn't defined on purpose. */ -template<typename, typename> -struct type_list_index; - -/** - * @brief Provides compile-time type access to the types of a type list. - * @tparam Type Type to look for and for which to return the index. - * @tparam First First type provided by the type list. - * @tparam Other Other types provided by the type list. - */ -template<typename Type, typename First, typename... Other> -struct type_list_index<Type, type_list<First, Other...>> { - /*! @brief Unsigned integer type. */ - using value_type = std::size_t; - /*! @brief Compile-time position of the given type in the sublist. */ - static constexpr value_type value = 1u + type_list_index<Type, type_list<Other...>>::value; -}; - -/** - * @brief Provides compile-time type access to the types of a type list. - * @tparam Type Type to look for and for which to return the index. - * @tparam Other Other types provided by the type list. - */ -template<typename Type, typename... Other> -struct type_list_index<Type, type_list<Type, Other...>> { - static_assert(type_list_index<Type, type_list<Other...>>::value == sizeof...(Other), "Non-unique type"); - /*! @brief Unsigned integer type. */ - using value_type = std::size_t; - /*! @brief Compile-time position of the given type in the sublist. */ - static constexpr value_type value = 0u; -}; - -/** - * @brief Provides compile-time type access to the types of a type list. - * @tparam Type Type to look for and for which to return the index. - */ -template<typename Type> -struct type_list_index<Type, type_list<>> { - /*! @brief Unsigned integer type. */ - using value_type = std::size_t; - /*! @brief Compile-time position of the given type in the sublist. */ - static constexpr value_type value = 0u; -}; - -/** - * @brief Helper variable template. - * @tparam List Type list. - * @tparam Type Type to look for and for which to return the index. - */ -template<typename Type, typename List> -inline constexpr std::size_t type_list_index_v = type_list_index<Type, List>::value; - -/** - * @brief Concatenates multiple type lists. - * @tparam Type Types provided by the first type list. - * @tparam Other Types provided by the second type list. - * @return A type list composed by the types of both the type lists. - */ -template<typename... Type, typename... Other> -constexpr type_list<Type..., Other...> operator+(type_list<Type...>, type_list<Other...>) { - return {}; -} - -/*! @brief Primary template isn't defined on purpose. */ -template<typename...> -struct type_list_cat; - -/*! @brief Concatenates multiple type lists. */ -template<> -struct type_list_cat<> { - /*! @brief A type list composed by the types of all the type lists. */ - using type = type_list<>; -}; - -/** - * @brief Concatenates multiple type lists. - * @tparam Type Types provided by the first type list. - * @tparam Other Types provided by the second type list. - * @tparam List Other type lists, if any. - */ -template<typename... Type, typename... Other, typename... List> -struct type_list_cat<type_list<Type...>, type_list<Other...>, List...> { - /*! @brief A type list composed by the types of all the type lists. */ - using type = typename type_list_cat<type_list<Type..., Other...>, List...>::type; -}; - -/** - * @brief Concatenates multiple type lists. - * @tparam Type Types provided by the type list. - */ -template<typename... Type> -struct type_list_cat<type_list<Type...>> { - /*! @brief A type list composed by the types of all the type lists. */ - using type = type_list<Type...>; -}; - -/** - * @brief Helper type. - * @tparam List Type lists to concatenate. - */ -template<typename... List> -using type_list_cat_t = typename type_list_cat<List...>::type; - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename...> -struct type_list_unique; - -template<typename First, typename... Other, typename... Type> -struct type_list_unique<type_list<First, Other...>, Type...> - : std::conditional_t<(std::is_same_v<First, Type> || ...), type_list_unique<type_list<Other...>, Type...>, type_list_unique<type_list<Other...>, Type..., First>> {}; - -template<typename... Type> -struct type_list_unique<type_list<>, Type...> { - using type = type_list<Type...>; -}; - -} // namespace internal -/*! @endcond */ - -/** - * @brief Removes duplicates types from a type list. - * @tparam List Type list. - */ -template<typename List> -struct type_list_unique { - /*! @brief A type list without duplicate types. */ - using type = typename internal::type_list_unique<List>::type; -}; - -/** - * @brief Helper type. - * @tparam List Type list. - */ -template<typename List> -using type_list_unique_t = typename type_list_unique<List>::type; - -/** - * @brief Provides the member constant `value` to true if a type list contains a - * given type, false otherwise. - * @tparam List Type list. - * @tparam Type Type to look for. - */ -template<typename List, typename Type> -struct type_list_contains; - -/** - * @copybrief type_list_contains - * @tparam Type Types provided by the type list. - * @tparam Other Type to look for. - */ -template<typename... Type, typename Other> -struct type_list_contains<type_list<Type...>, Other> - : std::bool_constant<(std::is_same_v<Type, Other> || ...)> {}; - -/** - * @brief Helper variable template. - * @tparam List Type list. - * @tparam Type Type to look for. - */ -template<typename List, typename Type> -inline constexpr bool type_list_contains_v = type_list_contains<List, Type>::value; - -/*! @brief Primary template isn't defined on purpose. */ -template<typename...> -struct type_list_diff; - -/** - * @brief Computes the difference between two type lists. - * @tparam Type Types provided by the first type list. - * @tparam Other Types provided by the second type list. - */ -template<typename... Type, typename... Other> -struct type_list_diff<type_list<Type...>, type_list<Other...>> { - /*! @brief A type list that is the difference between the two type lists. */ - using type = type_list_cat_t<std::conditional_t<type_list_contains_v<type_list<Other...>, Type>, type_list<>, type_list<Type>>...>; -}; - -/** - * @brief Helper type. - * @tparam List Type lists between which to compute the difference. - */ -template<typename... List> -using type_list_diff_t = typename type_list_diff<List...>::type; - -/*! @brief Primary template isn't defined on purpose. */ -template<typename, template<typename...> class> -struct type_list_transform; - -/** - * @brief Applies a given _function_ to a type list and generate a new list. - * @tparam Type Types provided by the type list. - * @tparam Op Unary operation as template class with a type member named `type`. - */ -template<typename... Type, template<typename...> class Op> -struct type_list_transform<type_list<Type...>, Op> { - /*! @brief Resulting type list after applying the transform function. */ - using type = type_list<typename Op<Type>::type...>; -}; - -/** - * @brief Helper type. - * @tparam List Type list. - * @tparam Op Unary operation as template class with a type member named `type`. - */ -template<typename List, template<typename...> class Op> -using type_list_transform_t = typename type_list_transform<List, Op>::type; - -/** - * @brief A class to use to push around lists of constant values, nothing more. - * @tparam Value Values provided by the value list. - */ -template<auto... Value> -struct value_list { - /*! @brief Value list type. */ - using type = value_list; - /*! @brief Compile-time number of elements in the value list. */ - static constexpr auto size = sizeof...(Value); -}; - -/*! @brief Primary template isn't defined on purpose. */ -template<std::size_t, typename> -struct value_list_element; - -/** - * @brief Provides compile-time indexed access to the values of a value list. - * @tparam Index Index of the value to return. - * @tparam Value First value provided by the value list. - * @tparam Other Other values provided by the value list. - */ -template<std::size_t Index, auto Value, auto... Other> -struct value_list_element<Index, value_list<Value, Other...>> - : value_list_element<Index - 1u, value_list<Other...>> {}; - -/** - * @brief Provides compile-time indexed access to the types of a type list. - * @tparam Value First value provided by the value list. - * @tparam Other Other values provided by the value list. - */ -template<auto Value, auto... Other> -struct value_list_element<0u, value_list<Value, Other...>> { - /*! @brief Searched type. */ - using type = decltype(Value); - /*! @brief Searched value. */ - static constexpr auto value = Value; -}; - -/** - * @brief Helper type. - * @tparam Index Index of the type to return. - * @tparam List Value list to search into. - */ -template<std::size_t Index, typename List> -using value_list_element_t = typename value_list_element<Index, List>::type; - -/** - * @brief Helper type. - * @tparam Index Index of the value to return. - * @tparam List Value list to search into. - */ -template<std::size_t Index, typename List> -inline constexpr auto value_list_element_v = value_list_element<Index, List>::value; - -/*! @brief Primary template isn't defined on purpose. */ -template<auto, typename> -struct value_list_index; - -/** - * @brief Provides compile-time type access to the values of a value list. - * @tparam Value Value to look for and for which to return the index. - * @tparam First First value provided by the value list. - * @tparam Other Other values provided by the value list. - */ -template<auto Value, auto First, auto... Other> -struct value_list_index<Value, value_list<First, Other...>> { - /*! @brief Unsigned integer type. */ - using value_type = std::size_t; - /*! @brief Compile-time position of the given value in the sublist. */ - static constexpr value_type value = 1u + value_list_index<Value, value_list<Other...>>::value; -}; - -/** - * @brief Provides compile-time type access to the values of a value list. - * @tparam Value Value to look for and for which to return the index. - * @tparam Other Other values provided by the value list. - */ -template<auto Value, auto... Other> -struct value_list_index<Value, value_list<Value, Other...>> { - static_assert(value_list_index<Value, value_list<Other...>>::value == sizeof...(Other), "Non-unique type"); - /*! @brief Unsigned integer type. */ - using value_type = std::size_t; - /*! @brief Compile-time position of the given value in the sublist. */ - static constexpr value_type value = 0u; -}; - -/** - * @brief Provides compile-time type access to the values of a value list. - * @tparam Value Value to look for and for which to return the index. - */ -template<auto Value> -struct value_list_index<Value, value_list<>> { - /*! @brief Unsigned integer type. */ - using value_type = std::size_t; - /*! @brief Compile-time position of the given type in the sublist. */ - static constexpr value_type value = 0u; -}; - -/** - * @brief Helper variable template. - * @tparam List Value list. - * @tparam Value Value to look for and for which to return the index. - */ -template<auto Value, typename List> -inline constexpr std::size_t value_list_index_v = value_list_index<Value, List>::value; - -/** - * @brief Concatenates multiple value lists. - * @tparam Value Values provided by the first value list. - * @tparam Other Values provided by the second value list. - * @return A value list composed by the values of both the value lists. - */ -template<auto... Value, auto... Other> -constexpr value_list<Value..., Other...> operator+(value_list<Value...>, value_list<Other...>) { - return {}; -} - -/*! @brief Primary template isn't defined on purpose. */ -template<typename...> -struct value_list_cat; - -/*! @brief Concatenates multiple value lists. */ -template<> -struct value_list_cat<> { - /*! @brief A value list composed by the values of all the value lists. */ - using type = value_list<>; -}; - -/** - * @brief Concatenates multiple value lists. - * @tparam Value Values provided by the first value list. - * @tparam Other Values provided by the second value list. - * @tparam List Other value lists, if any. - */ -template<auto... Value, auto... Other, typename... List> -struct value_list_cat<value_list<Value...>, value_list<Other...>, List...> { - /*! @brief A value list composed by the values of all the value lists. */ - using type = typename value_list_cat<value_list<Value..., Other...>, List...>::type; -}; - -/** - * @brief Concatenates multiple value lists. - * @tparam Value Values provided by the value list. - */ -template<auto... Value> -struct value_list_cat<value_list<Value...>> { - /*! @brief A value list composed by the values of all the value lists. */ - using type = value_list<Value...>; -}; - -/** - * @brief Helper type. - * @tparam List Value lists to concatenate. - */ -template<typename... List> -using value_list_cat_t = typename value_list_cat<List...>::type; - -/*! @brief Primary template isn't defined on purpose. */ -template<typename> -struct value_list_unique; - -/** - * @brief Removes duplicates values from a value list. - * @tparam Value One of the values provided by the given value list. - * @tparam Other The other values provided by the given value list. - */ -template<auto Value, auto... Other> -struct value_list_unique<value_list<Value, Other...>> { - /*! @brief A value list without duplicate types. */ - using type = std::conditional_t< - ((Value == Other) || ...), - typename value_list_unique<value_list<Other...>>::type, - value_list_cat_t<value_list<Value>, typename value_list_unique<value_list<Other...>>::type>>; -}; - -/*! @brief Removes duplicates values from a value list. */ -template<> -struct value_list_unique<value_list<>> { - /*! @brief A value list without duplicate types. */ - using type = value_list<>; -}; - -/** - * @brief Helper type. - * @tparam Type A value list. - */ -template<typename Type> -using value_list_unique_t = typename value_list_unique<Type>::type; - -/** - * @brief Provides the member constant `value` to true if a value list contains - * a given value, false otherwise. - * @tparam List Value list. - * @tparam Value Value to look for. - */ -template<typename List, auto Value> -struct value_list_contains; - -/** - * @copybrief value_list_contains - * @tparam Value Values provided by the value list. - * @tparam Other Value to look for. - */ -template<auto... Value, auto Other> -struct value_list_contains<value_list<Value...>, Other> - : std::bool_constant<((Value == Other) || ...)> {}; - -/** - * @brief Helper variable template. - * @tparam List Value list. - * @tparam Value Value to look for. - */ -template<typename List, auto Value> -inline constexpr bool value_list_contains_v = value_list_contains<List, Value>::value; - -/*! @brief Primary template isn't defined on purpose. */ -template<typename...> -struct value_list_diff; - -/** - * @brief Computes the difference between two value lists. - * @tparam Value Values provided by the first value list. - * @tparam Other Values provided by the second value list. - */ -template<auto... Value, auto... Other> -struct value_list_diff<value_list<Value...>, value_list<Other...>> { - /*! @brief A value list that is the difference between the two value lists. */ - using type = value_list_cat_t<std::conditional_t<value_list_contains_v<value_list<Other...>, Value>, value_list<>, value_list<Value>>...>; -}; - -/** - * @brief Helper type. - * @tparam List Value lists between which to compute the difference. - */ -template<typename... List> -using value_list_diff_t = typename value_list_diff<List...>::type; - -/*! @brief Same as std::is_invocable, but with tuples. */ -template<typename, typename> -struct is_applicable: std::false_type {}; - -/** - * @copybrief is_applicable - * @tparam Func A valid function type. - * @tparam Tuple Tuple-like type. - * @tparam Args The list of arguments to use to probe the function type. - */ -template<typename Func, template<typename...> class Tuple, typename... Args> -struct is_applicable<Func, Tuple<Args...>>: std::is_invocable<Func, Args...> {}; - -/** - * @copybrief is_applicable - * @tparam Func A valid function type. - * @tparam Tuple Tuple-like type. - * @tparam Args The list of arguments to use to probe the function type. - */ -template<typename Func, template<typename...> class Tuple, typename... Args> -struct is_applicable<Func, const Tuple<Args...>>: std::is_invocable<Func, Args...> {}; - -/** - * @brief Helper variable template. - * @tparam Func A valid function type. - * @tparam Args The list of arguments to use to probe the function type. - */ -template<typename Func, typename Args> -inline constexpr bool is_applicable_v = is_applicable<Func, Args>::value; - -/*! @brief Same as std::is_invocable_r, but with tuples for arguments. */ -template<typename, typename, typename> -struct is_applicable_r: std::false_type {}; - -/** - * @copybrief is_applicable_r - * @tparam Ret The type to which the return type of the function should be - * convertible. - * @tparam Func A valid function type. - * @tparam Args The list of arguments to use to probe the function type. - */ -template<typename Ret, typename Func, typename... Args> -struct is_applicable_r<Ret, Func, std::tuple<Args...>>: std::is_invocable_r<Ret, Func, Args...> {}; - -/** - * @brief Helper variable template. - * @tparam Ret The type to which the return type of the function should be - * convertible. - * @tparam Func A valid function type. - * @tparam Args The list of arguments to use to probe the function type. - */ -template<typename Ret, typename Func, typename Args> -inline constexpr bool is_applicable_r_v = is_applicable_r<Ret, Func, Args>::value; - -/** - * @brief Provides the member constant `value` to true if a given type is - * complete, false otherwise. - * @tparam Type The type to test. - */ -template<typename Type, typename = void> -struct is_complete: std::false_type {}; - -/*! @copydoc is_complete */ -template<typename Type> -struct is_complete<Type, std::void_t<decltype(sizeof(Type))>>: std::true_type {}; - -/** - * @brief Helper variable template. - * @tparam Type The type to test. - */ -template<typename Type> -inline constexpr bool is_complete_v = is_complete<Type>::value; - -/** - * @brief Provides the member constant `value` to true if a given type is an - * iterator, false otherwise. - * @tparam Type The type to test. - */ -template<typename Type, typename = void> -struct is_iterator: std::false_type {}; - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename, typename = void> -struct has_iterator_category: std::false_type {}; - -template<typename Type> -struct has_iterator_category<Type, std::void_t<typename std::iterator_traits<Type>::iterator_category>>: std::true_type {}; - -} // namespace internal -/*! @endcond */ - -/*! @copydoc is_iterator */ -template<typename Type> -struct is_iterator<Type, std::enable_if_t<!std::is_void_v<std::remove_cv_t<std::remove_pointer_t<Type>>>>> - : internal::has_iterator_category<Type> {}; - -/** - * @brief Helper variable template. - * @tparam Type The type to test. - */ -template<typename Type> -inline constexpr bool is_iterator_v = is_iterator<Type>::value; - -/** - * @brief Provides the member constant `value` to true if a given type is both - * an empty and non-final class, false otherwise. - * @tparam Type The type to test - */ -template<typename Type> -struct is_ebco_eligible - : std::bool_constant<std::is_empty_v<Type> && !std::is_final_v<Type>> {}; - -/** - * @brief Helper variable template. - * @tparam Type The type to test. - */ -template<typename Type> -inline constexpr bool is_ebco_eligible_v = is_ebco_eligible<Type>::value; - -/** - * @brief Provides the member constant `value` to true if `Type::is_transparent` - * is valid and denotes a type, false otherwise. - * @tparam Type The type to test. - */ -template<typename Type, typename = void> -struct is_transparent: std::false_type {}; - -/*! @copydoc is_transparent */ -template<typename Type> -struct is_transparent<Type, std::void_t<typename Type::is_transparent>>: std::true_type {}; - -/** - * @brief Helper variable template. - * @tparam Type The type to test. - */ -template<typename Type> -inline constexpr bool is_transparent_v = is_transparent<Type>::value; - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename, typename = void> -struct has_tuple_size_value: std::false_type {}; - -template<typename Type> -struct has_tuple_size_value<Type, std::void_t<decltype(std::tuple_size<const Type>::value)>>: std::true_type {}; - -template<typename, typename = void> -struct has_value_type: std::false_type {}; - -template<typename Type> -struct has_value_type<Type, std::void_t<typename Type::value_type>>: std::true_type {}; - -template<typename> -[[nodiscard]] constexpr bool dispatch_is_equality_comparable(); - -template<typename Type, std::size_t... Index> -[[nodiscard]] constexpr bool unpack_maybe_equality_comparable(std::index_sequence<Index...>) { - return (dispatch_is_equality_comparable<std::tuple_element_t<Index, Type>>() && ...); -} - -template<typename> -[[nodiscard]] constexpr bool maybe_equality_comparable(char) { - return false; -} - -template<typename Type> -[[nodiscard]] constexpr auto maybe_equality_comparable(int) -> decltype(std::declval<Type>() == std::declval<Type>()) { - return true; -} - -template<typename Type> -[[nodiscard]] constexpr bool dispatch_is_equality_comparable() { - // NOLINTBEGIN(modernize-use-transparent-functors) - if constexpr(std::is_array_v<Type>) { - return false; - } else if constexpr(!is_iterator_v<Type> && has_value_type<Type>::value) { - if constexpr(std::is_same_v<typename Type::value_type, Type> || dispatch_is_equality_comparable<typename Type::value_type>()) { - return maybe_equality_comparable<Type>(0); - } else { - return false; - } - } else if constexpr(is_complete_v<std::tuple_size<std::remove_cv_t<Type>>>) { - if constexpr(has_tuple_size_value<Type>::value) { - return maybe_equality_comparable<Type>(0) && unpack_maybe_equality_comparable<Type>(std::make_index_sequence<std::tuple_size<Type>::value>{}); - } else { - return maybe_equality_comparable<Type>(0); - } - } else { - return maybe_equality_comparable<Type>(0); - } - // NOLINTEND(modernize-use-transparent-functors) -} - -} // namespace internal -/*! @endcond */ - -/** - * @brief Provides the member constant `value` to true if a given type is - * equality comparable, false otherwise. - * @tparam Type The type to test. - */ -template<typename Type> -struct is_equality_comparable: std::bool_constant<internal::dispatch_is_equality_comparable<Type>()> {}; - -/*! @copydoc is_equality_comparable */ -template<typename Type> -struct is_equality_comparable<const Type>: is_equality_comparable<Type> {}; - -/** - * @brief Helper variable template. - * @tparam Type The type to test. - */ -template<typename Type> -inline constexpr bool is_equality_comparable_v = is_equality_comparable<Type>::value; - -/** - * @brief Transcribes the constness of a type to another type. - * @tparam To The type to which to transcribe the constness. - * @tparam From The type from which to transcribe the constness. - */ -template<typename To, typename From> -struct constness_as { - /*! @brief The type resulting from the transcription of the constness. */ - using type = std::remove_const_t<To>; -}; - -/*! @copydoc constness_as */ -template<typename To, typename From> -struct constness_as<To, const From> { - /*! @brief The type resulting from the transcription of the constness. */ - using type = const To; -}; - -/** - * @brief Alias template to facilitate the transcription of the constness. - * @tparam To The type to which to transcribe the constness. - * @tparam From The type from which to transcribe the constness. - */ -template<typename To, typename From> -using constness_as_t = typename constness_as<To, From>::type; - -/** - * @brief Extracts the class of a non-static member object or function. - * @tparam Member A pointer to a non-static member object or function. - */ -template<typename Member> -class member_class { - static_assert(std::is_member_pointer_v<Member>, "Invalid pointer type to non-static member object or function"); - - template<typename Class, typename Ret, typename... Args> - static Class *clazz(Ret (Class::*)(Args...)); - - template<typename Class, typename Ret, typename... Args> - static Class *clazz(Ret (Class::*)(Args...) const); - - template<typename Class, typename Type> - static Class *clazz(Type Class::*); - -public: - /*! @brief The class of the given non-static member object or function. */ - using type = std::remove_pointer_t<decltype(clazz(std::declval<Member>()))>; -}; - -/** - * @brief Helper type. - * @tparam Member A pointer to a non-static member object or function. - */ -template<typename Member> -using member_class_t = typename member_class<Member>::type; - -/** - * @brief Extracts the n-th argument of a _callable_ type. - * @tparam Index The index of the argument to extract. - * @tparam Candidate A valid _callable_ type. - */ -template<std::size_t Index, typename Candidate> -class nth_argument { - template<typename Ret, typename... Args> - static constexpr type_list<Args...> pick_up(Ret (*)(Args...)); - - template<typename Ret, typename Class, typename... Args> - static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...)); - - template<typename Ret, typename Class, typename... Args> - static constexpr type_list<Args...> pick_up(Ret (Class ::*)(Args...) const); - - template<typename Type, typename Class> - static constexpr type_list<Type> pick_up(Type Class ::*); - - template<typename Type> - static constexpr decltype(pick_up(&Type::operator())) pick_up(Type &&); - -public: - /*! @brief N-th argument of the _callable_ type. */ - using type = type_list_element_t<Index, decltype(pick_up(std::declval<Candidate>()))>; -}; - -/** - * @brief Helper type. - * @tparam Index The index of the argument to extract. - * @tparam Candidate A valid function, member function or data member type. - */ -template<std::size_t Index, typename Candidate> -using nth_argument_t = typename nth_argument<Index, Candidate>::type; - -} // namespace entt - -template<typename... Type> -struct std::tuple_size<entt::type_list<Type...>>: std::integral_constant<std::size_t, entt::type_list<Type...>::size> {}; - -template<std::size_t Index, typename... Type> -struct std::tuple_element<Index, entt::type_list<Type...>>: entt::type_list_element<Index, entt::type_list<Type...>> {}; - -template<auto... Value> -struct std::tuple_size<entt::value_list<Value...>>: std::integral_constant<std::size_t, entt::value_list<Value...>::size> {}; - -template<std::size_t Index, auto... Value> -struct std::tuple_element<Index, entt::value_list<Value...>>: entt::value_list_element<Index, entt::value_list<Value...>> {}; - -#endif diff --git a/deps/entt/include/entt/core/utility.hpp b/deps/entt/include/entt/core/utility.hpp deleted file mode 100644 index af8b5bd..0000000 --- a/deps/entt/include/entt/core/utility.hpp +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef ENTT_CORE_UTILITY_HPP -#define ENTT_CORE_UTILITY_HPP - -#include <type_traits> -#include <utility> - -namespace entt { - -/*! @brief Identity function object (waiting for C++20). */ -struct identity { - /*! @brief Indicates that this is a transparent function object. */ - using is_transparent = void; - - /** - * @brief Returns its argument unchanged. - * @tparam Type Type of the argument. - * @param value The actual argument. - * @return The submitted value as-is. - */ - template<typename Type> - [[nodiscard]] constexpr Type &&operator()(Type &&value) const noexcept { - return std::forward<Type>(value); - } -}; - -/** - * @brief Constant utility to disambiguate overloaded members of a class. - * @tparam Type Type of the desired overload. - * @tparam Class Type of class to which the member belongs. - * @param member A valid pointer to a member. - * @return Pointer to the member. - */ -template<typename Type, typename Class> -[[nodiscard]] constexpr auto overload(Type Class::*member) noexcept { - return member; -} - -/** - * @brief Constant utility to disambiguate overloaded functions. - * @tparam Func Function type of the desired overload. - * @param func A valid pointer to a function. - * @return Pointer to the function. - */ -template<typename Func> -[[nodiscard]] constexpr auto overload(Func *func) noexcept { - return func; -} - -/** - * @brief Helper type for visitors. - * @tparam Func Types of function objects. - */ -template<typename... Func> -struct overloaded: Func... { - using Func::operator()...; -}; - -/** - * @brief Deduction guide. - * @tparam Func Types of function objects. - */ -template<typename... Func> -overloaded(Func...) -> overloaded<Func...>; - -/** - * @brief Basic implementation of a y-combinator. - * @tparam Func Type of a potentially recursive function. - */ -template<typename Func> -struct y_combinator { - /** - * @brief Constructs a y-combinator from a given function. - * @param recursive A potentially recursive function. - */ - constexpr y_combinator(Func recursive) noexcept(std::is_nothrow_move_constructible_v<Func>) - : func{std::move(recursive)} {} - - /** - * @brief Invokes a y-combinator and therefore its underlying function. - * @tparam Args Types of arguments to use to invoke the underlying function. - * @param args Parameters to use to invoke the underlying function. - * @return Return value of the underlying function, if any. - */ - template<typename... Args> - constexpr decltype(auto) operator()(Args &&...args) const noexcept(std::is_nothrow_invocable_v<Func, const y_combinator &, Args...>) { - return func(*this, std::forward<Args>(args)...); - } - - /*! @copydoc operator()() */ - template<typename... Args> - constexpr decltype(auto) operator()(Args &&...args) noexcept(std::is_nothrow_invocable_v<Func, y_combinator &, Args...>) { - return func(*this, std::forward<Args>(args)...); - } - -private: - Func func; -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/entity/component.hpp b/deps/entt/include/entt/entity/component.hpp deleted file mode 100644 index 2e8a02b..0000000 --- a/deps/entt/include/entt/entity/component.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef ENTT_ENTITY_COMPONENT_HPP -#define ENTT_ENTITY_COMPONENT_HPP - -#include <cstddef> -#include <type_traits> -#include "../config/config.h" -#include "fwd.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename Type, typename = void> -struct in_place_delete: std::bool_constant<!(std::is_move_constructible_v<Type> && std::is_move_assignable_v<Type>)> {}; - -template<> -struct in_place_delete<void>: std::false_type {}; - -template<typename Type> -struct in_place_delete<Type, std::enable_if_t<Type::in_place_delete>> - : std::true_type {}; - -template<typename Type, typename = void> -struct page_size: std::integral_constant<std::size_t, !std::is_empty_v<ENTT_ETO_TYPE(Type)> * ENTT_PACKED_PAGE> {}; - -template<> -struct page_size<void>: std::integral_constant<std::size_t, 0u> {}; - -template<typename Type> -struct page_size<Type, std::void_t<decltype(Type::page_size)>> - : std::integral_constant<std::size_t, Type::page_size> {}; - -} // namespace internal -/*! @endcond */ - -/** - * @brief Common way to access various properties of components. - * @tparam Type Type of component. - */ -template<typename Type, typename = void> -struct component_traits { - static_assert(std::is_same_v<std::decay_t<Type>, Type>, "Unsupported type"); - - /*! @brief Component type. */ - using type = Type; - - /*! @brief Pointer stability, default is `false`. */ - static constexpr bool in_place_delete = internal::in_place_delete<Type>::value; - /*! @brief Page size, default is `ENTT_PACKED_PAGE` for non-empty types. */ - static constexpr std::size_t page_size = internal::page_size<Type>::value; -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/entity/entity.hpp b/deps/entt/include/entt/entity/entity.hpp deleted file mode 100644 index 3c3dae6..0000000 --- a/deps/entt/include/entt/entity/entity.hpp +++ /dev/null @@ -1,388 +0,0 @@ -#ifndef ENTT_ENTITY_ENTITY_HPP -#define ENTT_ENTITY_ENTITY_HPP - -#include <cstddef> -#include <cstdint> -#include <type_traits> -#include "../config/config.h" -#include "../core/bit.hpp" -#include "fwd.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename, typename = void> -struct entt_traits; - -template<typename Type> -struct entt_traits<Type, std::enable_if_t<std::is_enum_v<Type>>> - : entt_traits<std::underlying_type_t<Type>> { - using value_type = Type; -}; - -template<typename Type> -struct entt_traits<Type, std::enable_if_t<std::is_class_v<Type>>> - : entt_traits<typename Type::entity_type> { - using value_type = Type; -}; - -template<> -struct entt_traits<std::uint32_t> { - using value_type = std::uint32_t; - - using entity_type = std::uint32_t; - using version_type = std::uint16_t; - - static constexpr entity_type entity_mask = 0xFFFFF; - static constexpr entity_type version_mask = 0xFFF; -}; - -template<> -struct entt_traits<std::uint64_t> { - using value_type = std::uint64_t; - - using entity_type = std::uint64_t; - using version_type = std::uint32_t; - - static constexpr entity_type entity_mask = 0xFFFFFFFF; - static constexpr entity_type version_mask = 0xFFFFFFFF; -}; - -} // namespace internal -/*! @endcond */ - -/** - * @brief Common basic entity traits implementation. - * @tparam Traits Actual entity traits to use. - */ -template<typename Traits> -class basic_entt_traits { - static constexpr auto length = popcount(Traits::entity_mask); - - static_assert(Traits::entity_mask && ((Traits::entity_mask & (Traits::entity_mask + 1)) == 0), "Invalid entity mask"); - static_assert((Traits::version_mask & (Traits::version_mask + 1)) == 0, "Invalid version mask"); - -public: - /*! @brief Value type. */ - using value_type = typename Traits::value_type; - /*! @brief Underlying entity type. */ - using entity_type = typename Traits::entity_type; - /*! @brief Underlying version type. */ - using version_type = typename Traits::version_type; - - /*! @brief Entity mask size. */ - static constexpr entity_type entity_mask = Traits::entity_mask; - /*! @brief Version mask size */ - static constexpr entity_type version_mask = Traits::version_mask; - - /** - * @brief Converts an entity to its underlying type. - * @param value The value to convert. - * @return The integral representation of the given value. - */ - [[nodiscard]] static constexpr entity_type to_integral(const value_type value) noexcept { - return static_cast<entity_type>(value); - } - - /** - * @brief Returns the entity part once converted to the underlying type. - * @param value The value to convert. - * @return The integral representation of the entity part. - */ - [[nodiscard]] static constexpr entity_type to_entity(const value_type value) noexcept { - return (to_integral(value) & entity_mask); - } - - /** - * @brief Returns the version part once converted to the underlying type. - * @param value The value to convert. - * @return The integral representation of the version part. - */ - [[nodiscard]] static constexpr version_type to_version(const value_type value) noexcept { - if constexpr(Traits::version_mask == 0u) { - return version_type{}; - } else { - return (static_cast<version_type>(to_integral(value) >> length) & version_mask); - } - } - - /** - * @brief Returns the successor of a given identifier. - * @param value The identifier of which to return the successor. - * @return The successor of the given identifier. - */ - [[nodiscard]] static constexpr value_type next(const value_type value) noexcept { - const auto vers = to_version(value) + 1; - return construct(to_integral(value), static_cast<version_type>(vers + (vers == version_mask))); - } - - /** - * @brief Constructs an identifier from its parts. - * - * If the version part is not provided, a tombstone is returned.<br/> - * If the entity part is not provided, a null identifier is returned. - * - * @param entity The entity part of the identifier. - * @param version The version part of the identifier. - * @return A properly constructed identifier. - */ - [[nodiscard]] static constexpr value_type construct(const entity_type entity, const version_type version) noexcept { - if constexpr(Traits::version_mask == 0u) { - return value_type{entity & entity_mask}; - } else { - return value_type{(entity & entity_mask) | (static_cast<entity_type>(version & version_mask) << length)}; - } - } - - /** - * @brief Combines two identifiers in a single one. - * - * The returned identifier is a copy of the first element except for its - * version, which is taken from the second element. - * - * @param lhs The identifier from which to take the entity part. - * @param rhs The identifier from which to take the version part. - * @return A properly constructed identifier. - */ - [[nodiscard]] static constexpr value_type combine(const entity_type lhs, const entity_type rhs) noexcept { - if constexpr(Traits::version_mask == 0u) { - return value_type{lhs & entity_mask}; - } else { - return value_type{(lhs & entity_mask) | (rhs & (version_mask << length))}; - } - } -}; - -/** - * @brief Entity traits. - * @tparam Type Type of identifier. - */ -template<typename Type> -struct entt_traits: basic_entt_traits<internal::entt_traits<Type>> { - /*! @brief Base type. */ - using base_type = basic_entt_traits<internal::entt_traits<Type>>; - /*! @brief Page size, default is `ENTT_SPARSE_PAGE`. */ - static constexpr std::size_t page_size = ENTT_SPARSE_PAGE; -}; - -/** - * @brief Converts an entity to its underlying type. - * @tparam Entity The value type. - * @param value The value to convert. - * @return The integral representation of the given value. - */ -template<typename Entity> -[[nodiscard]] constexpr typename entt_traits<Entity>::entity_type to_integral(const Entity value) noexcept { - return entt_traits<Entity>::to_integral(value); -} - -/** - * @brief Returns the entity part once converted to the underlying type. - * @tparam Entity The value type. - * @param value The value to convert. - * @return The integral representation of the entity part. - */ -template<typename Entity> -[[nodiscard]] constexpr typename entt_traits<Entity>::entity_type to_entity(const Entity value) noexcept { - return entt_traits<Entity>::to_entity(value); -} - -/** - * @brief Returns the version part once converted to the underlying type. - * @tparam Entity The value type. - * @param value The value to convert. - * @return The integral representation of the version part. - */ -template<typename Entity> -[[nodiscard]] constexpr typename entt_traits<Entity>::version_type to_version(const Entity value) noexcept { - return entt_traits<Entity>::to_version(value); -} - -/*! @brief Null object for all identifiers. */ -struct null_t { - /** - * @brief Converts the null object to identifiers of any type. - * @tparam Entity Type of identifier. - * @return The null representation for the given type. - */ - template<typename Entity> - [[nodiscard]] constexpr operator Entity() const noexcept { - using traits_type = entt_traits<Entity>; - constexpr auto value = traits_type::construct(traits_type::entity_mask, traits_type::version_mask); - return value; - } - - /** - * @brief Compares two null objects. - * @param other A null object. - * @return True in all cases. - */ - [[nodiscard]] constexpr bool operator==([[maybe_unused]] const null_t other) const noexcept { - return true; - } - - /** - * @brief Compares two null objects. - * @param other A null object. - * @return False in all cases. - */ - [[nodiscard]] constexpr bool operator!=([[maybe_unused]] const null_t other) const noexcept { - return false; - } - - /** - * @brief Compares a null object and an identifier of any type. - * @tparam Entity Type of identifier. - * @param entity Identifier with which to compare. - * @return False if the two elements differ, true otherwise. - */ - template<typename Entity> - [[nodiscard]] constexpr bool operator==(const Entity entity) const noexcept { - using traits_type = entt_traits<Entity>; - return traits_type::to_entity(entity) == traits_type::to_entity(*this); - } - - /** - * @brief Compares a null object and an identifier of any type. - * @tparam Entity Type of identifier. - * @param entity Identifier with which to compare. - * @return True if the two elements differ, false otherwise. - */ - template<typename Entity> - [[nodiscard]] constexpr bool operator!=(const Entity entity) const noexcept { - return !(entity == *this); - } -}; - -/** - * @brief Compares a null object and an identifier of any type. - * @tparam Entity Type of identifier. - * @param lhs Identifier with which to compare. - * @param rhs A null object yet to be converted. - * @return False if the two elements differ, true otherwise. - */ -template<typename Entity> -[[nodiscard]] constexpr bool operator==(const Entity lhs, const null_t rhs) noexcept { - return rhs.operator==(lhs); -} - -/** - * @brief Compares a null object and an identifier of any type. - * @tparam Entity Type of identifier. - * @param lhs Identifier with which to compare. - * @param rhs A null object yet to be converted. - * @return True if the two elements differ, false otherwise. - */ -template<typename Entity> -[[nodiscard]] constexpr bool operator!=(const Entity lhs, const null_t rhs) noexcept { - return !(rhs == lhs); -} - -/*! @brief Tombstone object for all identifiers. */ -struct tombstone_t { - /** - * @brief Converts the tombstone object to identifiers of any type. - * @tparam Entity Type of identifier. - * @return The tombstone representation for the given type. - */ - template<typename Entity> - [[nodiscard]] constexpr operator Entity() const noexcept { - using traits_type = entt_traits<Entity>; - constexpr auto value = traits_type::construct(traits_type::entity_mask, traits_type::version_mask); - return value; - } - - /** - * @brief Compares two tombstone objects. - * @param other A tombstone object. - * @return True in all cases. - */ - [[nodiscard]] constexpr bool operator==([[maybe_unused]] const tombstone_t other) const noexcept { - return true; - } - - /** - * @brief Compares two tombstone objects. - * @param other A tombstone object. - * @return False in all cases. - */ - [[nodiscard]] constexpr bool operator!=([[maybe_unused]] const tombstone_t other) const noexcept { - return false; - } - - /** - * @brief Compares a tombstone object and an identifier of any type. - * @tparam Entity Type of identifier. - * @param entity Identifier with which to compare. - * @return False if the two elements differ, true otherwise. - */ - template<typename Entity> - [[nodiscard]] constexpr bool operator==(const Entity entity) const noexcept { - using traits_type = entt_traits<Entity>; - - if constexpr(traits_type::version_mask == 0u) { - return false; - } else { - return (traits_type::to_version(entity) == traits_type::to_version(*this)); - } - } - - /** - * @brief Compares a tombstone object and an identifier of any type. - * @tparam Entity Type of identifier. - * @param entity Identifier with which to compare. - * @return True if the two elements differ, false otherwise. - */ - template<typename Entity> - [[nodiscard]] constexpr bool operator!=(const Entity entity) const noexcept { - return !(entity == *this); - } -}; - -/** - * @brief Compares a tombstone object and an identifier of any type. - * @tparam Entity Type of identifier. - * @param lhs Identifier with which to compare. - * @param rhs A tombstone object yet to be converted. - * @return False if the two elements differ, true otherwise. - */ -template<typename Entity> -[[nodiscard]] constexpr bool operator==(const Entity lhs, const tombstone_t rhs) noexcept { - return rhs.operator==(lhs); -} - -/** - * @brief Compares a tombstone object and an identifier of any type. - * @tparam Entity Type of identifier. - * @param lhs Identifier with which to compare. - * @param rhs A tombstone object yet to be converted. - * @return True if the two elements differ, false otherwise. - */ -template<typename Entity> -[[nodiscard]] constexpr bool operator!=(const Entity lhs, const tombstone_t rhs) noexcept { - return !(rhs == lhs); -} - -/** - * @brief Compile-time constant for null entities. - * - * There exist implicit conversions from this variable to identifiers of any - * allowed type. Similarly, there exist comparison operators between the null - * entity and any other identifier. - */ -inline constexpr null_t null{}; - -/** - * @brief Compile-time constant for tombstone entities. - * - * There exist implicit conversions from this variable to identifiers of any - * allowed type. Similarly, there exist comparison operators between the - * tombstone entity and any other identifier. - */ -inline constexpr tombstone_t tombstone{}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/entity/fwd.hpp b/deps/entt/include/entt/entity/fwd.hpp deleted file mode 100644 index 17d23f6..0000000 --- a/deps/entt/include/entt/entity/fwd.hpp +++ /dev/null @@ -1,267 +0,0 @@ -#ifndef ENTT_ENTITY_FWD_HPP -#define ENTT_ENTITY_FWD_HPP - -#include <cstdint> -#include <memory> -#include <type_traits> -#include "../config/config.h" -#include "../core/fwd.hpp" -#include "../core/type_traits.hpp" - -namespace entt { - -/*! @brief Default entity identifier. */ -enum class entity : id_type {}; - -/*! @brief Storage deletion policy. */ -enum class deletion_policy : std::uint8_t { - /*! @brief Swap-and-pop deletion policy. */ - swap_and_pop = 0u, - /*! @brief In-place deletion policy. */ - in_place = 1u, - /*! @brief Swap-only deletion policy. */ - swap_only = 2u -}; - -template<typename Entity = entity, typename = std::allocator<Entity>> -class basic_sparse_set; - -template<typename Type, typename = entity, typename = std::allocator<Type>, typename = void> -class basic_storage; - -template<typename, typename> -class basic_sigh_mixin; - -template<typename Entity = entity, typename = std::allocator<Entity>> -class basic_registry; - -template<typename, typename, typename = void> -class basic_view; - -template<typename Type, typename = std::allocator<Type *>> -class basic_runtime_view; - -template<typename, typename, typename> -class basic_group; - -template<typename, typename = std::allocator<void>> -class basic_observer; - -template<typename> -class basic_organizer; - -template<typename, typename...> -class basic_handle; - -template<typename> -class basic_snapshot; - -template<typename> -class basic_snapshot_loader; - -template<typename> -class basic_continuous_loader; - -/*! @brief Alias declaration for the most common use case. */ -using sparse_set = basic_sparse_set<>; - -/** - * @brief Alias declaration for the most common use case. - * @tparam Type Element type. - */ -template<typename Type> -using storage = basic_storage<Type>; - -/** - * @brief Alias declaration for the most common use case. - * @tparam Type Underlying storage type. - */ -template<typename Type> -using sigh_mixin = basic_sigh_mixin<Type, basic_registry<typename Type::entity_type, typename Type::base_type::allocator_type>>; - -/*! @brief Alias declaration for the most common use case. */ -using registry = basic_registry<>; - -/*! @brief Alias declaration for the most common use case. */ -using observer = basic_observer<registry>; - -/*! @brief Alias declaration for the most common use case. */ -using organizer = basic_organizer<registry>; - -/*! @brief Alias declaration for the most common use case. */ -using handle = basic_handle<registry>; - -/*! @brief Alias declaration for the most common use case. */ -using const_handle = basic_handle<const registry>; - -/** - * @brief Alias declaration for the most common use case. - * @tparam Args Other template parameters. - */ -template<typename... Args> -using handle_view = basic_handle<registry, Args...>; - -/** - * @brief Alias declaration for the most common use case. - * @tparam Args Other template parameters. - */ -template<typename... Args> -using const_handle_view = basic_handle<const registry, Args...>; - -/*! @brief Alias declaration for the most common use case. */ -using snapshot = basic_snapshot<registry>; - -/*! @brief Alias declaration for the most common use case. */ -using snapshot_loader = basic_snapshot_loader<registry>; - -/*! @brief Alias declaration for the most common use case. */ -using continuous_loader = basic_continuous_loader<registry>; - -/*! @brief Alias declaration for the most common use case. */ -using runtime_view = basic_runtime_view<sparse_set>; - -/*! @brief Alias declaration for the most common use case. */ -using const_runtime_view = basic_runtime_view<const sparse_set>; - -/** - * @brief Alias for exclusion lists. - * @tparam Type List of types. - */ -template<typename... Type> -struct exclude_t final: type_list<Type...> { - /*! @brief Default constructor. */ - explicit constexpr exclude_t() = default; -}; - -/** - * @brief Variable template for exclusion lists. - * @tparam Type List of types. - */ -template<typename... Type> -inline constexpr exclude_t<Type...> exclude{}; - -/** - * @brief Alias for lists of observed elements. - * @tparam Type List of types. - */ -template<typename... Type> -struct get_t final: type_list<Type...> { - /*! @brief Default constructor. */ - explicit constexpr get_t() = default; -}; - -/** - * @brief Variable template for lists of observed elements. - * @tparam Type List of types. - */ -template<typename... Type> -inline constexpr get_t<Type...> get{}; - -/** - * @brief Alias for lists of owned elements. - * @tparam Type List of types. - */ -template<typename... Type> -struct owned_t final: type_list<Type...> { - /*! @brief Default constructor. */ - explicit constexpr owned_t() = default; -}; - -/** - * @brief Variable template for lists of owned elements. - * @tparam Type List of types. - */ -template<typename... Type> -inline constexpr owned_t<Type...> owned{}; - -/** - * @brief Applies a given _function_ to a get list and generate a new list. - * @tparam Type Types provided by the get list. - * @tparam Op Unary operation as template class with a type member named `type`. - */ -template<typename... Type, template<typename...> class Op> -struct type_list_transform<get_t<Type...>, Op> { - /*! @brief Resulting get list after applying the transform function. */ - using type = get_t<typename Op<Type>::type...>; -}; - -/** - * @brief Applies a given _function_ to an exclude list and generate a new list. - * @tparam Type Types provided by the exclude list. - * @tparam Op Unary operation as template class with a type member named `type`. - */ -template<typename... Type, template<typename...> class Op> -struct type_list_transform<exclude_t<Type...>, Op> { - /*! @brief Resulting exclude list after applying the transform function. */ - using type = exclude_t<typename Op<Type>::type...>; -}; - -/** - * @brief Applies a given _function_ to an owned list and generate a new list. - * @tparam Type Types provided by the owned list. - * @tparam Op Unary operation as template class with a type member named `type`. - */ -template<typename... Type, template<typename...> class Op> -struct type_list_transform<owned_t<Type...>, Op> { - /*! @brief Resulting owned list after applying the transform function. */ - using type = owned_t<typename Op<Type>::type...>; -}; - -/** - * @brief Provides a common way to define storage types. - * @tparam Type Storage value type. - * @tparam Entity A valid entity type. - * @tparam Allocator Type of allocator used to manage memory and elements. - */ -template<typename Type, typename Entity = entity, typename Allocator = std::allocator<Type>, typename = void> -struct storage_type { - /*! @brief Type-to-storage conversion result. */ - using type = ENTT_STORAGE(sigh_mixin, basic_storage<Type, Entity, Allocator>); -}; - -/** - * @brief Helper type. - * @tparam Args Arguments to forward. - */ -template<typename... Args> -using storage_type_t = typename storage_type<Args...>::type; - -/** - * Type-to-storage conversion utility that preserves constness. - * @tparam Type Storage value type, eventually const. - * @tparam Entity A valid entity type. - * @tparam Allocator Type of allocator used to manage memory and elements. - */ -template<typename Type, typename Entity = entity, typename Allocator = std::allocator<std::remove_const_t<Type>>> -struct storage_for { - /*! @brief Type-to-storage conversion result. */ - using type = constness_as_t<storage_type_t<std::remove_const_t<Type>, Entity, Allocator>, Type>; -}; - -/** - * @brief Helper type. - * @tparam Args Arguments to forward. - */ -template<typename... Args> -using storage_for_t = typename storage_for<Args...>::type; - -/** - * @brief Alias declaration for the most common use case. - * @tparam Get Types of storage iterated by the view. - * @tparam Exclude Types of storage used to filter the view. - */ -template<typename Get, typename Exclude = exclude_t<>> -using view = basic_view<type_list_transform_t<Get, storage_for>, type_list_transform_t<Exclude, storage_for>>; - -/** - * @brief Alias declaration for the most common use case. - * @tparam Owned Types of storage _owned_ by the group. - * @tparam Get Types of storage _observed_ by the group. - * @tparam Exclude Types of storage used to filter the group. - */ -template<typename Owned, typename Get, typename Exclude> -using group = basic_group<type_list_transform_t<Owned, storage_for>, type_list_transform_t<Get, storage_for>, type_list_transform_t<Exclude, storage_for>>; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/entity/group.hpp b/deps/entt/include/entt/entity/group.hpp deleted file mode 100644 index 32abb3a..0000000 --- a/deps/entt/include/entt/entity/group.hpp +++ /dev/null @@ -1,1057 +0,0 @@ -#ifndef ENTT_ENTITY_GROUP_HPP -#define ENTT_ENTITY_GROUP_HPP - -#include <array> -#include <cstddef> -#include <iterator> -#include <tuple> -#include <type_traits> -#include <utility> -#include "../config/config.h" -#include "../core/algorithm.hpp" -#include "../core/fwd.hpp" -#include "../core/iterator.hpp" -#include "../core/type_info.hpp" -#include "../core/type_traits.hpp" -#include "entity.hpp" -#include "fwd.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename, typename, typename> -class extended_group_iterator; - -template<typename It, typename... Owned, typename... Get> -class extended_group_iterator<It, owned_t<Owned...>, get_t<Get...>> { - template<typename Type> - [[nodiscard]] auto index_to_element([[maybe_unused]] Type &cpool) const { - if constexpr(std::is_void_v<typename Type::value_type>) { - return std::make_tuple(); - } else { - return std::forward_as_tuple(cpool.rbegin()[it.index()]); - } - } - -public: - using iterator_type = It; - using value_type = decltype(std::tuple_cat(std::make_tuple(*std::declval<It>()), std::declval<Owned>().get_as_tuple({})..., std::declval<Get>().get_as_tuple({})...)); - using pointer = input_iterator_pointer<value_type>; - using reference = value_type; - using difference_type = std::ptrdiff_t; - using iterator_category = std::input_iterator_tag; - using iterator_concept = std::forward_iterator_tag; - - constexpr extended_group_iterator() - : it{}, - pools{} {} - - extended_group_iterator(iterator_type from, std::tuple<Owned *..., Get *...> cpools) - : it{from}, - pools{std::move(cpools)} {} - - extended_group_iterator &operator++() noexcept { - return ++it, *this; - } - - extended_group_iterator operator++(int) noexcept { - extended_group_iterator orig = *this; - return ++(*this), orig; - } - - [[nodiscard]] reference operator*() const noexcept { - return std::tuple_cat(std::make_tuple(*it), index_to_element(*std::get<Owned *>(pools))..., std::get<Get *>(pools)->get_as_tuple(*it)...); - } - - [[nodiscard]] pointer operator->() const noexcept { - return operator*(); - } - - [[nodiscard]] constexpr iterator_type base() const noexcept { - return it; - } - - template<typename... Lhs, typename... Rhs> - friend constexpr bool operator==(const extended_group_iterator<Lhs...> &, const extended_group_iterator<Rhs...> &) noexcept; - -private: - It it; - std::tuple<Owned *..., Get *...> pools; -}; - -template<typename... Lhs, typename... Rhs> -[[nodiscard]] constexpr bool operator==(const extended_group_iterator<Lhs...> &lhs, const extended_group_iterator<Rhs...> &rhs) noexcept { - return lhs.it == rhs.it; -} - -template<typename... Lhs, typename... Rhs> -[[nodiscard]] constexpr bool operator!=(const extended_group_iterator<Lhs...> &lhs, const extended_group_iterator<Rhs...> &rhs) noexcept { - return !(lhs == rhs); -} - -struct group_descriptor { - using size_type = std::size_t; - virtual ~group_descriptor() noexcept = default; - [[nodiscard]] virtual bool owned(const id_type) const noexcept { - return false; - } -}; - -template<typename Type, std::size_t Owned, std::size_t Get, std::size_t Exclude> -class group_handler final: public group_descriptor { - using entity_type = typename Type::entity_type; - - void swap_elements(const std::size_t pos, const entity_type entt) { - for(size_type next{}; next < Owned; ++next) { - pools[next]->swap_elements((*pools[next])[pos], entt); - } - } - - void push_on_construct(const entity_type entt) { - if(std::apply([entt, pos = len](auto *cpool, auto *...other) { return cpool->contains(entt) && !(cpool->index(entt) < pos) && (other->contains(entt) && ...); }, pools) - && std::apply([entt](auto *...cpool) { return (!cpool->contains(entt) && ...); }, filter)) { - swap_elements(len++, entt); - } - } - - void push_on_destroy(const entity_type entt) { - if(std::apply([entt, pos = len](auto *cpool, auto *...other) { return cpool->contains(entt) && !(cpool->index(entt) < pos) && (other->contains(entt) && ...); }, pools) - && std::apply([entt](auto *...cpool) { return (0u + ... + cpool->contains(entt)) == 1u; }, filter)) { - swap_elements(len++, entt); - } - } - - void remove_if(const entity_type entt) { - if(pools[0u]->contains(entt) && (pools[0u]->index(entt) < len)) { - swap_elements(--len, entt); - } - } - - void common_setup() { - // we cannot iterate backwards because we want to leave behind valid entities in case of owned types - for(auto first = pools[0u]->rbegin(), last = first + pools[0u]->size(); first != last; ++first) { - push_on_construct(*first); - } - } - -public: - using common_type = Type; - using size_type = typename Type::size_type; - - template<typename... OGType, typename... EType> - group_handler(std::tuple<OGType &...> ogpool, std::tuple<EType &...> epool) - : pools{std::apply([](auto &&...cpool) { return std::array<common_type *, (Owned + Get)>{&cpool...}; }, ogpool)}, - filter{std::apply([](auto &&...cpool) { return std::array<common_type *, Exclude>{&cpool...}; }, epool)} { - std::apply([this](auto &...cpool) { ((cpool.on_construct().template connect<&group_handler::push_on_construct>(*this), cpool.on_destroy().template connect<&group_handler::remove_if>(*this)), ...); }, ogpool); - std::apply([this](auto &...cpool) { ((cpool.on_construct().template connect<&group_handler::remove_if>(*this), cpool.on_destroy().template connect<&group_handler::push_on_destroy>(*this)), ...); }, epool); - common_setup(); - } - - [[nodiscard]] bool owned(const id_type hash) const noexcept override { - for(size_type pos{}; pos < Owned; ++pos) { - if(pools[pos]->type().hash() == hash) { - return true; - } - } - - return false; - } - - [[nodiscard]] size_type length() const noexcept { - return len; - } - - template<std::size_t Index> - [[nodiscard]] common_type *storage() const noexcept { - if constexpr(Index < (Owned + Get)) { - return pools[Index]; - } else { - return filter[Index - (Owned + Get)]; - } - } - -private: - std::array<common_type *, (Owned + Get)> pools; - std::array<common_type *, Exclude> filter; - std::size_t len{}; -}; - -template<typename Type, std::size_t Get, std::size_t Exclude> -class group_handler<Type, 0u, Get, Exclude> final: public group_descriptor { - using entity_type = typename Type::entity_type; - - void push_on_construct(const entity_type entt) { - if(!elem.contains(entt) - && std::apply([entt](auto *...cpool) { return (cpool->contains(entt) && ...); }, pools) - && std::apply([entt](auto *...cpool) { return (!cpool->contains(entt) && ...); }, filter)) { - elem.push(entt); - } - } - - void push_on_destroy(const entity_type entt) { - if(!elem.contains(entt) - && std::apply([entt](auto *...cpool) { return (cpool->contains(entt) && ...); }, pools) - && std::apply([entt](auto *...cpool) { return (0u + ... + cpool->contains(entt)) == 1u; }, filter)) { - elem.push(entt); - } - } - - void remove_if(const entity_type entt) { - elem.remove(entt); - } - - void common_setup() { - for(const auto entity: *pools[0u]) { - push_on_construct(entity); - } - } - -public: - using common_type = Type; - - template<typename Allocator, typename... GType, typename... EType> - group_handler(const Allocator &allocator, std::tuple<GType &...> gpool, std::tuple<EType &...> epool) - : pools{std::apply([](auto &&...cpool) { return std::array<common_type *, Get>{&cpool...}; }, gpool)}, - filter{std::apply([](auto &&...cpool) { return std::array<common_type *, Exclude>{&cpool...}; }, epool)}, - elem{allocator} { - std::apply([this](auto &...cpool) { ((cpool.on_construct().template connect<&group_handler::push_on_construct>(*this), cpool.on_destroy().template connect<&group_handler::remove_if>(*this)), ...); }, gpool); - std::apply([this](auto &...cpool) { ((cpool.on_construct().template connect<&group_handler::remove_if>(*this), cpool.on_destroy().template connect<&group_handler::push_on_destroy>(*this)), ...); }, epool); - common_setup(); - } - - [[nodiscard]] common_type &handle() noexcept { - return elem; - } - - [[nodiscard]] const common_type &handle() const noexcept { - return elem; - } - - template<std::size_t Index> - [[nodiscard]] common_type *storage() const noexcept { - if constexpr(Index < Get) { - return pools[Index]; - } else { - return filter[Index - Get]; - } - } - -private: - std::array<common_type *, Get> pools; - std::array<common_type *, Exclude> filter; - common_type elem; -}; - -} // namespace internal -/*! @endcond */ - -/** - * @brief Group. - * - * Primary template isn't defined on purpose. All the specializations give a - * compile-time error, but for a few reasonable cases. - */ -template<typename, typename, typename> -class basic_group; - -/** - * @brief Non-owning group. - * - * A non-owning group returns all entities and only the entities that are at - * least in the given storage. Moreover, it's guaranteed that the entity list is - * tightly packed in memory for fast iterations. - * - * @b Important - * - * Iterators aren't invalidated if: - * - * * New elements are added to the storage. - * * The entity currently pointed is modified (for example, elements are added - * or removed from it). - * * The entity currently pointed is destroyed. - * - * In all other cases, modifying the pools iterated by the group in any way - * invalidates all the iterators. - * - * @tparam Get Types of storage _observed_ by the group. - * @tparam Exclude Types of storage used to filter the group. - */ -template<typename... Get, typename... Exclude> -class basic_group<owned_t<>, get_t<Get...>, exclude_t<Exclude...>> { - using base_type = std::common_type_t<typename Get::base_type..., typename Exclude::base_type...>; - using underlying_type = typename base_type::entity_type; - - template<typename Type> - static constexpr std::size_t index_of = type_list_index_v<std::remove_const_t<Type>, type_list<typename Get::element_type..., typename Exclude::element_type...>>; - - template<std::size_t... Index> - [[nodiscard]] auto pools_for(std::index_sequence<Index...>) const noexcept { - using return_type = std::tuple<Get *...>; - return descriptor ? return_type{static_cast<Get *>(descriptor->template storage<Index>())...} : return_type{}; - } - -public: - /*! @brief Underlying entity identifier. */ - using entity_type = underlying_type; - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - /*! @brief Common type among all storage types. */ - using common_type = base_type; - /*! @brief Random access iterator type. */ - using iterator = typename common_type::iterator; - /*! @brief Reverse iterator type. */ - using reverse_iterator = typename common_type::reverse_iterator; - /*! @brief Iterable group type. */ - using iterable = iterable_adaptor<internal::extended_group_iterator<iterator, owned_t<>, get_t<Get...>>>; - /*! @brief Group handler type. */ - using handler = internal::group_handler<common_type, 0u, sizeof...(Get), sizeof...(Exclude)>; - - /** - * @brief Group opaque identifier. - * @return Group opaque identifier. - */ - static id_type group_id() noexcept { - return type_hash<basic_group<owned_t<>, get_t<std::remove_const_t<Get>...>, exclude_t<std::remove_const_t<Exclude>...>>>::value(); - } - - /*! @brief Default constructor to use to create empty, invalid groups. */ - basic_group() noexcept - : descriptor{} {} - - /** - * @brief Constructs a group from a set of storage classes. - * @param ref A reference to a group handler. - */ - basic_group(handler &ref) noexcept - : descriptor{&ref} {} - - /** - * @brief Returns the leading storage of a group. - * @return The leading storage of the group. - */ - [[nodiscard]] const common_type &handle() const noexcept { - return descriptor->handle(); - } - - /** - * @brief Returns the storage for a given element type, if any. - * @tparam Type Type of element of which to return the storage. - * @return The storage for the given element type. - */ - template<typename Type> - [[nodiscard]] auto *storage() const noexcept { - return storage<index_of<Type>>(); - } - - /** - * @brief Returns the storage for a given index, if any. - * @tparam Index Index of the storage to return. - * @return The storage for the given index. - */ - template<std::size_t Index> - [[nodiscard]] auto *storage() const noexcept { - using type = type_list_element_t<Index, type_list<Get..., Exclude...>>; - return *this ? static_cast<type *>(descriptor->template storage<Index>()) : nullptr; - } - - /** - * @brief Returns the number of entities that are part of the group. - * @return Number of entities that are part of the group. - */ - [[nodiscard]] size_type size() const noexcept { - return *this ? handle().size() : size_type{}; - } - - /** - * @brief Returns the number of elements that a group has currently - * allocated space for. - * @return Capacity of the group. - */ - [[nodiscard]] size_type capacity() const noexcept { - return *this ? handle().capacity() : size_type{}; - } - - /*! @brief Requests the removal of unused capacity. */ - void shrink_to_fit() { - if(*this) { - descriptor->handle().shrink_to_fit(); - } - } - - /** - * @brief Checks whether a group is empty. - * @return True if the group is empty, false otherwise. - */ - [[nodiscard]] bool empty() const noexcept { - return !*this || handle().empty(); - } - - /** - * @brief Returns an iterator to the first entity of the group. - * - * If the group is empty, the returned iterator will be equal to `end()`. - * - * @return An iterator to the first entity of the group. - */ - [[nodiscard]] iterator begin() const noexcept { - return *this ? handle().begin() : iterator{}; - } - - /** - * @brief Returns an iterator that is past the last entity of the group. - * @return An iterator to the entity following the last entity of the - * group. - */ - [[nodiscard]] iterator end() const noexcept { - return *this ? handle().end() : iterator{}; - } - - /** - * @brief Returns an iterator to the first entity of the reversed group. - * - * If the group is empty, the returned iterator will be equal to `rend()`. - * - * @return An iterator to the first entity of the reversed group. - */ - [[nodiscard]] reverse_iterator rbegin() const noexcept { - return *this ? handle().rbegin() : reverse_iterator{}; - } - - /** - * @brief Returns an iterator that is past the last entity of the reversed - * group. - * @return An iterator to the entity following the last entity of the - * reversed group. - */ - [[nodiscard]] reverse_iterator rend() const noexcept { - return *this ? handle().rend() : reverse_iterator{}; - } - - /** - * @brief Returns the first entity of the group, if any. - * @return The first entity of the group if one exists, the null entity - * otherwise. - */ - [[nodiscard]] entity_type front() const noexcept { - const auto it = begin(); - return it != end() ? *it : null; - } - - /** - * @brief Returns the last entity of the group, if any. - * @return The last entity of the group if one exists, the null entity - * otherwise. - */ - [[nodiscard]] entity_type back() const noexcept { - const auto it = rbegin(); - return it != rend() ? *it : null; - } - - /** - * @brief Finds an entity. - * @param entt A valid identifier. - * @return An iterator to the given entity if it's found, past the end - * iterator otherwise. - */ - [[nodiscard]] iterator find(const entity_type entt) const noexcept { - return *this ? handle().find(entt) : iterator{}; - } - - /** - * @brief Returns the identifier that occupies the given position. - * @param pos Position of the element to return. - * @return The identifier that occupies the given position. - */ - [[nodiscard]] entity_type operator[](const size_type pos) const { - return begin()[pos]; - } - - /** - * @brief Checks if a group is properly initialized. - * @return True if the group is properly initialized, false otherwise. - */ - [[nodiscard]] explicit operator bool() const noexcept { - return descriptor != nullptr; - } - - /** - * @brief Checks if a group contains an entity. - * @param entt A valid identifier. - * @return True if the group contains the given entity, false otherwise. - */ - [[nodiscard]] bool contains(const entity_type entt) const noexcept { - return *this && handle().contains(entt); - } - - /** - * @brief Returns the elements assigned to the given entity. - * @tparam Type Type of the element to get. - * @tparam Other Other types of elements to get. - * @param entt A valid identifier. - * @return The elements assigned to the entity. - */ - template<typename Type, typename... Other> - [[nodiscard]] decltype(auto) get(const entity_type entt) const { - return get<index_of<Type>, index_of<Other>...>(entt); - } - - /** - * @brief Returns the elements assigned to the given entity. - * @tparam Index Indexes of the elements to get. - * @param entt A valid identifier. - * @return The elements assigned to the entity. - */ - template<std::size_t... Index> - [[nodiscard]] decltype(auto) get(const entity_type entt) const { - const auto cpools = pools_for(std::index_sequence_for<Get...>{}); - - if constexpr(sizeof...(Index) == 0) { - return std::apply([entt](auto *...curr) { return std::tuple_cat(curr->get_as_tuple(entt)...); }, cpools); - } else if constexpr(sizeof...(Index) == 1) { - return (std::get<Index>(cpools)->get(entt), ...); - } else { - return std::tuple_cat(std::get<Index>(cpools)->get_as_tuple(entt)...); - } - } - - /** - * @brief Iterates entities and elements and applies the given function - * object to them. - * - * The function object is invoked for each entity. It is provided with the - * entity itself and a set of references to non-empty elements. The - * _constness_ of the elements is as requested.<br/> - * The signature of the function must be equivalent to one of the following - * forms: - * - * @code{.cpp} - * void(const entity_type, Type &...); - * void(Type &...); - * @endcode - * - * @note - * Empty types aren't explicitly instantiated and therefore they are never - * returned during iterations. - * - * @tparam Func Type of the function object to invoke. - * @param func A valid function object. - */ - template<typename Func> - void each(Func func) const { - for(const auto entt: *this) { - if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_group>().get({})))>) { - std::apply(func, std::tuple_cat(std::make_tuple(entt), get(entt))); - } else { - std::apply(func, get(entt)); - } - } - } - - /** - * @brief Returns an iterable object to use to _visit_ a group. - * - * The iterable object returns tuples that contain the current entity and a - * set of references to its non-empty elements. The _constness_ of the - * elements is as requested. - * - * @note - * Empty types aren't explicitly instantiated and therefore they are never - * returned during iterations. - * - * @return An iterable object to use to _visit_ the group. - */ - [[nodiscard]] iterable each() const noexcept { - const auto cpools = pools_for(std::index_sequence_for<Get...>{}); - return iterable{{begin(), cpools}, {end(), cpools}}; - } - - /** - * @brief Sort a group according to the given comparison function. - * - * The comparison function object must return `true` if the first element - * is _less_ than the second one, `false` otherwise. The signature of the - * comparison function should be equivalent to one of the following: - * - * @code{.cpp} - * bool(std::tuple<Type &...>, std::tuple<Type &...>); - * bool(const Type &..., const Type &...); - * bool(const Entity, const Entity); - * @endcode - * - * Where `Type` are such that they are iterated by the group.<br/> - * Moreover, the comparison function object shall induce a - * _strict weak ordering_ on the values. - * - * The sort function object must offer a member function template - * `operator()` that accepts three arguments: - * - * * An iterator to the first element of the range to sort. - * * An iterator past the last element of the range to sort. - * * A comparison function to use to compare the elements. - * - * @tparam Type Optional type of element to compare. - * @tparam Other Other optional types of elements to compare. - * @tparam Compare Type of comparison function object. - * @tparam Sort Type of sort function object. - * @tparam Args Types of arguments to forward to the sort function object. - * @param compare A valid comparison function object. - * @param algo A valid sort function object. - * @param args Arguments to forward to the sort function object, if any. - */ - template<typename Type, typename... Other, typename Compare, typename Sort = std_sort, typename... Args> - void sort(Compare compare, Sort algo = Sort{}, Args &&...args) { - sort<index_of<Type>, index_of<Other>...>(std::move(compare), std::move(algo), std::forward<Args>(args)...); - } - - /** - * @brief Sort a group according to the given comparison function. - * - * @sa sort - * - * @tparam Index Optional indexes of elements to compare. - * @tparam Compare Type of comparison function object. - * @tparam Sort Type of sort function object. - * @tparam Args Types of arguments to forward to the sort function object. - * @param compare A valid comparison function object. - * @param algo A valid sort function object. - * @param args Arguments to forward to the sort function object, if any. - */ - template<std::size_t... Index, typename Compare, typename Sort = std_sort, typename... Args> - void sort(Compare compare, Sort algo = Sort{}, Args &&...args) { - if(*this) { - if constexpr(sizeof...(Index) == 0) { - static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function"); - descriptor->handle().sort(std::move(compare), std::move(algo), std::forward<Args>(args)...); - } else { - auto comp = [&compare, cpools = pools_for(std::index_sequence_for<Get...>{})](const entity_type lhs, const entity_type rhs) { - if constexpr(sizeof...(Index) == 1) { - return compare((std::get<Index>(cpools)->get(lhs), ...), (std::get<Index>(cpools)->get(rhs), ...)); - } else { - return compare(std::forward_as_tuple(std::get<Index>(cpools)->get(lhs)...), std::forward_as_tuple(std::get<Index>(cpools)->get(rhs)...)); - } - }; - - descriptor->handle().sort(std::move(comp), std::move(algo), std::forward<Args>(args)...); - } - } - } - - /** - * @brief Sort entities according to their order in a range. - * - * The shared pool of entities and thus its order is affected by the changes - * to each and every pool that it tracks. - * - * @tparam It Type of input iterator. - * @param first An iterator to the first element of the range of entities. - * @param last An iterator past the last element of the range of entities. - */ - template<typename It> - void sort_as(It first, It last) const { - if(*this) { - descriptor->handle().sort_as(first, last); - } - } - -private: - handler *descriptor; -}; - -/** - * @brief Owning group. - * - * Owning groups returns all entities and only the entities that are at - * least in the given storage. Moreover: - * - * * It's guaranteed that the entity list is tightly packed in memory for fast - * iterations. - * * It's guaranteed that all elements in the owned storage are tightly packed - * in memory for even faster iterations and to allow direct access. - * * They stay true to the order of the owned storage and all instances have the - * same order in memory. - * - * The more types of storage are owned, the faster it is to iterate a group. - * - * @b Important - * - * Iterators aren't invalidated if: - * - * * New elements are added to the storage. - * * The entity currently pointed is modified (for example, elements are added - * or removed from it). - * * The entity currently pointed is destroyed. - * - * In all other cases, modifying the pools iterated by the group in any way - * invalidates all the iterators. - * - * @tparam Owned Types of storage _owned_ by the group. - * @tparam Get Types of storage _observed_ by the group. - * @tparam Exclude Types of storage used to filter the group. - */ -template<typename... Owned, typename... Get, typename... Exclude> -class basic_group<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>> { - static_assert(((Owned::storage_policy != deletion_policy::in_place) && ...), "Groups do not support in-place delete"); - - using base_type = std::common_type_t<typename Owned::base_type..., typename Get::base_type..., typename Exclude::base_type...>; - using underlying_type = typename base_type::entity_type; - - template<typename Type> - static constexpr std::size_t index_of = type_list_index_v<std::remove_const_t<Type>, type_list<typename Owned::element_type..., typename Get::element_type..., typename Exclude::element_type...>>; - - template<std::size_t... Index, std::size_t... Other> - [[nodiscard]] auto pools_for(std::index_sequence<Index...>, std::index_sequence<Other...>) const noexcept { - using return_type = std::tuple<Owned *..., Get *...>; - return descriptor ? return_type{static_cast<Owned *>(descriptor->template storage<Index>())..., static_cast<Get *>(descriptor->template storage<sizeof...(Owned) + Other>())...} : return_type{}; - } - -public: - /*! @brief Underlying entity identifier. */ - using entity_type = underlying_type; - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - /*! @brief Common type among all storage types. */ - using common_type = base_type; - /*! @brief Random access iterator type. */ - using iterator = typename common_type::iterator; - /*! @brief Reverse iterator type. */ - using reverse_iterator = typename common_type::reverse_iterator; - /*! @brief Iterable group type. */ - using iterable = iterable_adaptor<internal::extended_group_iterator<iterator, owned_t<Owned...>, get_t<Get...>>>; - /*! @brief Group handler type. */ - using handler = internal::group_handler<common_type, sizeof...(Owned), sizeof...(Get), sizeof...(Exclude)>; - - /** - * @brief Group opaque identifier. - * @return Group opaque identifier. - */ - static id_type group_id() noexcept { - return type_hash<basic_group<owned_t<std::remove_const_t<Owned>...>, get_t<std::remove_const_t<Get>...>, exclude_t<std::remove_const_t<Exclude>...>>>::value(); - } - - /*! @brief Default constructor to use to create empty, invalid groups. */ - basic_group() noexcept - : descriptor{} {} - - /** - * @brief Constructs a group from a set of storage classes. - * @param ref A reference to a group handler. - */ - basic_group(handler &ref) noexcept - : descriptor{&ref} {} - - /** - * @brief Returns the leading storage of a group. - * @return The leading storage of the group. - */ - [[nodiscard]] const common_type &handle() const noexcept { - return *storage<0>(); - } - - /** - * @brief Returns the storage for a given element type, if any. - * @tparam Type Type of element of which to return the storage. - * @return The storage for the given element type. - */ - template<typename Type> - [[nodiscard]] auto *storage() const noexcept { - return storage<index_of<Type>>(); - } - - /** - * @brief Returns the storage for a given index, if any. - * @tparam Index Index of the storage to return. - * @return The storage for the given index. - */ - template<std::size_t Index> - [[nodiscard]] auto *storage() const noexcept { - using type = type_list_element_t<Index, type_list<Owned..., Get..., Exclude...>>; - return *this ? static_cast<type *>(descriptor->template storage<Index>()) : nullptr; - } - - /** - * @brief Returns the number of entities that that are part of the group. - * @return Number of entities that that are part of the group. - */ - [[nodiscard]] size_type size() const noexcept { - return *this ? descriptor->length() : size_type{}; - } - - /** - * @brief Checks whether a group is empty. - * @return True if the group is empty, false otherwise. - */ - [[nodiscard]] bool empty() const noexcept { - return !*this || !descriptor->length(); - } - - /** - * @brief Returns an iterator to the first entity of the group. - * - * If the group is empty, the returned iterator will be equal to `end()`. - * - * @return An iterator to the first entity of the group. - */ - [[nodiscard]] iterator begin() const noexcept { - return *this ? (handle().end() - descriptor->length()) : iterator{}; - } - - /** - * @brief Returns an iterator that is past the last entity of the group. - * @return An iterator to the entity following the last entity of the - * group. - */ - [[nodiscard]] iterator end() const noexcept { - return *this ? handle().end() : iterator{}; - } - - /** - * @brief Returns an iterator to the first entity of the reversed group. - * - * If the group is empty, the returned iterator will be equal to `rend()`. - * - * @return An iterator to the first entity of the reversed group. - */ - [[nodiscard]] reverse_iterator rbegin() const noexcept { - return *this ? handle().rbegin() : reverse_iterator{}; - } - - /** - * @brief Returns an iterator that is past the last entity of the reversed - * group. - * @return An iterator to the entity following the last entity of the - * reversed group. - */ - [[nodiscard]] reverse_iterator rend() const noexcept { - return *this ? (handle().rbegin() + descriptor->length()) : reverse_iterator{}; - } - - /** - * @brief Returns the first entity of the group, if any. - * @return The first entity of the group if one exists, the null entity - * otherwise. - */ - [[nodiscard]] entity_type front() const noexcept { - const auto it = begin(); - return it != end() ? *it : null; - } - - /** - * @brief Returns the last entity of the group, if any. - * @return The last entity of the group if one exists, the null entity - * otherwise. - */ - [[nodiscard]] entity_type back() const noexcept { - const auto it = rbegin(); - return it != rend() ? *it : null; - } - - /** - * @brief Finds an entity. - * @param entt A valid identifier. - * @return An iterator to the given entity if it's found, past the end - * iterator otherwise. - */ - [[nodiscard]] iterator find(const entity_type entt) const noexcept { - const auto it = *this ? handle().find(entt) : iterator{}; - return it >= begin() ? it : iterator{}; - } - - /** - * @brief Returns the identifier that occupies the given position. - * @param pos Position of the element to return. - * @return The identifier that occupies the given position. - */ - [[nodiscard]] entity_type operator[](const size_type pos) const { - return begin()[pos]; - } - - /** - * @brief Checks if a group is properly initialized. - * @return True if the group is properly initialized, false otherwise. - */ - [[nodiscard]] explicit operator bool() const noexcept { - return descriptor != nullptr; - } - - /** - * @brief Checks if a group contains an entity. - * @param entt A valid identifier. - * @return True if the group contains the given entity, false otherwise. - */ - [[nodiscard]] bool contains(const entity_type entt) const noexcept { - return *this && handle().contains(entt) && (handle().index(entt) < (descriptor->length())); - } - - /** - * @brief Returns the elements assigned to the given entity. - * @tparam Type Type of the element to get. - * @tparam Other Other types of elements to get. - * @param entt A valid identifier. - * @return The elements assigned to the entity. - */ - template<typename Type, typename... Other> - [[nodiscard]] decltype(auto) get(const entity_type entt) const { - return get<index_of<Type>, index_of<Other>...>(entt); - } - - /** - * @brief Returns the elements assigned to the given entity. - * @tparam Index Indexes of the elements to get. - * @param entt A valid identifier. - * @return The elements assigned to the entity. - */ - template<std::size_t... Index> - [[nodiscard]] decltype(auto) get(const entity_type entt) const { - const auto cpools = pools_for(std::index_sequence_for<Owned...>{}, std::index_sequence_for<Get...>{}); - - if constexpr(sizeof...(Index) == 0) { - return std::apply([entt](auto *...curr) { return std::tuple_cat(curr->get_as_tuple(entt)...); }, cpools); - } else if constexpr(sizeof...(Index) == 1) { - return (std::get<Index>(cpools)->get(entt), ...); - } else { - return std::tuple_cat(std::get<Index>(cpools)->get_as_tuple(entt)...); - } - } - - /** - * @brief Iterates entities and elements and applies the given function - * object to them. - * - * The function object is invoked for each entity. It is provided with the - * entity itself and a set of references to non-empty elements. The - * _constness_ of the elements is as requested.<br/> - * The signature of the function must be equivalent to one of the following - * forms: - * - * @code{.cpp} - * void(const entity_type, Type &...); - * void(Type &...); - * @endcode - * - * @note - * Empty types aren't explicitly instantiated and therefore they are never - * returned during iterations. - * - * @tparam Func Type of the function object to invoke. - * @param func A valid function object. - */ - template<typename Func> - void each(Func func) const { - for(auto args: each()) { - if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_group>().get({})))>) { - std::apply(func, args); - } else { - std::apply([&func](auto, auto &&...less) { func(std::forward<decltype(less)>(less)...); }, args); - } - } - } - - /** - * @brief Returns an iterable object to use to _visit_ a group. - * - * The iterable object returns tuples that contain the current entity and a - * set of references to its non-empty elements. The _constness_ of the - * elements is as requested. - * - * @note - * Empty types aren't explicitly instantiated and therefore they are never - * returned during iterations. - * - * @return An iterable object to use to _visit_ the group. - */ - [[nodiscard]] iterable each() const noexcept { - const auto cpools = pools_for(std::index_sequence_for<Owned...>{}, std::index_sequence_for<Get...>{}); - return iterable{{begin(), cpools}, {end(), cpools}}; - } - - /** - * @brief Sort a group according to the given comparison function. - * - * The comparison function object must return `true` if the first element - * is _less_ than the second one, `false` otherwise. The signature of the - * comparison function should be equivalent to one of the following: - * - * @code{.cpp} - * bool(std::tuple<Type &...>, std::tuple<Type &...>); - * bool(const Type &, const Type &); - * bool(const Entity, const Entity); - * @endcode - * - * Where `Type` are either owned types or not but still such that they are - * iterated by the group.<br/> - * Moreover, the comparison function object shall induce a - * _strict weak ordering_ on the values. - * - * The sort function object must offer a member function template - * `operator()` that accepts three arguments: - * - * * An iterator to the first element of the range to sort. - * * An iterator past the last element of the range to sort. - * * A comparison function to use to compare the elements. - * - * @tparam Type Optional type of element to compare. - * @tparam Other Other optional types of elements to compare. - * @tparam Compare Type of comparison function object. - * @tparam Sort Type of sort function object. - * @tparam Args Types of arguments to forward to the sort function object. - * @param compare A valid comparison function object. - * @param algo A valid sort function object. - * @param args Arguments to forward to the sort function object, if any. - */ - template<typename Type, typename... Other, typename Compare, typename Sort = std_sort, typename... Args> - void sort(Compare compare, Sort algo = Sort{}, Args &&...args) const { - sort<index_of<Type>, index_of<Other>...>(std::move(compare), std::move(algo), std::forward<Args>(args)...); - } - - /** - * @brief Sort a group according to the given comparison function. - * - * @sa sort - * - * @tparam Index Optional indexes of elements to compare. - * @tparam Compare Type of comparison function object. - * @tparam Sort Type of sort function object. - * @tparam Args Types of arguments to forward to the sort function object. - * @param compare A valid comparison function object. - * @param algo A valid sort function object. - * @param args Arguments to forward to the sort function object, if any. - */ - template<std::size_t... Index, typename Compare, typename Sort = std_sort, typename... Args> - void sort(Compare compare, Sort algo = Sort{}, Args &&...args) const { - const auto cpools = pools_for(std::index_sequence_for<Owned...>{}, std::index_sequence_for<Get...>{}); - - if constexpr(sizeof...(Index) == 0) { - static_assert(std::is_invocable_v<Compare, const entity_type, const entity_type>, "Invalid comparison function"); - storage<0>()->sort_n(descriptor->length(), std::move(compare), std::move(algo), std::forward<Args>(args)...); - } else { - auto comp = [&compare, &cpools](const entity_type lhs, const entity_type rhs) { - if constexpr(sizeof...(Index) == 1) { - return compare((std::get<Index>(cpools)->get(lhs), ...), (std::get<Index>(cpools)->get(rhs), ...)); - } else { - return compare(std::forward_as_tuple(std::get<Index>(cpools)->get(lhs)...), std::forward_as_tuple(std::get<Index>(cpools)->get(rhs)...)); - } - }; - - storage<0>()->sort_n(descriptor->length(), std::move(comp), std::move(algo), std::forward<Args>(args)...); - } - - auto cb = [this](auto *head, auto *...other) { - for(auto next = descriptor->length(); next; --next) { - const auto pos = next - 1; - [[maybe_unused]] const auto entt = head->data()[pos]; - (other->swap_elements(other->data()[pos], entt), ...); - } - }; - - std::apply(cb, cpools); - } - -private: - handler *descriptor; -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/entity/handle.hpp b/deps/entt/include/entt/entity/handle.hpp deleted file mode 100644 index 15e82fd..0000000 --- a/deps/entt/include/entt/entity/handle.hpp +++ /dev/null @@ -1,431 +0,0 @@ -#ifndef ENTT_ENTITY_HANDLE_HPP -#define ENTT_ENTITY_HANDLE_HPP - -#include <iterator> -#include <tuple> -#include <type_traits> -#include <utility> -#include "../config/config.h" -#include "../core/iterator.hpp" -#include "../core/type_traits.hpp" -#include "entity.hpp" -#include "fwd.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename It> -class handle_storage_iterator final { - template<typename Other> - friend class handle_storage_iterator; - - using underlying_type = std::remove_reference_t<typename It::value_type::second_type>; - using entity_type = typename underlying_type::entity_type; - -public: - using value_type = typename std::iterator_traits<It>::value_type; - using pointer = input_iterator_pointer<value_type>; - using reference = value_type; - using difference_type = std::ptrdiff_t; - using iterator_category = std::input_iterator_tag; - using iterator_concept = std::forward_iterator_tag; - - constexpr handle_storage_iterator() noexcept - : entt{null}, - it{}, - last{} {} - - constexpr handle_storage_iterator(entity_type value, It from, It to) noexcept - : entt{value}, - it{from}, - last{to} { - while(it != last && !it->second.contains(entt)) { - ++it; - } - } - - constexpr handle_storage_iterator &operator++() noexcept { - while(++it != last && !it->second.contains(entt)) {} - return *this; - } - - constexpr handle_storage_iterator operator++(int) noexcept { - handle_storage_iterator orig = *this; - return ++(*this), orig; - } - - [[nodiscard]] constexpr reference operator*() const noexcept { - return *it; - } - - [[nodiscard]] constexpr pointer operator->() const noexcept { - return operator*(); - } - - template<typename ILhs, typename IRhs> - friend constexpr bool operator==(const handle_storage_iterator<ILhs> &, const handle_storage_iterator<IRhs> &) noexcept; - -private: - entity_type entt; - It it; - It last; -}; - -template<typename ILhs, typename IRhs> -[[nodiscard]] constexpr bool operator==(const handle_storage_iterator<ILhs> &lhs, const handle_storage_iterator<IRhs> &rhs) noexcept { - return lhs.it == rhs.it; -} - -template<typename ILhs, typename IRhs> -[[nodiscard]] constexpr bool operator!=(const handle_storage_iterator<ILhs> &lhs, const handle_storage_iterator<IRhs> &rhs) noexcept { - return !(lhs == rhs); -} - -} // namespace internal -/*! @endcond */ - -/** - * @brief Non-owning handle to an entity. - * - * Tiny wrapper around a registry and an entity. - * - * @tparam Registry Basic registry type. - * @tparam Scope Types to which to restrict the scope of a handle. - */ -template<typename Registry, typename... Scope> -class basic_handle { - using traits_type = entt_traits<typename Registry::entity_type>; - - [[nodiscard]] auto &owner_or_assert() const noexcept { - ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry"); - return static_cast<Registry &>(*owner); - } - -public: - /*! @brief Type of registry accepted by the handle. */ - using registry_type = Registry; - /*! @brief Underlying entity identifier. */ - using entity_type = typename traits_type::value_type; - /*! @brief Underlying version type. */ - using version_type = typename traits_type::version_type; - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - /*! @brief Iterable handle type. */ - using iterable = iterable_adaptor<internal::handle_storage_iterator<typename decltype(std::declval<registry_type>().storage())::iterator>>; - - /*! @brief Constructs an invalid handle. */ - basic_handle() noexcept - : owner{}, - entt{null} {} - - /** - * @brief Constructs a handle from a given registry and entity. - * @param ref An instance of the registry class. - * @param value A valid identifier. - */ - basic_handle(registry_type &ref, entity_type value) noexcept - : owner{&ref}, - entt{value} {} - - /** - * @brief Returns an iterable object to use to _visit_ a handle. - * - * The iterable object returns a pair that contains the name and a reference - * to the current storage.<br/> - * Returned storage are those that contain the entity associated with the - * handle. - * - * @return An iterable object to use to _visit_ the handle. - */ - [[nodiscard]] iterable storage() const noexcept { - auto underlying = owner_or_assert().storage(); - return iterable{{entt, underlying.begin(), underlying.end()}, {entt, underlying.end(), underlying.end()}}; - } - - /*! @copydoc valid */ - [[nodiscard]] explicit operator bool() const noexcept { - return owner && owner->valid(entt); - } - - /** - * @brief Checks if a handle refers to non-null registry pointer and entity. - * @return True if the handle refers to non-null registry and entity, false - * otherwise. - */ - [[nodiscard]] bool valid() const { - return static_cast<bool>(*this); - } - - /** - * @brief Returns a pointer to the underlying registry, if any. - * @return A pointer to the underlying registry, if any. - */ - [[nodiscard]] registry_type *registry() const noexcept { - return owner; - } - - /** - * @brief Returns the entity associated with a handle. - * @return The entity associated with the handle. - */ - [[nodiscard]] entity_type entity() const noexcept { - return entt; - } - - /*! @copydoc entity */ - [[nodiscard]] operator entity_type() const noexcept { - return entity(); - } - - /*! @brief Destroys the entity associated with a handle. */ - void destroy() { - owner_or_assert().destroy(std::exchange(entt, null)); - } - - /** - * @brief Destroys the entity associated with a handle. - * @param version A desired version upon destruction. - */ - void destroy(const version_type version) { - owner_or_assert().destroy(std::exchange(entt, null), version); - } - - /** - * @brief Assigns the given element to a handle. - * @tparam Type Type of element to create. - * @tparam Args Types of arguments to use to construct the element. - * @param args Parameters to use to initialize the element. - * @return A reference to the newly created element. - */ - template<typename Type, typename... Args> - // NOLINTNEXTLINE(modernize-use-nodiscard) - decltype(auto) emplace(Args &&...args) const { - static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v<Type, Scope>), "Invalid type"); - return owner_or_assert().template emplace<Type>(entt, std::forward<Args>(args)...); - } - - /** - * @brief Assigns or replaces the given element for a handle. - * @tparam Type Type of element to assign or replace. - * @tparam Args Types of arguments to use to construct the element. - * @param args Parameters to use to initialize the element. - * @return A reference to the newly created element. - */ - template<typename Type, typename... Args> - decltype(auto) emplace_or_replace(Args &&...args) const { - static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v<Type, Scope>), "Invalid type"); - return owner_or_assert().template emplace_or_replace<Type>(entt, std::forward<Args>(args)...); - } - - /** - * @brief Patches the given element for a handle. - * @tparam Type Type of element to patch. - * @tparam Func Types of the function objects to invoke. - * @param func Valid function objects. - * @return A reference to the patched element. - */ - template<typename Type, typename... Func> - decltype(auto) patch(Func &&...func) const { - static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v<Type, Scope>), "Invalid type"); - return owner_or_assert().template patch<Type>(entt, std::forward<Func>(func)...); - } - - /** - * @brief Replaces the given element for a handle. - * @tparam Type Type of element to replace. - * @tparam Args Types of arguments to use to construct the element. - * @param args Parameters to use to initialize the element. - * @return A reference to the element being replaced. - */ - template<typename Type, typename... Args> - decltype(auto) replace(Args &&...args) const { - static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v<Type, Scope>), "Invalid type"); - return owner_or_assert().template replace<Type>(entt, std::forward<Args>(args)...); - } - - /** - * @brief Removes the given elements from a handle. - * @tparam Type Types of elements to remove. - * @return The number of elements actually removed. - */ - template<typename... Type> - // NOLINTNEXTLINE(modernize-use-nodiscard) - size_type remove() const { - static_assert(sizeof...(Scope) == 0 || (type_list_contains_v<type_list<Scope...>, Type> && ...), "Invalid type"); - return owner_or_assert().template remove<Type...>(entt); - } - - /** - * @brief Erases the given elements from a handle. - * @tparam Type Types of elements to erase. - */ - template<typename... Type> - void erase() const { - static_assert(sizeof...(Scope) == 0 || (type_list_contains_v<type_list<Scope...>, Type> && ...), "Invalid type"); - owner_or_assert().template erase<Type...>(entt); - } - - /** - * @brief Checks if a handle has all the given elements. - * @tparam Type Elements for which to perform the check. - * @return True if the handle has all the elements, false otherwise. - */ - template<typename... Type> - [[nodiscard]] decltype(auto) all_of() const { - return owner_or_assert().template all_of<Type...>(entt); - } - - /** - * @brief Checks if a handle has at least one of the given elements. - * @tparam Type Elements for which to perform the check. - * @return True if the handle has at least one of the given elements, - * false otherwise. - */ - template<typename... Type> - [[nodiscard]] decltype(auto) any_of() const { - return owner_or_assert().template any_of<Type...>(entt); - } - - /** - * @brief Returns references to the given elements for a handle. - * @tparam Type Types of elements to get. - * @return References to the elements owned by the handle. - */ - template<typename... Type> - [[nodiscard]] decltype(auto) get() const { - static_assert(sizeof...(Scope) == 0 || (type_list_contains_v<type_list<Scope...>, Type> && ...), "Invalid type"); - return owner_or_assert().template get<Type...>(entt); - } - - /** - * @brief Returns a reference to the given element for a handle. - * @tparam Type Type of element to get. - * @tparam Args Types of arguments to use to construct the element. - * @param args Parameters to use to initialize the element. - * @return Reference to the element owned by the handle. - */ - template<typename Type, typename... Args> - [[nodiscard]] decltype(auto) get_or_emplace(Args &&...args) const { - static_assert(((sizeof...(Scope) == 0) || ... || std::is_same_v<Type, Scope>), "Invalid type"); - return owner_or_assert().template get_or_emplace<Type>(entt, std::forward<Args>(args)...); - } - - /** - * @brief Returns pointers to the given elements for a handle. - * @tparam Type Types of elements to get. - * @return Pointers to the elements owned by the handle. - */ - template<typename... Type> - [[nodiscard]] auto try_get() const { - static_assert(sizeof...(Scope) == 0 || (type_list_contains_v<type_list<Scope...>, Type> && ...), "Invalid type"); - return owner_or_assert().template try_get<Type...>(entt); - } - - /** - * @brief Checks if a handle has elements assigned. - * @return True if the handle has no elements assigned, false otherwise. - */ - [[nodiscard]] bool orphan() const { - return owner_or_assert().orphan(entt); - } - - /** - * @brief Returns a const handle from a non-const one. - * @tparam Other A valid entity type. - * @tparam Args Scope of the handle to construct. - * @return A const handle referring to the same registry and the same - * entity. - */ - template<typename Other, typename... Args> - operator basic_handle<Other, Args...>() const noexcept { - static_assert(std::is_same_v<Other, Registry> || std::is_same_v<std::remove_const_t<Other>, Registry>, "Invalid conversion between different handles"); - static_assert((sizeof...(Scope) == 0 || ((sizeof...(Args) != 0 && sizeof...(Args) <= sizeof...(Scope)) && ... && (type_list_contains_v<type_list<Scope...>, Args>))), "Invalid conversion between different handles"); - return owner ? basic_handle<Other, Args...>{*owner, entt} : basic_handle<Other, Args...>{}; - } - -private: - registry_type *owner; - entity_type entt; -}; - -/** - * @brief Compares two handles. - * @tparam Args Scope of the first handle. - * @tparam Other Scope of the second handle. - * @param lhs A valid handle. - * @param rhs A valid handle. - * @return True if both handles refer to the same registry and the same - * entity, false otherwise. - */ -template<typename... Args, typename... Other> -[[nodiscard]] bool operator==(const basic_handle<Args...> &lhs, const basic_handle<Other...> &rhs) noexcept { - return lhs.registry() == rhs.registry() && lhs.entity() == rhs.entity(); -} - -/** - * @brief Compares two handles. - * @tparam Args Scope of the first handle. - * @tparam Other Scope of the second handle. - * @param lhs A valid handle. - * @param rhs A valid handle. - * @return False if both handles refer to the same registry and the same - * entity, true otherwise. - */ -template<typename... Args, typename... Other> -[[nodiscard]] bool operator!=(const basic_handle<Args...> &lhs, const basic_handle<Other...> &rhs) noexcept { - return !(lhs == rhs); -} - -/** - * @brief Compares a handle with the null object. - * @tparam Args Scope of the handle. - * @param lhs A valid handle. - * @param rhs A null object yet to be converted. - * @return False if the two elements differ, true otherwise. - */ -template<typename... Args> -[[nodiscard]] constexpr bool operator==(const basic_handle<Args...> &lhs, const null_t rhs) noexcept { - return (lhs.entity() == rhs); -} - -/** - * @brief Compares a handle with the null object. - * @tparam Args Scope of the handle. - * @param lhs A null object yet to be converted. - * @param rhs A valid handle. - * @return False if the two elements differ, true otherwise. - */ -template<typename... Args> -[[nodiscard]] constexpr bool operator==(const null_t lhs, const basic_handle<Args...> &rhs) noexcept { - return (rhs == lhs); -} - -/** - * @brief Compares a handle with the null object. - * @tparam Args Scope of the handle. - * @param lhs A valid handle. - * @param rhs A null object yet to be converted. - * @return True if the two elements differ, false otherwise. - */ -template<typename... Args> -[[nodiscard]] constexpr bool operator!=(const basic_handle<Args...> &lhs, const null_t rhs) noexcept { - return (lhs.entity() != rhs); -} - -/** - * @brief Compares a handle with the null object. - * @tparam Args Scope of the handle. - * @param lhs A null object yet to be converted. - * @param rhs A valid handle. - * @return True if the two elements differ, false otherwise. - */ -template<typename... Args> -[[nodiscard]] constexpr bool operator!=(const null_t lhs, const basic_handle<Args...> &rhs) noexcept { - return (rhs != lhs); -} - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/entity/helper.hpp b/deps/entt/include/entt/entity/helper.hpp deleted file mode 100644 index 4ad2e27..0000000 --- a/deps/entt/include/entt/entity/helper.hpp +++ /dev/null @@ -1,255 +0,0 @@ -#ifndef ENTT_ENTITY_HELPER_HPP -#define ENTT_ENTITY_HELPER_HPP - -#include <memory> -#include <type_traits> -#include <utility> -#include "../core/fwd.hpp" -#include "../core/type_traits.hpp" -#include "component.hpp" -#include "fwd.hpp" -#include "group.hpp" -#include "storage.hpp" -#include "view.hpp" - -namespace entt { - -/** - * @brief Converts a registry to a view. - * @tparam Registry Basic registry type. - */ -template<typename Registry> -class as_view { - template<typename... Get, typename... Exclude> - [[nodiscard]] auto dispatch(get_t<Get...>, exclude_t<Exclude...>) const { - return reg.template view<constness_as_t<typename Get::element_type, Get>...>(exclude_t<constness_as_t<typename Exclude::element_type, Exclude>...>{}); - } - -public: - /*! @brief Type of registry to convert. */ - using registry_type = Registry; - /*! @brief Underlying entity identifier. */ - using entity_type = typename registry_type::entity_type; - - /** - * @brief Constructs a converter for a given registry. - * @param source A valid reference to a registry. - */ - as_view(registry_type &source) noexcept - : reg{source} {} - - /** - * @brief Conversion function from a registry to a view. - * @tparam Get Type of storage used to construct the view. - * @tparam Exclude Types of storage used to filter the view. - * @return A newly created view. - */ - template<typename Get, typename Exclude> - operator basic_view<Get, Exclude>() const { - return dispatch(Get{}, Exclude{}); - } - -private: - registry_type ® -}; - -/** - * @brief Converts a registry to a group. - * @tparam Registry Basic registry type. - */ -template<typename Registry> -class as_group { - template<typename... Owned, typename... Get, typename... Exclude> - [[nodiscard]] auto dispatch(owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>) const { - if constexpr(std::is_const_v<registry_type>) { - return reg.template group_if_exists<typename Owned::element_type...>(get_t<typename Get::element_type...>{}, exclude_t<typename Exclude::element_type...>{}); - } else { - return reg.template group<constness_as_t<typename Owned::element_type, Owned>...>(get_t<constness_as_t<typename Get::element_type, Get>...>{}, exclude_t<constness_as_t<typename Exclude::element_type, Exclude>...>{}); - } - } - -public: - /*! @brief Type of registry to convert. */ - using registry_type = Registry; - /*! @brief Underlying entity identifier. */ - using entity_type = typename registry_type::entity_type; - - /** - * @brief Constructs a converter for a given registry. - * @param source A valid reference to a registry. - */ - as_group(registry_type &source) noexcept - : reg{source} {} - - /** - * @brief Conversion function from a registry to a group. - * @tparam Owned Types of _owned_ by the group. - * @tparam Get Types of storage _observed_ by the group. - * @tparam Exclude Types of storage used to filter the group. - * @return A newly created group. - */ - template<typename Owned, typename Get, typename Exclude> - operator basic_group<Owned, Get, Exclude>() const { - return dispatch(Owned{}, Get{}, Exclude{}); - } - -private: - registry_type ® -}; - -/** - * @brief Helper to create a listener that directly invokes a member function. - * @tparam Member Member function to invoke on an element of the given type. - * @tparam Registry Basic registry type. - * @param reg A registry that contains the given entity and its elements. - * @param entt Entity from which to get the element. - */ -template<auto Member, typename Registry = std::decay_t<nth_argument_t<0u, decltype(Member)>>> -void invoke(Registry ®, const typename Registry::entity_type entt) { - static_assert(std::is_member_function_pointer_v<decltype(Member)>, "Invalid pointer to non-static member function"); - (reg.template get<member_class_t<decltype(Member)>>(entt).*Member)(reg, entt); -} - -/** - * @brief Returns the entity associated with a given element. - * - * @warning - * Currently, this function only works correctly with the default storage as it - * makes assumptions about how the elements are laid out. - * - * @tparam Args Storage type template parameters. - * @param storage A storage that contains the given element. - * @param instance A valid element instance. - * @return The entity associated with the given element. - */ -template<typename... Args> -typename basic_storage<Args...>::entity_type to_entity(const basic_storage<Args...> &storage, const typename basic_storage<Args...>::value_type &instance) { - using traits_type = component_traits<typename basic_storage<Args...>::value_type>; - static_assert(traits_type::page_size != 0u, "Unexpected page size"); - const typename basic_storage<Args...>::base_type &base = storage; - const auto *addr = std::addressof(instance); - - for(auto it = base.rbegin(), last = base.rend(); it < last; it += traits_type::page_size) { - if(const auto dist = (addr - std::addressof(storage.get(*it))); dist >= 0 && dist < static_cast<decltype(dist)>(traits_type::page_size)) { - return *(it + dist); - } - } - - return null; -} - -/*! @brief Primary template isn't defined on purpose. */ -template<typename...> -struct sigh_helper; - -/** - * @brief Signal connection helper for registries. - * @tparam Registry Basic registry type. - */ -template<typename Registry> -struct sigh_helper<Registry> { - /*! @brief Registry type. */ - using registry_type = Registry; - - /** - * @brief Constructs a helper for a given registry. - * @param ref A valid reference to a registry. - */ - sigh_helper(registry_type &ref) - : bucket{&ref} {} - - /** - * @brief Binds a properly initialized helper to a given signal type. - * @tparam Type Type of signal to bind the helper to. - * @param id Optional name for the underlying storage to use. - * @return A helper for a given registry and signal type. - */ - template<typename Type> - auto with(const id_type id = type_hash<Type>::value()) noexcept { - return sigh_helper<registry_type, Type>{*bucket, id}; - } - - /** - * @brief Returns a reference to the underlying registry. - * @return A reference to the underlying registry. - */ - [[nodiscard]] registry_type ®istry() noexcept { - return *bucket; - } - -private: - registry_type *bucket; -}; - -/** - * @brief Signal connection helper for registries. - * @tparam Registry Basic registry type. - * @tparam Type Type of signal to connect listeners to. - */ -template<typename Registry, typename Type> -struct sigh_helper<Registry, Type> final: sigh_helper<Registry> { - /*! @brief Registry type. */ - using registry_type = Registry; - - /** - * @brief Constructs a helper for a given registry. - * @param ref A valid reference to a registry. - * @param id Optional name for the underlying storage to use. - */ - sigh_helper(registry_type &ref, const id_type id = type_hash<Type>::value()) - : sigh_helper<Registry>{ref}, - name{id} {} - - /** - * @brief Forwards the call to `on_construct` on the underlying storage. - * @tparam Candidate Function or member to connect. - * @tparam Args Type of class or type of payload, if any. - * @param args A valid object that fits the purpose, if any. - * @return This helper. - */ - template<auto Candidate, typename... Args> - auto on_construct(Args &&...args) { - this->registry().template on_construct<Type>(name).template connect<Candidate>(std::forward<Args>(args)...); - return *this; - } - - /** - * @brief Forwards the call to `on_update` on the underlying storage. - * @tparam Candidate Function or member to connect. - * @tparam Args Type of class or type of payload, if any. - * @param args A valid object that fits the purpose, if any. - * @return This helper. - */ - template<auto Candidate, typename... Args> - auto on_update(Args &&...args) { - this->registry().template on_update<Type>(name).template connect<Candidate>(std::forward<Args>(args)...); - return *this; - } - - /** - * @brief Forwards the call to `on_destroy` on the underlying storage. - * @tparam Candidate Function or member to connect. - * @tparam Args Type of class or type of payload, if any. - * @param args A valid object that fits the purpose, if any. - * @return This helper. - */ - template<auto Candidate, typename... Args> - auto on_destroy(Args &&...args) { - this->registry().template on_destroy<Type>(name).template connect<Candidate>(std::forward<Args>(args)...); - return *this; - } - -private: - id_type name; -}; - -/** - * @brief Deduction guide. - * @tparam Registry Basic registry type. - */ -template<typename Registry> -sigh_helper(Registry &) -> sigh_helper<Registry>; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/entity/mixin.hpp b/deps/entt/include/entt/entity/mixin.hpp deleted file mode 100644 index c8ebd57..0000000 --- a/deps/entt/include/entt/entity/mixin.hpp +++ /dev/null @@ -1,318 +0,0 @@ -#ifndef ENTT_ENTITY_MIXIN_HPP -#define ENTT_ENTITY_MIXIN_HPP - -#include <type_traits> -#include <utility> -#include "../config/config.h" -#include "../core/any.hpp" -#include "../signal/sigh.hpp" -#include "entity.hpp" -#include "fwd.hpp" - -namespace entt { - -/** - * @brief Mixin type used to add signal support to storage types. - * - * The function type of a listener is equivalent to: - * - * @code{.cpp} - * void(basic_registry<entity_type> &, entity_type); - * @endcode - * - * This applies to all signals made available. - * - * @tparam Type Underlying storage type. - * @tparam Registry Basic registry type. - */ -template<typename Type, typename Registry> -class basic_sigh_mixin final: public Type { - using underlying_type = Type; - using owner_type = Registry; - - using basic_registry_type = basic_registry<typename underlying_type::entity_type, typename underlying_type::base_type::allocator_type>; - using sigh_type = sigh<void(owner_type &, const typename underlying_type::entity_type), typename underlying_type::allocator_type>; - using underlying_iterator = typename underlying_type::base_type::basic_iterator; - - static_assert(std::is_base_of_v<basic_registry_type, owner_type>, "Invalid registry type"); - - [[nodiscard]] auto &owner_or_assert() const noexcept { - ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry"); - return static_cast<owner_type &>(*owner); - } - -private: - void pop(underlying_iterator first, underlying_iterator last) final { - if(auto ® = owner_or_assert(); destruction.empty()) { - underlying_type::pop(first, last); - } else { - for(; first != last; ++first) { - const auto entt = *first; - destruction.publish(reg, entt); - const auto it = underlying_type::find(entt); - underlying_type::pop(it, it + 1u); - } - } - } - - void pop_all() final { - if(auto ® = owner_or_assert(); !destruction.empty()) { - if constexpr(std::is_same_v<typename underlying_type::element_type, typename underlying_type::entity_type>) { - for(typename underlying_type::size_type pos{}, last = underlying_type::free_list(); pos < last; ++pos) { - destruction.publish(reg, underlying_type::base_type::operator[](pos)); - } - } else { - for(auto entt: static_cast<typename underlying_type::base_type &>(*this)) { - if constexpr(underlying_type::storage_policy == deletion_policy::in_place) { - if(entt != tombstone) { - destruction.publish(reg, entt); - } - } else { - destruction.publish(reg, entt); - } - } - } - } - - underlying_type::pop_all(); - } - - underlying_iterator try_emplace(const typename underlying_type::entity_type entt, const bool force_back, const void *value) final { - const auto it = underlying_type::try_emplace(entt, force_back, value); - - if(auto ® = owner_or_assert(); it != underlying_type::base_type::end()) { - construction.publish(reg, *it); - } - - return it; - } - -public: - /*! @brief Allocator type. */ - using allocator_type = typename underlying_type::allocator_type; - /*! @brief Underlying entity identifier. */ - using entity_type = typename underlying_type::entity_type; - /*! @brief Expected registry type. */ - using registry_type = owner_type; - - /*! @brief Default constructor. */ - basic_sigh_mixin() - : basic_sigh_mixin{allocator_type{}} {} - - /** - * @brief Constructs an empty storage with a given allocator. - * @param allocator The allocator to use. - */ - explicit basic_sigh_mixin(const allocator_type &allocator) - : underlying_type{allocator}, - owner{}, - construction{allocator}, - destruction{allocator}, - update{allocator} {} - - /*! @brief Default copy constructor, deleted on purpose. */ - basic_sigh_mixin(const basic_sigh_mixin &) = delete; - - /** - * @brief Move constructor. - * @param other The instance to move from. - */ - basic_sigh_mixin(basic_sigh_mixin &&other) noexcept - : underlying_type{std::move(other)}, - owner{other.owner}, - construction{std::move(other.construction)}, - destruction{std::move(other.destruction)}, - update{std::move(other.update)} {} - - /** - * @brief Allocator-extended move constructor. - * @param other The instance to move from. - * @param allocator The allocator to use. - */ - basic_sigh_mixin(basic_sigh_mixin &&other, const allocator_type &allocator) - : underlying_type{std::move(other), allocator}, - owner{other.owner}, - construction{std::move(other.construction), allocator}, - destruction{std::move(other.destruction), allocator}, - update{std::move(other.update), allocator} {} - - /*! @brief Default destructor. */ - ~basic_sigh_mixin() noexcept override = default; - - /** - * @brief Default copy assignment operator, deleted on purpose. - * @return This mixin. - */ - basic_sigh_mixin &operator=(const basic_sigh_mixin &) = delete; - - /** - * @brief Move assignment operator. - * @param other The instance to move from. - * @return This mixin. - */ - basic_sigh_mixin &operator=(basic_sigh_mixin &&other) noexcept { - owner = other.owner; - construction = std::move(other.construction); - destruction = std::move(other.destruction); - update = std::move(other.update); - underlying_type::operator=(std::move(other)); - return *this; - } - - /** - * @brief Exchanges the contents with those of a given storage. - * @param other Storage to exchange the content with. - */ - void swap(basic_sigh_mixin &other) { - using std::swap; - swap(owner, other.owner); - swap(construction, other.construction); - swap(destruction, other.destruction); - swap(update, other.update); - underlying_type::swap(other); - } - - /** - * @brief Returns a sink object. - * - * The sink returned by this function can be used to receive notifications - * whenever a new instance is created and assigned to an entity.<br/> - * Listeners are invoked after the object has been assigned to the entity. - * - * @sa sink - * - * @return A temporary sink object. - */ - [[nodiscard]] auto on_construct() noexcept { - return sink{construction}; - } - - /** - * @brief Returns a sink object. - * - * The sink returned by this function can be used to receive notifications - * whenever an instance is explicitly updated.<br/> - * Listeners are invoked after the object has been updated. - * - * @sa sink - * - * @return A temporary sink object. - */ - [[nodiscard]] auto on_update() noexcept { - return sink{update}; - } - - /** - * @brief Returns a sink object. - * - * The sink returned by this function can be used to receive notifications - * whenever an instance is removed from an entity and thus destroyed.<br/> - * Listeners are invoked before the object has been removed from the entity. - * - * @sa sink - * - * @return A temporary sink object. - */ - [[nodiscard]] auto on_destroy() noexcept { - return sink{destruction}; - } - - /** - * @brief Emplace elements into a storage. - * - * The behavior of this operation depends on the underlying storage type - * (for example, components vs entities).<br/> - * Refer to the specific documentation for more details. - * - * @return A return value as returned by the underlying storage. - */ - auto emplace() { - const auto entt = underlying_type::emplace(); - construction.publish(owner_or_assert(), entt); - return entt; - } - - /** - * @brief Emplace elements into a storage. - * - * The behavior of this operation depends on the underlying storage type - * (for example, components vs entities).<br/> - * Refer to the specific documentation for more details. - * - * @tparam Args Types of arguments to forward to the underlying storage. - * @param hint A valid identifier. - * @param args Parameters to forward to the underlying storage. - * @return A return value as returned by the underlying storage. - */ - template<typename... Args> - decltype(auto) emplace(const entity_type hint, Args &&...args) { - if constexpr(std::is_same_v<typename underlying_type::element_type, typename underlying_type::entity_type>) { - const auto entt = underlying_type::emplace(hint, std::forward<Args>(args)...); - construction.publish(owner_or_assert(), entt); - return entt; - } else { - underlying_type::emplace(hint, std::forward<Args>(args)...); - construction.publish(owner_or_assert(), hint); - return this->get(hint); - } - } - - /** - * @brief Patches the given instance for an entity. - * @tparam Func Types of the function objects to invoke. - * @param entt A valid identifier. - * @param func Valid function objects. - * @return A reference to the patched instance. - */ - template<typename... Func> - decltype(auto) patch(const entity_type entt, Func &&...func) { - underlying_type::patch(entt, std::forward<Func>(func)...); - update.publish(owner_or_assert(), entt); - return this->get(entt); - } - - /** - * @brief Emplace elements into a storage. - * - * The behavior of this operation depends on the underlying storage type - * (for example, components vs entities).<br/> - * Refer to the specific documentation for more details. - * - * @tparam It Iterator type (as required by the underlying storage type). - * @tparam Args Types of arguments to forward to the underlying storage. - * @param first An iterator to the first element of the range. - * @param last An iterator past the last element of the range. - * @param args Parameters to use to forward to the underlying storage. - */ - template<typename It, typename... Args> - void insert(It first, It last, Args &&...args) { - auto from = underlying_type::size(); - underlying_type::insert(first, last, std::forward<Args>(args)...); - - if(auto ® = owner_or_assert(); !construction.empty()) { - for(const auto to = underlying_type::size(); from != to; ++from) { - construction.publish(reg, underlying_type::operator[](from)); - } - } - } - - /** - * @brief Forwards variables to derived classes, if any. - * @param value A variable wrapped in an opaque container. - */ - void bind(any value) noexcept final { - auto *reg = any_cast<basic_registry_type>(&value); - owner = reg ? reg : owner; - underlying_type::bind(std::move(value)); - } - -private: - basic_registry_type *owner; - sigh_type construction; - sigh_type destruction; - sigh_type update; -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/entity/observer.hpp b/deps/entt/include/entt/entity/observer.hpp deleted file mode 100644 index c280e4d..0000000 --- a/deps/entt/include/entt/entity/observer.hpp +++ /dev/null @@ -1,438 +0,0 @@ -#ifndef ENTT_ENTITY_OBSERVER_HPP -#define ENTT_ENTITY_OBSERVER_HPP - -#include <cstddef> -#include <cstdint> -#include <limits> -#include <type_traits> -#include <utility> -#include "../core/type_traits.hpp" -#include "fwd.hpp" -#include "storage.hpp" - -namespace entt { - -/*! @brief Grouping matcher. */ -template<typename...> -struct matcher {}; - -/** - * @brief Collector. - * - * Primary template isn't defined on purpose. All the specializations give a - * compile-time error, but for a few reasonable cases. - */ -template<typename...> -struct basic_collector; - -/** - * @brief Collector. - * - * A collector contains a set of rules (literally, matchers) to use to track - * entities.<br/> - * Its main purpose is to generate a descriptor that allows an observer to know - * how to connect to a registry. - */ -template<> -struct basic_collector<> { - /** - * @brief Adds a grouping matcher to the collector. - * @tparam AllOf Types of elements tracked by the matcher. - * @tparam NoneOf Types of elements used to filter out entities. - * @return The updated collector. - */ - template<typename... AllOf, typename... NoneOf> - static constexpr auto group(exclude_t<NoneOf...> = exclude_t{}) noexcept { - return basic_collector<matcher<type_list<>, type_list<>, type_list<NoneOf...>, AllOf...>>{}; - } - - /** - * @brief Adds an observing matcher to the collector. - * @tparam AnyOf Type of element for which changes should be detected. - * @return The updated collector. - */ - template<typename AnyOf> - static constexpr auto update() noexcept { - return basic_collector<matcher<type_list<>, type_list<>, AnyOf>>{}; - } -}; - -/** - * @brief Collector. - * @copydetails basic_collector<> - * @tparam Reject Untracked types used to filter out entities. - * @tparam Require Untracked types required by the matcher. - * @tparam Rule Specific details of the current matcher. - * @tparam Other Other matchers. - */ -template<typename... Reject, typename... Require, typename... Rule, typename... Other> -struct basic_collector<matcher<type_list<Reject...>, type_list<Require...>, Rule...>, Other...> { - /*! @brief Current matcher. */ - using current_type = matcher<type_list<Reject...>, type_list<Require...>, Rule...>; - - /** - * @brief Adds a grouping matcher to the collector. - * @tparam AllOf Types of elements tracked by the matcher. - * @tparam NoneOf Types of elements used to filter out entities. - * @return The updated collector. - */ - template<typename... AllOf, typename... NoneOf> - static constexpr auto group(exclude_t<NoneOf...> = exclude_t{}) noexcept { - return basic_collector<matcher<type_list<>, type_list<>, type_list<NoneOf...>, AllOf...>, current_type, Other...>{}; - } - - /** - * @brief Adds an observing matcher to the collector. - * @tparam AnyOf Type of element for which changes should be detected. - * @return The updated collector. - */ - template<typename AnyOf> - static constexpr auto update() noexcept { - return basic_collector<matcher<type_list<>, type_list<>, AnyOf>, current_type, Other...>{}; - } - - /** - * @brief Updates the filter of the last added matcher. - * @tparam AllOf Types of elements required by the matcher. - * @tparam NoneOf Types of elements used to filter out entities. - * @return The updated collector. - */ - template<typename... AllOf, typename... NoneOf> - static constexpr auto where(exclude_t<NoneOf...> = exclude_t{}) noexcept { - using extended_type = matcher<type_list<Reject..., NoneOf...>, type_list<Require..., AllOf...>, Rule...>; - return basic_collector<extended_type, Other...>{}; - } -}; - -/*! @brief Variable template used to ease the definition of collectors. */ -inline constexpr basic_collector<> collector{}; - -/** - * @brief Observer. - * - * An observer returns all the entities and only the entities that fit the - * requirements of at least one matcher. Moreover, it's guaranteed that the - * entity list is tightly packed in memory for fast iterations.<br/> - * In general, observers don't stay true to the order of any set of elements. - * - * Observers work mainly with two types of matchers, provided through a - * collector: - * - * * Observing matcher: an observer will return at least all the living entities - * for which one or more of the given elements have been updated and not yet - * destroyed. - * * Grouping matcher: an observer will return at least all the living entities - * that would have entered the given group if it existed and that would have - * not yet left it. - * - * If an entity respects the requirements of multiple matchers, it will be - * returned once and only once by the observer in any case. - * - * Matchers support also filtering by means of a _where_ clause that accepts - * both a list of types and an exclusion list.<br/> - * Whenever a matcher finds that an entity matches its requirements, the - * condition of the filter is verified before to register the entity itself. - * Moreover, a registered entity isn't returned by the observer if the condition - * set by the filter is broken in the meantime. - * - * @b Important - * - * Iterators aren't invalidated if: - * - * * New instances of the given elements are created and assigned to entities. - * * The entity currently pointed is modified (as an example, if one of the - * given elements is removed from the entity to which the iterator points). - * * The entity currently pointed is destroyed. - * - * In all the other cases, modifying the pools of the given elements in any way - * invalidates all the iterators. - * - * @warning - * Lifetime of an observer doesn't necessarily have to overcome that of the - * registry to which it is connected. However, the observer must be disconnected - * from the registry before being destroyed to avoid crashes due to dangling - * pointers. - * - * @tparam Registry Basic registry type. - * @tparam Allocator Type of allocator used to manage memory and elements. - */ -template<typename Registry, typename Allocator> -class basic_observer { - using mask_type = std::uint64_t; - using storage_type = basic_storage<mask_type, typename Registry::entity_type, typename std::allocator_traits<Allocator>::template rebind_alloc<mask_type>>; - - template<std::size_t Index> - static void discard_if(storage_type &storage, Registry &, const typename Registry::entity_type entt) { - if(storage.contains(entt) && !(storage.get(entt) &= (~(1 << Index)))) { - storage.erase(entt); - } - } - - template<typename> - struct matcher_handler; - - template<typename... Reject, typename... Require, typename AnyOf> - struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, AnyOf>> { - template<std::size_t Index> - static void maybe_valid_if(storage_type &storage, Registry &parent, const typename Registry::entity_type entt) { - if(parent.template all_of<Require...>(entt) && !parent.template any_of<Reject...>(entt)) { - if(!storage.contains(entt)) { - storage.emplace(entt); - } - - storage.get(entt) |= (1 << Index); - } - } - - template<std::size_t Index> - static void connect(storage_type &storage, Registry &parent) { - (parent.template on_destroy<Require>().template connect<&discard_if<Index>>(storage), ...); - (parent.template on_construct<Reject>().template connect<&discard_if<Index>>(storage), ...); - parent.template on_update<AnyOf>().template connect<&maybe_valid_if<Index>>(storage); - parent.template on_destroy<AnyOf>().template connect<&discard_if<Index>>(storage); - } - - static void disconnect(storage_type &storage, Registry &parent) { - (parent.template on_destroy<Require>().disconnect(&storage), ...); - (parent.template on_construct<Reject>().disconnect(&storage), ...); - parent.template on_update<AnyOf>().disconnect(&storage); - parent.template on_destroy<AnyOf>().disconnect(&storage); - } - }; - - template<typename... Reject, typename... Require, typename... NoneOf, typename... AllOf> - struct matcher_handler<matcher<type_list<Reject...>, type_list<Require...>, type_list<NoneOf...>, AllOf...>> { - template<std::size_t Index, typename... Ignore> - static void maybe_valid_if(storage_type &storage, Registry &parent, const typename Registry::entity_type entt) { - bool guard{}; - - if constexpr(sizeof...(Ignore) == 0) { - guard = parent.template all_of<AllOf..., Require...>(entt) && !parent.template any_of<NoneOf..., Reject...>(entt); - } else { - guard = parent.template all_of<AllOf..., Require...>(entt) && ((std::is_same_v<Ignore..., NoneOf> || !parent.template any_of<NoneOf>(entt)) && ...) && !parent.template any_of<Reject...>(entt); - } - - if(guard) { - if(!storage.contains(entt)) { - storage.emplace(entt); - } - - storage.get(entt) |= (1 << Index); - } - } - - template<std::size_t Index> - static void connect(storage_type &storage, Registry &parent) { - (parent.template on_destroy<Require>().template connect<&discard_if<Index>>(storage), ...); - (parent.template on_construct<Reject>().template connect<&discard_if<Index>>(storage), ...); - (parent.template on_construct<AllOf>().template connect<&maybe_valid_if<Index>>(storage), ...); - (parent.template on_destroy<NoneOf>().template connect<&maybe_valid_if<Index, NoneOf>>(storage), ...); - (parent.template on_destroy<AllOf>().template connect<&discard_if<Index>>(storage), ...); - (parent.template on_construct<NoneOf>().template connect<&discard_if<Index>>(storage), ...); - } - - static void disconnect(storage_type &storage, Registry &parent) { - (parent.template on_destroy<Require>().disconnect(&storage), ...); - (parent.template on_construct<Reject>().disconnect(&storage), ...); - (parent.template on_construct<AllOf>().disconnect(&storage), ...); - (parent.template on_destroy<NoneOf>().disconnect(&storage), ...); - (parent.template on_destroy<AllOf>().disconnect(&storage), ...); - (parent.template on_construct<NoneOf>().disconnect(&storage), ...); - } - }; - - template<typename... Matcher> - static void disconnect(Registry &parent, storage_type &storage) { - (matcher_handler<Matcher>::disconnect(storage, parent), ...); - } - - template<typename... Matcher, std::size_t... Index> - static void connect(Registry &parent, storage_type &storage, std::index_sequence<Index...>) { - static_assert(sizeof...(Matcher) < std::numeric_limits<mask_type>::digits, "Too many matchers"); - (matcher_handler<Matcher>::template connect<Index>(storage, parent), ...); - } - -public: - /*! @brief Allocator type. */ - using allocator_type = Allocator; - /*! Basic registry type. */ - using registry_type = Registry; - /*! @brief Underlying entity identifier. */ - using entity_type = typename registry_type::entity_type; - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - /*! @brief Random access iterator type. */ - using iterator = typename registry_type::common_type::iterator; - - /*! @brief Default constructor. */ - basic_observer() - : basic_observer{allocator_type{}} {} - - /** - * @brief Constructs an empty storage with a given allocator. - * @param allocator The allocator to use. - */ - explicit basic_observer(const allocator_type &allocator) - : release{}, - parent{}, - storage{allocator} {} - - /*! @brief Default copy constructor, deleted on purpose. */ - basic_observer(const basic_observer &) = delete; - - /*! @brief Default move constructor, deleted on purpose. */ - basic_observer(basic_observer &&) = delete; - - /** - * @brief Creates an observer and connects it to a given registry. - * @tparam Matcher Types of matchers to use to initialize the observer. - * @param reg A valid reference to a registry. - * @param allocator The allocator to use. - */ - template<typename... Matcher> - basic_observer(registry_type ®, basic_collector<Matcher...>, const allocator_type &allocator = allocator_type{}) - : release{&basic_observer::disconnect<Matcher...>}, - parent{®}, - storage{allocator} { - connect<Matcher...>(reg, storage, std::index_sequence_for<Matcher...>{}); - } - - /*! @brief Default destructor. */ - ~basic_observer() noexcept = default; - - /** - * @brief Default copy assignment operator, deleted on purpose. - * @return This observer. - */ - basic_observer &operator=(const basic_observer &) = delete; - - /** - * @brief Default move assignment operator, deleted on purpose. - * @return This observer. - */ - basic_observer &operator=(basic_observer &&) = delete; - - /** - * @brief Connects an observer to a given registry. - * @tparam Matcher Types of matchers to use to initialize the observer. - * @param reg A valid reference to a registry. - */ - template<typename... Matcher> - void connect(registry_type ®, basic_collector<Matcher...>) { - disconnect(); - storage.clear(); - - parent = ® - release = &basic_observer::disconnect<Matcher...>; - connect<Matcher...>(reg, storage, std::index_sequence_for<Matcher...>{}); - } - - /*! @brief Disconnects an observer from the registry it keeps track of. */ - void disconnect() { - if(release) { - release(*parent, storage); - release = nullptr; - } - } - - /** - * @brief Returns the number of elements in an observer. - * @return Number of elements. - */ - [[nodiscard]] size_type size() const noexcept { - return storage.size(); - } - - /** - * @brief Checks whether an observer is empty. - * @return True if the observer is empty, false otherwise. - */ - [[nodiscard]] bool empty() const noexcept { - return storage.empty(); - } - - /** - * @brief Direct access to the list of entities of the observer. - * - * The returned pointer is such that range `[data(), data() + size())` is - * always a valid range, even if the container is empty. - * - * @note - * Entities are in the reverse order as returned by the `begin`/`end` - * iterators. - * - * @return A pointer to the array of entities. - */ - [[nodiscard]] const entity_type *data() const noexcept { - return storage.data(); - } - - /** - * @brief Returns an iterator to the first entity of the observer. - * - * If the observer is empty, the returned iterator will be equal to `end()`. - * - * @return An iterator to the first entity of the observer. - */ - [[nodiscard]] iterator begin() const noexcept { - return storage.storage_type::base_type::begin(); - } - - /** - * @brief Returns an iterator that is past the last entity of the observer. - * @return An iterator to the entity following the last entity of the - * observer. - */ - [[nodiscard]] iterator end() const noexcept { - return storage.storage_type::base_type::end(); - } - - /*! @brief Clears the underlying container. */ - void clear() noexcept { - storage.clear(); - } - - /** - * @brief Iterates entities and applies the given function object to them. - * - * The function object is invoked for each entity.<br/> - * The signature of the function must be equivalent to the following form: - * - * @code{.cpp} - * void(const entity_type); - * @endcode - * - * @tparam Func Type of the function object to invoke. - * @param func A valid function object. - */ - template<typename Func> - void each(Func func) const { - for(const auto entity: *this) { - func(entity); - } - } - - /** - * @brief Iterates entities and applies the given function object to them, - * then clears the observer. - * - * @sa each - * - * @tparam Func Type of the function object to invoke. - * @param func A valid function object. - */ - template<typename Func> - void each(Func func) { - std::as_const(*this).each(std::move(func)); - clear(); - } - -private: - void (*release)(registry_type &, storage_type &); - registry_type *parent; - storage_type storage; -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/entity/organizer.hpp b/deps/entt/include/entt/entity/organizer.hpp deleted file mode 100644 index a73fea4..0000000 --- a/deps/entt/include/entt/entity/organizer.hpp +++ /dev/null @@ -1,424 +0,0 @@ -#ifndef ENTT_ENTITY_ORGANIZER_HPP -#define ENTT_ENTITY_ORGANIZER_HPP - -#include <cstddef> -#include <type_traits> -#include <utility> -#include <vector> -#include "../core/type_info.hpp" -#include "../core/type_traits.hpp" -#include "../core/utility.hpp" -#include "../graph/adjacency_matrix.hpp" -#include "../graph/flow.hpp" -#include "fwd.hpp" -#include "helper.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename> -struct is_view: std::false_type {}; - -template<typename... Args> -struct is_view<basic_view<Args...>>: std::true_type {}; - -template<typename Type> -inline constexpr bool is_view_v = is_view<Type>::value; - -template<typename Type, typename Override> -struct unpack_type { - using ro = std::conditional_t< - type_list_contains_v<Override, const Type> || (std::is_const_v<Type> && !type_list_contains_v<Override, std::remove_const_t<Type>>), - type_list<std::remove_const_t<Type>>, - type_list<>>; - - using rw = std::conditional_t< - type_list_contains_v<Override, std::remove_const_t<Type>> || (!std::is_const_v<Type> && !type_list_contains_v<Override, const Type>), - type_list<Type>, - type_list<>>; -}; - -template<typename... Args, typename... Override> -struct unpack_type<basic_registry<Args...>, type_list<Override...>> { - using ro = type_list<>; - using rw = type_list<>; -}; - -template<typename... Args, typename... Override> -struct unpack_type<const basic_registry<Args...>, type_list<Override...>> - : unpack_type<basic_registry<Args...>, type_list<Override...>> {}; - -template<typename... Get, typename... Exclude, typename... Override> -struct unpack_type<basic_view<get_t<Get...>, exclude_t<Exclude...>>, type_list<Override...>> { - using ro = type_list_cat_t<type_list<typename Exclude::element_type...>, typename unpack_type<constness_as_t<typename Get::element_type, Get>, type_list<Override...>>::ro...>; - using rw = type_list_cat_t<typename unpack_type<constness_as_t<typename Get::element_type, Get>, type_list<Override...>>::rw...>; -}; - -template<typename... Get, typename... Exclude, typename... Override> -struct unpack_type<const basic_view<get_t<Get...>, exclude_t<Exclude...>>, type_list<Override...>> - : unpack_type<basic_view<get_t<Get...>, exclude_t<Exclude...>>, type_list<Override...>> {}; - -template<typename, typename> -struct resource_traits; - -template<typename... Args, typename... Req> -struct resource_traits<type_list<Args...>, type_list<Req...>> { - using args = type_list<std::remove_const_t<Args>...>; - using ro = type_list_cat_t<typename unpack_type<Args, type_list<Req...>>::ro..., typename unpack_type<Req, type_list<>>::ro...>; - using rw = type_list_cat_t<typename unpack_type<Args, type_list<Req...>>::rw..., typename unpack_type<Req, type_list<>>::rw...>; -}; - -template<typename... Req, typename Ret, typename... Args> -resource_traits<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> free_function_to_resource_traits(Ret (*)(Args...)); - -template<typename... Req, typename Ret, typename Type, typename... Args> -resource_traits<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> constrained_function_to_resource_traits(Ret (*)(Type &, Args...)); - -template<typename... Req, typename Ret, typename Class, typename... Args> -resource_traits<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> constrained_function_to_resource_traits(Ret (Class::*)(Args...)); - -template<typename... Req, typename Ret, typename Class, typename... Args> -resource_traits<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> constrained_function_to_resource_traits(Ret (Class::*)(Args...) const); - -} // namespace internal -/*! @endcond */ - -/** - * @brief Utility class for creating a static task graph. - * - * This class offers minimal support (but sufficient in many cases) for creating - * an execution graph from functions and their requirements on resources.<br/> - * Note that the resulting tasks aren't executed in any case. This isn't the - * goal of the tool. Instead, they are returned to the user in the form of a - * graph that allows for safe execution. - * - * @tparam Registry Basic registry type. - */ -template<typename Registry> -class basic_organizer final { - using callback_type = void(const void *, Registry &); - using prepare_type = void(Registry &); - using dependency_type = std::size_t(const bool, const type_info **, const std::size_t); - - struct vertex_data final { - std::size_t ro_count{}; - std::size_t rw_count{}; - const char *name{}; - const void *payload{}; - callback_type *callback{}; - dependency_type *dependency{}; - prepare_type *prepare{}; - const type_info *info{}; - }; - - template<typename Type> - [[nodiscard]] static decltype(auto) extract(Registry ®) { - if constexpr(std::is_same_v<Type, Registry>) { - return reg; - } else if constexpr(internal::is_view_v<Type>) { - return static_cast<Type>(as_view{reg}); - } else { - return reg.ctx().template emplace<std::remove_reference_t<Type>>(); - } - } - - template<typename... Args> - [[nodiscard]] static auto to_args(Registry ®, type_list<Args...>) { - return std::tuple<decltype(extract<Args>(reg))...>(extract<Args>(reg)...); - } - - template<typename... Type> - [[nodiscard]] static std::size_t fill_dependencies(type_list<Type...>, [[maybe_unused]] const type_info **buffer, [[maybe_unused]] const std::size_t count) { - if constexpr(sizeof...(Type) == 0u) { - return {}; - } else { - const type_info *info[]{&type_id<Type>()...}; - const auto length = count < sizeof...(Type) ? count : sizeof...(Type); - - for(std::size_t pos{}; pos < length; ++pos) { - buffer[pos] = info[pos]; - } - - return length; - } - } - - template<typename... RO, typename... RW> - void track_dependencies(std::size_t index, const bool requires_registry, type_list<RO...>, type_list<RW...>) { - builder.bind(static_cast<id_type>(index)); - builder.set(type_hash<Registry>::value(), requires_registry || (sizeof...(RO) + sizeof...(RW) == 0u)); - (builder.ro(type_hash<RO>::value()), ...); - (builder.rw(type_hash<RW>::value()), ...); - } - -public: - /*! Basic registry type. */ - using registry_type = Registry; - /*! @brief Underlying entity identifier. */ - using entity_type = typename registry_type::entity_type; - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - /*! @brief Raw task function type. */ - using function_type = callback_type; - - /*! @brief Vertex type of a task graph defined as an adjacency list. */ - struct vertex { - /** - * @brief Constructs a vertex of the task graph. - * @param data The data associated with the vertex. - * @param from List of in-edges of the vertex. - * @param to List of out-edges of the vertex. - */ - vertex(vertex_data data, std::vector<std::size_t> from, std::vector<std::size_t> to) - : node{std::move(data)}, - in{std::move(from)}, - out{std::move(to)} {} - - /** - * @brief Fills a buffer with the type info objects for the writable - * resources of a vertex. - * @param buffer A buffer pre-allocated by the user. - * @param length The length of the user-supplied buffer. - * @return The number of type info objects written to the buffer. - */ - [[nodiscard]] size_type ro_dependency(const type_info **buffer, const std::size_t length) const noexcept { - return node.dependency(false, buffer, length); - } - - /** - * @brief Fills a buffer with the type info objects for the read-only - * resources of a vertex. - * @param buffer A buffer pre-allocated by the user. - * @param length The length of the user-supplied buffer. - * @return The number of type info objects written to the buffer. - */ - [[nodiscard]] size_type rw_dependency(const type_info **buffer, const std::size_t length) const noexcept { - return node.dependency(true, buffer, length); - } - - /** - * @brief Returns the number of read-only resources of a vertex. - * @return The number of read-only resources of the vertex. - */ - [[nodiscard]] size_type ro_count() const noexcept { - return node.ro_count; - } - - /** - * @brief Returns the number of writable resources of a vertex. - * @return The number of writable resources of the vertex. - */ - [[nodiscard]] size_type rw_count() const noexcept { - return node.rw_count; - } - - /** - * @brief Checks if a vertex is also a top-level one. - * @return True if the vertex is a top-level one, false otherwise. - */ - [[nodiscard]] bool top_level() const noexcept { - return in.empty(); - } - - /** - * @brief Returns a type info object associated with a vertex. - * @return A properly initialized type info object. - */ - [[nodiscard]] const type_info &info() const noexcept { - return *node.info; - } - - /** - * @brief Returns a user defined name associated with a vertex, if any. - * @return The user defined name associated with the vertex, if any. - */ - [[nodiscard]] const char *name() const noexcept { - return node.name; - } - - /** - * @brief Returns the function associated with a vertex. - * @return The function associated with the vertex. - */ - [[nodiscard]] function_type *callback() const noexcept { - return node.callback; - } - - /** - * @brief Returns the payload associated with a vertex, if any. - * @return The payload associated with the vertex, if any. - */ - [[nodiscard]] const void *data() const noexcept { - return node.payload; - } - - /** - * @brief Returns the list of in-edges of a vertex. - * @return The list of in-edges of a vertex. - */ - [[nodiscard]] const std::vector<std::size_t> &in_edges() const noexcept { - return in; - } - - /** - * @brief Returns the list of out-edges of a vertex. - * @return The list of out-edges of a vertex. - */ - [[nodiscard]] const std::vector<std::size_t> &out_edges() const noexcept { - return out; - } - - /** - * @brief Returns the list of nodes reachable from a given vertex. - * @return The list of nodes reachable from the vertex. - */ - [[deprecated("use ::out_edges")]] [[nodiscard]] const std::vector<std::size_t> &children() const noexcept { - return out_edges(); - } - - /** - * @brief Prepares a registry and assures that all required resources - * are properly instantiated before using them. - * @param reg A valid registry. - */ - void prepare(registry_type ®) const { - node.prepare ? node.prepare(reg) : void(); - } - - private: - vertex_data node; - std::vector<std::size_t> in; - std::vector<std::size_t> out; - }; - - /** - * @brief Adds a free function to the task list. - * @tparam Candidate Function to add to the task list. - * @tparam Req Additional requirements and/or override resource access mode. - * @param name Optional name to associate with the task. - */ - template<auto Candidate, typename... Req> - void emplace(const char *name = nullptr) { - using resource_type = decltype(internal::free_function_to_resource_traits<Req...>(Candidate)); - constexpr auto requires_registry = type_list_contains_v<typename resource_type::args, registry_type>; - - callback_type *callback = +[](const void *, registry_type ®) { - std::apply(Candidate, to_args(reg, typename resource_type::args{})); - }; - - vertex_data vdata{ - resource_type::ro::size, - resource_type::rw::size, - name, - nullptr, - callback, - +[](const bool rw, const type_info **buffer, const std::size_t length) { return rw ? fill_dependencies(typename resource_type::rw{}, buffer, length) : fill_dependencies(typename resource_type::ro{}, buffer, length); }, - +[](registry_type ®) { void(to_args(reg, typename resource_type::args{})); }, - &type_id<std::integral_constant<decltype(Candidate), Candidate>>()}; - - track_dependencies(vertices.size(), requires_registry, typename resource_type::ro{}, typename resource_type::rw{}); - vertices.push_back(std::move(vdata)); - } - - /** - * @brief Adds a free function with payload or a member function with an - * instance to the task list. - * @tparam Candidate Function or member to add to the task list. - * @tparam Req Additional requirements and/or override resource access mode. - * @tparam Type Type of class or type of payload. - * @param value_or_instance A valid object that fits the purpose. - * @param name Optional name to associate with the task. - */ - template<auto Candidate, typename... Req, typename Type> - void emplace(Type &value_or_instance, const char *name = nullptr) { - using resource_type = decltype(internal::constrained_function_to_resource_traits<Req...>(Candidate)); - constexpr auto requires_registry = type_list_contains_v<typename resource_type::args, registry_type>; - - callback_type *callback = +[](const void *payload, registry_type ®) { - Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload)); - std::apply(Candidate, std::tuple_cat(std::forward_as_tuple(*curr), to_args(reg, typename resource_type::args{}))); - }; - - vertex_data vdata{ - resource_type::ro::size, - resource_type::rw::size, - name, - &value_or_instance, - callback, - +[](const bool rw, const type_info **buffer, const std::size_t length) { return rw ? fill_dependencies(typename resource_type::rw{}, buffer, length) : fill_dependencies(typename resource_type::ro{}, buffer, length); }, - +[](registry_type ®) { void(to_args(reg, typename resource_type::args{})); }, - &type_id<std::integral_constant<decltype(Candidate), Candidate>>()}; - - track_dependencies(vertices.size(), requires_registry, typename resource_type::ro{}, typename resource_type::rw{}); - vertices.push_back(std::move(vdata)); - } - - /** - * @brief Adds an user defined function with optional payload to the task - * list. - * @tparam Req Additional requirements and/or override resource access mode. - * @param func Function to add to the task list. - * @param payload User defined arbitrary data. - * @param name Optional name to associate with the task. - */ - template<typename... Req> - void emplace(function_type *func, const void *payload = nullptr, const char *name = nullptr) { - using resource_type = internal::resource_traits<type_list<>, type_list<Req...>>; - track_dependencies(vertices.size(), true, typename resource_type::ro{}, typename resource_type::rw{}); - - vertex_data vdata{ - resource_type::ro::size, - resource_type::rw::size, - name, - payload, - func, - +[](const bool rw, const type_info **buffer, const std::size_t length) { return rw ? fill_dependencies(typename resource_type::rw{}, buffer, length) : fill_dependencies(typename resource_type::ro{}, buffer, length); }, - nullptr, - &type_id<void>()}; - - vertices.push_back(std::move(vdata)); - } - - /** - * @brief Generates a task graph for the current content. - * @return The adjacency list of the task graph. - */ - [[nodiscard]] std::vector<vertex> graph() { - std::vector<vertex> adjacency_list{}; - adjacency_list.reserve(vertices.size()); - auto adjacency_matrix = builder.graph(); - - for(auto curr: adjacency_matrix.vertices()) { - std::vector<std::size_t> in{}; - std::vector<std::size_t> out{}; - - for(auto &&edge: adjacency_matrix.in_edges(curr)) { - in.push_back(edge.first); - } - - for(auto &&edge: adjacency_matrix.out_edges(curr)) { - out.push_back(edge.second); - } - - adjacency_list.emplace_back(vertices[curr], std::move(in), std::move(out)); - } - - return adjacency_list; - } - - /*! @brief Erases all elements from a container. */ - void clear() { - builder.clear(); - vertices.clear(); - } - -private: - std::vector<vertex_data> vertices; - flow builder; -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/entity/ranges.hpp b/deps/entt/include/entt/entity/ranges.hpp deleted file mode 100644 index a80c84e..0000000 --- a/deps/entt/include/entt/entity/ranges.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef ENTT_ENTITY_RANGES_HPP -#define ENTT_ENTITY_RANGES_HPP - -#if __has_include(<version>) -# include <version> -# -# if defined(__cpp_lib_ranges) -# include <ranges> -# include "fwd.hpp" - -template<class... Args> -inline constexpr bool std::ranges::enable_borrowed_range<entt::basic_view<Args...>>{true}; - -template<class... Args> -inline constexpr bool std::ranges::enable_borrowed_range<entt::basic_group<Args...>>{true}; - -template<class... Args> -inline constexpr bool std::ranges::enable_view<entt::basic_view<Args...>>{true}; - -template<class... Args> -inline constexpr bool std::ranges::enable_view<entt::basic_group<Args...>>{true}; - -# endif -#endif - -#endif
\ No newline at end of file diff --git a/deps/entt/include/entt/entity/registry.hpp b/deps/entt/include/entt/entity/registry.hpp deleted file mode 100644 index c4c0098..0000000 --- a/deps/entt/include/entt/entity/registry.hpp +++ /dev/null @@ -1,1222 +0,0 @@ -#ifndef ENTT_ENTITY_REGISTRY_HPP -#define ENTT_ENTITY_REGISTRY_HPP - -#include <algorithm> -#include <array> -#include <cstddef> -#include <functional> -#include <iterator> -#include <memory> -#include <tuple> -#include <type_traits> -#include <utility> -#include <vector> -#include "../config/config.h" -#include "../container/dense_map.hpp" -#include "../core/algorithm.hpp" -#include "../core/any.hpp" -#include "../core/fwd.hpp" -#include "../core/iterator.hpp" -#include "../core/memory.hpp" -#include "../core/type_info.hpp" -#include "../core/type_traits.hpp" -#include "../core/utility.hpp" -#include "entity.hpp" -#include "fwd.hpp" -#include "group.hpp" -#include "mixin.hpp" -#include "sparse_set.hpp" -#include "storage.hpp" -#include "view.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename It> -class registry_storage_iterator final { - template<typename Other> - friend class registry_storage_iterator; - - using mapped_type = std::remove_reference_t<decltype(std::declval<It>()->second)>; - -public: - using value_type = std::pair<id_type, constness_as_t<typename mapped_type::element_type, mapped_type> &>; - using pointer = input_iterator_pointer<value_type>; - using reference = value_type; - using difference_type = std::ptrdiff_t; - using iterator_category = std::input_iterator_tag; - using iterator_concept = std::random_access_iterator_tag; - - constexpr registry_storage_iterator() noexcept - : it{} {} - - constexpr registry_storage_iterator(It iter) noexcept - : it{iter} {} - - template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>> - constexpr registry_storage_iterator(const registry_storage_iterator<Other> &other) noexcept - : registry_storage_iterator{other.it} {} - - constexpr registry_storage_iterator &operator++() noexcept { - return ++it, *this; - } - - constexpr registry_storage_iterator operator++(int) noexcept { - registry_storage_iterator orig = *this; - return ++(*this), orig; - } - - constexpr registry_storage_iterator &operator--() noexcept { - return --it, *this; - } - - constexpr registry_storage_iterator operator--(int) noexcept { - registry_storage_iterator orig = *this; - return operator--(), orig; - } - - constexpr registry_storage_iterator &operator+=(const difference_type value) noexcept { - it += value; - return *this; - } - - constexpr registry_storage_iterator operator+(const difference_type value) const noexcept { - registry_storage_iterator copy = *this; - return (copy += value); - } - - constexpr registry_storage_iterator &operator-=(const difference_type value) noexcept { - return (*this += -value); - } - - constexpr registry_storage_iterator operator-(const difference_type value) const noexcept { - return (*this + -value); - } - - [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept { - return {it[value].first, *it[value].second}; - } - - [[nodiscard]] constexpr reference operator*() const noexcept { - return operator[](0); - } - - [[nodiscard]] constexpr pointer operator->() const noexcept { - return operator*(); - } - - template<typename Lhs, typename Rhs> - friend constexpr std::ptrdiff_t operator-(const registry_storage_iterator<Lhs> &, const registry_storage_iterator<Rhs> &) noexcept; - - template<typename Lhs, typename Rhs> - friend constexpr bool operator==(const registry_storage_iterator<Lhs> &, const registry_storage_iterator<Rhs> &) noexcept; - - template<typename Lhs, typename Rhs> - friend constexpr bool operator<(const registry_storage_iterator<Lhs> &, const registry_storage_iterator<Rhs> &) noexcept; - -private: - It it; -}; - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr std::ptrdiff_t operator-(const registry_storage_iterator<Lhs> &lhs, const registry_storage_iterator<Rhs> &rhs) noexcept { - return lhs.it - rhs.it; -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator==(const registry_storage_iterator<Lhs> &lhs, const registry_storage_iterator<Rhs> &rhs) noexcept { - return lhs.it == rhs.it; -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator!=(const registry_storage_iterator<Lhs> &lhs, const registry_storage_iterator<Rhs> &rhs) noexcept { - return !(lhs == rhs); -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator<(const registry_storage_iterator<Lhs> &lhs, const registry_storage_iterator<Rhs> &rhs) noexcept { - return lhs.it < rhs.it; -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator>(const registry_storage_iterator<Lhs> &lhs, const registry_storage_iterator<Rhs> &rhs) noexcept { - return rhs < lhs; -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator<=(const registry_storage_iterator<Lhs> &lhs, const registry_storage_iterator<Rhs> &rhs) noexcept { - return !(lhs > rhs); -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator>=(const registry_storage_iterator<Lhs> &lhs, const registry_storage_iterator<Rhs> &rhs) noexcept { - return !(lhs < rhs); -} - -template<typename Allocator> -class registry_context { - using alloc_traits = std::allocator_traits<Allocator>; - using allocator_type = typename alloc_traits::template rebind_alloc<std::pair<const id_type, basic_any<0u>>>; - -public: - explicit registry_context(const allocator_type &allocator) - : ctx{allocator} {} - - template<typename Type, typename... Args> - Type &emplace_as(const id_type id, Args &&...args) { - return any_cast<Type &>(ctx.try_emplace(id, std::in_place_type<Type>, std::forward<Args>(args)...).first->second); - } - - template<typename Type, typename... Args> - Type &emplace(Args &&...args) { - return emplace_as<Type>(type_id<Type>().hash(), std::forward<Args>(args)...); - } - - template<typename Type> - Type &insert_or_assign(const id_type id, Type &&value) { - return any_cast<std::remove_cv_t<std::remove_reference_t<Type>> &>(ctx.insert_or_assign(id, std::forward<Type>(value)).first->second); - } - - template<typename Type> - Type &insert_or_assign(Type &&value) { - return insert_or_assign(type_id<Type>().hash(), std::forward<Type>(value)); - } - - template<typename Type> - bool erase(const id_type id = type_id<Type>().hash()) { - const auto it = ctx.find(id); - return it != ctx.end() && it->second.type() == type_id<Type>() ? (ctx.erase(it), true) : false; - } - - template<typename Type> - [[nodiscard]] const Type &get(const id_type id = type_id<Type>().hash()) const { - return any_cast<const Type &>(ctx.at(id)); - } - - template<typename Type> - [[nodiscard]] Type &get(const id_type id = type_id<Type>().hash()) { - return any_cast<Type &>(ctx.at(id)); - } - - template<typename Type> - [[nodiscard]] const Type *find(const id_type id = type_id<Type>().hash()) const { - const auto it = ctx.find(id); - return it != ctx.cend() ? any_cast<const Type>(&it->second) : nullptr; - } - - template<typename Type> - [[nodiscard]] Type *find(const id_type id = type_id<Type>().hash()) { - const auto it = ctx.find(id); - return it != ctx.end() ? any_cast<Type>(&it->second) : nullptr; - } - - template<typename Type> - [[nodiscard]] bool contains(const id_type id = type_id<Type>().hash()) const { - const auto it = ctx.find(id); - return it != ctx.cend() && it->second.type() == type_id<Type>(); - } - -private: - dense_map<id_type, basic_any<0u>, identity, std::equal_to<>, allocator_type> ctx; -}; - -} // namespace internal -/*! @endcond */ - -/** - * @brief Fast and reliable entity-component system. - * @tparam Entity A valid entity type. - * @tparam Allocator Type of allocator used to manage memory and elements. - */ -template<typename Entity, typename Allocator> -class basic_registry { - using base_type = basic_sparse_set<Entity, Allocator>; - using alloc_traits = std::allocator_traits<Allocator>; - static_assert(std::is_same_v<typename alloc_traits::value_type, Entity>, "Invalid value type"); - // std::shared_ptr because of its type erased allocator which is useful here - using pool_container_type = dense_map<id_type, std::shared_ptr<base_type>, identity, std::equal_to<>, typename alloc_traits::template rebind_alloc<std::pair<const id_type, std::shared_ptr<base_type>>>>; - using group_container_type = dense_map<id_type, std::shared_ptr<internal::group_descriptor>, identity, std::equal_to<>, typename alloc_traits::template rebind_alloc<std::pair<const id_type, std::shared_ptr<internal::group_descriptor>>>>; - using traits_type = entt_traits<Entity>; - - template<typename Type> - [[nodiscard]] auto &assure([[maybe_unused]] const id_type id = type_hash<Type>::value()) { - static_assert(std::is_same_v<Type, std::decay_t<Type>>, "Non-decayed types not allowed"); - - if constexpr(std::is_same_v<Type, entity_type>) { - ENTT_ASSERT(id == type_hash<Type>::value(), "User entity storage not allowed"); - return entities; - } else { - using storage_type = storage_for_type<Type>; - - if(auto it = pools.find(id); it == pools.cend()) { - using alloc_type = typename storage_type::allocator_type; - typename pool_container_type::mapped_type cpool{}; - - if constexpr(std::is_void_v<Type> && !std::is_constructible_v<alloc_type, allocator_type>) { - // std::allocator<void> has no cross constructors (waiting for C++20) - cpool = std::allocate_shared<storage_type>(get_allocator(), alloc_type{}); - } else { - cpool = std::allocate_shared<storage_type>(get_allocator(), get_allocator()); - } - - pools.emplace(id, cpool); - cpool->bind(forward_as_any(*this)); - - return static_cast<storage_type &>(*cpool); - } else { - ENTT_ASSERT(it->second->type() == type_id<Type>(), "Unexpected type"); - return static_cast<storage_type &>(*it->second); - } - } - } - - template<typename Type> - [[nodiscard]] const auto *assure([[maybe_unused]] const id_type id = type_hash<Type>::value()) const { - static_assert(std::is_same_v<Type, std::decay_t<Type>>, "Non-decayed types not allowed"); - - if constexpr(std::is_same_v<Type, entity_type>) { - ENTT_ASSERT(id == type_hash<Type>::value(), "User entity storage not allowed"); - return &entities; - } else { - if(const auto it = pools.find(id); it != pools.cend()) { - ENTT_ASSERT(it->second->type() == type_id<Type>(), "Unexpected type"); - return static_cast<const storage_for_type<Type> *>(it->second.get()); - } - - return static_cast<const storage_for_type<Type> *>(nullptr); - } - } - - void rebind() { - entities.bind(forward_as_any(*this)); - - for(auto &&curr: pools) { - curr.second->bind(forward_as_any(*this)); - } - } - -public: - /*! @brief Allocator type. */ - using allocator_type = Allocator; - /*! @brief Underlying entity identifier. */ - using entity_type = typename traits_type::value_type; - /*! @brief Underlying version type. */ - using version_type = typename traits_type::version_type; - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - /*! @brief Common type among all storage types. */ - using common_type = base_type; - /*! @brief Context type. */ - using context = internal::registry_context<allocator_type>; - /*! @brief Iterable registry type. */ - using iterable = iterable_adaptor<internal::registry_storage_iterator<typename pool_container_type::iterator>>; - /*! @brief Constant iterable registry type. */ - using const_iterable = iterable_adaptor<internal::registry_storage_iterator<typename pool_container_type::const_iterator>>; - - /** - * @copybrief storage_for - * @tparam Type Storage value type, eventually const. - */ - template<typename Type> - using storage_for_type = typename storage_for<Type, Entity, typename alloc_traits::template rebind_alloc<std::remove_const_t<Type>>>::type; - - /*! @brief Default constructor. */ - basic_registry() - : basic_registry{allocator_type{}} {} - - /** - * @brief Constructs an empty registry with a given allocator. - * @param allocator The allocator to use. - */ - explicit basic_registry(const allocator_type &allocator) - : basic_registry{0u, allocator} {} - - /** - * @brief Allocates enough memory upon construction to store `count` pools. - * @param count The number of pools to allocate memory for. - * @param allocator The allocator to use. - */ - basic_registry(const size_type count, const allocator_type &allocator = allocator_type{}) - : vars{allocator}, - pools{allocator}, - groups{allocator}, - entities{allocator} { - pools.reserve(count); - rebind(); - } - - /*! @brief Default copy constructor, deleted on purpose. */ - basic_registry(const basic_registry &) = delete; - - /** - * @brief Move constructor. - * @param other The instance to move from. - */ - basic_registry(basic_registry &&other) noexcept - : vars{std::move(other.vars)}, - pools{std::move(other.pools)}, - groups{std::move(other.groups)}, - entities{std::move(other.entities)} { - rebind(); - } - - /*! @brief Default destructor. */ - ~basic_registry() noexcept = default; - - /** - * @brief Default copy assignment operator, deleted on purpose. - * @return This mixin. - */ - basic_registry &operator=(const basic_registry &) = delete; - - /** - * @brief Move assignment operator. - * @param other The instance to move from. - * @return This registry. - */ - basic_registry &operator=(basic_registry &&other) noexcept { - vars = std::move(other.vars); - pools = std::move(other.pools); - groups = std::move(other.groups); - entities = std::move(other.entities); - - rebind(); - - return *this; - } - - /** - * @brief Exchanges the contents with those of a given registry. - * @param other Registry to exchange the content with. - */ - void swap(basic_registry &other) { - using std::swap; - - swap(vars, other.vars); - swap(pools, other.pools); - swap(groups, other.groups); - swap(entities, other.entities); - - rebind(); - other.rebind(); - } - - /** - * @brief Returns the associated allocator. - * @return The associated allocator. - */ - [[nodiscard]] constexpr allocator_type get_allocator() const noexcept { - return entities.get_allocator(); - } - - /** - * @brief Returns an iterable object to use to _visit_ a registry. - * - * The iterable object returns a pair that contains the name and a reference - * to the current storage. - * - * @return An iterable object to use to _visit_ the registry. - */ - [[nodiscard]] iterable storage() noexcept { - return iterable{pools.begin(), pools.end()}; - } - - /*! @copydoc storage */ - [[nodiscard]] const_iterable storage() const noexcept { - return const_iterable{pools.cbegin(), pools.cend()}; - } - - /** - * @brief Finds the storage associated with a given name, if any. - * @param id Name used to map the storage within the registry. - * @return A pointer to the storage if it exists, a null pointer otherwise. - */ - [[nodiscard]] common_type *storage(const id_type id) { - return const_cast<common_type *>(std::as_const(*this).storage(id)); - } - - /** - * @brief Finds the storage associated with a given name, if any. - * @param id Name used to map the storage within the registry. - * @return A pointer to the storage if it exists, a null pointer otherwise. - */ - [[nodiscard]] const common_type *storage(const id_type id) const { - const auto it = pools.find(id); - return it == pools.cend() ? nullptr : it->second.get(); - } - - /** - * @brief Returns the storage for a given element type. - * @tparam Type Type of element of which to return the storage. - * @param id Optional name used to map the storage within the registry. - * @return The storage for the given element type. - */ - template<typename Type> - storage_for_type<Type> &storage(const id_type id = type_hash<Type>::value()) { - return assure<Type>(id); - } - - /** - * @brief Returns the storage for a given element type, if any. - * @tparam Type Type of element of which to return the storage. - * @param id Optional name used to map the storage within the registry. - * @return The storage for the given element type. - */ - template<typename Type> - [[nodiscard]] const storage_for_type<Type> *storage(const id_type id = type_hash<Type>::value()) const { - return assure<Type>(id); - } - - /** - * @brief Checks if an identifier refers to a valid entity. - * @param entt An identifier, either valid or not. - * @return True if the identifier is valid, false otherwise. - */ - [[nodiscard]] bool valid(const entity_type entt) const { - return static_cast<size_type>(entities.find(entt).index()) < entities.free_list(); - } - - /** - * @brief Returns the actual version for an identifier. - * @param entt A valid identifier. - * @return The version for the given identifier if valid, the tombstone - * version otherwise. - */ - [[nodiscard]] version_type current(const entity_type entt) const { - return entities.current(entt); - } - - /** - * @brief Creates a new entity or recycles a destroyed one. - * @return A valid identifier. - */ - [[nodiscard]] entity_type create() { - return entities.emplace(); - } - - /** - * @copybrief create - * - * If the requested entity isn't in use, the suggested identifier is used. - * Otherwise, a new identifier is generated. - * - * @param hint Required identifier. - * @return A valid identifier. - */ - [[nodiscard]] entity_type create(const entity_type hint) { - return entities.emplace(hint); - } - - /** - * @brief Assigns each element in a range an identifier. - * - * @sa create - * - * @tparam It Type of forward iterator. - * @param first An iterator to the first element of the range to generate. - * @param last An iterator past the last element of the range to generate. - */ - template<typename It> - void create(It first, It last) { - entities.insert(std::move(first), std::move(last)); - } - - /** - * @brief Destroys an entity and releases its identifier. - * - * @warning - * Adding or removing elements to an entity that is being destroyed can - * result in undefined behavior. - * - * @param entt A valid identifier. - * @return The version of the recycled entity. - */ - version_type destroy(const entity_type entt) { - for(size_type pos = pools.size(); pos; --pos) { - pools.begin()[pos - 1u].second->remove(entt); - } - - entities.erase(entt); - return entities.current(entt); - } - - /** - * @brief Destroys an entity and releases its identifier. - * - * The suggested version or the valid version closest to the suggested one - * is used instead of the implicitly generated version. - * - * @sa destroy - * - * @param entt A valid identifier. - * @param version A desired version upon destruction. - * @return The version actually assigned to the entity. - */ - version_type destroy(const entity_type entt, const version_type version) { - destroy(entt); - const auto elem = traits_type::construct(traits_type::to_entity(entt), version); - return entities.bump((elem == tombstone) ? traits_type::next(elem) : elem); - } - - /** - * @brief Destroys all entities in a range and releases their identifiers. - * - * @sa destroy - * - * @tparam It Type of input iterator. - * @param first An iterator to the first element of the range of entities. - * @param last An iterator past the last element of the range of entities. - */ - template<typename It> - void destroy(It first, It last) { - const auto to = entities.sort_as(first, last); - const auto from = entities.cend() - entities.free_list(); - - for(auto &&curr: pools) { - curr.second->remove(from, to); - } - - entities.erase(from, to); - } - - /** - * @brief Assigns the given element to an entity. - * - * The element must have a proper constructor or be of aggregate type. - * - * @warning - * Attempting to assign an element to an entity that already owns it results - * in undefined behavior. - * - * @tparam Type Type of element to create. - * @tparam Args Types of arguments to use to construct the element. - * @param entt A valid identifier. - * @param args Parameters to use to initialize the element. - * @return A reference to the newly created element. - */ - template<typename Type, typename... Args> - decltype(auto) emplace(const entity_type entt, Args &&...args) { - ENTT_ASSERT(valid(entt), "Invalid entity"); - return assure<Type>().emplace(entt, std::forward<Args>(args)...); - } - - /** - * @brief Assigns each entity in a range the given element. - * - * @sa emplace - * - * @tparam Type Type of element to create. - * @tparam It Type of input iterator. - * @param first An iterator to the first element of the range of entities. - * @param last An iterator past the last element of the range of entities. - * @param value An instance of the element to assign. - */ - template<typename Type, typename It> - void insert(It first, It last, const Type &value = {}) { - ENTT_ASSERT(std::all_of(first, last, [this](const auto entt) { return valid(entt); }), "Invalid entity"); - assure<Type>().insert(std::move(first), std::move(last), value); - } - - /** - * @brief Assigns each entity in a range the given elements. - * - * @sa emplace - * - * @tparam Type Type of element to create. - * @tparam EIt Type of input iterator. - * @tparam CIt Type of input iterator. - * @param first An iterator to the first element of the range of entities. - * @param last An iterator past the last element of the range of entities. - * @param from An iterator to the first element of the range of elements. - */ - template<typename Type, typename EIt, typename CIt, typename = std::enable_if_t<std::is_same_v<typename std::iterator_traits<CIt>::value_type, Type>>> - void insert(EIt first, EIt last, CIt from) { - ENTT_ASSERT(std::all_of(first, last, [this](const auto entt) { return valid(entt); }), "Invalid entity"); - assure<Type>().insert(first, last, from); - } - - /** - * @brief Assigns or replaces the given element for an entity. - * - * @sa emplace - * @sa replace - * - * @tparam Type Type of element to assign or replace. - * @tparam Args Types of arguments to use to construct the element. - * @param entt A valid identifier. - * @param args Parameters to use to initialize the element. - * @return A reference to the newly created element. - */ - template<typename Type, typename... Args> - decltype(auto) emplace_or_replace(const entity_type entt, Args &&...args) { - if(auto &cpool = assure<Type>(); cpool.contains(entt)) { - return cpool.patch(entt, [&args...](auto &...curr) { ((curr = Type{std::forward<Args>(args)...}), ...); }); - } else { - ENTT_ASSERT(valid(entt), "Invalid entity"); - return cpool.emplace(entt, std::forward<Args>(args)...); - } - } - - /** - * @brief Patches the given element for an entity. - * - * The signature of the function should be equivalent to the following: - * - * @code{.cpp} - * void(Type &); - * @endcode - * - * @warning - * Attempting to patch an element of an entity that doesn't own it results - * in undefined behavior. - * - * @tparam Type Type of element to patch. - * @tparam Func Types of the function objects to invoke. - * @param entt A valid identifier. - * @param func Valid function objects. - * @return A reference to the patched element. - */ - template<typename Type, typename... Func> - decltype(auto) patch(const entity_type entt, Func &&...func) { - return assure<Type>().patch(entt, std::forward<Func>(func)...); - } - - /** - * @brief Replaces the given element for an entity. - * - * The element must have a proper constructor or be of aggregate type. - * - * @warning - * Attempting to replace an element of an entity that doesn't own it results - * in undefined behavior. - * - * @tparam Type Type of element to replace. - * @tparam Args Types of arguments to use to construct the element. - * @param entt A valid identifier. - * @param args Parameters to use to initialize the element. - * @return A reference to the element being replaced. - */ - template<typename Type, typename... Args> - decltype(auto) replace(const entity_type entt, Args &&...args) { - return patch<Type>(entt, [&args...](auto &...curr) { ((curr = Type{std::forward<Args>(args)...}), ...); }); - } - - /** - * @brief Removes the given elements from an entity. - * @tparam Type Type of element to remove. - * @tparam Other Other types of elements to remove. - * @param entt A valid identifier. - * @return The number of elements actually removed. - */ - template<typename Type, typename... Other> - size_type remove(const entity_type entt) { - return (assure<Type>().remove(entt) + ... + assure<Other>().remove(entt)); - } - - /** - * @brief Removes the given elements from all the entities in a range. - * - * @sa remove - * - * @tparam Type Type of element to remove. - * @tparam Other Other types of elements to remove. - * @tparam It Type of input iterator. - * @param first An iterator to the first element of the range of entities. - * @param last An iterator past the last element of the range of entities. - * @return The number of elements actually removed. - */ - template<typename Type, typename... Other, typename It> - size_type remove(It first, It last) { - size_type count{}; - - if constexpr(std::is_same_v<It, typename common_type::iterator>) { - std::array cpools{static_cast<common_type *>(&assure<Type>()), static_cast<common_type *>(&assure<Other>())...}; - - for(auto from = cpools.begin(), to = cpools.end(); from != to; ++from) { - if constexpr(sizeof...(Other) != 0u) { - if((*from)->data() == first.data()) { - std::swap((*from), cpools.back()); - } - } - - count += (*from)->remove(first, last); - } - - } else { - for(auto cpools = std::forward_as_tuple(assure<Type>(), assure<Other>()...); first != last; ++first) { - count += std::apply([entt = *first](auto &...curr) { return (curr.remove(entt) + ... + 0u); }, cpools); - } - } - - return count; - } - - /** - * @brief Erases the given elements from an entity. - * - * @warning - * Attempting to erase an element from an entity that doesn't own it results - * in undefined behavior. - * - * @tparam Type Types of elements to erase. - * @tparam Other Other types of elements to erase. - * @param entt A valid identifier. - */ - template<typename Type, typename... Other> - void erase(const entity_type entt) { - (assure<Type>().erase(entt), (assure<Other>().erase(entt), ...)); - } - - /** - * @brief Erases the given elements from all the entities in a range. - * - * @sa erase - * - * @tparam Type Types of elements to erase. - * @tparam Other Other types of elements to erase. - * @tparam It Type of input iterator. - * @param first An iterator to the first element of the range of entities. - * @param last An iterator past the last element of the range of entities. - */ - template<typename Type, typename... Other, typename It> - void erase(It first, It last) { - if constexpr(std::is_same_v<It, typename common_type::iterator>) { - std::array cpools{static_cast<common_type *>(&assure<Type>()), static_cast<common_type *>(&assure<Other>())...}; - - for(auto from = cpools.begin(), to = cpools.end(); from != to; ++from) { - if constexpr(sizeof...(Other) != 0u) { - if((*from)->data() == first.data()) { - std::swap(*from, cpools.back()); - } - } - - (*from)->erase(first, last); - } - } else { - for(auto cpools = std::forward_as_tuple(assure<Type>(), assure<Other>()...); first != last; ++first) { - std::apply([entt = *first](auto &...curr) { (curr.erase(entt), ...); }, cpools); - } - } - } - - /** - * @brief Erases elements satisfying specific criteria from an entity. - * - * The function type is equivalent to: - * - * @code{.cpp} - * void(const id_type, typename basic_registry<Entity>::common_type &); - * @endcode - * - * Only storage where the entity exists are passed to the function. - * - * @tparam Func Type of the function object to invoke. - * @param entt A valid identifier. - * @param func A valid function object. - */ - template<typename Func> - void erase_if(const entity_type entt, Func func) { - for(auto [id, cpool]: storage()) { - if(cpool.contains(entt) && func(id, std::as_const(cpool))) { - cpool.erase(entt); - } - } - } - - /** - * @brief Removes all tombstones from a registry or only the pools for the - * given elements. - * @tparam Type Types of elements for which to clear all tombstones. - */ - template<typename... Type> - void compact() { - if constexpr(sizeof...(Type) == 0u) { - for(auto &&curr: pools) { - curr.second->compact(); - } - } else { - (assure<Type>().compact(), ...); - } - } - - /** - * @brief Check if an entity is part of all the given storage. - * @tparam Type Type of storage to check for. - * @param entt A valid identifier. - * @return True if the entity is part of all the storage, false otherwise. - */ - template<typename... Type> - [[nodiscard]] bool all_of([[maybe_unused]] const entity_type entt) const { - if constexpr(sizeof...(Type) == 1u) { - auto *cpool = assure<std::remove_const_t<Type>...>(); - return cpool && cpool->contains(entt); - } else { - return (all_of<Type>(entt) && ...); - } - } - - /** - * @brief Check if an entity is part of at least one given storage. - * @tparam Type Type of storage to check for. - * @param entt A valid identifier. - * @return True if the entity is part of at least one storage, false - * otherwise. - */ - template<typename... Type> - [[nodiscard]] bool any_of([[maybe_unused]] const entity_type entt) const { - return (all_of<Type>(entt) || ...); - } - - /** - * @brief Returns references to the given elements for an entity. - * - * @warning - * Attempting to get an element from an entity that doesn't own it results - * in undefined behavior. - * - * @tparam Type Types of elements to get. - * @param entt A valid identifier. - * @return References to the elements owned by the entity. - */ - template<typename... Type> - [[nodiscard]] decltype(auto) get([[maybe_unused]] const entity_type entt) const { - if constexpr(sizeof...(Type) == 1u) { - return (assure<std::remove_const_t<Type>>()->get(entt), ...); - } else { - return std::forward_as_tuple(get<Type>(entt)...); - } - } - - /*! @copydoc get */ - template<typename... Type> - [[nodiscard]] decltype(auto) get([[maybe_unused]] const entity_type entt) { - if constexpr(sizeof...(Type) == 1u) { - return (static_cast<storage_for_type<Type> &>(assure<std::remove_const_t<Type>>()).get(entt), ...); - } else { - return std::forward_as_tuple(get<Type>(entt)...); - } - } - - /** - * @brief Returns a reference to the given element for an entity. - * - * In case the entity doesn't own the element, the parameters provided are - * used to construct it. - * - * @sa get - * @sa emplace - * - * @tparam Type Type of element to get. - * @tparam Args Types of arguments to use to construct the element. - * @param entt A valid identifier. - * @param args Parameters to use to initialize the element. - * @return Reference to the element owned by the entity. - */ - template<typename Type, typename... Args> - [[nodiscard]] decltype(auto) get_or_emplace(const entity_type entt, Args &&...args) { - if(auto &cpool = assure<Type>(); cpool.contains(entt)) { - return cpool.get(entt); - } else { - ENTT_ASSERT(valid(entt), "Invalid entity"); - return cpool.emplace(entt, std::forward<Args>(args)...); - } - } - - /** - * @brief Returns pointers to the given elements for an entity. - * - * @note - * The registry retains ownership of the pointed-to elements. - * - * @tparam Type Types of elements to get. - * @param entt A valid identifier. - * @return Pointers to the elements owned by the entity. - */ - template<typename... Type> - [[nodiscard]] auto try_get([[maybe_unused]] const entity_type entt) const { - if constexpr(sizeof...(Type) == 1u) { - const auto *cpool = assure<std::remove_const_t<Type>...>(); - return (cpool && cpool->contains(entt)) ? std::addressof(cpool->get(entt)) : nullptr; - } else { - return std::make_tuple(try_get<Type>(entt)...); - } - } - - /*! @copydoc try_get */ - template<typename... Type> - [[nodiscard]] auto try_get([[maybe_unused]] const entity_type entt) { - if constexpr(sizeof...(Type) == 1u) { - return (const_cast<Type *>(std::as_const(*this).template try_get<Type>(entt)), ...); - } else { - return std::make_tuple(try_get<Type>(entt)...); - } - } - - /** - * @brief Clears a whole registry or the pools for the given elements. - * @tparam Type Types of elements to remove from their entities. - */ - template<typename... Type> - void clear() { - if constexpr(sizeof...(Type) == 0u) { - for(size_type pos = pools.size(); pos; --pos) { - pools.begin()[pos - 1u].second->clear(); - } - - const auto elem = entities.each(); - entities.erase(elem.begin().base(), elem.end().base()); - } else { - (assure<Type>().clear(), ...); - } - } - - /** - * @brief Checks if an entity has elements assigned. - * @param entt A valid identifier. - * @return True if the entity has no elements assigned, false otherwise. - */ - [[nodiscard]] bool orphan(const entity_type entt) const { - return std::none_of(pools.cbegin(), pools.cend(), [entt](auto &&curr) { return curr.second->contains(entt); }); - } - - /** - * @brief Returns a sink object for the given element. - * - * Use this function to receive notifications whenever a new instance of the - * given element is created and assigned to an entity.<br/> - * The function type for a listener is equivalent to: - * - * @code{.cpp} - * void(basic_registry<Entity> &, Entity); - * @endcode - * - * Listeners are invoked **after** assigning the element to the entity. - * - * @sa sink - * - * @tparam Type Type of element of which to get the sink. - * @param id Optional name used to map the storage within the registry. - * @return A temporary sink object. - */ - template<typename Type> - [[nodiscard]] auto on_construct(const id_type id = type_hash<Type>::value()) { - return assure<Type>(id).on_construct(); - } - - /** - * @brief Returns a sink object for the given element. - * - * Use this function to receive notifications whenever an instance of the - * given element is explicitly updated.<br/> - * The function type for a listener is equivalent to: - * - * @code{.cpp} - * void(basic_registry<Entity> &, Entity); - * @endcode - * - * Listeners are invoked **after** updating the element. - * - * @sa sink - * - * @tparam Type Type of element of which to get the sink. - * @param id Optional name used to map the storage within the registry. - * @return A temporary sink object. - */ - template<typename Type> - [[nodiscard]] auto on_update(const id_type id = type_hash<Type>::value()) { - return assure<Type>(id).on_update(); - } - - /** - * @brief Returns a sink object for the given element. - * - * Use this function to receive notifications whenever an instance of the - * given element is removed from an entity and thus destroyed.<br/> - * The function type for a listener is equivalent to: - * - * @code{.cpp} - * void(basic_registry<Entity> &, Entity); - * @endcode - * - * Listeners are invoked **before** removing the element from the entity. - * - * @sa sink - * - * @tparam Type Type of element of which to get the sink. - * @param id Optional name used to map the storage within the registry. - * @return A temporary sink object. - */ - template<typename Type> - [[nodiscard]] auto on_destroy(const id_type id = type_hash<Type>::value()) { - return assure<Type>(id).on_destroy(); - } - - /** - * @brief Returns a view for the given elements. - * @tparam Type Type of element used to construct the view. - * @tparam Other Other types of elements used to construct the view. - * @tparam Exclude Types of elements used to filter the view. - * @return A newly created view. - */ - template<typename Type, typename... Other, typename... Exclude> - [[nodiscard]] basic_view<get_t<storage_for_type<const Type>, storage_for_type<const Other>...>, exclude_t<storage_for_type<const Exclude>...>> - view(exclude_t<Exclude...> = exclude_t{}) const { - const auto cpools = std::make_tuple(assure<std::remove_const_t<Type>>(), assure<std::remove_const_t<Other>>()..., assure<std::remove_const_t<Exclude>>()...); - basic_view<get_t<storage_for_type<const Type>, storage_for_type<const Other>...>, exclude_t<storage_for_type<const Exclude>...>> elem{}; - std::apply([&elem](const auto *...curr) { ((curr ? elem.storage(*curr) : void()), ...); }, cpools); - return elem; - } - - /*! @copydoc view */ - template<typename Type, typename... Other, typename... Exclude> - [[nodiscard]] basic_view<get_t<storage_for_type<Type>, storage_for_type<Other>...>, exclude_t<storage_for_type<Exclude>...>> - view(exclude_t<Exclude...> = exclude_t{}) { - return {assure<std::remove_const_t<Type>>(), assure<std::remove_const_t<Other>>()..., assure<std::remove_const_t<Exclude>>()...}; - } - - /** - * @brief Returns a group for the given elements. - * @tparam Owned Types of storage _owned_ by the group. - * @tparam Get Types of storage _observed_ by the group, if any. - * @tparam Exclude Types of storage used to filter the group, if any. - * @return A newly created group. - */ - template<typename... Owned, typename... Get, typename... Exclude> - basic_group<owned_t<storage_for_type<Owned>...>, get_t<storage_for_type<Get>...>, exclude_t<storage_for_type<Exclude>...>> - group(get_t<Get...> = get_t{}, exclude_t<Exclude...> = exclude_t{}) { - using group_type = basic_group<owned_t<storage_for_type<Owned>...>, get_t<storage_for_type<Get>...>, exclude_t<storage_for_type<Exclude>...>>; - using handler_type = typename group_type::handler; - - if(auto it = groups.find(group_type::group_id()); it != groups.cend()) { - return {*std::static_pointer_cast<handler_type>(it->second)}; - } - - std::shared_ptr<handler_type> handler{}; - - if constexpr(sizeof...(Owned) == 0u) { - handler = std::allocate_shared<handler_type>(get_allocator(), get_allocator(), std::forward_as_tuple(assure<std::remove_const_t<Get>>()...), std::forward_as_tuple(assure<std::remove_const_t<Exclude>>()...)); - } else { - handler = std::allocate_shared<handler_type>(get_allocator(), std::forward_as_tuple(assure<std::remove_const_t<Owned>>()..., assure<std::remove_const_t<Get>>()...), std::forward_as_tuple(assure<std::remove_const_t<Exclude>>()...)); - ENTT_ASSERT(std::all_of(groups.cbegin(), groups.cend(), [](const auto &data) { return !(data.second->owned(type_id<Owned>().hash()) || ...); }), "Conflicting groups"); - } - - groups.emplace(group_type::group_id(), handler); - return {*handler}; - } - - /*! @copydoc group */ - template<typename... Owned, typename... Get, typename... Exclude> - [[nodiscard]] basic_group<owned_t<storage_for_type<const Owned>...>, get_t<storage_for_type<const Get>...>, exclude_t<storage_for_type<const Exclude>...>> - group_if_exists(get_t<Get...> = get_t{}, exclude_t<Exclude...> = exclude_t{}) const { - using group_type = basic_group<owned_t<storage_for_type<const Owned>...>, get_t<storage_for_type<const Get>...>, exclude_t<storage_for_type<const Exclude>...>>; - using handler_type = typename group_type::handler; - - if(auto it = groups.find(group_type::group_id()); it != groups.cend()) { - return {*std::static_pointer_cast<handler_type>(it->second)}; - } - - return {}; - } - - /** - * @brief Checks whether the given elements belong to any group. - * @tparam Type Types of elements in which one is interested. - * @return True if the pools of the given elements are _free_, false - * otherwise. - */ - template<typename... Type> - [[nodiscard]] bool owned() const { - return std::any_of(groups.cbegin(), groups.cend(), [](auto &&data) { return (data.second->owned(type_id<Type>().hash()) || ...); }); - } - - /** - * @brief Sorts the elements of a given element. - * - * The comparison function object returns `true` if the first element is - * _less_ than the second one, `false` otherwise. Its signature is also - * equivalent to one of the following: - * - * @code{.cpp} - * bool(const Entity, const Entity); - * bool(const Type &, const Type &); - * @endcode - * - * Moreover, it shall induce a _strict weak ordering_ on the values.<br/> - * The sort function object offers an `operator()` that accepts: - * - * * An iterator to the first element of the range to sort. - * * An iterator past the last element of the range to sort. - * * A comparison function object to use to compare the elements. - * - * The comparison function object hasn't necessarily the type of the one - * passed along with the other parameters to this member function. - * - * @warning - * Pools of elements owned by a group cannot be sorted. - * - * @tparam Type Type of elements to sort. - * @tparam Compare Type of comparison function object. - * @tparam Sort Type of sort function object. - * @tparam Args Types of arguments to forward to the sort function object. - * @param compare A valid comparison function object. - * @param algo A valid sort function object. - * @param args Arguments to forward to the sort function object, if any. - */ - template<typename Type, typename Compare, typename Sort = std_sort, typename... Args> - void sort(Compare compare, Sort algo = Sort{}, Args &&...args) { - ENTT_ASSERT(!owned<Type>(), "Cannot sort owned storage"); - auto &cpool = assure<Type>(); - - if constexpr(std::is_invocable_v<Compare, decltype(cpool.get({})), decltype(cpool.get({}))>) { - auto comp = [&cpool, compare = std::move(compare)](const auto lhs, const auto rhs) { return compare(std::as_const(cpool.get(lhs)), std::as_const(cpool.get(rhs))); }; - cpool.sort(std::move(comp), std::move(algo), std::forward<Args>(args)...); - } else { - cpool.sort(std::move(compare), std::move(algo), std::forward<Args>(args)...); - } - } - - /** - * @brief Sorts two pools of elements in the same way. - * - * Entities and elements in `To` which are part of both storage are sorted - * internally with the order they have in `From`. The others follow in no - * particular order. - * - * @warning - * Pools of elements owned by a group cannot be sorted. - * - * @tparam To Type of elements to sort. - * @tparam From Type of elements to use to sort. - */ - template<typename To, typename From> - void sort() { - ENTT_ASSERT(!owned<To>(), "Cannot sort owned storage"); - const base_type &cpool = assure<From>(); - assure<To>().sort_as(cpool.begin(), cpool.end()); - } - - /** - * @brief Returns the context object, that is, a general purpose container. - * @return The context object, that is, a general purpose container. - */ - [[nodiscard]] context &ctx() noexcept { - return vars; - } - - /*! @copydoc ctx */ - [[nodiscard]] const context &ctx() const noexcept { - return vars; - } - -private: - context vars; - pool_container_type pools; - group_container_type groups; - storage_for_type<entity_type> entities; -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/entity/runtime_view.hpp b/deps/entt/include/entt/entity/runtime_view.hpp deleted file mode 100644 index c0dfa01..0000000 --- a/deps/entt/include/entt/entity/runtime_view.hpp +++ /dev/null @@ -1,318 +0,0 @@ -#ifndef ENTT_ENTITY_RUNTIME_VIEW_HPP -#define ENTT_ENTITY_RUNTIME_VIEW_HPP - -#include <algorithm> -#include <cstddef> -#include <iterator> -#include <utility> -#include <vector> -#include "entity.hpp" -#include "fwd.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename Set> -class runtime_view_iterator final { - using iterator_type = typename Set::iterator; - using iterator_traits = std::iterator_traits<iterator_type>; - - [[nodiscard]] bool valid() const { - return (!tombstone_check || *it != tombstone) - && std::all_of(++pools->begin(), pools->end(), [entt = *it](const auto *curr) { return curr->contains(entt); }) - && std::none_of(filter->cbegin(), filter->cend(), [entt = *it](const auto *curr) { return curr && curr->contains(entt); }); - } - -public: - using value_type = typename iterator_traits::value_type; - using pointer = typename iterator_traits::pointer; - using reference = typename iterator_traits::reference; - using difference_type = typename iterator_traits::difference_type; - using iterator_category = std::bidirectional_iterator_tag; - - constexpr runtime_view_iterator() noexcept - : pools{}, - filter{}, - it{}, - tombstone_check{} {} - - // NOLINTNEXTLINE(bugprone-easily-swappable-parameters) - runtime_view_iterator(const std::vector<Set *> &cpools, const std::vector<Set *> &ignore, iterator_type curr) noexcept - : pools{&cpools}, - filter{&ignore}, - it{curr}, - tombstone_check{pools->size() == 1u && (*pools)[0u]->policy() == deletion_policy::in_place} { - if(it != (*pools)[0]->end() && !valid()) { - ++(*this); - } - } - - runtime_view_iterator &operator++() { - ++it; - for(const auto last = (*pools)[0]->end(); it != last && !valid(); ++it) {} - return *this; - } - - runtime_view_iterator operator++(int) { - runtime_view_iterator orig = *this; - return ++(*this), orig; - } - - runtime_view_iterator &operator--() { - --it; - for(const auto first = (*pools)[0]->begin(); it != first && !valid(); --it) {} - return *this; - } - - runtime_view_iterator operator--(int) { - runtime_view_iterator orig = *this; - return operator--(), orig; - } - - [[nodiscard]] pointer operator->() const noexcept { - return it.operator->(); - } - - [[nodiscard]] reference operator*() const noexcept { - return *operator->(); - } - - [[nodiscard]] constexpr bool operator==(const runtime_view_iterator &other) const noexcept { - return it == other.it; - } - - [[nodiscard]] constexpr bool operator!=(const runtime_view_iterator &other) const noexcept { - return !(*this == other); - } - -private: - const std::vector<Set *> *pools; - const std::vector<Set *> *filter; - iterator_type it; - bool tombstone_check; -}; - -} // namespace internal -/*! @endcond */ - -/** - * @brief Generic runtime view. - * - * Runtime views iterate over those entities that are at least in the given - * storage. During initialization, a runtime view looks at the number of - * entities available for each element and uses the smallest set in order to get - * a performance boost when iterating. - * - * @b Important - * - * Iterators aren't invalidated if: - * - * * New elements are added to the storage. - * * The entity currently pointed is modified (for example, elements are added - * or removed from it). - * * The entity currently pointed is destroyed. - * - * In all other cases, modifying the storage iterated by the view in any way - * invalidates all the iterators. - * - * @tparam Type Common base type. - * @tparam Allocator Type of allocator used to manage memory and elements. - */ -template<typename Type, typename Allocator> -class basic_runtime_view { - using alloc_traits = std::allocator_traits<Allocator>; - static_assert(std::is_same_v<typename alloc_traits::value_type, Type *>, "Invalid value type"); - using container_type = std::vector<Type *, Allocator>; - -public: - /*! @brief Allocator type. */ - using allocator_type = Allocator; - /*! @brief Underlying entity identifier. */ - using entity_type = typename Type::entity_type; - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - /*! @brief Common type among all storage types. */ - using common_type = Type; - /*! @brief Bidirectional iterator type. */ - using iterator = internal::runtime_view_iterator<common_type>; - - /*! @brief Default constructor to use to create empty, invalid views. */ - basic_runtime_view() noexcept - : basic_runtime_view{allocator_type{}} {} - - /** - * @brief Constructs an empty, invalid view with a given allocator. - * @param allocator The allocator to use. - */ - explicit basic_runtime_view(const allocator_type &allocator) - : pools{allocator}, - filter{allocator} {} - - /*! @brief Default copy constructor. */ - basic_runtime_view(const basic_runtime_view &) = default; - - /** - * @brief Allocator-extended copy constructor. - * @param other The instance to copy from. - * @param allocator The allocator to use. - */ - basic_runtime_view(const basic_runtime_view &other, const allocator_type &allocator) - : pools{other.pools, allocator}, - filter{other.filter, allocator} {} - - /*! @brief Default move constructor. */ - basic_runtime_view(basic_runtime_view &&) noexcept(std::is_nothrow_move_constructible_v<container_type>) = default; - - /** - * @brief Allocator-extended move constructor. - * @param other The instance to move from. - * @param allocator The allocator to use. - */ - basic_runtime_view(basic_runtime_view &&other, const allocator_type &allocator) - : pools{std::move(other.pools), allocator}, - filter{std::move(other.filter), allocator} {} - - /*! @brief Default destructor. */ - ~basic_runtime_view() noexcept = default; - - /** - * @brief Default copy assignment operator. - * @return This runtime view. - */ - basic_runtime_view &operator=(const basic_runtime_view &) = default; - - /** - * @brief Default move assignment operator. - * @return This runtime view. - */ - basic_runtime_view &operator=(basic_runtime_view &&) noexcept(std::is_nothrow_move_assignable_v<container_type>) = default; - - /** - * @brief Exchanges the contents with those of a given view. - * @param other View to exchange the content with. - */ - void swap(basic_runtime_view &other) { - using std::swap; - swap(pools, other.pools); - swap(filter, other.filter); - } - - /** - * @brief Returns the associated allocator. - * @return The associated allocator. - */ - [[nodiscard]] constexpr allocator_type get_allocator() const noexcept { - return pools.get_allocator(); - } - - /*! @brief Clears the view. */ - void clear() { - pools.clear(); - filter.clear(); - } - - /** - * @brief Appends an opaque storage object to a runtime view. - * @param base An opaque reference to a storage object. - * @return This runtime view. - */ - basic_runtime_view &iterate(common_type &base) { - if(pools.empty() || !(base.size() < pools[0u]->size())) { - pools.push_back(&base); - } else { - pools.push_back(std::exchange(pools[0u], &base)); - } - - return *this; - } - - /** - * @brief Adds an opaque storage object as a filter of a runtime view. - * @param base An opaque reference to a storage object. - * @return This runtime view. - */ - basic_runtime_view &exclude(common_type &base) { - filter.push_back(&base); - return *this; - } - - /** - * @brief Estimates the number of entities iterated by the view. - * @return Estimated number of entities iterated by the view. - */ - [[nodiscard]] size_type size_hint() const { - return pools.empty() ? size_type{} : pools.front()->size(); - } - - /** - * @brief Returns an iterator to the first entity that has the given - * elements. - * - * If the view is empty, the returned iterator will be equal to `end()`. - * - * @return An iterator to the first entity that has the given elements. - */ - [[nodiscard]] iterator begin() const { - return pools.empty() ? iterator{} : iterator{pools, filter, pools[0]->begin()}; - } - - /** - * @brief Returns an iterator that is past the last entity that has the - * given elements. - * @return An iterator to the entity following the last entity that has the - * given elements. - */ - [[nodiscard]] iterator end() const { - return pools.empty() ? iterator{} : iterator{pools, filter, pools[0]->end()}; - } - - /** - * @brief Checks whether a view is initialized or not. - * @return True if the view is initialized, false otherwise. - */ - [[nodiscard]] explicit operator bool() const noexcept { - return !(pools.empty() && filter.empty()); - } - - /** - * @brief Checks if a view contains an entity. - * @param entt A valid identifier. - * @return True if the view contains the given entity, false otherwise. - */ - [[nodiscard]] bool contains(const entity_type entt) const { - return !pools.empty() - && std::all_of(pools.cbegin(), pools.cend(), [entt](const auto *curr) { return curr->contains(entt); }) - && std::none_of(filter.cbegin(), filter.cend(), [entt](const auto *curr) { return curr && curr->contains(entt); }); - } - - /** - * @brief Iterates entities and applies the given function object to them. - * - * The function object is invoked for each entity. It is provided only with - * the entity itself.<br/> - * The signature of the function should be equivalent to the following: - * - * @code{.cpp} - * void(const entity_type); - * @endcode - * - * @tparam Func Type of the function object to invoke. - * @param func A valid function object. - */ - template<typename Func> - void each(Func func) const { - for(const auto entity: *this) { - func(entity); - } - } - -private: - container_type pools; - container_type filter; -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/entity/snapshot.hpp b/deps/entt/include/entt/entity/snapshot.hpp deleted file mode 100644 index 970efba..0000000 --- a/deps/entt/include/entt/entity/snapshot.hpp +++ /dev/null @@ -1,509 +0,0 @@ -#ifndef ENTT_ENTITY_SNAPSHOT_HPP -#define ENTT_ENTITY_SNAPSHOT_HPP - -#include <cstddef> -#include <iterator> -#include <tuple> -#include <type_traits> -#include <utility> -#include <vector> -#include "../config/config.h" -#include "../container/dense_map.hpp" -#include "../core/type_traits.hpp" -#include "entity.hpp" -#include "fwd.hpp" -#include "view.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename Registry> -void orphans(Registry ®istry) { - auto &storage = registry.template storage<typename Registry::entity_type>(); - - for(auto entt: storage) { - if(registry.orphan(entt)) { - storage.erase(entt); - } - } -} - -} // namespace internal -/*! @endcond */ - -/** - * @brief Utility class to create snapshots from a registry. - * - * A _snapshot_ can be either a dump of the entire registry or a narrower - * selection of elements of interest.<br/> - * This type can be used in both cases if provided with a correctly configured - * output archive. - * - * @tparam Registry Basic registry type. - */ -template<typename Registry> -class basic_snapshot { - static_assert(!std::is_const_v<Registry>, "Non-const registry type required"); - using traits_type = entt_traits<typename Registry::entity_type>; - -public: - /*! Basic registry type. */ - using registry_type = Registry; - /*! @brief Underlying entity identifier. */ - using entity_type = typename registry_type::entity_type; - - /** - * @brief Constructs an instance that is bound to a given registry. - * @param source A valid reference to a registry. - */ - basic_snapshot(const registry_type &source) noexcept - : reg{&source} {} - - /*! @brief Default copy constructor, deleted on purpose. */ - basic_snapshot(const basic_snapshot &) = delete; - - /*! @brief Default move constructor. */ - basic_snapshot(basic_snapshot &&) noexcept = default; - - /*! @brief Default destructor. */ - ~basic_snapshot() noexcept = default; - - /** - * @brief Default copy assignment operator, deleted on purpose. - * @return This snapshot. - */ - basic_snapshot &operator=(const basic_snapshot &) = delete; - - /** - * @brief Default move assignment operator. - * @return This snapshot. - */ - basic_snapshot &operator=(basic_snapshot &&) noexcept = default; - - /** - * @brief Serializes all elements of a type with associated identifiers. - * @tparam Type Type of elements to serialize. - * @tparam Archive Type of output archive. - * @param archive A valid reference to an output archive. - * @param id Optional name used to map the storage within the registry. - * @return An object of this type to continue creating the snapshot. - */ - template<typename Type, typename Archive> - const basic_snapshot &get(Archive &archive, const id_type id = type_hash<Type>::value()) const { - if(const auto *storage = reg->template storage<Type>(id); storage) { - const typename registry_type::common_type &base = *storage; - - archive(static_cast<typename traits_type::entity_type>(storage->size())); - - if constexpr(std::is_same_v<Type, entity_type>) { - archive(static_cast<typename traits_type::entity_type>(storage->free_list())); - - for(auto first = base.rbegin(), last = base.rend(); first != last; ++first) { - archive(*first); - } - } else if constexpr(registry_type::template storage_for_type<Type>::storage_policy == deletion_policy::in_place) { - for(auto it = base.rbegin(), last = base.rend(); it != last; ++it) { - if(const auto entt = *it; entt == tombstone) { - archive(static_cast<entity_type>(null)); - } else { - archive(entt); - std::apply([&archive](auto &&...args) { (archive(std::forward<decltype(args)>(args)), ...); }, storage->get_as_tuple(entt)); - } - } - } else { - for(auto elem: storage->reach()) { - std::apply([&archive](auto &&...args) { (archive(std::forward<decltype(args)>(args)), ...); }, elem); - } - } - } else { - archive(typename traits_type::entity_type{}); - } - - return *this; - } - - /** - * @brief Serializes all elements of a type with associated identifiers for - * the entities in a range. - * @tparam Type Type of elements to serialize. - * @tparam Archive Type of output archive. - * @tparam It Type of input iterator. - * @param archive A valid reference to an output archive. - * @param first An iterator to the first element of the range to serialize. - * @param last An iterator past the last element of the range to serialize. - * @param id Optional name used to map the storage within the registry. - * @return An object of this type to continue creating the snapshot. - */ - template<typename Type, typename Archive, typename It> - const basic_snapshot &get(Archive &archive, It first, It last, const id_type id = type_hash<Type>::value()) const { - static_assert(!std::is_same_v<Type, entity_type>, "Entity types not supported"); - - if(const auto *storage = reg->template storage<Type>(id); storage && !storage->empty()) { - archive(static_cast<typename traits_type::entity_type>(std::distance(first, last))); - - for(; first != last; ++first) { - if(const auto entt = *first; storage->contains(entt)) { - archive(entt); - std::apply([&archive](auto &&...args) { (archive(std::forward<decltype(args)>(args)), ...); }, storage->get_as_tuple(entt)); - } else { - archive(static_cast<entity_type>(null)); - } - } - } else { - archive(typename traits_type::entity_type{}); - } - - return *this; - } - -private: - const registry_type *reg; -}; - -/** - * @brief Utility class to restore a snapshot as a whole. - * - * A snapshot loader requires that the destination registry be empty and loads - * all the data at once while keeping intact the identifiers that the entities - * originally had.<br/> - * An example of use is the implementation of a save/restore utility. - * - * @tparam Registry Basic registry type. - */ -template<typename Registry> -class basic_snapshot_loader { - static_assert(!std::is_const_v<Registry>, "Non-const registry type required"); - using traits_type = entt_traits<typename Registry::entity_type>; - -public: - /*! Basic registry type. */ - using registry_type = Registry; - /*! @brief Underlying entity identifier. */ - using entity_type = typename registry_type::entity_type; - - /** - * @brief Constructs an instance that is bound to a given registry. - * @param source A valid reference to a registry. - */ - basic_snapshot_loader(registry_type &source) noexcept - : reg{&source} { - // restoring a snapshot as a whole requires a clean registry - ENTT_ASSERT(reg->template storage<entity_type>().free_list() == 0u, "Registry must be empty"); - } - - /*! @brief Default copy constructor, deleted on purpose. */ - basic_snapshot_loader(const basic_snapshot_loader &) = delete; - - /*! @brief Default move constructor. */ - basic_snapshot_loader(basic_snapshot_loader &&) noexcept = default; - - /*! @brief Default destructor. */ - ~basic_snapshot_loader() noexcept = default; - - /** - * @brief Default copy assignment operator, deleted on purpose. - * @return This loader. - */ - basic_snapshot_loader &operator=(const basic_snapshot_loader &) = delete; - - /** - * @brief Default move assignment operator. - * @return This loader. - */ - basic_snapshot_loader &operator=(basic_snapshot_loader &&) noexcept = default; - - /** - * @brief Restores all elements of a type with associated identifiers. - * @tparam Type Type of elements to restore. - * @tparam Archive Type of input archive. - * @param archive A valid reference to an input archive. - * @param id Optional name used to map the storage within the registry. - * @return A valid loader to continue restoring data. - */ - template<typename Type, typename Archive> - basic_snapshot_loader &get(Archive &archive, const id_type id = type_hash<Type>::value()) { - auto &storage = reg->template storage<Type>(id); - typename traits_type::entity_type length{}; - - archive(length); - - if constexpr(std::is_same_v<Type, entity_type>) { - typename traits_type::entity_type count{}; - - storage.reserve(length); - archive(count); - - for(entity_type entity = null; length; --length) { - archive(entity); - storage.emplace(entity); - } - - storage.free_list(count); - } else { - auto &other = reg->template storage<entity_type>(); - entity_type entt{null}; - - while(length--) { - if(archive(entt); entt != null) { - const auto entity = other.contains(entt) ? entt : other.emplace(entt); - ENTT_ASSERT(entity == entt, "Entity not available for use"); - - if constexpr(std::tuple_size_v<decltype(storage.get_as_tuple({}))> == 0u) { - storage.emplace(entity); - } else { - Type elem{}; - archive(elem); - storage.emplace(entity, std::move(elem)); - } - } - } - } - - return *this; - } - - /** - * @brief Destroys those entities that have no elements. - * - * In case all the entities were serialized but only part of the elements - * was saved, it could happen that some of the entities have no elements - * once restored.<br/> - * This function helps to identify and destroy those entities. - * - * @return A valid loader to continue restoring data. - */ - basic_snapshot_loader &orphans() { - internal::orphans(*reg); - return *this; - } - -private: - registry_type *reg; -}; - -/** - * @brief Utility class for _continuous loading_. - * - * A _continuous loader_ is designed to load data from a source registry to a - * (possibly) non-empty destination. The loader can accommodate in a registry - * more than one snapshot in a sort of _continuous loading_ that updates the - * destination one step at a time.<br/> - * Identifiers that entities originally had are not transferred to the target. - * Instead, the loader maps remote identifiers to local ones while restoring a - * snapshot.<br/> - * An example of use is the implementation of a client-server application with - * the requirement of transferring somehow parts of the representation side to - * side. - * - * @tparam Registry Basic registry type. - */ -template<typename Registry> -class basic_continuous_loader { - static_assert(!std::is_const_v<Registry>, "Non-const registry type required"); - using traits_type = entt_traits<typename Registry::entity_type>; - - void restore(typename Registry::entity_type entt) { - if(const auto entity = to_entity(entt); remloc.contains(entity) && remloc[entity].first == entt) { - if(!reg->valid(remloc[entity].second)) { - remloc[entity].second = reg->create(); - } - } else { - remloc.insert_or_assign(entity, std::make_pair(entt, reg->create())); - } - } - - template<typename Container> - auto update(int, Container &container) -> decltype(typename Container::mapped_type{}, void()) { - // map like container - Container other; - - for(auto &&pair: container) { - using first_type = std::remove_const_t<typename std::decay_t<decltype(pair)>::first_type>; - using second_type = typename std::decay_t<decltype(pair)>::second_type; - - if constexpr(std::is_same_v<first_type, entity_type> && std::is_same_v<second_type, entity_type>) { - other.emplace(map(pair.first), map(pair.second)); - } else if constexpr(std::is_same_v<first_type, entity_type>) { - other.emplace(map(pair.first), std::move(pair.second)); - } else { - static_assert(std::is_same_v<second_type, entity_type>, "Neither the key nor the value are of entity type"); - other.emplace(std::move(pair.first), map(pair.second)); - } - } - - using std::swap; - swap(container, other); - } - - template<typename Container> - auto update(char, Container &container) -> decltype(typename Container::value_type{}, void()) { - // vector like container - static_assert(std::is_same_v<typename Container::value_type, entity_type>, "Invalid value type"); - - for(auto &&entt: container) { - entt = map(entt); - } - } - - template<typename Component, typename Other, typename Member> - void update([[maybe_unused]] Component &instance, [[maybe_unused]] Member Other::*member) { - if constexpr(!std::is_same_v<Component, Other>) { - return; - } else if constexpr(std::is_same_v<Member, entity_type>) { - instance.*member = map(instance.*member); - } else { - // maybe a container? let's try... - update(0, instance.*member); - } - } - -public: - /*! Basic registry type. */ - using registry_type = Registry; - /*! @brief Underlying entity identifier. */ - using entity_type = typename registry_type::entity_type; - - /** - * @brief Constructs an instance that is bound to a given registry. - * @param source A valid reference to a registry. - */ - basic_continuous_loader(registry_type &source) noexcept - : remloc{source.get_allocator()}, - reg{&source} {} - - /*! @brief Default copy constructor, deleted on purpose. */ - basic_continuous_loader(const basic_continuous_loader &) = delete; - - /*! @brief Default move constructor. */ - basic_continuous_loader(basic_continuous_loader &&) noexcept = default; - - /*! @brief Default destructor. */ - ~basic_continuous_loader() noexcept = default; - - /** - * @brief Default copy assignment operator, deleted on purpose. - * @return This loader. - */ - basic_continuous_loader &operator=(const basic_continuous_loader &) = delete; - - /** - * @brief Default move assignment operator. - * @return This loader. - */ - basic_continuous_loader &operator=(basic_continuous_loader &&) noexcept = default; - - /** - * @brief Restores all elements of a type with associated identifiers. - * - * It creates local counterparts for remote elements as needed.<br/> - * Members are either data members of type entity_type or containers of - * entities. In both cases, a loader visits them and replaces entities with - * their local counterpart. - * - * @tparam Type Type of elements to restore. - * @tparam Archive Type of input archive. - * @param archive A valid reference to an input archive. - * @param id Optional name used to map the storage within the registry. - * @return A valid loader to continue restoring data. - */ - template<typename Type, typename Archive> - basic_continuous_loader &get(Archive &archive, const id_type id = type_hash<Type>::value()) { - auto &storage = reg->template storage<Type>(id); - typename traits_type::entity_type length{}; - entity_type entt{null}; - - archive(length); - - if constexpr(std::is_same_v<Type, entity_type>) { - typename traits_type::entity_type in_use{}; - - storage.reserve(length); - archive(in_use); - - for(std::size_t pos{}; pos < in_use; ++pos) { - archive(entt); - restore(entt); - } - - for(std::size_t pos = in_use; pos < length; ++pos) { - archive(entt); - - if(const auto entity = to_entity(entt); remloc.contains(entity)) { - if(reg->valid(remloc[entity].second)) { - reg->destroy(remloc[entity].second); - } - - remloc.erase(entity); - } - } - } else { - for(auto &&ref: remloc) { - storage.remove(ref.second.second); - } - - while(length--) { - if(archive(entt); entt != null) { - restore(entt); - - if constexpr(std::tuple_size_v<decltype(storage.get_as_tuple({}))> == 0u) { - storage.emplace(map(entt)); - } else { - Type elem{}; - archive(elem); - storage.emplace(map(entt), std::move(elem)); - } - } - } - } - - return *this; - } - - /** - * @brief Destroys those entities that have no elements. - * - * In case all the entities were serialized but only part of the elements - * was saved, it could happen that some of the entities have no elements - * once restored.<br/> - * This function helps to identify and destroy those entities. - * - * @return A non-const reference to this loader. - */ - basic_continuous_loader &orphans() { - internal::orphans(*reg); - return *this; - } - - /** - * @brief Tests if a loader knows about a given entity. - * @param entt A valid identifier. - * @return True if `entity` is managed by the loader, false otherwise. - */ - [[nodiscard]] bool contains(entity_type entt) const noexcept { - const auto it = remloc.find(to_entity(entt)); - return it != remloc.cend() && it->second.first == entt; - } - - /** - * @brief Returns the identifier to which an entity refers. - * @param entt A valid identifier. - * @return The local identifier if any, the null entity otherwise. - */ - [[nodiscard]] entity_type map(entity_type entt) const noexcept { - if(const auto it = remloc.find(to_entity(entt)); it != remloc.cend() && it->second.first == entt) { - return it->second.second; - } - - return null; - } - -private: - dense_map<typename traits_type::entity_type, std::pair<entity_type, entity_type>> remloc; - registry_type *reg; -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/entity/sparse_set.hpp b/deps/entt/include/entt/entity/sparse_set.hpp deleted file mode 100644 index b0c251b..0000000 --- a/deps/entt/include/entt/entity/sparse_set.hpp +++ /dev/null @@ -1,1068 +0,0 @@ -#ifndef ENTT_ENTITY_SPARSE_SET_HPP -#define ENTT_ENTITY_SPARSE_SET_HPP - -#include <cstddef> -#include <iterator> -#include <memory> -#include <type_traits> -#include <utility> -#include <vector> -#include "../config/config.h" -#include "../core/algorithm.hpp" -#include "../core/any.hpp" -#include "../core/bit.hpp" -#include "../core/type_info.hpp" -#include "entity.hpp" -#include "fwd.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename Container> -struct sparse_set_iterator final { - using value_type = typename Container::value_type; - using pointer = typename Container::const_pointer; - using reference = typename Container::const_reference; - using difference_type = typename Container::difference_type; - using iterator_category = std::random_access_iterator_tag; - - constexpr sparse_set_iterator() noexcept - : packed{}, - offset{} {} - - constexpr sparse_set_iterator(const Container &ref, const difference_type idx) noexcept - : packed{&ref}, - offset{idx} {} - - constexpr sparse_set_iterator &operator++() noexcept { - return --offset, *this; - } - - constexpr sparse_set_iterator operator++(int) noexcept { - sparse_set_iterator orig = *this; - return ++(*this), orig; - } - - constexpr sparse_set_iterator &operator--() noexcept { - return ++offset, *this; - } - - constexpr sparse_set_iterator operator--(int) noexcept { - sparse_set_iterator orig = *this; - return operator--(), orig; - } - - constexpr sparse_set_iterator &operator+=(const difference_type value) noexcept { - offset -= value; - return *this; - } - - constexpr sparse_set_iterator operator+(const difference_type value) const noexcept { - sparse_set_iterator copy = *this; - return (copy += value); - } - - constexpr sparse_set_iterator &operator-=(const difference_type value) noexcept { - return (*this += -value); - } - - constexpr sparse_set_iterator operator-(const difference_type value) const noexcept { - return (*this + -value); - } - - [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept { - return (*packed)[index() - value]; - } - - [[nodiscard]] constexpr pointer operator->() const noexcept { - return std::addressof(operator[](0)); - } - - [[nodiscard]] constexpr reference operator*() const noexcept { - return operator[](0); - } - - [[nodiscard]] constexpr pointer data() const noexcept { - return packed ? packed->data() : nullptr; - } - - [[nodiscard]] constexpr difference_type index() const noexcept { - return offset - 1; - } - -private: - const Container *packed; - difference_type offset; -}; - -template<typename Container> -[[nodiscard]] constexpr std::ptrdiff_t operator-(const sparse_set_iterator<Container> &lhs, const sparse_set_iterator<Container> &rhs) noexcept { - return rhs.index() - lhs.index(); -} - -template<typename Container> -[[nodiscard]] constexpr bool operator==(const sparse_set_iterator<Container> &lhs, const sparse_set_iterator<Container> &rhs) noexcept { - return lhs.index() == rhs.index(); -} - -template<typename Container> -[[nodiscard]] constexpr bool operator!=(const sparse_set_iterator<Container> &lhs, const sparse_set_iterator<Container> &rhs) noexcept { - return !(lhs == rhs); -} - -template<typename Container> -[[nodiscard]] constexpr bool operator<(const sparse_set_iterator<Container> &lhs, const sparse_set_iterator<Container> &rhs) noexcept { - return lhs.index() > rhs.index(); -} - -template<typename Container> -[[nodiscard]] constexpr bool operator>(const sparse_set_iterator<Container> &lhs, const sparse_set_iterator<Container> &rhs) noexcept { - return rhs < lhs; -} - -template<typename Container> -[[nodiscard]] constexpr bool operator<=(const sparse_set_iterator<Container> &lhs, const sparse_set_iterator<Container> &rhs) noexcept { - return !(lhs > rhs); -} - -template<typename Container> -[[nodiscard]] constexpr bool operator>=(const sparse_set_iterator<Container> &lhs, const sparse_set_iterator<Container> &rhs) noexcept { - return !(lhs < rhs); -} - -} // namespace internal -/*! @endcond */ - -/** - * @brief Sparse set implementation. - * - * Sparse set or packed array or whatever is the name users give it.<br/> - * Two arrays: an _external_ one and an _internal_ one; a _sparse_ one and a - * _packed_ one; one used for direct access through contiguous memory, the other - * one used to get the data through an extra level of indirection.<br/> - * This type of data structure is widely documented in the literature and on the - * web. This is nothing more than a customized implementation suitable for the - * purpose of the framework. - * - * @note - * Internal data structures arrange elements to maximize performance. There are - * no guarantees that entities are returned in the insertion order when iterate - * a sparse set. Do not make assumption on the order in any case. - * - * @tparam Entity A valid entity type. - * @tparam Allocator Type of allocator used to manage memory and elements. - */ -template<typename Entity, typename Allocator> -class basic_sparse_set { - using alloc_traits = std::allocator_traits<Allocator>; - static_assert(std::is_same_v<typename alloc_traits::value_type, Entity>, "Invalid value type"); - using sparse_container_type = std::vector<typename alloc_traits::pointer, typename alloc_traits::template rebind_alloc<typename alloc_traits::pointer>>; - using packed_container_type = std::vector<Entity, Allocator>; - using traits_type = entt_traits<Entity>; - - static constexpr auto max_size = static_cast<std::size_t>(traits_type::to_entity(null)); - - [[nodiscard]] auto policy_to_head() const noexcept { - return static_cast<size_type>(max_size * (mode != deletion_policy::swap_only)); - } - - [[nodiscard]] auto sparse_ptr(const Entity entt) const { - const auto pos = static_cast<size_type>(traits_type::to_entity(entt)); - const auto page = pos / traits_type::page_size; - return (page < sparse.size() && sparse[page]) ? (sparse[page] + fast_mod(pos, traits_type::page_size)) : nullptr; - } - - [[nodiscard]] auto &sparse_ref(const Entity entt) const { - ENTT_ASSERT(sparse_ptr(entt), "Invalid element"); - const auto pos = static_cast<size_type>(traits_type::to_entity(entt)); - return sparse[pos / traits_type::page_size][fast_mod(pos, traits_type::page_size)]; - } - - [[nodiscard]] auto to_iterator(const Entity entt) const { - return --(end() - index(entt)); - } - - [[nodiscard]] auto &assure_at_least(const Entity entt) { - const auto pos = static_cast<size_type>(traits_type::to_entity(entt)); - const auto page = pos / traits_type::page_size; - - if(!(page < sparse.size())) { - sparse.resize(page + 1u, nullptr); - } - - if(!sparse[page]) { - constexpr entity_type init = null; - auto page_allocator{packed.get_allocator()}; - sparse[page] = alloc_traits::allocate(page_allocator, traits_type::page_size); - std::uninitialized_fill(sparse[page], sparse[page] + traits_type::page_size, init); - } - - return sparse[page][fast_mod(pos, traits_type::page_size)]; - } - - void release_sparse_pages() { - auto page_allocator{packed.get_allocator()}; - - for(auto &&page: sparse) { - if(page != nullptr) { - std::destroy(page, page + traits_type::page_size); - alloc_traits::deallocate(page_allocator, page, traits_type::page_size); - page = nullptr; - } - } - } - - void swap_at(const std::size_t lhs, const std::size_t rhs) { - auto &from = packed[lhs]; - auto &to = packed[rhs]; - - sparse_ref(from) = traits_type::combine(static_cast<typename traits_type::entity_type>(rhs), traits_type::to_integral(from)); - sparse_ref(to) = traits_type::combine(static_cast<typename traits_type::entity_type>(lhs), traits_type::to_integral(to)); - - std::swap(from, to); - } - -private: - [[nodiscard]] virtual const void *get_at(const std::size_t) const { - return nullptr; - } - - virtual void swap_or_move([[maybe_unused]] const std::size_t lhs, [[maybe_unused]] const std::size_t rhs) { - ENTT_ASSERT((mode != deletion_policy::swap_only) || ((lhs < head) == (rhs < head)), "Cross swapping is not supported"); - } - -protected: - /*! @brief Random access iterator type. */ - using basic_iterator = internal::sparse_set_iterator<packed_container_type>; - - /** - * @brief Erases an entity from a sparse set. - * @param it An iterator to the element to pop. - */ - void swap_only(const basic_iterator it) { - ENTT_ASSERT(mode == deletion_policy::swap_only, "Deletion policy mismatch"); - const auto pos = index(*it); - bump(traits_type::next(*it)); - swap_at(pos, head -= (pos < head)); - } - - /** - * @brief Erases an entity from a sparse set. - * @param it An iterator to the element to pop. - */ - void swap_and_pop(const basic_iterator it) { - ENTT_ASSERT(mode == deletion_policy::swap_and_pop, "Deletion policy mismatch"); - auto &self = sparse_ref(*it); - const auto entt = traits_type::to_entity(self); - sparse_ref(packed.back()) = traits_type::combine(entt, traits_type::to_integral(packed.back())); - packed[static_cast<size_type>(entt)] = packed.back(); - // unnecessary but it helps to detect nasty bugs - ENTT_ASSERT((packed.back() = null, true), ""); - // lazy self-assignment guard - self = null; - packed.pop_back(); - } - - /** - * @brief Erases an entity from a sparse set. - * @param it An iterator to the element to pop. - */ - void in_place_pop(const basic_iterator it) { - ENTT_ASSERT(mode == deletion_policy::in_place, "Deletion policy mismatch"); - const auto pos = static_cast<size_type>(traits_type::to_entity(std::exchange(sparse_ref(*it), null))); - packed[pos] = traits_type::combine(static_cast<typename traits_type::entity_type>(std::exchange(head, pos)), tombstone); - } - -protected: - /** - * @brief Erases entities from a sparse set. - * @param first An iterator to the first element of the range of entities. - * @param last An iterator past the last element of the range of entities. - */ - virtual void pop(basic_iterator first, basic_iterator last) { - switch(mode) { - case deletion_policy::swap_and_pop: - for(; first != last; ++first) { - swap_and_pop(first); - } - break; - case deletion_policy::in_place: - for(; first != last; ++first) { - in_place_pop(first); - } - break; - case deletion_policy::swap_only: - for(; first != last; ++first) { - swap_only(first); - } - break; - } - } - - /*! @brief Erases all entities of a sparse set. */ - virtual void pop_all() { - switch(mode) { - case deletion_policy::in_place: - if(head != max_size) { - for(auto first = begin(); !(first.index() < 0); ++first) { - if(*first != tombstone) { - sparse_ref(*first) = null; - } - } - break; - } - [[fallthrough]]; - case deletion_policy::swap_only: - case deletion_policy::swap_and_pop: - for(auto first = begin(); !(first.index() < 0); ++first) { - sparse_ref(*first) = null; - } - break; - } - - head = policy_to_head(); - packed.clear(); - } - - /** - * @brief Assigns an entity to a sparse set. - * @param entt A valid identifier. - * @param force_back Force back insertion. - * @return Iterator pointing to the emplaced element. - */ - virtual basic_iterator try_emplace(const Entity entt, const bool force_back, const void * = nullptr) { - ENTT_ASSERT(entt != null && entt != tombstone, "Invalid element"); - auto &elem = assure_at_least(entt); - auto pos = size(); - - switch(mode) { - case deletion_policy::in_place: - if(head != max_size && !force_back) { - pos = head; - ENTT_ASSERT(elem == null, "Slot not available"); - elem = traits_type::combine(static_cast<typename traits_type::entity_type>(head), traits_type::to_integral(entt)); - head = static_cast<size_type>(traits_type::to_entity(std::exchange(packed[pos], entt))); - break; - } - [[fallthrough]]; - case deletion_policy::swap_and_pop: - packed.push_back(entt); - ENTT_ASSERT(elem == null, "Slot not available"); - elem = traits_type::combine(static_cast<typename traits_type::entity_type>(packed.size() - 1u), traits_type::to_integral(entt)); - break; - case deletion_policy::swap_only: - if(elem == null) { - packed.push_back(entt); - elem = traits_type::combine(static_cast<typename traits_type::entity_type>(packed.size() - 1u), traits_type::to_integral(entt)); - } else { - ENTT_ASSERT(!(static_cast<size_type>(traits_type::to_entity(elem)) < head), "Slot not available"); - bump(entt); - } - - pos = head++; - swap_at(static_cast<size_type>(traits_type::to_entity(elem)), pos); - break; - } - - return --(end() - static_cast<typename iterator::difference_type>(pos)); - } - -public: - /*! @brief Allocator type. */ - using allocator_type = Allocator; - /*! @brief Underlying entity identifier. */ - using entity_type = typename traits_type::value_type; - /*! @brief Underlying version type. */ - using version_type = typename traits_type::version_type; - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - /*! @brief Pointer type to contained entities. */ - using pointer = typename packed_container_type::const_pointer; - /*! @brief Random access iterator type. */ - using iterator = basic_iterator; - /*! @brief Constant random access iterator type. */ - using const_iterator = iterator; - /*! @brief Reverse iterator type. */ - using reverse_iterator = std::reverse_iterator<iterator>; - /*! @brief Constant reverse iterator type. */ - using const_reverse_iterator = std::reverse_iterator<const_iterator>; - - /*! @brief Default constructor. */ - basic_sparse_set() - : basic_sparse_set{type_id<void>()} {} - - /** - * @brief Constructs an empty container with a given allocator. - * @param allocator The allocator to use. - */ - explicit basic_sparse_set(const allocator_type &allocator) - : basic_sparse_set{deletion_policy::swap_and_pop, allocator} {} - - /** - * @brief Constructs an empty container with the given policy and allocator. - * @param pol Type of deletion policy. - * @param allocator The allocator to use (possibly default-constructed). - */ - explicit basic_sparse_set(deletion_policy pol, const allocator_type &allocator = {}) - : basic_sparse_set{type_id<void>(), pol, allocator} {} - - /** - * @brief Constructs an empty container with the given value type, policy - * and allocator. - * @param elem Returned value type, if any. - * @param pol Type of deletion policy. - * @param allocator The allocator to use (possibly default-constructed). - */ - explicit basic_sparse_set(const type_info &elem, deletion_policy pol = deletion_policy::swap_and_pop, const allocator_type &allocator = {}) - : sparse{allocator}, - packed{allocator}, - info{&elem}, - mode{pol}, - head{policy_to_head()} { - ENTT_ASSERT(traits_type::version_mask || mode != deletion_policy::in_place, "Policy does not support zero-sized versions"); - } - - /*! @brief Default copy constructor, deleted on purpose. */ - basic_sparse_set(const basic_sparse_set &) = delete; - - /** - * @brief Move constructor. - * @param other The instance to move from. - */ - basic_sparse_set(basic_sparse_set &&other) noexcept - : sparse{std::move(other.sparse)}, - packed{std::move(other.packed)}, - info{other.info}, - mode{other.mode}, - head{std::exchange(other.head, policy_to_head())} {} - - /** - * @brief Allocator-extended move constructor. - * @param other The instance to move from. - * @param allocator The allocator to use. - */ - basic_sparse_set(basic_sparse_set &&other, const allocator_type &allocator) - : sparse{std::move(other.sparse), allocator}, - packed{std::move(other.packed), allocator}, - info{other.info}, - mode{other.mode}, - head{std::exchange(other.head, policy_to_head())} { - ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a sparse set is not allowed"); - } - - /*! @brief Default destructor. */ - virtual ~basic_sparse_set() noexcept { - release_sparse_pages(); - } - - /** - * @brief Default copy assignment operator, deleted on purpose. - * @return This sparse set. - */ - basic_sparse_set &operator=(const basic_sparse_set &) = delete; - - /** - * @brief Move assignment operator. - * @param other The instance to move from. - * @return This sparse set. - */ - basic_sparse_set &operator=(basic_sparse_set &&other) noexcept { - ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a sparse set is not allowed"); - - release_sparse_pages(); - sparse = std::move(other.sparse); - packed = std::move(other.packed); - info = other.info; - mode = other.mode; - head = std::exchange(other.head, policy_to_head()); - return *this; - } - - /** - * @brief Exchanges the contents with those of a given sparse set. - * @param other Sparse set to exchange the content with. - */ - void swap(basic_sparse_set &other) { - using std::swap; - swap(sparse, other.sparse); - swap(packed, other.packed); - swap(info, other.info); - swap(mode, other.mode); - swap(head, other.head); - } - - /** - * @brief Returns the associated allocator. - * @return The associated allocator. - */ - [[nodiscard]] constexpr allocator_type get_allocator() const noexcept { - return packed.get_allocator(); - } - - /** - * @brief Returns the deletion policy of a sparse set. - * @return The deletion policy of the sparse set. - */ - [[nodiscard]] deletion_policy policy() const noexcept { - return mode; - } - - /** - * @brief Returns data on the free list whose meaning depends on the mode. - * @return Free list information that is mode dependent. - */ - [[nodiscard]] size_type free_list() const noexcept { - return head; - } - - /** - * @brief Sets data on the free list whose meaning depends on the mode. - * @param value Free list information that is mode dependent. - */ - void free_list(const size_type value) noexcept { - ENTT_ASSERT((mode == deletion_policy::swap_only) && !(value > packed.size()), "Invalid value"); - head = value; - } - - /** - * @brief Increases the capacity of a sparse set. - * - * If the new capacity is greater than the current capacity, new storage is - * allocated, otherwise the method does nothing. - * - * @param cap Desired capacity. - */ - virtual void reserve(const size_type cap) { - packed.reserve(cap); - } - - /** - * @brief Returns the number of elements that a sparse set has currently - * allocated space for. - * @return Capacity of the sparse set. - */ - [[nodiscard]] virtual size_type capacity() const noexcept { - return packed.capacity(); - } - - /*! @brief Requests the removal of unused capacity. */ - virtual void shrink_to_fit() { - packed.shrink_to_fit(); - } - - /** - * @brief Returns the extent of a sparse set. - * - * The extent of a sparse set is also the size of the internal sparse array. - * There is no guarantee that the internal packed array has the same size. - * Usually the size of the internal sparse array is equal or greater than - * the one of the internal packed array. - * - * @return Extent of the sparse set. - */ - [[nodiscard]] size_type extent() const noexcept { - return sparse.size() * traits_type::page_size; - } - - /** - * @brief Returns the number of elements in a sparse set. - * - * The number of elements is also the size of the internal packed array. - * There is no guarantee that the internal sparse array has the same size. - * Usually the size of the internal sparse array is equal or greater than - * the one of the internal packed array. - * - * @return Number of elements. - */ - [[nodiscard]] size_type size() const noexcept { - return packed.size(); - } - - /** - * @brief Checks whether a sparse set is empty. - * @return True if the sparse set is empty, false otherwise. - */ - [[nodiscard]] bool empty() const noexcept { - return packed.empty(); - } - - /** - * @brief Checks whether a sparse set is fully packed. - * @return True if the sparse set is fully packed, false otherwise. - */ - [[nodiscard]] bool contiguous() const noexcept { - return (mode != deletion_policy::in_place) || (head == max_size); - } - - /** - * @brief Direct access to the internal packed array. - * @return A pointer to the internal packed array. - */ - [[nodiscard]] pointer data() const noexcept { - return packed.data(); - } - - /** - * @brief Returns an iterator to the beginning. - * - * If the sparse set is empty, the returned iterator will be equal to - * `end()`. - * - * @return An iterator to the first entity of the sparse set. - */ - [[nodiscard]] iterator begin() const noexcept { - const auto pos = static_cast<typename iterator::difference_type>(packed.size()); - return iterator{packed, pos}; - } - - /*! @copydoc begin */ - [[nodiscard]] const_iterator cbegin() const noexcept { - return begin(); - } - - /** - * @brief Returns an iterator to the end. - * @return An iterator to the element following the last entity of a sparse - * set. - */ - [[nodiscard]] iterator end() const noexcept { - return iterator{packed, {}}; - } - - /*! @copydoc end */ - [[nodiscard]] const_iterator cend() const noexcept { - return end(); - } - - /** - * @brief Returns a reverse iterator to the beginning. - * - * If the sparse set is empty, the returned iterator will be equal to - * `rend()`. - * - * @return An iterator to the first entity of the reversed internal packed - * array. - */ - [[nodiscard]] reverse_iterator rbegin() const noexcept { - return std::make_reverse_iterator(end()); - } - - /*! @copydoc rbegin */ - [[nodiscard]] const_reverse_iterator crbegin() const noexcept { - return rbegin(); - } - - /** - * @brief Returns a reverse iterator to the end. - * @return An iterator to the element following the last entity of the - * reversed sparse set. - */ - [[nodiscard]] reverse_iterator rend() const noexcept { - return std::make_reverse_iterator(begin()); - } - - /*! @copydoc rend */ - [[nodiscard]] const_reverse_iterator crend() const noexcept { - return rend(); - } - - /** - * @brief Finds an entity. - * @param entt A valid identifier. - * @return An iterator to the given entity if it's found, past the end - * iterator otherwise. - */ - [[nodiscard]] const_iterator find(const entity_type entt) const noexcept { - return contains(entt) ? to_iterator(entt) : end(); - } - - /** - * @brief Checks if a sparse set contains an entity. - * @param entt A valid identifier. - * @return True if the sparse set contains the entity, false otherwise. - */ - [[nodiscard]] bool contains(const entity_type entt) const noexcept { - const auto elem = sparse_ptr(entt); - constexpr auto cap = traits_type::entity_mask; - constexpr auto mask = traits_type::to_integral(null) & ~cap; - // testing versions permits to avoid accessing the packed array - return elem && (((mask & traits_type::to_integral(entt)) ^ traits_type::to_integral(*elem)) < cap); - } - - /** - * @brief Returns the contained version for an identifier. - * @param entt A valid identifier. - * @return The version for the given identifier if present, the tombstone - * version otherwise. - */ - [[nodiscard]] version_type current(const entity_type entt) const noexcept { - const auto elem = sparse_ptr(entt); - constexpr auto fallback = traits_type::to_version(tombstone); - return elem ? traits_type::to_version(*elem) : fallback; - } - - /** - * @brief Returns the position of an entity in a sparse set. - * - * @warning - * Attempting to get the position of an entity that doesn't belong to the - * sparse set results in undefined behavior. - * - * @param entt A valid identifier. - * @return The position of the entity in the sparse set. - */ - [[nodiscard]] size_type index(const entity_type entt) const noexcept { - ENTT_ASSERT(contains(entt), "Set does not contain entity"); - return static_cast<size_type>(traits_type::to_entity(sparse_ref(entt))); - } - - /** - * @brief Returns the entity at specified location. - * @param pos The position for which to return the entity. - * @return The entity at specified location. - */ - [[nodiscard]] entity_type operator[](const size_type pos) const noexcept { - ENTT_ASSERT(pos < packed.size(), "Index out of bounds"); - return packed[pos]; - } - - /** - * @brief Returns the element assigned to an entity, if any. - * - * @warning - * Attempting to use an entity that doesn't belong to the sparse set results - * in undefined behavior. - * - * @param entt A valid identifier. - * @return An opaque pointer to the element assigned to the entity, if any. - */ - [[nodiscard]] const void *value(const entity_type entt) const noexcept { - return get_at(index(entt)); - } - - /*! @copydoc value */ - [[nodiscard]] void *value(const entity_type entt) noexcept { - return const_cast<void *>(std::as_const(*this).value(entt)); - } - - /** - * @brief Assigns an entity to a sparse set. - * - * @warning - * Attempting to assign an entity that already belongs to the sparse set - * results in undefined behavior. - * - * @param entt A valid identifier. - * @param elem Optional opaque element to forward to mixins, if any. - * @return Iterator pointing to the emplaced element in case of success, the - * `end()` iterator otherwise. - */ - iterator push(const entity_type entt, const void *elem = nullptr) { - return try_emplace(entt, false, elem); - } - - /** - * @brief Assigns one or more entities to a sparse set. - * - * @warning - * Attempting to assign an entity that already belongs to the sparse set - * results in undefined behavior. - * - * @tparam It Type of input iterator. - * @param first An iterator to the first element of the range of entities. - * @param last An iterator past the last element of the range of entities. - * @return Iterator pointing to the first element inserted in case of - * success, the `end()` iterator otherwise. - */ - template<typename It> - iterator push(It first, It last) { - auto curr = end(); - - for(; first != last; ++first) { - curr = try_emplace(*first, true); - } - - return curr; - } - - /** - * @brief Bump the version number of an entity. - * - * @warning - * Attempting to bump the version of an entity that doesn't belong to the - * sparse set results in undefined behavior. - * - * @param entt A valid identifier. - * @return The version of the given identifier. - */ - version_type bump(const entity_type entt) { - auto &elem = sparse_ref(entt); - ENTT_ASSERT(entt != null && elem != tombstone, "Cannot set the required version"); - elem = traits_type::combine(traits_type::to_integral(elem), traits_type::to_integral(entt)); - packed[static_cast<size_type>(traits_type::to_entity(elem))] = entt; - return traits_type::to_version(entt); - } - - /** - * @brief Erases an entity from a sparse set. - * - * @warning - * Attempting to erase an entity that doesn't belong to the sparse set - * results in undefined behavior. - * - * @param entt A valid identifier. - */ - void erase(const entity_type entt) { - const auto it = to_iterator(entt); - pop(it, it + 1u); - } - - /** - * @brief Erases entities from a set. - * - * @sa erase - * - * @tparam It Type of input iterator. - * @param first An iterator to the first element of the range of entities. - * @param last An iterator past the last element of the range of entities. - */ - template<typename It> - void erase(It first, It last) { - if constexpr(std::is_same_v<It, basic_iterator>) { - pop(first, last); - } else { - for(; first != last; ++first) { - erase(*first); - } - } - } - - /** - * @brief Removes an entity from a sparse set if it exists. - * @param entt A valid identifier. - * @return True if the entity is actually removed, false otherwise. - */ - bool remove(const entity_type entt) { - return contains(entt) && (erase(entt), true); - } - - /** - * @brief Removes entities from a sparse set if they exist. - * @tparam It Type of input iterator. - * @param first An iterator to the first element of the range of entities. - * @param last An iterator past the last element of the range of entities. - * @return The number of entities actually removed. - */ - template<typename It> - size_type remove(It first, It last) { - size_type count{}; - - if constexpr(std::is_same_v<It, basic_iterator>) { - while(first != last) { - while(first != last && !contains(*first)) { - ++first; - } - - const auto it = first; - - while(first != last && contains(*first)) { - ++first; - } - - count += std::distance(it, first); - erase(it, first); - } - } else { - for(; first != last; ++first) { - count += remove(*first); - } - } - - return count; - } - - /*! @brief Removes all tombstones from a sparse set. */ - void compact() { - if(mode == deletion_policy::in_place) { - size_type from = packed.size(); - size_type pos = std::exchange(head, max_size); - - for(; from && packed[from - 1u] == tombstone; --from) {} - - while(pos != max_size) { - if(const auto to = std::exchange(pos, static_cast<size_type>(traits_type::to_entity(packed[pos]))); to < from) { - --from; - swap_or_move(from, to); - - packed[to] = packed[from]; - const auto elem = static_cast<typename traits_type::entity_type>(to); - sparse_ref(packed[to]) = traits_type::combine(elem, traits_type::to_integral(packed[to])); - - for(; from && packed[from - 1u] == tombstone; --from) {} - } - } - - packed.erase(packed.begin() + from, packed.end()); - } - } - - /** - * @brief Swaps two entities in a sparse set. - * - * For what it's worth, this function affects both the internal sparse array - * and the internal packed array. Users should not care of that anyway. - * - * @warning - * Attempting to swap entities that don't belong to the sparse set results - * in undefined behavior. - * - * @param lhs A valid identifier. - * @param rhs A valid identifier. - */ - void swap_elements(const entity_type lhs, const entity_type rhs) { - const auto from = index(lhs); - const auto to = index(rhs); - - // basic no-leak guarantee if swapping throws - swap_or_move(from, to); - swap_at(from, to); - } - - /** - * @brief Sort the first count elements according to the given comparison - * function. - * - * The comparison function object must return `true` if the first element - * is _less_ than the second one, `false` otherwise. The signature of the - * comparison function should be equivalent to the following: - * - * @code{.cpp} - * bool(const Entity, const Entity); - * @endcode - * - * Moreover, the comparison function object shall induce a - * _strict weak ordering_ on the values. - * - * The sort function object must offer a member function template - * `operator()` that accepts three arguments: - * - * * An iterator to the first element of the range to sort. - * * An iterator past the last element of the range to sort. - * * A comparison function to use to compare the elements. - * - * @tparam Compare Type of comparison function object. - * @tparam Sort Type of sort function object. - * @tparam Args Types of arguments to forward to the sort function object. - * @param length Number of elements to sort. - * @param compare A valid comparison function object. - * @param algo A valid sort function object. - * @param args Arguments to forward to the sort function object, if any. - */ - template<typename Compare, typename Sort = std_sort, typename... Args> - void sort_n(const size_type length, Compare compare, Sort algo = Sort{}, Args &&...args) { - ENTT_ASSERT((mode != deletion_policy::in_place) || (head == max_size), "Sorting with tombstones not allowed"); - ENTT_ASSERT(!(length > packed.size()), "Length exceeds the number of elements"); - - algo(packed.rend() - length, packed.rend(), std::move(compare), std::forward<Args>(args)...); - - for(size_type pos{}; pos < length; ++pos) { - auto curr = pos; - auto next = index(packed[curr]); - - while(curr != next) { - const auto idx = index(packed[next]); - const auto entt = packed[curr]; - - swap_or_move(next, idx); - const auto elem = static_cast<typename traits_type::entity_type>(curr); - sparse_ref(entt) = traits_type::combine(elem, traits_type::to_integral(packed[curr])); - curr = std::exchange(next, idx); - } - } - } - - /** - * @brief Sort all elements according to the given comparison function. - * - * @sa sort_n - * - * @tparam Compare Type of comparison function object. - * @tparam Sort Type of sort function object. - * @tparam Args Types of arguments to forward to the sort function object. - * @param compare A valid comparison function object. - * @param algo A valid sort function object. - * @param args Arguments to forward to the sort function object, if any. - */ - template<typename Compare, typename Sort = std_sort, typename... Args> - void sort(Compare compare, Sort algo = Sort{}, Args &&...args) { - const size_type len = (mode == deletion_policy::swap_only) ? head : packed.size(); - sort_n(len, std::move(compare), std::move(algo), std::forward<Args>(args)...); - } - - /** - * @brief Sort entities according to their order in a range. - * - * Entities that are part of both the sparse set and the range are ordered - * internally according to the order they have in the range.<br/> - * All other entities goes to the end of the sparse set and there are no - * guarantees on their order. - * - * @tparam It Type of input iterator. - * @param first An iterator to the first element of the range of entities. - * @param last An iterator past the last element of the range of entities. - * @return An iterator past the last of the elements actually shared. - */ - template<typename It> - iterator sort_as(It first, It last) { - ENTT_ASSERT((mode != deletion_policy::in_place) || (head == max_size), "Sorting with tombstones not allowed"); - const size_type len = (mode == deletion_policy::swap_only) ? head : packed.size(); - auto it = end() - static_cast<typename iterator::difference_type>(len); - - for(const auto other = end(); (it != other) && (first != last); ++first) { - if(const auto curr = *first; contains(curr)) { - if(const auto entt = *it; entt != curr) { - // basic no-leak guarantee (with invalid state) if swapping throws - swap_elements(entt, curr); - } - - ++it; - } - } - - return it; - } - - /*! @brief Clears a sparse set. */ - void clear() { - pop_all(); - // sanity check to avoid subtle issues due to storage classes - ENTT_ASSERT((compact(), size()) == 0u, "Non-empty set"); - head = policy_to_head(); - packed.clear(); - } - - /** - * @brief Returned value type, if any. - * @return Returned value type, if any. - */ - [[nodiscard]] const type_info &type() const noexcept { - return *info; - } - - /*! @brief Forwards variables to derived classes, if any. */ - // NOLINTNEXTLINE(performance-unnecessary-value-param) - virtual void bind(any) noexcept {} - -private: - sparse_container_type sparse; - packed_container_type packed; - const type_info *info; - deletion_policy mode; - size_type head; -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/entity/storage.hpp b/deps/entt/include/entt/entity/storage.hpp deleted file mode 100644 index 6c1c570..0000000 --- a/deps/entt/include/entt/entity/storage.hpp +++ /dev/null @@ -1,1205 +0,0 @@ -#ifndef ENTT_ENTITY_STORAGE_HPP -#define ENTT_ENTITY_STORAGE_HPP - -#include <cstddef> -#include <iterator> -#include <memory> -#include <tuple> -#include <type_traits> -#include <utility> -#include <vector> -#include "../config/config.h" -#include "../core/bit.hpp" -#include "../core/iterator.hpp" -#include "../core/memory.hpp" -#include "../core/type_info.hpp" -#include "component.hpp" -#include "entity.hpp" -#include "fwd.hpp" -#include "sparse_set.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename Container> -class storage_iterator final { - friend storage_iterator<const Container>; - - using container_type = std::remove_const_t<Container>; - using alloc_traits = std::allocator_traits<typename container_type::allocator_type>; - - using iterator_traits = std::iterator_traits<std::conditional_t< - std::is_const_v<Container>, - typename alloc_traits::template rebind_traits<typename std::pointer_traits<typename container_type::value_type>::element_type>::const_pointer, - typename alloc_traits::template rebind_traits<typename std::pointer_traits<typename container_type::value_type>::element_type>::pointer>>; - -public: - using value_type = typename iterator_traits::value_type; - using pointer = typename iterator_traits::pointer; - using reference = typename iterator_traits::reference; - using difference_type = typename iterator_traits::difference_type; - using iterator_category = std::random_access_iterator_tag; - - constexpr storage_iterator() noexcept = default; - - constexpr storage_iterator(Container *ref, const difference_type idx) noexcept - : payload{ref}, - offset{idx} {} - - template<bool Const = std::is_const_v<Container>, typename = std::enable_if_t<Const>> - constexpr storage_iterator(const storage_iterator<std::remove_const_t<Container>> &other) noexcept - : storage_iterator{other.payload, other.offset} {} - - constexpr storage_iterator &operator++() noexcept { - return --offset, *this; - } - - constexpr storage_iterator operator++(int) noexcept { - storage_iterator orig = *this; - return ++(*this), orig; - } - - constexpr storage_iterator &operator--() noexcept { - return ++offset, *this; - } - - constexpr storage_iterator operator--(int) noexcept { - storage_iterator orig = *this; - return operator--(), orig; - } - - constexpr storage_iterator &operator+=(const difference_type value) noexcept { - offset -= value; - return *this; - } - - constexpr storage_iterator operator+(const difference_type value) const noexcept { - storage_iterator copy = *this; - return (copy += value); - } - - constexpr storage_iterator &operator-=(const difference_type value) noexcept { - return (*this += -value); - } - - constexpr storage_iterator operator-(const difference_type value) const noexcept { - return (*this + -value); - } - - [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept { - const auto pos = index() - value; - constexpr auto page_size = component_traits<value_type>::page_size; - return (*payload)[pos / page_size][fast_mod(static_cast<std::size_t>(pos), page_size)]; - } - - [[nodiscard]] constexpr pointer operator->() const noexcept { - return std::addressof(operator[](0)); - } - - [[nodiscard]] constexpr reference operator*() const noexcept { - return operator[](0); - } - - [[nodiscard]] constexpr difference_type index() const noexcept { - return offset - 1; - } - -private: - Container *payload; - difference_type offset; -}; - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr std::ptrdiff_t operator-(const storage_iterator<Lhs> &lhs, const storage_iterator<Rhs> &rhs) noexcept { - return rhs.index() - lhs.index(); -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator==(const storage_iterator<Lhs> &lhs, const storage_iterator<Rhs> &rhs) noexcept { - return lhs.index() == rhs.index(); -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator!=(const storage_iterator<Lhs> &lhs, const storage_iterator<Rhs> &rhs) noexcept { - return !(lhs == rhs); -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator<(const storage_iterator<Lhs> &lhs, const storage_iterator<Rhs> &rhs) noexcept { - return lhs.index() > rhs.index(); -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator>(const storage_iterator<Lhs> &lhs, const storage_iterator<Rhs> &rhs) noexcept { - return rhs < lhs; -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator<=(const storage_iterator<Lhs> &lhs, const storage_iterator<Rhs> &rhs) noexcept { - return !(lhs > rhs); -} - -template<typename Lhs, typename Rhs> -[[nodiscard]] constexpr bool operator>=(const storage_iterator<Lhs> &lhs, const storage_iterator<Rhs> &rhs) noexcept { - return !(lhs < rhs); -} - -template<typename It, typename... Other> -class extended_storage_iterator final { - template<typename Iter, typename... Args> - friend class extended_storage_iterator; - -public: - using iterator_type = It; - using value_type = decltype(std::tuple_cat(std::make_tuple(*std::declval<It>()), std::forward_as_tuple(*std::declval<Other>()...))); - using pointer = input_iterator_pointer<value_type>; - using reference = value_type; - using difference_type = std::ptrdiff_t; - using iterator_category = std::input_iterator_tag; - using iterator_concept = std::forward_iterator_tag; - - constexpr extended_storage_iterator() - : it{} {} - - constexpr extended_storage_iterator(iterator_type base, Other... other) - : it{base, other...} {} - - template<typename... Args, typename = std::enable_if_t<(!std::is_same_v<Other, Args> && ...) && (std::is_constructible_v<Other, Args> && ...)>> - constexpr extended_storage_iterator(const extended_storage_iterator<It, Args...> &other) - : it{other.it} {} - - constexpr extended_storage_iterator &operator++() noexcept { - return ++std::get<It>(it), (++std::get<Other>(it), ...), *this; - } - - constexpr extended_storage_iterator operator++(int) noexcept { - extended_storage_iterator orig = *this; - return ++(*this), orig; - } - - [[nodiscard]] constexpr pointer operator->() const noexcept { - return operator*(); - } - - [[nodiscard]] constexpr reference operator*() const noexcept { - return {*std::get<It>(it), *std::get<Other>(it)...}; - } - - [[nodiscard]] constexpr iterator_type base() const noexcept { - return std::get<It>(it); - } - - template<typename... Lhs, typename... Rhs> - friend constexpr bool operator==(const extended_storage_iterator<Lhs...> &, const extended_storage_iterator<Rhs...> &) noexcept; - -private: - std::tuple<It, Other...> it; -}; - -template<typename... Lhs, typename... Rhs> -[[nodiscard]] constexpr bool operator==(const extended_storage_iterator<Lhs...> &lhs, const extended_storage_iterator<Rhs...> &rhs) noexcept { - return std::get<0>(lhs.it) == std::get<0>(rhs.it); -} - -template<typename... Lhs, typename... Rhs> -[[nodiscard]] constexpr bool operator!=(const extended_storage_iterator<Lhs...> &lhs, const extended_storage_iterator<Rhs...> &rhs) noexcept { - return !(lhs == rhs); -} - -} // namespace internal -/*! @endcond */ - -/** - * @brief Storage implementation. - * - * Internal data structures arrange elements to maximize performance. There are - * no guarantees that objects are returned in the insertion order when iterate - * a storage. Do not make assumption on the order in any case. - * - * @warning - * Empty types aren't explicitly instantiated. Therefore, many of the functions - * normally available for non-empty types will not be available for empty ones. - * - * @tparam Type Element type. - * @tparam Entity A valid entity type. - * @tparam Allocator Type of allocator used to manage memory and elements. - */ -template<typename Type, typename Entity, typename Allocator, typename> -class basic_storage: public basic_sparse_set<Entity, typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>> { - using alloc_traits = std::allocator_traits<Allocator>; - static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type"); - using container_type = std::vector<typename alloc_traits::pointer, typename alloc_traits::template rebind_alloc<typename alloc_traits::pointer>>; - using underlying_type = basic_sparse_set<Entity, typename alloc_traits::template rebind_alloc<Entity>>; - using underlying_iterator = typename underlying_type::basic_iterator; - using traits_type = component_traits<Type>; - - [[nodiscard]] auto &element_at(const std::size_t pos) const { - return payload[pos / traits_type::page_size][fast_mod(pos, traits_type::page_size)]; - } - - auto assure_at_least(const std::size_t pos) { - const auto idx = pos / traits_type::page_size; - - if(!(idx < payload.size())) { - auto curr = payload.size(); - allocator_type allocator{get_allocator()}; - payload.resize(idx + 1u, nullptr); - - ENTT_TRY { - for(const auto last = payload.size(); curr < last; ++curr) { - payload[curr] = alloc_traits::allocate(allocator, traits_type::page_size); - } - } - ENTT_CATCH { - payload.resize(curr); - ENTT_THROW; - } - } - - return payload[idx] + fast_mod(pos, traits_type::page_size); - } - - template<typename... Args> - auto emplace_element(const Entity entt, const bool force_back, Args &&...args) { - const auto it = base_type::try_emplace(entt, force_back); - - ENTT_TRY { - auto elem = assure_at_least(static_cast<size_type>(it.index())); - entt::uninitialized_construct_using_allocator(to_address(elem), get_allocator(), std::forward<Args>(args)...); - } - ENTT_CATCH { - base_type::pop(it, it + 1u); - ENTT_THROW; - } - - return it; - } - - void shrink_to_size(const std::size_t sz) { - const auto from = (sz + traits_type::page_size - 1u) / traits_type::page_size; - allocator_type allocator{get_allocator()}; - - for(auto pos = sz, length = base_type::size(); pos < length; ++pos) { - if constexpr(traits_type::in_place_delete) { - if(base_type::data()[pos] != tombstone) { - alloc_traits::destroy(allocator, std::addressof(element_at(pos))); - } - } else { - alloc_traits::destroy(allocator, std::addressof(element_at(pos))); - } - } - - for(auto pos = from, last = payload.size(); pos < last; ++pos) { - alloc_traits::deallocate(allocator, payload[pos], traits_type::page_size); - } - - payload.resize(from); - } - -private: - [[nodiscard]] const void *get_at(const std::size_t pos) const final { - return std::addressof(element_at(pos)); - } - - void swap_or_move([[maybe_unused]] const std::size_t from, [[maybe_unused]] const std::size_t to) override { - static constexpr bool is_pinned_type_v = !(std::is_move_constructible_v<Type> && std::is_move_assignable_v<Type>); - // use a runtime value to avoid compile-time suppression that drives the code coverage tool crazy - ENTT_ASSERT((from + 1u) && !is_pinned_type_v, "Pinned type"); - - if constexpr(!is_pinned_type_v) { - auto &elem = element_at(from); - - if constexpr(traits_type::in_place_delete) { - if(base_type::operator[](to) == tombstone) { - allocator_type allocator{get_allocator()}; - entt::uninitialized_construct_using_allocator(to_address(assure_at_least(to)), allocator, std::move(elem)); - alloc_traits::destroy(allocator, std::addressof(elem)); - return; - } - } - - using std::swap; - swap(elem, element_at(to)); - } - } - -protected: - /** - * @brief Erases entities from a storage. - * @param first An iterator to the first element of the range of entities. - * @param last An iterator past the last element of the range of entities. - */ - void pop(underlying_iterator first, underlying_iterator last) override { - for(allocator_type allocator{get_allocator()}; first != last; ++first) { - // cannot use first.index() because it would break with cross iterators - auto &elem = element_at(base_type::index(*first)); - - if constexpr(traits_type::in_place_delete) { - base_type::in_place_pop(first); - alloc_traits::destroy(allocator, std::addressof(elem)); - } else { - auto &other = element_at(base_type::size() - 1u); - // destroying on exit allows reentrant destructors - [[maybe_unused]] auto unused = std::exchange(elem, std::move(other)); - alloc_traits::destroy(allocator, std::addressof(other)); - base_type::swap_and_pop(first); - } - } - } - - /*! @brief Erases all entities of a storage. */ - void pop_all() override { - allocator_type allocator{get_allocator()}; - - for(auto first = base_type::begin(); !(first.index() < 0); ++first) { - if constexpr(traits_type::in_place_delete) { - if(*first != tombstone) { - base_type::in_place_pop(first); - alloc_traits::destroy(allocator, std::addressof(element_at(static_cast<size_type>(first.index())))); - } - } else { - base_type::swap_and_pop(first); - alloc_traits::destroy(allocator, std::addressof(element_at(static_cast<size_type>(first.index())))); - } - } - } - - /** - * @brief Assigns an entity to a storage. - * @param entt A valid identifier. - * @param value Optional opaque value. - * @param force_back Force back insertion. - * @return Iterator pointing to the emplaced element. - */ - underlying_iterator try_emplace([[maybe_unused]] const Entity entt, [[maybe_unused]] const bool force_back, const void *value) override { - if(value) { - if constexpr(std::is_copy_constructible_v<element_type>) { - return emplace_element(entt, force_back, *static_cast<const element_type *>(value)); - } else { - return base_type::end(); - } - } else { - if constexpr(std::is_default_constructible_v<element_type>) { - return emplace_element(entt, force_back); - } else { - return base_type::end(); - } - } - } - -public: - /*! @brief Allocator type. */ - using allocator_type = Allocator; - /*! @brief Base type. */ - using base_type = underlying_type; - /*! @brief Element type. */ - using element_type = Type; - /*! @brief Type of the objects assigned to entities. */ - using value_type = element_type; - /*! @brief Underlying entity identifier. */ - using entity_type = Entity; - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - /*! @brief Pointer type to contained elements. */ - using pointer = typename container_type::pointer; - /*! @brief Constant pointer type to contained elements. */ - using const_pointer = typename alloc_traits::template rebind_traits<typename alloc_traits::const_pointer>::const_pointer; - /*! @brief Random access iterator type. */ - using iterator = internal::storage_iterator<container_type>; - /*! @brief Constant random access iterator type. */ - using const_iterator = internal::storage_iterator<const container_type>; - /*! @brief Reverse iterator type. */ - using reverse_iterator = std::reverse_iterator<iterator>; - /*! @brief Constant reverse iterator type. */ - using const_reverse_iterator = std::reverse_iterator<const_iterator>; - /*! @brief Extended iterable storage proxy. */ - using iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::iterator, iterator>>; - /*! @brief Constant extended iterable storage proxy. */ - using const_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::const_iterator, const_iterator>>; - /*! @brief Extended reverse iterable storage proxy. */ - using reverse_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::reverse_iterator, reverse_iterator>>; - /*! @brief Constant extended reverse iterable storage proxy. */ - using const_reverse_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::const_reverse_iterator, const_reverse_iterator>>; - /*! @brief Storage deletion policy. */ - static constexpr deletion_policy storage_policy{traits_type::in_place_delete}; - - /*! @brief Default constructor. */ - basic_storage() - : basic_storage{allocator_type{}} {} - - /** - * @brief Constructs an empty storage with a given allocator. - * @param allocator The allocator to use. - */ - explicit basic_storage(const allocator_type &allocator) - : base_type{type_id<element_type>(), storage_policy, allocator}, - payload{allocator} {} - - /*! @brief Default copy constructor, deleted on purpose. */ - basic_storage(const basic_storage &) = delete; - - /** - * @brief Move constructor. - * @param other The instance to move from. - */ - basic_storage(basic_storage &&other) noexcept - : base_type{std::move(other)}, - payload{std::move(other.payload)} {} - - /** - * @brief Allocator-extended move constructor. - * @param other The instance to move from. - * @param allocator The allocator to use. - */ - basic_storage(basic_storage &&other, const allocator_type &allocator) - : base_type{std::move(other), allocator}, - payload{std::move(other.payload), allocator} { - ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a storage is not allowed"); - } - - /*! @brief Default destructor. */ - ~basic_storage() noexcept override { - shrink_to_size(0u); - } - - /** - * @brief Default copy assignment operator, deleted on purpose. - * @return This storage. - */ - basic_storage &operator=(const basic_storage &) = delete; - - /** - * @brief Move assignment operator. - * @param other The instance to move from. - * @return This storage. - */ - basic_storage &operator=(basic_storage &&other) noexcept { - ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a storage is not allowed"); - shrink_to_size(0u); - payload = std::move(other.payload); - base_type::operator=(std::move(other)); - return *this; - } - - /** - * @brief Exchanges the contents with those of a given storage. - * @param other Storage to exchange the content with. - */ - void swap(basic_storage &other) { - using std::swap; - swap(payload, other.payload); - base_type::swap(other); - } - - /** - * @brief Returns the associated allocator. - * @return The associated allocator. - */ - [[nodiscard]] constexpr allocator_type get_allocator() const noexcept { - return payload.get_allocator(); - } - - /** - * @brief Increases the capacity of a storage. - * - * If the new capacity is greater than the current capacity, new storage is - * allocated, otherwise the method does nothing. - * - * @param cap Desired capacity. - */ - void reserve(const size_type cap) override { - if(cap != 0u) { - base_type::reserve(cap); - assure_at_least(cap - 1u); - } - } - - /** - * @brief Returns the number of elements that a storage has currently - * allocated space for. - * @return Capacity of the storage. - */ - [[nodiscard]] size_type capacity() const noexcept override { - return payload.size() * traits_type::page_size; - } - - /*! @brief Requests the removal of unused capacity. */ - void shrink_to_fit() override { - base_type::shrink_to_fit(); - shrink_to_size(base_type::size()); - } - - /** - * @brief Direct access to the array of objects. - * @return A pointer to the array of objects. - */ - [[nodiscard]] const_pointer raw() const noexcept { - return payload.data(); - } - - /*! @copydoc raw */ - [[nodiscard]] pointer raw() noexcept { - return payload.data(); - } - - /** - * @brief Returns an iterator to the beginning. - * - * If the storage is empty, the returned iterator will be equal to `end()`. - * - * @return An iterator to the first instance of the internal array. - */ - [[nodiscard]] const_iterator cbegin() const noexcept { - const auto pos = static_cast<typename iterator::difference_type>(base_type::size()); - return const_iterator{&payload, pos}; - } - - /*! @copydoc cbegin */ - [[nodiscard]] const_iterator begin() const noexcept { - return cbegin(); - } - - /*! @copydoc begin */ - [[nodiscard]] iterator begin() noexcept { - const auto pos = static_cast<typename iterator::difference_type>(base_type::size()); - return iterator{&payload, pos}; - } - - /** - * @brief Returns an iterator to the end. - * @return An iterator to the element following the last instance of the - * internal array. - */ - [[nodiscard]] const_iterator cend() const noexcept { - return const_iterator{&payload, {}}; - } - - /*! @copydoc cend */ - [[nodiscard]] const_iterator end() const noexcept { - return cend(); - } - - /*! @copydoc end */ - [[nodiscard]] iterator end() noexcept { - return iterator{&payload, {}}; - } - - /** - * @brief Returns a reverse iterator to the beginning. - * - * If the storage is empty, the returned iterator will be equal to `rend()`. - * - * @return An iterator to the first instance of the reversed internal array. - */ - [[nodiscard]] const_reverse_iterator crbegin() const noexcept { - return std::make_reverse_iterator(cend()); - } - - /*! @copydoc crbegin */ - [[nodiscard]] const_reverse_iterator rbegin() const noexcept { - return crbegin(); - } - - /*! @copydoc rbegin */ - [[nodiscard]] reverse_iterator rbegin() noexcept { - return std::make_reverse_iterator(end()); - } - - /** - * @brief Returns a reverse iterator to the end. - * @return An iterator to the element following the last instance of the - * reversed internal array. - */ - [[nodiscard]] const_reverse_iterator crend() const noexcept { - return std::make_reverse_iterator(cbegin()); - } - - /*! @copydoc crend */ - [[nodiscard]] const_reverse_iterator rend() const noexcept { - return crend(); - } - - /*! @copydoc rend */ - [[nodiscard]] reverse_iterator rend() noexcept { - return std::make_reverse_iterator(begin()); - } - - /** - * @brief Returns the object assigned to an entity. - * - * @warning - * Attempting to use an entity that doesn't belong to the storage results in - * undefined behavior. - * - * @param entt A valid identifier. - * @return The object assigned to the entity. - */ - [[nodiscard]] const value_type &get(const entity_type entt) const noexcept { - return element_at(base_type::index(entt)); - } - - /*! @copydoc get */ - [[nodiscard]] value_type &get(const entity_type entt) noexcept { - return const_cast<value_type &>(std::as_const(*this).get(entt)); - } - - /** - * @brief Returns the object assigned to an entity as a tuple. - * @param entt A valid identifier. - * @return The object assigned to the entity as a tuple. - */ - [[nodiscard]] std::tuple<const value_type &> get_as_tuple(const entity_type entt) const noexcept { - return std::forward_as_tuple(get(entt)); - } - - /*! @copydoc get_as_tuple */ - [[nodiscard]] std::tuple<value_type &> get_as_tuple(const entity_type entt) noexcept { - return std::forward_as_tuple(get(entt)); - } - - /** - * @brief Assigns an entity to a storage and constructs its object. - * - * @warning - * Attempting to use an entity that already belongs to the storage results - * in undefined behavior. - * - * @tparam Args Types of arguments to use to construct the object. - * @param entt A valid identifier. - * @param args Parameters to use to construct an object for the entity. - * @return A reference to the newly created object. - */ - template<typename... Args> - value_type &emplace(const entity_type entt, Args &&...args) { - if constexpr(std::is_aggregate_v<value_type> && (sizeof...(Args) != 0u || !std::is_default_constructible_v<value_type>)) { - const auto it = emplace_element(entt, false, Type{std::forward<Args>(args)...}); - return element_at(static_cast<size_type>(it.index())); - } else { - const auto it = emplace_element(entt, false, std::forward<Args>(args)...); - return element_at(static_cast<size_type>(it.index())); - } - } - - /** - * @brief Updates the instance assigned to a given entity in-place. - * @tparam Func Types of the function objects to invoke. - * @param entt A valid identifier. - * @param func Valid function objects. - * @return A reference to the updated instance. - */ - template<typename... Func> - value_type &patch(const entity_type entt, Func &&...func) { - const auto idx = base_type::index(entt); - auto &elem = element_at(idx); - (std::forward<Func>(func)(elem), ...); - return elem; - } - - /** - * @brief Assigns one or more entities to a storage and constructs their - * objects from a given instance. - * - * @warning - * Attempting to assign an entity that already belongs to the storage - * results in undefined behavior. - * - * @tparam It Type of input iterator. - * @param first An iterator to the first element of the range of entities. - * @param last An iterator past the last element of the range of entities. - * @param value An instance of the object to construct. - * @return Iterator pointing to the first element inserted, if any. - */ - template<typename It> - iterator insert(It first, It last, const value_type &value = {}) { - for(; first != last; ++first) { - emplace_element(*first, true, value); - } - - return begin(); - } - - /** - * @brief Assigns one or more entities to a storage and constructs their - * objects from a given range. - * - * @sa construct - * - * @tparam EIt Type of input iterator. - * @tparam CIt Type of input iterator. - * @param first An iterator to the first element of the range of entities. - * @param last An iterator past the last element of the range of entities. - * @param from An iterator to the first element of the range of objects. - * @return Iterator pointing to the first element inserted, if any. - */ - template<typename EIt, typename CIt, typename = std::enable_if_t<std::is_same_v<typename std::iterator_traits<CIt>::value_type, value_type>>> - iterator insert(EIt first, EIt last, CIt from) { - for(; first != last; ++first, ++from) { - emplace_element(*first, true, *from); - } - - return begin(); - } - - /** - * @brief Returns an iterable object to use to _visit_ a storage. - * - * The iterable object returns a tuple that contains the current entity and - * a reference to its element. - * - * @return An iterable object to use to _visit_ the storage. - */ - [[nodiscard]] iterable each() noexcept { - return iterable{{base_type::begin(), begin()}, {base_type::end(), end()}}; - } - - /*! @copydoc each */ - [[nodiscard]] const_iterable each() const noexcept { - return const_iterable{{base_type::cbegin(), cbegin()}, {base_type::cend(), cend()}}; - } - - /** - * @brief Returns a reverse iterable object to use to _visit_ a storage. - * - * @sa each - * - * @return A reverse iterable object to use to _visit_ the storage. - */ - [[nodiscard]] reverse_iterable reach() noexcept { - return reverse_iterable{{base_type::rbegin(), rbegin()}, {base_type::rend(), rend()}}; - } - - /*! @copydoc reach */ - [[nodiscard]] const_reverse_iterable reach() const noexcept { - return const_reverse_iterable{{base_type::crbegin(), crbegin()}, {base_type::crend(), crend()}}; - } - -private: - container_type payload; -}; - -/*! @copydoc basic_storage */ -template<typename Type, typename Entity, typename Allocator> -class basic_storage<Type, Entity, Allocator, std::enable_if_t<component_traits<Type>::page_size == 0u>> - : public basic_sparse_set<Entity, typename std::allocator_traits<Allocator>::template rebind_alloc<Entity>> { - using alloc_traits = std::allocator_traits<Allocator>; - static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type"); - using traits_type = component_traits<Type>; - -public: - /*! @brief Allocator type. */ - using allocator_type = Allocator; - /*! @brief Base type. */ - using base_type = basic_sparse_set<Entity, typename alloc_traits::template rebind_alloc<Entity>>; - /*! @brief Element type. */ - using element_type = Type; - /*! @brief Type of the objects assigned to entities. */ - using value_type = void; - /*! @brief Underlying entity identifier. */ - using entity_type = Entity; - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - /*! @brief Extended iterable storage proxy. */ - using iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::iterator>>; - /*! @brief Constant extended iterable storage proxy. */ - using const_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::const_iterator>>; - /*! @brief Extended reverse iterable storage proxy. */ - using reverse_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::reverse_iterator>>; - /*! @brief Constant extended reverse iterable storage proxy. */ - using const_reverse_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::const_reverse_iterator>>; - /*! @brief Storage deletion policy. */ - static constexpr deletion_policy storage_policy{traits_type::in_place_delete}; - - /*! @brief Default constructor. */ - basic_storage() - : basic_storage{allocator_type{}} {} - - /** - * @brief Constructs an empty container with a given allocator. - * @param allocator The allocator to use. - */ - explicit basic_storage(const allocator_type &allocator) - : base_type{type_id<element_type>(), storage_policy, allocator} {} - - /*! @brief Default copy constructor, deleted on purpose. */ - basic_storage(const basic_storage &) = delete; - - /** - * @brief Move constructor. - * @param other The instance to move from. - */ - basic_storage(basic_storage &&other) noexcept = default; - - /** - * @brief Allocator-extended move constructor. - * @param other The instance to move from. - * @param allocator The allocator to use. - */ - basic_storage(basic_storage &&other, const allocator_type &allocator) - : base_type{std::move(other), allocator} {} - - /*! @brief Default destructor. */ - ~basic_storage() noexcept override = default; - - /** - * @brief Default copy assignment operator, deleted on purpose. - * @return This storage. - */ - basic_storage &operator=(const basic_storage &) = delete; - - /** - * @brief Move assignment operator. - * @param other The instance to move from. - * @return This storage. - */ - basic_storage &operator=(basic_storage &&other) noexcept = default; - - /** - * @brief Returns the associated allocator. - * @return The associated allocator. - */ - [[nodiscard]] constexpr allocator_type get_allocator() const noexcept { - // std::allocator<void> has no cross constructors (waiting for C++20) - if constexpr(std::is_void_v<element_type> && !std::is_constructible_v<allocator_type, typename base_type::allocator_type>) { - return allocator_type{}; - } else { - return allocator_type{base_type::get_allocator()}; - } - } - - /** - * @brief Returns the object assigned to an entity, that is `void`. - * - * @warning - * Attempting to use an entity that doesn't belong to the storage results in - * undefined behavior. - * - * @param entt A valid identifier. - */ - void get([[maybe_unused]] const entity_type entt) const noexcept { - ENTT_ASSERT(base_type::contains(entt), "Invalid entity"); - } - - /** - * @brief Returns an empty tuple. - * @param entt A valid identifier. - * @return Returns an empty tuple. - */ - [[nodiscard]] std::tuple<> get_as_tuple([[maybe_unused]] const entity_type entt) const noexcept { - ENTT_ASSERT(base_type::contains(entt), "Invalid entity"); - return std::tuple{}; - } - - /** - * @brief Assigns an entity to a storage and constructs its object. - * - * @warning - * Attempting to use an entity that already belongs to the storage results - * in undefined behavior. - * - * @tparam Args Types of arguments to use to construct the object. - * @param entt A valid identifier. - */ - template<typename... Args> - void emplace(const entity_type entt, Args &&...) { - base_type::try_emplace(entt, false); - } - - /** - * @brief Updates the instance assigned to a given entity in-place. - * @tparam Func Types of the function objects to invoke. - * @param entt A valid identifier. - * @param func Valid function objects. - */ - template<typename... Func> - void patch([[maybe_unused]] const entity_type entt, Func &&...func) { - ENTT_ASSERT(base_type::contains(entt), "Invalid entity"); - (std::forward<Func>(func)(), ...); - } - - /** - * @brief Assigns entities to a storage. - * @tparam It Type of input iterator. - * @tparam Args Types of optional arguments. - * @param first An iterator to the first element of the range of entities. - * @param last An iterator past the last element of the range of entities. - */ - template<typename It, typename... Args> - void insert(It first, It last, Args &&...) { - for(; first != last; ++first) { - base_type::try_emplace(*first, true); - } - } - - /** - * @brief Returns an iterable object to use to _visit_ a storage. - * - * The iterable object returns a tuple that contains the current entity. - * - * @return An iterable object to use to _visit_ the storage. - */ - [[nodiscard]] iterable each() noexcept { - return iterable{base_type::begin(), base_type::end()}; - } - - /*! @copydoc each */ - [[nodiscard]] const_iterable each() const noexcept { - return const_iterable{base_type::cbegin(), base_type::cend()}; - } - - /** - * @brief Returns a reverse iterable object to use to _visit_ a storage. - * - * @sa each - * - * @return A reverse iterable object to use to _visit_ the storage. - */ - [[nodiscard]] reverse_iterable reach() noexcept { - return reverse_iterable{{base_type::rbegin()}, {base_type::rend()}}; - } - - /*! @copydoc reach */ - [[nodiscard]] const_reverse_iterable reach() const noexcept { - return const_reverse_iterable{{base_type::crbegin()}, {base_type::crend()}}; - } -}; - -/** - * @brief Swap-only entity storage specialization. - * @tparam Entity A valid entity type. - * @tparam Allocator Type of allocator used to manage memory and elements. - */ -template<typename Entity, typename Allocator> -class basic_storage<Entity, Entity, Allocator> - : public basic_sparse_set<Entity, Allocator> { - using alloc_traits = std::allocator_traits<Allocator>; - static_assert(std::is_same_v<typename alloc_traits::value_type, Entity>, "Invalid value type"); - using underlying_iterator = typename basic_sparse_set<Entity, Allocator>::basic_iterator; - using traits_type = entt_traits<Entity>; - - auto next() noexcept { - entity_type entt = null; - - do { - ENTT_ASSERT(placeholder < traits_type::to_entity(null), "No more entities available"); - entt = traits_type::combine(static_cast<typename traits_type::entity_type>(placeholder++), {}); - } while(base_type::current(entt) != traits_type::to_version(tombstone) && entt != null); - - return entt; - } - -protected: - /*! @brief Erases all entities of a storage. */ - void pop_all() override { - base_type::pop_all(); - placeholder = {}; - } - - /** - * @brief Assigns an entity to a storage. - * @param hint A valid identifier. - * @return Iterator pointing to the emplaced element. - */ - underlying_iterator try_emplace(const Entity hint, const bool, const void *) override { - return base_type::find(emplace(hint)); - } - -public: - /*! @brief Allocator type. */ - using allocator_type = Allocator; - /*! @brief Base type. */ - using base_type = basic_sparse_set<Entity, Allocator>; - /*! @brief Element type. */ - using element_type = Entity; - /*! @brief Type of the objects assigned to entities. */ - using value_type = void; - /*! @brief Underlying entity identifier. */ - using entity_type = Entity; - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - /*! @brief Extended iterable storage proxy. */ - using iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::iterator>>; - /*! @brief Constant extended iterable storage proxy. */ - using const_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::const_iterator>>; - /*! @brief Extended reverse iterable storage proxy. */ - using reverse_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::reverse_iterator>>; - /*! @brief Constant extended reverse iterable storage proxy. */ - using const_reverse_iterable = iterable_adaptor<internal::extended_storage_iterator<typename base_type::const_reverse_iterator>>; - /*! @brief Storage deletion policy. */ - static constexpr deletion_policy storage_policy = deletion_policy::swap_only; - - /*! @brief Default constructor. */ - basic_storage() - : basic_storage{allocator_type{}} { - } - - /** - * @brief Constructs an empty container with a given allocator. - * @param allocator The allocator to use. - */ - explicit basic_storage(const allocator_type &allocator) - : base_type{type_id<void>(), storage_policy, allocator} {} - - /*! @brief Default copy constructor, deleted on purpose. */ - basic_storage(const basic_storage &) = delete; - - /** - * @brief Move constructor. - * @param other The instance to move from. - */ - basic_storage(basic_storage &&other) noexcept - : base_type{std::move(other)}, - placeholder{other.placeholder} {} - - /** - * @brief Allocator-extended move constructor. - * @param other The instance to move from. - * @param allocator The allocator to use. - */ - basic_storage(basic_storage &&other, const allocator_type &allocator) - : base_type{std::move(other), allocator}, - placeholder{other.placeholder} {} - - /*! @brief Default destructor. */ - ~basic_storage() noexcept override = default; - - /** - * @brief Default copy assignment operator, deleted on purpose. - * @return This storage. - */ - basic_storage &operator=(const basic_storage &) = delete; - - /** - * @brief Move assignment operator. - * @param other The instance to move from. - * @return This storage. - */ - basic_storage &operator=(basic_storage &&other) noexcept { - placeholder = other.placeholder; - base_type::operator=(std::move(other)); - return *this; - } - - /** - * @brief Returns the object assigned to an entity, that is `void`. - * - * @warning - * Attempting to use an entity that doesn't belong to the storage results in - * undefined behavior. - * - * @param entt A valid identifier. - */ - void get([[maybe_unused]] const entity_type entt) const noexcept { - ENTT_ASSERT(base_type::index(entt) < base_type::free_list(), "The requested entity is not a live one"); - } - - /** - * @brief Returns an empty tuple. - * @param entt A valid identifier. - * @return Returns an empty tuple. - */ - [[nodiscard]] std::tuple<> get_as_tuple([[maybe_unused]] const entity_type entt) const noexcept { - ENTT_ASSERT(base_type::index(entt) < base_type::free_list(), "The requested entity is not a live one"); - return std::tuple{}; - } - - /** - * @brief Creates a new identifier or recycles a destroyed one. - * @return A valid identifier. - */ - entity_type emplace() { - const auto len = base_type::free_list(); - const auto entt = (len == base_type::size()) ? next() : base_type::data()[len]; - return *base_type::try_emplace(entt, true); - } - - /** - * @brief Creates a new identifier or recycles a destroyed one. - * - * If the requested identifier isn't in use, the suggested one is used. - * Otherwise, a new identifier is returned. - * - * @param hint Required identifier. - * @return A valid identifier. - */ - entity_type emplace(const entity_type hint) { - if(hint != null && hint != tombstone) { - if(const auto curr = traits_type::construct(traits_type::to_entity(hint), base_type::current(hint)); curr == tombstone || !(base_type::index(curr) < base_type::free_list())) { - return *base_type::try_emplace(hint, true); - } - } - - return emplace(); - } - - /** - * @brief Updates a given identifier. - * @tparam Func Types of the function objects to invoke. - * @param entt A valid identifier. - * @param func Valid function objects. - */ - template<typename... Func> - void patch([[maybe_unused]] const entity_type entt, Func &&...func) { - ENTT_ASSERT(base_type::index(entt) < base_type::free_list(), "The requested entity is not a live one"); - (std::forward<Func>(func)(), ...); - } - - /** - * @brief Assigns each element in a range an identifier. - * @tparam It Type of mutable forward iterator. - * @param first An iterator to the first element of the range to generate. - * @param last An iterator past the last element of the range to generate. - */ - template<typename It> - void insert(It first, It last) { - for(const auto sz = base_type::size(); first != last && base_type::free_list() != sz; ++first) { - *first = *base_type::try_emplace(base_type::data()[base_type::free_list()], true); - } - - for(; first != last; ++first) { - *first = *base_type::try_emplace(next(), true); - } - } - - /** - * @brief Returns an iterable object to use to _visit_ a storage. - * - * The iterable object returns a tuple that contains the current entity. - * - * @return An iterable object to use to _visit_ the storage. - */ - [[nodiscard]] iterable each() noexcept { - return std::as_const(*this).each(); - } - - /*! @copydoc each */ - [[nodiscard]] const_iterable each() const noexcept { - const auto it = base_type::cend(); - return const_iterable{it - base_type::free_list(), it}; - } - - /** - * @brief Returns a reverse iterable object to use to _visit_ a storage. - * - * @sa each - * - * @return A reverse iterable object to use to _visit_ the storage. - */ - [[nodiscard]] reverse_iterable reach() noexcept { - return std::as_const(*this).reach(); - } - - /*! @copydoc reach */ - [[nodiscard]] const_reverse_iterable reach() const noexcept { - const auto it = base_type::crbegin(); - return const_reverse_iterable{it, it + base_type::free_list()}; - } - -private: - size_type placeholder{}; -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/entity/storage_mixin.hpp b/deps/entt/include/entt/entity/storage_mixin.hpp deleted file mode 100644 index 0686e4e..0000000 --- a/deps/entt/include/entt/entity/storage_mixin.hpp +++ /dev/null @@ -1,236 +0,0 @@ -#ifndef ENTT_ENTITY_SIGH_STORAGE_MIXIN_HPP -#define ENTT_ENTITY_SIGH_STORAGE_MIXIN_HPP - -#include <utility> -#include "../config/config.h" -#include "../core/any.hpp" -#include "../signal/sigh.hpp" -#include "fwd.hpp" - -namespace entt { - -/** - * @brief Mixin type used to add signal support to storage types. - * - * The function type of a listener is equivalent to: - * - * @code{.cpp} - * void(basic_registry<entity_type> &, entity_type); - * @endcode - * - * This applies to all signals made available. - * - * @tparam Type The type of the underlying storage. - */ -template<typename Type> -class sigh_storage_mixin final: public Type { - using basic_registry_type = basic_registry<typename Type::entity_type, typename Type::base_type::allocator_type>; - using sigh_type = sigh<void(basic_registry_type &, const typename Type::entity_type), typename Type::allocator_type>; - using basic_iterator = typename Type::basic_iterator; - - void pop(basic_iterator first, basic_iterator last) override { - ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry"); - - for(; first != last; ++first) { - const auto entt = *first; - destruction.publish(*owner, entt); - const auto it = Type::find(entt); - Type::pop(it, it + 1u); - } - } - - basic_iterator try_emplace(const typename basic_registry_type::entity_type entt, const bool force_back, const void *value) final { - ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry"); - Type::try_emplace(entt, force_back, value); - construction.publish(*owner, entt); - return Type::find(entt); - } - -public: - /*! @brief Allocator type. */ - using allocator_type = typename Type::allocator_type; - /*! @brief Underlying entity identifier. */ - using entity_type = typename Type::entity_type; - /*! @brief Expected registry type. */ - using registry_type = basic_registry_type; - - /*! @brief Default constructor. */ - sigh_storage_mixin() - : sigh_storage_mixin{allocator_type{}} {} - - /** - * @brief Constructs an empty storage with a given allocator. - * @param allocator The allocator to use. - */ - explicit sigh_storage_mixin(const allocator_type &allocator) - : Type{allocator}, - owner{}, - construction{allocator}, - destruction{allocator}, - update{allocator} {} - - /** - * @brief Move constructor. - * @param other The instance to move from. - */ - sigh_storage_mixin(sigh_storage_mixin &&other) noexcept - : Type{std::move(other)}, - owner{other.owner}, - construction{std::move(other.construction)}, - destruction{std::move(other.destruction)}, - update{std::move(other.update)} {} - - /** - * @brief Allocator-extended move constructor. - * @param other The instance to move from. - * @param allocator The allocator to use. - */ - sigh_storage_mixin(sigh_storage_mixin &&other, const allocator_type &allocator) noexcept - : Type{std::move(other), allocator}, - owner{other.owner}, - construction{std::move(other.construction), allocator}, - destruction{std::move(other.destruction), allocator}, - update{std::move(other.update), allocator} {} - - /** - * @brief Move assignment operator. - * @param other The instance to move from. - * @return This storage. - */ - sigh_storage_mixin &operator=(sigh_storage_mixin &&other) noexcept { - Type::operator=(std::move(other)); - owner = other.owner; - construction = std::move(other.construction); - destruction = std::move(other.destruction); - update = std::move(other.update); - return *this; - } - - /** - * @brief Exchanges the contents with those of a given storage. - * @param other Storage to exchange the content with. - */ - void swap(sigh_storage_mixin &other) { - using std::swap; - Type::swap(other); - swap(owner, other.owner); - swap(construction, other.construction); - swap(destruction, other.destruction); - swap(update, other.update); - } - - /** - * @brief Returns a sink object. - * - * The sink returned by this function can be used to receive notifications - * whenever a new instance is created and assigned to an entity.<br/> - * Listeners are invoked after the object has been assigned to the entity. - * - * @sa sink - * - * @return A temporary sink object. - */ - [[nodiscard]] auto on_construct() noexcept { - return sink{construction}; - } - - /** - * @brief Returns a sink object. - * - * The sink returned by this function can be used to receive notifications - * whenever an instance is explicitly updated.<br/> - * Listeners are invoked after the object has been updated. - * - * @sa sink - * - * @return A temporary sink object. - */ - [[nodiscard]] auto on_update() noexcept { - return sink{update}; - } - - /** - * @brief Returns a sink object. - * - * The sink returned by this function can be used to receive notifications - * whenever an instance is removed from an entity and thus destroyed.<br/> - * Listeners are invoked before the object has been removed from the entity. - * - * @sa sink - * - * @return A temporary sink object. - */ - [[nodiscard]] auto on_destroy() noexcept { - return sink{destruction}; - } - - /** - * @brief Assigns entities to a storage. - * @tparam Args Types of arguments to use to construct the object. - * @param entt A valid identifier. - * @param args Parameters to use to initialize the object. - * @return A reference to the newly created object. - */ - template<typename... Args> - decltype(auto) emplace(const entity_type entt, Args &&...args) { - ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry"); - Type::emplace(entt, std::forward<Args>(args)...); - construction.publish(*owner, entt); - return this->get(entt); - } - - /** - * @brief Patches the given instance for an entity. - * @tparam Func Types of the function objects to invoke. - * @param entt A valid identifier. - * @param func Valid function objects. - * @return A reference to the patched instance. - */ - template<typename... Func> - decltype(auto) patch(const entity_type entt, Func &&...func) { - ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry"); - Type::patch(entt, std::forward<Func>(func)...); - update.publish(*owner, entt); - return this->get(entt); - } - - /** - * @brief Assigns entities to a storage. - * @tparam It Type of input iterator. - * @tparam Args Types of arguments to use to construct the objects assigned - * to the entities. - * @param first An iterator to the first element of the range of entities. - * @param last An iterator past the last element of the range of entities. - * @param args Parameters to use to initialize the objects assigned to the - * entities. - */ - template<typename It, typename... Args> - void insert(It first, It last, Args &&...args) { - ENTT_ASSERT(owner != nullptr, "Invalid pointer to registry"); - Type::insert(first, last, std::forward<Args>(args)...); - - for(auto it = construction.empty() ? last : first; it != last; ++it) { - construction.publish(*owner, *it); - } - } - - /** - * @brief Forwards variables to derived classes, if any. - * @param value A variable wrapped in an opaque container. - */ - void bind(any value) noexcept final { - auto *reg = any_cast<basic_registry_type>(&value); - owner = reg ? reg : owner; - Type::bind(std::move(value)); - } - -private: - basic_registry_type *owner; - sigh_type construction; - sigh_type destruction; - sigh_type update; -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/entity/view.hpp b/deps/entt/include/entt/entity/view.hpp deleted file mode 100644 index f59bff4..0000000 --- a/deps/entt/include/entt/entity/view.hpp +++ /dev/null @@ -1,1076 +0,0 @@ -#ifndef ENTT_ENTITY_VIEW_HPP -#define ENTT_ENTITY_VIEW_HPP - -#include <array> -#include <cstddef> -#include <iterator> -#include <tuple> -#include <type_traits> -#include <utility> -#include "../config/config.h" -#include "../core/iterator.hpp" -#include "../core/type_traits.hpp" -#include "entity.hpp" -#include "fwd.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename It, typename Entity> -[[nodiscard]] bool all_of(It first, const It last, const Entity entt) noexcept { - for(; (first != last) && (*first)->contains(entt); ++first) {} - return first == last; -} - -template<typename It, typename Entity> -[[nodiscard]] bool none_of(It first, const It last, const Entity entt) noexcept { - for(; (first != last) && !(*first && (*first)->contains(entt)); ++first) {} - return first == last; -} - -template<typename It> -[[nodiscard]] bool fully_initialized(It first, const It last) noexcept { - for(; (first != last) && *first; ++first) {} - return first == last; -} - -template<typename Result, typename View, typename Other, std::size_t... GLhs, std::size_t... ELhs, std::size_t... GRhs, std::size_t... ERhs> -[[nodiscard]] Result view_pack(const View &view, const Other &other, std::index_sequence<GLhs...>, std::index_sequence<ELhs...>, std::index_sequence<GRhs...>, std::index_sequence<ERhs...>) { - Result elem{}; - // friend-initialization, avoid multiple calls to refresh - elem.pools = {view.template storage<GLhs>()..., other.template storage<GRhs>()...}; - elem.filter = {view.template storage<sizeof...(GLhs) + ELhs>()..., other.template storage<sizeof...(GRhs) + ERhs>()...}; - elem.refresh(); - return elem; -} - -template<typename Type, std::size_t Get, std::size_t Exclude> -class view_iterator final { - template<typename, typename...> - friend class extended_view_iterator; - - using iterator_type = typename Type::const_iterator; - using iterator_traits = std::iterator_traits<iterator_type>; - - [[nodiscard]] bool valid(const typename iterator_traits::value_type entt) const noexcept { - return ((Get != 1u) || (entt != tombstone)) - && internal::all_of(pools.begin(), pools.begin() + index, entt) && internal::all_of(pools.begin() + index + 1, pools.end(), entt) - && internal::none_of(filter.begin(), filter.end(), entt); - } - - void seek_next() { - for(constexpr iterator_type sentinel{}; it != sentinel && !valid(*it); ++it) {} - } - -public: - using value_type = typename iterator_traits::value_type; - using pointer = typename iterator_traits::pointer; - using reference = typename iterator_traits::reference; - using difference_type = typename iterator_traits::difference_type; - using iterator_category = std::forward_iterator_tag; - - constexpr view_iterator() noexcept - : it{}, - pools{}, - filter{}, - index{} {} - - view_iterator(iterator_type first, std::array<const Type *, Get> value, std::array<const Type *, Exclude> excl, const std::size_t idx) noexcept - : it{first}, - pools{value}, - filter{excl}, - index{idx} { - seek_next(); - } - - view_iterator &operator++() noexcept { - ++it; - seek_next(); - return *this; - } - - view_iterator operator++(int) noexcept { - view_iterator orig = *this; - return ++(*this), orig; - } - - [[nodiscard]] pointer operator->() const noexcept { - return &*it; - } - - [[nodiscard]] reference operator*() const noexcept { - return *operator->(); - } - - template<typename LhsType, auto... LhsArgs, typename RhsType, auto... RhsArgs> - friend constexpr bool operator==(const view_iterator<LhsType, LhsArgs...> &, const view_iterator<RhsType, RhsArgs...> &) noexcept; - -private: - iterator_type it; - std::array<const Type *, Get> pools; - std::array<const Type *, Exclude> filter; - std::size_t index; -}; - -template<typename LhsType, auto... LhsArgs, typename RhsType, auto... RhsArgs> -[[nodiscard]] constexpr bool operator==(const view_iterator<LhsType, LhsArgs...> &lhs, const view_iterator<RhsType, RhsArgs...> &rhs) noexcept { - return lhs.it == rhs.it; -} - -template<typename LhsType, auto... LhsArgs, typename RhsType, auto... RhsArgs> -[[nodiscard]] constexpr bool operator!=(const view_iterator<LhsType, LhsArgs...> &lhs, const view_iterator<RhsType, RhsArgs...> &rhs) noexcept { - return !(lhs == rhs); -} - -template<typename It, typename... Get> -class extended_view_iterator final { - template<std::size_t... Index> - [[nodiscard]] auto dereference(std::index_sequence<Index...>) const noexcept { - return std::tuple_cat(std::make_tuple(*it), static_cast<Get *>(const_cast<constness_as_t<typename Get::base_type, Get> *>(std::get<Index>(it.pools)))->get_as_tuple(*it)...); - } - -public: - using iterator_type = It; - using value_type = decltype(std::tuple_cat(std::make_tuple(*std::declval<It>()), std::declval<Get>().get_as_tuple({})...)); - using pointer = input_iterator_pointer<value_type>; - using reference = value_type; - using difference_type = std::ptrdiff_t; - using iterator_category = std::input_iterator_tag; - using iterator_concept = std::forward_iterator_tag; - - constexpr extended_view_iterator() - : it{} {} - - extended_view_iterator(iterator_type from) - : it{from} {} - - extended_view_iterator &operator++() noexcept { - return ++it, *this; - } - - extended_view_iterator operator++(int) noexcept { - extended_view_iterator orig = *this; - return ++(*this), orig; - } - - [[nodiscard]] reference operator*() const noexcept { - return dereference(std::index_sequence_for<Get...>{}); - } - - [[nodiscard]] pointer operator->() const noexcept { - return operator*(); - } - - [[nodiscard]] constexpr iterator_type base() const noexcept { - return it; - } - - template<typename... Lhs, typename... Rhs> - friend bool constexpr operator==(const extended_view_iterator<Lhs...> &, const extended_view_iterator<Rhs...> &) noexcept; - -private: - It it; -}; - -template<typename... Lhs, typename... Rhs> -[[nodiscard]] constexpr bool operator==(const extended_view_iterator<Lhs...> &lhs, const extended_view_iterator<Rhs...> &rhs) noexcept { - return lhs.it == rhs.it; -} - -template<typename... Lhs, typename... Rhs> -[[nodiscard]] constexpr bool operator!=(const extended_view_iterator<Lhs...> &lhs, const extended_view_iterator<Rhs...> &rhs) noexcept { - return !(lhs == rhs); -} - -} // namespace internal -/*! @endcond */ - -/** - * @brief View implementation. - * - * Primary template isn't defined on purpose. All the specializations give a - * compile-time error, but for a few reasonable cases. - * - * @b Important - * - * View iterators aren't invalidated if: - * - * * New elements are added to the storage iterated by the view. - * * The entity currently returned is modified (for example, elements are added - * or removed from it). - * * The entity currently returned is destroyed. - * - * In all other cases, modifying the storage iterated by a view in any way can - * invalidate all iterators. - */ -template<typename, typename, typename> -class basic_view; - -/** - * @brief Basic storage view implementation. - * @warning For internal use only, backward compatibility not guaranteed. - * @tparam Type Common type among all storage types. - * @tparam Get Number of storage iterated by the view. - * @tparam Exclude Number of storage used to filter the view. - */ -template<typename Type, std::size_t Get, std::size_t Exclude> -class basic_common_view { - template<typename Return, typename View, typename Other, std::size_t... GLhs, std::size_t... ELhs, std::size_t... GRhs, std::size_t... ERhs> - friend Return internal::view_pack(const View &, const Other &, std::index_sequence<GLhs...>, std::index_sequence<ELhs...>, std::index_sequence<GRhs...>, std::index_sequence<ERhs...>); - - [[nodiscard]] auto offset() const noexcept { - ENTT_ASSERT(index != Get, "Invalid view"); - return (pools[index]->policy() == deletion_policy::swap_only) ? pools[index]->free_list() : pools[index]->size(); - } - - void unchecked_refresh() noexcept { - index = 0u; - - if constexpr(Get > 1u) { - for(size_type pos{1u}; pos < Get; ++pos) { - if(pools[pos]->size() < pools[index]->size()) { - index = pos; - } - } - } - } - -protected: - /*! @cond TURN_OFF_DOXYGEN */ - basic_common_view() noexcept = default; - - basic_common_view(std::array<const Type *, Get> value, std::array<const Type *, Exclude> excl) noexcept - : pools{value}, - filter{excl}, - index{Get} { - unchecked_refresh(); - } - - [[nodiscard]] const Type *pool_at(const std::size_t pos) const noexcept { - return pools[pos]; - } - - [[nodiscard]] const Type *storage(const std::size_t pos) const noexcept { - return (pos < Get) ? pools[pos] : filter[pos - Get]; - } - - void storage(const std::size_t pos, const Type *elem) noexcept { - if(pos < Get) { - pools[pos] = elem; - refresh(); - } else { - filter[pos - Get] = elem; - } - } - - [[nodiscard]] bool none_of(const typename Type::entity_type entt) const noexcept { - return internal::none_of(filter.begin(), filter.end(), entt); - } - - void use(const std::size_t pos) noexcept { - index = (index != Get) ? pos : Get; - } - /*! @endcond */ - -public: - /*! @brief Common type among all storage types. */ - using common_type = Type; - /*! @brief Underlying entity identifier. */ - using entity_type = typename Type::entity_type; - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - /*! @brief Forward iterator type. */ - using iterator = internal::view_iterator<common_type, Get, Exclude>; - - /*! @brief Updates the internal leading view if required. */ - void refresh() noexcept { - size_type pos = (index != Get) * Get; - for(; pos < Get && pools[pos] != nullptr; ++pos) {} - - if(pos == Get) { - unchecked_refresh(); - } - } - - /** - * @brief Returns the leading storage of a view, if any. - * @return The leading storage of the view. - */ - [[nodiscard]] const common_type *handle() const noexcept { - return (index != Get) ? pools[index] : nullptr; - } - - /** - * @brief Estimates the number of entities iterated by the view. - * @return Estimated number of entities iterated by the view. - */ - [[nodiscard]] size_type size_hint() const noexcept { - return (index != Get) ? pools[index]->size() : size_type{}; - } - - /** - * @brief Returns an iterator to the first entity of the view. - * - * If the view is empty, the returned iterator will be equal to `end()`. - * - * @return An iterator to the first entity of the view. - */ - [[nodiscard]] iterator begin() const noexcept { - return (index != Get) ? iterator{pools[index]->end() - static_cast<typename iterator::difference_type>(offset()), pools, filter, index} : iterator{}; - } - - /** - * @brief Returns an iterator that is past the last entity of the view. - * @return An iterator to the entity following the last entity of the view. - */ - [[nodiscard]] iterator end() const noexcept { - return (index != Get) ? iterator{pools[index]->end(), pools, filter, index} : iterator{}; - } - - /** - * @brief Returns the first entity of the view, if any. - * @return The first entity of the view if one exists, the null entity - * otherwise. - */ - [[nodiscard]] entity_type front() const noexcept { - const auto it = begin(); - return it != end() ? *it : null; - } - - /** - * @brief Returns the last entity of the view, if any. - * @return The last entity of the view if one exists, the null entity - * otherwise. - */ - [[nodiscard]] entity_type back() const noexcept { - if(index != Get) { - auto it = pools[index]->rbegin(); - const auto last = it + static_cast<typename iterator::difference_type>(offset()); - for(; it != last && !contains(*it); ++it) {} - return it == last ? null : *it; - } - - return null; - } - - /** - * @brief Finds an entity. - * @param entt A valid identifier. - * @return An iterator to the given entity if it's found, past the end - * iterator otherwise. - */ - [[nodiscard]] iterator find(const entity_type entt) const noexcept { - return contains(entt) ? iterator{pools[index]->find(entt), pools, filter, index} : end(); - } - - /** - * @brief Checks if a view is fully initialized. - * @return True if the view is fully initialized, false otherwise. - */ - [[nodiscard]] explicit operator bool() const noexcept { - return (index != Get) && internal::fully_initialized(filter.begin(), filter.end()); - } - - /** - * @brief Checks if a view contains an entity. - * @param entt A valid identifier. - * @return True if the view contains the given entity, false otherwise. - */ - [[nodiscard]] bool contains(const entity_type entt) const noexcept { - return (index != Get) - && internal::all_of(pools.begin(), pools.end(), entt) - && internal::none_of(filter.begin(), filter.end(), entt) - && pools[index]->index(entt) < offset(); - } - -private: - std::array<const common_type *, Get> pools{}; - std::array<const common_type *, Exclude> filter{}; - size_type index{Get}; -}; - -/** - * @brief General purpose view. - * - * This view visits all entities that are at least in the given storage. During - * initialization, it also looks at the number of elements available for each - * storage and uses the smallest set in order to get a performance boost. - * - * @sa basic_view - * - * @tparam Get Types of storage iterated by the view. - * @tparam Exclude Types of storage used to filter the view. - */ -template<typename... Get, typename... Exclude> -class basic_view<get_t<Get...>, exclude_t<Exclude...>, std::enable_if_t<(sizeof...(Get) + sizeof...(Exclude) > 1)>> - : public basic_common_view<std::common_type_t<typename Get::base_type..., typename Exclude::base_type...>, sizeof...(Get), sizeof...(Exclude)> { - using base_type = basic_common_view<std::common_type_t<typename Get::base_type..., typename Exclude::base_type...>, sizeof...(Get), sizeof...(Exclude)>; - - template<typename Type> - static constexpr std::size_t index_of = type_list_index_v<std::remove_const_t<Type>, type_list<typename Get::element_type..., typename Exclude::element_type...>>; - - template<std::size_t... Index> - [[nodiscard]] auto get(const typename base_type::entity_type entt, std::index_sequence<Index...>) const noexcept { - return std::tuple_cat(storage<Index>()->get_as_tuple(entt)...); - } - - template<std::size_t Curr, std::size_t Other, typename... Args> - [[nodiscard]] auto dispatch_get(const std::tuple<typename base_type::entity_type, Args...> &curr) const { - if constexpr(Curr == Other) { - return std::forward_as_tuple(std::get<Args>(curr)...); - } else { - return storage<Other>()->get_as_tuple(std::get<0>(curr)); - } - } - - template<std::size_t Curr, typename Func, std::size_t... Index> - void each(Func &func, std::index_sequence<Index...>) const { - static constexpr bool tombstone_check_required = ((sizeof...(Get) == 1u) && ... && (Get::storage_policy == deletion_policy::in_place)); - - for(const auto curr: storage<Curr>()->each()) { - if(const auto entt = std::get<0>(curr); (!tombstone_check_required || (entt != tombstone)) && ((Curr == Index || base_type::pool_at(Index)->contains(entt)) && ...) && base_type::none_of(entt)) { - if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_view>().get({})))>) { - std::apply(func, std::tuple_cat(std::make_tuple(entt), dispatch_get<Curr, Index>(curr)...)); - } else { - std::apply(func, std::tuple_cat(dispatch_get<Curr, Index>(curr)...)); - } - } - } - } - - template<typename Func, std::size_t... Index> - void pick_and_each(Func &func, std::index_sequence<Index...> seq) const { - if(const auto *view = base_type::handle(); view != nullptr) { - ((view == base_type::pool_at(Index) ? each<Index>(func, seq) : void()), ...); - } - } - -public: - /*! @brief Common type among all storage types. */ - using common_type = typename base_type::common_type; - /*! @brief Underlying entity identifier. */ - using entity_type = typename base_type::entity_type; - /*! @brief Unsigned integer type. */ - using size_type = typename base_type::size_type; - /*! @brief Forward iterator type. */ - using iterator = typename base_type::iterator; - /*! @brief Iterable view type. */ - using iterable = iterable_adaptor<internal::extended_view_iterator<iterator, Get...>>; - - /*! @brief Default constructor to use to create empty, invalid views. */ - basic_view() noexcept - : base_type{} {} - - /** - * @brief Constructs a view from a set of storage classes. - * @param value The storage for the types to iterate. - * @param excl The storage for the types used to filter the view. - */ - basic_view(Get &...value, Exclude &...excl) noexcept - : base_type{{&value...}, {&excl...}} { - } - - /** - * @brief Constructs a view from a set of storage classes. - * @param value The storage for the types to iterate. - * @param excl The storage for the types used to filter the view. - */ - basic_view(std::tuple<Get &...> value, std::tuple<Exclude &...> excl = {}) noexcept - : basic_view{std::make_from_tuple<basic_view>(std::tuple_cat(value, excl))} {} - - /** - * @brief Forces a view to use a given element to drive iterations - * @tparam Type Type of element to use to drive iterations. - */ - template<typename Type> - void use() noexcept { - use<index_of<Type>>(); - } - - /** - * @brief Forces a view to use a given element to drive iterations - * @tparam Index Index of the element to use to drive iterations. - */ - template<std::size_t Index> - void use() noexcept { - base_type::use(Index); - } - - /** - * @brief Returns the storage for a given element type, if any. - * @tparam Type Type of element of which to return the storage. - * @return The storage for the given element type. - */ - template<typename Type> - [[nodiscard]] auto *storage() const noexcept { - return storage<index_of<Type>>(); - } - - /** - * @brief Returns the storage for a given index, if any. - * @tparam Index Index of the storage to return. - * @return The storage for the given index. - */ - template<std::size_t Index> - [[nodiscard]] auto *storage() const noexcept { - using type = type_list_element_t<Index, type_list<Get..., Exclude...>>; - return static_cast<type *>(const_cast<constness_as_t<common_type, type> *>(base_type::storage(Index))); - } - - /** - * @brief Assigns a storage to a view. - * @tparam Type Type of storage to assign to the view. - * @param elem A storage to assign to the view. - */ - template<typename Type> - void storage(Type &elem) noexcept { - storage<index_of<typename Type::element_type>>(elem); - } - - /** - * @brief Assigns a storage to a view. - * @tparam Index Index of the storage to assign to the view. - * @tparam Type Type of storage to assign to the view. - * @param elem A storage to assign to the view. - */ - template<std::size_t Index, typename Type> - void storage(Type &elem) noexcept { - static_assert(std::is_convertible_v<Type &, type_list_element_t<Index, type_list<Get..., Exclude...>> &>, "Unexpected type"); - base_type::storage(Index, &elem); - } - - /** - * @brief Returns the elements assigned to the given entity. - * @param entt A valid identifier. - * @return The elements assigned to the given entity. - */ - [[nodiscard]] decltype(auto) operator[](const entity_type entt) const { - return get(entt); - } - - /** - * @brief Returns the elements assigned to the given entity. - * @tparam Type Type of the element to get. - * @tparam Other Other types of elements to get. - * @param entt A valid identifier. - * @return The elements assigned to the entity. - */ - template<typename Type, typename... Other> - [[nodiscard]] decltype(auto) get(const entity_type entt) const { - return get<index_of<Type>, index_of<Other>...>(entt); - } - - /** - * @brief Returns the elements assigned to the given entity. - * @tparam Index Indexes of the elements to get. - * @param entt A valid identifier. - * @return The elements assigned to the entity. - */ - template<std::size_t... Index> - [[nodiscard]] decltype(auto) get(const entity_type entt) const { - if constexpr(sizeof...(Index) == 0) { - return get(entt, std::index_sequence_for<Get...>{}); - } else if constexpr(sizeof...(Index) == 1) { - return (storage<Index>()->get(entt), ...); - } else { - return std::tuple_cat(storage<Index>()->get_as_tuple(entt)...); - } - } - - /** - * @brief Iterates entities and elements and applies the given function - * object to them. - * - * The signature of the function must be equivalent to one of the following - * (non-empty types only, constness as requested): - * - * @code{.cpp} - * void(const entity_type, Type &...); - * void(Type &...); - * @endcode - * - * @tparam Func Type of the function object to invoke. - * @param func A valid function object. - */ - template<typename Func> - void each(Func func) const { - pick_and_each(func, std::index_sequence_for<Get...>{}); - } - - /** - * @brief Returns an iterable object to use to _visit_ a view. - * - * The iterable object returns a tuple that contains the current entity and - * a set of references to its non-empty elements. The _constness_ of the - * elements is as requested. - * - * @return An iterable object to use to _visit_ the view. - */ - [[nodiscard]] iterable each() const noexcept { - return iterable{base_type::begin(), base_type::end()}; - } - - /** - * @brief Combines two views in a _more specific_ one. - * @tparam OGet Element list of the view to combine with. - * @tparam OExclude Filter list of the view to combine with. - * @param other The view to combine with. - * @return A more specific view. - */ - template<typename... OGet, typename... OExclude> - [[nodiscard]] auto operator|(const basic_view<get_t<OGet...>, exclude_t<OExclude...>> &other) const noexcept { - return internal::view_pack<basic_view<get_t<Get..., OGet...>, exclude_t<Exclude..., OExclude...>>>( - *this, other, std::index_sequence_for<Get...>{}, std::index_sequence_for<Exclude...>{}, std::index_sequence_for<OGet...>{}, std::index_sequence_for<OExclude...>{}); - } -}; - -/** - * @brief Basic storage view implementation. - * @warning For internal use only, backward compatibility not guaranteed. - * @tparam Type Common type among all storage types. - * @tparam Policy Storage policy. - */ -template<typename Type, deletion_policy Policy> -class basic_storage_view { -protected: - /*! @cond TURN_OFF_DOXYGEN */ - basic_storage_view() noexcept = default; - - basic_storage_view(const Type *value) noexcept - : leading{value} { - ENTT_ASSERT(leading->policy() == Policy, "Unexpected storage policy"); - } - /*! @endcond */ - -public: - /*! @brief Common type among all storage types. */ - using common_type = Type; - /*! @brief Underlying entity identifier. */ - using entity_type = typename common_type::entity_type; - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - /*! @brief Random access iterator type. */ - using iterator = std::conditional_t<Policy == deletion_policy::in_place, internal::view_iterator<common_type, 1u, 0u>, typename common_type::iterator>; - /*! @brief Reverse iterator type. */ - using reverse_iterator = std::conditional_t<Policy == deletion_policy::in_place, void, typename common_type::reverse_iterator>; - - /** - * @brief Returns the leading storage of a view, if any. - * @return The leading storage of the view. - */ - [[nodiscard]] const common_type *handle() const noexcept { - return leading; - } - - /** - * @brief Returns the number of entities that have the given element. - * @tparam Pol Dummy template parameter used for sfinae purposes only. - * @return Number of entities that have the given element. - */ - template<typename..., deletion_policy Pol = Policy> - [[nodiscard]] std::enable_if_t<Pol != deletion_policy::in_place, size_type> size() const noexcept { - if constexpr(Policy == deletion_policy::swap_and_pop) { - return leading ? leading->size() : size_type{}; - } else { - static_assert(Policy == deletion_policy::swap_only, "Unexpected storage policy"); - return leading ? leading->free_list() : size_type{}; - } - } - - /** - * @brief Estimates the number of entities iterated by the view. - * @tparam Pol Dummy template parameter used for sfinae purposes only. - * @return Estimated number of entities iterated by the view. - */ - template<typename..., deletion_policy Pol = Policy> - [[nodiscard]] std::enable_if_t<Pol == deletion_policy::in_place, size_type> size_hint() const noexcept { - return leading ? leading->size() : size_type{}; - } - - /** - * @brief Checks whether a view is empty. - * @tparam Pol Dummy template parameter used for sfinae purposes only. - * @return True if the view is empty, false otherwise. - */ - template<typename..., deletion_policy Pol = Policy> - [[nodiscard]] std::enable_if_t<Pol != deletion_policy::in_place, bool> empty() const noexcept { - if constexpr(Policy == deletion_policy::swap_and_pop) { - return !leading || leading->empty(); - } else { - static_assert(Policy == deletion_policy::swap_only, "Unexpected storage policy"); - return !leading || (leading->free_list() == 0u); - } - } - - /** - * @brief Returns an iterator to the first entity of the view. - * - * If the view is empty, the returned iterator will be equal to `end()`. - * - * @return An iterator to the first entity of the view. - */ - [[nodiscard]] iterator begin() const noexcept { - if constexpr(Policy == deletion_policy::swap_and_pop) { - return leading ? leading->begin() : iterator{}; - } else if constexpr(Policy == deletion_policy::swap_only) { - return leading ? (leading->end() - leading->free_list()) : iterator{}; - } else { - static_assert(Policy == deletion_policy::in_place, "Unexpected storage policy"); - return leading ? iterator{leading->begin(), {leading}, {}, 0u} : iterator{}; - } - } - - /** - * @brief Returns an iterator that is past the last entity of the view. - * @return An iterator to the entity following the last entity of the view. - */ - [[nodiscard]] iterator end() const noexcept { - if constexpr(Policy == deletion_policy::swap_and_pop || Policy == deletion_policy::swap_only) { - return leading ? leading->end() : iterator{}; - } else { - static_assert(Policy == deletion_policy::in_place, "Unexpected storage policy"); - return leading ? iterator{leading->end(), {leading}, {}, 0u} : iterator{}; - } - } - - /** - * @brief Returns an iterator to the first entity of the reversed view. - * - * If the view is empty, the returned iterator will be equal to `rend()`. - * - * @tparam Pol Dummy template parameter used for sfinae purposes only. - * @return An iterator to the first entity of the reversed view. - */ - template<typename..., deletion_policy Pol = Policy> - [[nodiscard]] std::enable_if_t<Pol != deletion_policy::in_place, reverse_iterator> rbegin() const noexcept { - return leading ? leading->rbegin() : reverse_iterator{}; - } - - /** - * @brief Returns an iterator that is past the last entity of the reversed - * view. - * @tparam Pol Dummy template parameter used for sfinae purposes only. - * @return An iterator to the entity following the last entity of the - * reversed view. - */ - template<typename..., deletion_policy Pol = Policy> - [[nodiscard]] std::enable_if_t<Pol != deletion_policy::in_place, reverse_iterator> rend() const noexcept { - if constexpr(Policy == deletion_policy::swap_and_pop) { - return leading ? leading->rend() : reverse_iterator{}; - } else { - static_assert(Policy == deletion_policy::swap_only, "Unexpected storage policy"); - return leading ? (leading->rbegin() + leading->free_list()) : reverse_iterator{}; - } - } - - /** - * @brief Returns the first entity of the view, if any. - * @return The first entity of the view if one exists, the null entity - * otherwise. - */ - [[nodiscard]] entity_type front() const noexcept { - if constexpr(Policy == deletion_policy::swap_and_pop) { - return empty() ? null : *leading->begin(); - } else if constexpr(Policy == deletion_policy::swap_only) { - return empty() ? null : *(leading->end() - leading->free_list()); - } else { - static_assert(Policy == deletion_policy::in_place, "Unexpected storage policy"); - const auto it = begin(); - return (it == end()) ? null : *it; - } - } - - /** - * @brief Returns the last entity of the view, if any. - * @return The last entity of the view if one exists, the null entity - * otherwise. - */ - [[nodiscard]] entity_type back() const noexcept { - if constexpr(Policy == deletion_policy::swap_and_pop || Policy == deletion_policy::swap_only) { - return empty() ? null : *leading->rbegin(); - } else { - static_assert(Policy == deletion_policy::in_place, "Unexpected storage policy"); - - if(leading) { - auto it = leading->rbegin(); - const auto last = leading->rend(); - for(; (it != last) && (*it == tombstone); ++it) {} - return it == last ? null : *it; - } - - return null; - } - } - - /** - * @brief Finds an entity. - * @param entt A valid identifier. - * @return An iterator to the given entity if it's found, past the end - * iterator otherwise. - */ - [[nodiscard]] iterator find(const entity_type entt) const noexcept { - if constexpr(Policy == deletion_policy::swap_and_pop) { - return leading ? leading->find(entt) : iterator{}; - } else if constexpr(Policy == deletion_policy::swap_only) { - const auto it = leading ? leading->find(entt) : iterator{}; - return leading && (static_cast<size_type>(it.index()) < leading->free_list()) ? it : iterator{}; - } else { - const auto it = leading ? leading->find(entt) : typename common_type::iterator{}; - return iterator{it, {leading}, {}, 0u}; - } - } - - /** - * @brief Checks if a view is fully initialized. - * @return True if the view is fully initialized, false otherwise. - */ - [[nodiscard]] explicit operator bool() const noexcept { - return (leading != nullptr); - } - - /** - * @brief Checks if a view contains an entity. - * @param entt A valid identifier. - * @return True if the view contains the given entity, false otherwise. - */ - [[nodiscard]] bool contains(const entity_type entt) const noexcept { - if constexpr(Policy == deletion_policy::swap_and_pop || Policy == deletion_policy::in_place) { - return leading && leading->contains(entt); - } else { - static_assert(Policy == deletion_policy::swap_only, "Unexpected storage policy"); - return leading && leading->contains(entt) && (leading->index(entt) < leading->free_list()); - } - } - -private: - const common_type *leading{}; -}; - -/** - * @brief Storage view specialization. - * - * This specialization offers a boost in terms of performance. It can access the - * underlying data structure directly and avoid superfluous checks. - * - * @sa basic_view - * - * @tparam Get Type of storage iterated by the view. - */ -template<typename Get> -class basic_view<get_t<Get>, exclude_t<>> - : public basic_storage_view<typename Get::base_type, Get::storage_policy> { - using base_type = basic_storage_view<typename Get::base_type, Get::storage_policy>; - -public: - /*! @brief Common type among all storage types. */ - using common_type = typename base_type::common_type; - /*! @brief Underlying entity identifier. */ - using entity_type = typename base_type::entity_type; - /*! @brief Unsigned integer type. */ - using size_type = typename base_type::size_type; - /*! @brief Random access iterator type. */ - using iterator = typename base_type::iterator; - /*! @brief Reverse iterator type. */ - using reverse_iterator = typename base_type::reverse_iterator; - /*! @brief Iterable view type. */ - using iterable = std::conditional_t<Get::storage_policy == deletion_policy::in_place, iterable_adaptor<internal::extended_view_iterator<iterator, Get>>, decltype(std::declval<Get>().each())>; - - /*! @brief Default constructor to use to create empty, invalid views. */ - basic_view() noexcept - : base_type{} {} - - /** - * @brief Constructs a view from a storage class. - * @param value The storage for the type to iterate. - */ - basic_view(Get &value) noexcept - : base_type{&value} { - } - - /** - * @brief Constructs a view from a storage class. - * @param value The storage for the type to iterate. - */ - basic_view(std::tuple<Get &> value, std::tuple<> = {}) noexcept - : basic_view{std::get<0>(value)} {} - - /** - * @brief Returns the storage for a given element type, if any. - * @tparam Type Type of element of which to return the storage. - * @return The storage for the given element type. - */ - template<typename Type = typename Get::element_type> - [[nodiscard]] auto *storage() const noexcept { - static_assert(std::is_same_v<std::remove_const_t<Type>, typename Get::element_type>, "Invalid element type"); - return storage<0>(); - } - - /** - * @brief Returns the storage for a given index, if any. - * @tparam Index Index of the storage to return. - * @return The storage for the given index. - */ - template<std::size_t Index> - [[nodiscard]] auto *storage() const noexcept { - static_assert(Index == 0u, "Index out of bounds"); - return static_cast<Get *>(const_cast<constness_as_t<common_type, Get> *>(base_type::handle())); - } - - /** - * @brief Assigns a storage to a view. - * @param elem A storage to assign to the view. - */ - void storage(Get &elem) noexcept { - storage<0>(elem); - } - - /** - * @brief Assigns a storage to a view. - * @tparam Index Index of the storage to assign to the view. - * @param elem A storage to assign to the view. - */ - template<std::size_t Index> - void storage(Get &elem) noexcept { - static_assert(Index == 0u, "Index out of bounds"); - *this = basic_view{elem}; - } - - /** - * @brief Returns a pointer to the underlying storage. - * @return A pointer to the underlying storage. - */ - [[nodiscard]] Get *operator->() const noexcept { - return storage(); - } - - /** - * @brief Returns the element assigned to the given entity. - * @param entt A valid identifier. - * @return The element assigned to the given entity. - */ - [[nodiscard]] decltype(auto) operator[](const entity_type entt) const { - return storage()->get(entt); - } - - /** - * @brief Returns the element assigned to the given entity. - * @tparam Elem Type of the element to get. - * @param entt A valid identifier. - * @return The element assigned to the entity. - */ - template<typename Elem> - [[nodiscard]] decltype(auto) get(const entity_type entt) const { - static_assert(std::is_same_v<std::remove_const_t<Elem>, typename Get::element_type>, "Invalid element type"); - return get<0>(entt); - } - - /** - * @brief Returns the element assigned to the given entity. - * @tparam Index Index of the element to get. - * @param entt A valid identifier. - * @return The element assigned to the entity. - */ - template<std::size_t... Index> - [[nodiscard]] decltype(auto) get(const entity_type entt) const { - if constexpr(sizeof...(Index) == 0) { - return storage()->get_as_tuple(entt); - } else { - return storage<Index...>()->get(entt); - } - } - - /** - * @brief Iterates entities and elements and applies the given function - * object to them. - * - * The signature of the function must be equivalent to one of the following - * (non-empty types only, constness as requested): - * - * @code{.cpp} - * void(const entity_type, Type &); - * void(typename Type &); - * @endcode - * - * @tparam Func Type of the function object to invoke. - * @param func A valid function object. - */ - template<typename Func> - void each(Func func) const { - if constexpr(is_applicable_v<Func, decltype(std::tuple_cat(std::tuple<entity_type>{}, std::declval<basic_view>().get({})))>) { - for(const auto pack: each()) { - std::apply(func, pack); - } - } else if constexpr(Get::storage_policy == deletion_policy::swap_and_pop || Get::storage_policy == deletion_policy::swap_only) { - if constexpr(std::is_void_v<typename Get::value_type>) { - for(size_type pos = base_type::size(); pos; --pos) { - func(); - } - } else { - if(const auto len = base_type::size(); len != 0u) { - for(auto last = storage()->end(), first = last - len; first != last; ++first) { - func(*first); - } - } - } - } else { - static_assert(Get::storage_policy == deletion_policy::in_place, "Unexpected storage policy"); - - for(const auto pack: each()) { - std::apply([&func](const auto, auto &&...elem) { func(std::forward<decltype(elem)>(elem)...); }, pack); - } - } - } - - /** - * @brief Returns an iterable object to use to _visit_ a view. - * - * The iterable object returns a tuple that contains the current entity and - * a reference to its element if it's a non-empty one. The _constness_ of - * the element is as requested. - * - * @return An iterable object to use to _visit_ the view. - */ - [[nodiscard]] iterable each() const noexcept { - if constexpr(Get::storage_policy == deletion_policy::swap_and_pop || Get::storage_policy == deletion_policy::swap_only) { - return base_type::handle() ? storage()->each() : iterable{}; - } else { - static_assert(Get::storage_policy == deletion_policy::in_place, "Unexpected storage policy"); - return iterable{base_type::begin(), base_type::end()}; - } - } - - /** - * @brief Combines two views in a _more specific_ one. - * @tparam OGet Element list of the view to combine with. - * @tparam OExclude Filter list of the view to combine with. - * @param other The view to combine with. - * @return A more specific view. - */ - template<typename... OGet, typename... OExclude> - [[nodiscard]] auto operator|(const basic_view<get_t<OGet...>, exclude_t<OExclude...>> &other) const noexcept { - return internal::view_pack<basic_view<get_t<Get, OGet...>, exclude_t<OExclude...>>>( - *this, other, std::index_sequence_for<Get>{}, std::index_sequence_for<>{}, std::index_sequence_for<OGet...>{}, std::index_sequence_for<OExclude...>{}); - } -}; - -/** - * @brief Deduction guide. - * @tparam Type Type of storage classes used to create the view. - * @param storage The storage for the types to iterate. - */ -template<typename... Type> -basic_view(Type &...storage) -> basic_view<get_t<Type...>, exclude_t<>>; - -/** - * @brief Deduction guide. - * @tparam Get Types of elements iterated by the view. - * @tparam Exclude Types of elements used to filter the view. - */ -template<typename... Get, typename... Exclude> -basic_view(std::tuple<Get &...>, std::tuple<Exclude &...> = {}) -> basic_view<get_t<Get...>, exclude_t<Exclude...>>; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/entt.hpp b/deps/entt/include/entt/entt.hpp deleted file mode 100644 index a00fed5..0000000 --- a/deps/entt/include/entt/entt.hpp +++ /dev/null @@ -1,67 +0,0 @@ -// IWYU pragma: begin_exports -#include "config/config.h" -#include "config/macro.h" -#include "config/version.h" -#include "container/dense_map.hpp" -#include "container/dense_set.hpp" -#include "container/table.hpp" -#include "core/algorithm.hpp" -#include "core/any.hpp" -#include "core/attribute.h" -#include "core/bit.hpp" -#include "core/compressed_pair.hpp" -#include "core/enum.hpp" -#include "core/family.hpp" -#include "core/hashed_string.hpp" -#include "core/ident.hpp" -#include "core/iterator.hpp" -#include "core/memory.hpp" -#include "core/monostate.hpp" -#include "core/ranges.hpp" -#include "core/tuple.hpp" -#include "core/type_info.hpp" -#include "core/type_traits.hpp" -#include "core/utility.hpp" -#include "entity/component.hpp" -#include "entity/entity.hpp" -#include "entity/group.hpp" -#include "entity/handle.hpp" -#include "entity/helper.hpp" -#include "entity/mixin.hpp" -#include "entity/observer.hpp" -#include "entity/organizer.hpp" -#include "entity/ranges.hpp" -#include "entity/registry.hpp" -#include "entity/runtime_view.hpp" -#include "entity/snapshot.hpp" -#include "entity/sparse_set.hpp" -#include "entity/storage.hpp" -#include "entity/view.hpp" -#include "graph/adjacency_matrix.hpp" -#include "graph/dot.hpp" -#include "graph/flow.hpp" -#include "locator/locator.hpp" -#include "meta/adl_pointer.hpp" -#include "meta/container.hpp" -#include "meta/context.hpp" -#include "meta/factory.hpp" -#include "meta/meta.hpp" -#include "meta/node.hpp" -#include "meta/pointer.hpp" -#include "meta/policy.hpp" -#include "meta/range.hpp" -#include "meta/resolve.hpp" -#include "meta/template.hpp" -#include "meta/type_traits.hpp" -#include "meta/utility.hpp" -#include "poly/poly.hpp" -#include "process/process.hpp" -#include "process/scheduler.hpp" -#include "resource/cache.hpp" -#include "resource/loader.hpp" -#include "resource/resource.hpp" -#include "signal/delegate.hpp" -#include "signal/dispatcher.hpp" -#include "signal/emitter.hpp" -#include "signal/sigh.hpp" -// IWYU pragma: end_exports diff --git a/deps/entt/include/entt/fwd.hpp b/deps/entt/include/entt/fwd.hpp deleted file mode 100644 index 4b6e60c..0000000 --- a/deps/entt/include/entt/fwd.hpp +++ /dev/null @@ -1,11 +0,0 @@ -// IWYU pragma: begin_exports -#include "container/fwd.hpp" -#include "core/fwd.hpp" -#include "entity/fwd.hpp" -#include "graph/fwd.hpp" -#include "meta/fwd.hpp" -#include "poly/fwd.hpp" -#include "process/fwd.hpp" -#include "resource/fwd.hpp" -#include "signal/fwd.hpp" -// IWYU pragma: end_exports diff --git a/deps/entt/include/entt/graph/adjacency_matrix.hpp b/deps/entt/include/entt/graph/adjacency_matrix.hpp deleted file mode 100644 index 85025be..0000000 --- a/deps/entt/include/entt/graph/adjacency_matrix.hpp +++ /dev/null @@ -1,336 +0,0 @@ -#ifndef ENTT_GRAPH_ADJACENCY_MATRIX_HPP -#define ENTT_GRAPH_ADJACENCY_MATRIX_HPP - -#include <cstddef> -#include <iterator> -#include <memory> -#include <type_traits> -#include <utility> -#include <vector> -#include "../config/config.h" -#include "../core/iterator.hpp" -#include "fwd.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename It> -class edge_iterator { - using size_type = std::size_t; - -public: - using value_type = std::pair<size_type, size_type>; - using pointer = input_iterator_pointer<value_type>; - using reference = value_type; - using difference_type = std::ptrdiff_t; - using iterator_category = std::input_iterator_tag; - using iterator_concept = std::forward_iterator_tag; - - constexpr edge_iterator() noexcept = default; - - // NOLINTNEXTLINE(bugprone-easily-swappable-parameters) - constexpr edge_iterator(It base, const size_type vertices, const size_type from, const size_type to, const size_type step) noexcept - : it{std::move(base)}, - vert{vertices}, - pos{from}, - last{to}, - offset{step} { - for(; pos != last && !it[pos]; pos += offset) {} - } - - constexpr edge_iterator &operator++() noexcept { - for(pos += offset; pos != last && !it[pos]; pos += offset) {} - return *this; - } - - constexpr edge_iterator operator++(int) noexcept { - edge_iterator orig = *this; - return ++(*this), orig; - } - - [[nodiscard]] constexpr reference operator*() const noexcept { - return *operator->(); - } - - [[nodiscard]] constexpr pointer operator->() const noexcept { - return std::make_pair<size_type>(pos / vert, pos % vert); - } - - template<typename Type> - friend constexpr bool operator==(const edge_iterator<Type> &, const edge_iterator<Type> &) noexcept; - -private: - It it{}; - size_type vert{}; - size_type pos{}; - size_type last{}; - size_type offset{}; -}; - -template<typename Container> -[[nodiscard]] inline constexpr bool operator==(const edge_iterator<Container> &lhs, const edge_iterator<Container> &rhs) noexcept { - return lhs.pos == rhs.pos; -} - -template<typename Container> -[[nodiscard]] inline constexpr bool operator!=(const edge_iterator<Container> &lhs, const edge_iterator<Container> &rhs) noexcept { - return !(lhs == rhs); -} - -} // namespace internal -/*! @endcond */ - -/** - * @brief Basic implementation of a directed adjacency matrix. - * @tparam Category Either a directed or undirected category tag. - * @tparam Allocator Type of allocator used to manage memory and elements. - */ -template<typename Category, typename Allocator> -class adjacency_matrix { - using alloc_traits = std::allocator_traits<Allocator>; - static_assert(std::is_base_of_v<directed_tag, Category>, "Invalid graph category"); - static_assert(std::is_same_v<typename alloc_traits::value_type, std::size_t>, "Invalid value type"); - using container_type = std::vector<std::size_t, typename alloc_traits::template rebind_alloc<std::size_t>>; - -public: - /*! @brief Allocator type. */ - using allocator_type = Allocator; - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - /*! @brief Vertex type. */ - using vertex_type = size_type; - /*! @brief Edge type. */ - using edge_type = std::pair<vertex_type, vertex_type>; - /*! @brief Vertex iterator type. */ - using vertex_iterator = iota_iterator<vertex_type>; - /*! @brief Edge iterator type. */ - using edge_iterator = internal::edge_iterator<typename container_type::const_iterator>; - /*! @brief Out-edge iterator type. */ - using out_edge_iterator = edge_iterator; - /*! @brief In-edge iterator type. */ - using in_edge_iterator = edge_iterator; - /*! @brief Graph category tag. */ - using graph_category = Category; - - /*! @brief Default constructor. */ - adjacency_matrix() noexcept(noexcept(allocator_type{})) - : adjacency_matrix{0u} { - } - - /** - * @brief Constructs an empty container with a given allocator. - * @param allocator The allocator to use. - */ - explicit adjacency_matrix(const allocator_type &allocator) noexcept - : adjacency_matrix{0u, allocator} {} - - /** - * @brief Constructs an empty container with a given allocator and user - * supplied number of vertices. - * @param vertices Number of vertices. - * @param allocator The allocator to use. - */ - adjacency_matrix(const size_type vertices, const allocator_type &allocator = allocator_type{}) - : matrix{vertices * vertices, allocator}, - vert{vertices} {} - - /*! @brief Default copy constructor. */ - adjacency_matrix(const adjacency_matrix &) = default; - - /** - * @brief Allocator-extended copy constructor. - * @param other The instance to copy from. - * @param allocator The allocator to use. - */ - adjacency_matrix(const adjacency_matrix &other, const allocator_type &allocator) - : matrix{other.matrix, allocator}, - vert{other.vert} {} - - /*! @brief Default move constructor. */ - adjacency_matrix(adjacency_matrix &&) noexcept = default; - - /** - * @brief Allocator-extended move constructor. - * @param other The instance to move from. - * @param allocator The allocator to use. - */ - adjacency_matrix(adjacency_matrix &&other, const allocator_type &allocator) - : matrix{std::move(other.matrix), allocator}, - vert{other.vert} {} - - /*! @brief Default destructor. */ - ~adjacency_matrix() noexcept = default; - - /** - * @brief Default copy assignment operator. - * @return This container. - */ - adjacency_matrix &operator=(const adjacency_matrix &) = default; - - /** - * @brief Default move assignment operator. - * @return This container. - */ - adjacency_matrix &operator=(adjacency_matrix &&) noexcept = default; - - /** - * @brief Returns the associated allocator. - * @return The associated allocator. - */ - [[nodiscard]] constexpr allocator_type get_allocator() const noexcept { - return matrix.get_allocator(); - } - - /*! @brief Clears the adjacency matrix. */ - void clear() noexcept { - matrix.clear(); - vert = {}; - } - - /** - * @brief Exchanges the contents with those of a given adjacency matrix. - * @param other Adjacency matrix to exchange the content with. - */ - void swap(adjacency_matrix &other) { - using std::swap; - swap(matrix, other.matrix); - swap(vert, other.vert); - } - - /** - * @brief Returns true if an adjacency matrix is empty, false otherwise. - * - * @warning - * Potentially expensive, try to avoid it on hot paths. - * - * @return True if the adjacency matrix is empty, false otherwise. - */ - [[nodiscard]] bool empty() const noexcept { - const auto iterable = edges(); - return (iterable.begin() == iterable.end()); - } - - /** - * @brief Returns the number of vertices. - * @return The number of vertices. - */ - [[nodiscard]] size_type size() const noexcept { - return vert; - } - - /** - * @brief Returns an iterable object to visit all vertices of a matrix. - * @return An iterable object to visit all vertices of a matrix. - */ - [[nodiscard]] iterable_adaptor<vertex_iterator> vertices() const noexcept { - return {0u, vert}; - } - - /** - * @brief Returns an iterable object to visit all edges of a matrix. - * @return An iterable object to visit all edges of a matrix. - */ - [[nodiscard]] iterable_adaptor<edge_iterator> edges() const noexcept { - const auto it = matrix.cbegin(); - const auto sz = matrix.size(); - return {{it, vert, 0u, sz, 1u}, {it, vert, sz, sz, 1u}}; - } - - /** - * @brief Returns an iterable object to visit all out-edges of a vertex. - * @param vertex The vertex of which to return all out-edges. - * @return An iterable object to visit all out-edges of a vertex. - */ - [[nodiscard]] iterable_adaptor<out_edge_iterator> out_edges(const vertex_type vertex) const noexcept { - const auto it = matrix.cbegin(); - const auto from = vertex * vert; - const auto to = from + vert; - return {{it, vert, from, to, 1u}, {it, vert, to, to, 1u}}; - } - - /** - * @brief Returns an iterable object to visit all in-edges of a vertex. - * @param vertex The vertex of which to return all in-edges. - * @return An iterable object to visit all in-edges of a vertex. - */ - [[nodiscard]] iterable_adaptor<in_edge_iterator> in_edges(const vertex_type vertex) const noexcept { - const auto it = matrix.cbegin(); - const auto from = vertex; - const auto to = vert * vert + from; - return {{it, vert, from, to, vert}, {it, vert, to, to, vert}}; - } - - /** - * @brief Resizes an adjacency matrix. - * @param vertices The new number of vertices. - */ - void resize(const size_type vertices) { - adjacency_matrix other{vertices, get_allocator()}; - - for(auto [lhs, rhs]: edges()) { - other.insert(lhs, rhs); - } - - other.swap(*this); - } - - /** - * @brief Inserts an edge into the adjacency matrix, if it does not exist. - * @param lhs The left hand vertex of the edge. - * @param rhs The right hand vertex of the edge. - * @return A pair consisting of an iterator to the inserted element (or to - * the element that prevented the insertion) and a bool denoting whether the - * insertion took place. - */ - std::pair<edge_iterator, bool> insert(const vertex_type lhs, const vertex_type rhs) { - const auto pos = lhs * vert + rhs; - - if constexpr(std::is_same_v<graph_category, undirected_tag>) { - const auto rev = rhs * vert + lhs; - ENTT_ASSERT(matrix[pos] == matrix[rev], "Something went really wrong"); - matrix[rev] = 1u; - } - - const auto inserted = !std::exchange(matrix[pos], 1u); - return {edge_iterator{matrix.cbegin(), vert, pos, matrix.size(), 1u}, inserted}; - } - - /** - * @brief Removes the edge associated with a pair of given vertices. - * @param lhs The left hand vertex of the edge. - * @param rhs The right hand vertex of the edge. - * @return Number of elements removed (either 0 or 1). - */ - size_type erase(const vertex_type lhs, const vertex_type rhs) { - const auto pos = lhs * vert + rhs; - - if constexpr(std::is_same_v<graph_category, undirected_tag>) { - const auto rev = rhs * vert + lhs; - ENTT_ASSERT(matrix[pos] == matrix[rev], "Something went really wrong"); - matrix[rev] = 0u; - } - - return std::exchange(matrix[pos], 0u); - } - - /** - * @brief Checks if an adjacency matrix contains a given edge. - * @param lhs The left hand vertex of the edge. - * @param rhs The right hand vertex of the edge. - * @return True if there is such an edge, false otherwise. - */ - [[nodiscard]] bool contains(const vertex_type lhs, const vertex_type rhs) const { - const auto pos = lhs * vert + rhs; - return pos < matrix.size() && matrix[pos]; - } - -private: - container_type matrix; - size_type vert; -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/graph/dot.hpp b/deps/entt/include/entt/graph/dot.hpp deleted file mode 100644 index 1da13e8..0000000 --- a/deps/entt/include/entt/graph/dot.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef ENTT_GRAPH_DOT_HPP -#define ENTT_GRAPH_DOT_HPP - -#include <ostream> -#include <type_traits> -#include "fwd.hpp" - -namespace entt { - -/** - * @brief Outputs a graph in dot format. - * @tparam Graph Graph type, valid as long as it exposes edges and vertices. - * @tparam Writer Vertex decorator type. - * @param out A standard output stream. - * @param graph The graph to output. - * @param writer Vertex decorator object. - */ -template<typename Graph, typename Writer> -void dot(std::ostream &out, const Graph &graph, Writer writer) { - static_assert(std::is_base_of_v<directed_tag, typename Graph::graph_category>, "Invalid graph category"); - - if constexpr(std::is_same_v<typename Graph::graph_category, undirected_tag>) { - out << "graph{"; - } else { - out << "digraph{"; - } - - for(auto &&vertex: graph.vertices()) { - out << vertex << "["; - writer(out, vertex); - out << "];"; - } - - for(auto [lhs, rhs]: graph.edges()) { - if constexpr(std::is_same_v<typename Graph::graph_category, undirected_tag>) { - out << lhs << "--" << rhs << ";"; - } else { - out << lhs << "->" << rhs << ";"; - } - } - - out << "}"; -} - -/** - * @brief Outputs a graph in dot format. - * @tparam Graph Graph type, valid as long as it exposes edges and vertices. - * @param out A standard output stream. - * @param graph The graph to output. - */ -template<typename Graph> -void dot(std::ostream &out, const Graph &graph) { - return dot(out, graph, [](auto &&...) {}); -} - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/graph/flow.hpp b/deps/entt/include/entt/graph/flow.hpp deleted file mode 100644 index 0e3721e..0000000 --- a/deps/entt/include/entt/graph/flow.hpp +++ /dev/null @@ -1,351 +0,0 @@ -#ifndef ENTT_GRAPH_FLOW_HPP -#define ENTT_GRAPH_FLOW_HPP - -#include <algorithm> -#include <cstddef> -#include <functional> -#include <iterator> -#include <memory> -#include <type_traits> -#include <utility> -#include <vector> -#include "../config/config.h" -#include "../container/dense_map.hpp" -#include "../container/dense_set.hpp" -#include "../core/compressed_pair.hpp" -#include "../core/fwd.hpp" -#include "../core/iterator.hpp" -#include "../core/utility.hpp" -#include "adjacency_matrix.hpp" -#include "fwd.hpp" - -namespace entt { - -/** - * @brief Utility class for creating task graphs. - * @tparam Allocator Type of allocator used to manage memory and elements. - */ -template<typename Allocator> -class basic_flow { - using alloc_traits = std::allocator_traits<Allocator>; - static_assert(std::is_same_v<typename alloc_traits::value_type, id_type>, "Invalid value type"); - using task_container_type = dense_set<id_type, identity, std::equal_to<>, typename alloc_traits::template rebind_alloc<id_type>>; - using ro_rw_container_type = std::vector<std::pair<std::size_t, bool>, typename alloc_traits::template rebind_alloc<std::pair<std::size_t, bool>>>; - using deps_container_type = dense_map<id_type, ro_rw_container_type, identity, std::equal_to<>, typename alloc_traits::template rebind_alloc<std::pair<const id_type, ro_rw_container_type>>>; - using adjacency_matrix_type = adjacency_matrix<directed_tag, typename alloc_traits::template rebind_alloc<std::size_t>>; - - void emplace(const id_type res, const bool is_rw) { - ENTT_ASSERT(index.first() < vertices.size(), "Invalid node"); - - if(!deps.contains(res) && sync_on != vertices.size()) { - deps[res].emplace_back(sync_on, true); - } - - deps[res].emplace_back(index.first(), is_rw); - } - - void setup_graph(adjacency_matrix_type &matrix) const { - for(const auto &elem: deps) { - const auto last = elem.second.cend(); - auto it = elem.second.cbegin(); - - while(it != last) { - if(it->second) { - // rw item - if(auto curr = it++; it != last) { - if(it->second) { - matrix.insert(curr->first, it->first); - } else if(const auto next = std::find_if(it, last, [](const auto &value) { return value.second; }); next != last) { - for(; it != next; ++it) { - matrix.insert(curr->first, it->first); - matrix.insert(it->first, next->first); - } - } else { - for(; it != next; ++it) { - matrix.insert(curr->first, it->first); - } - } - } - } else { - // ro item (first iteration only) - if(const auto next = std::find_if(it, last, [](const auto &value) { return value.second; }); next != last) { - for(; it != next; ++it) { - matrix.insert(it->first, next->first); - } - } else { - it = last; - } - } - } - } - } - - void transitive_closure(adjacency_matrix_type &matrix) const { - const auto length = matrix.size(); - - for(std::size_t vk{}; vk < length; ++vk) { - for(std::size_t vi{}; vi < length; ++vi) { - for(std::size_t vj{}; vj < length; ++vj) { - if(matrix.contains(vi, vk) && matrix.contains(vk, vj)) { - matrix.insert(vi, vj); - } - } - } - } - } - - void transitive_reduction(adjacency_matrix_type &matrix) const { - const auto length = matrix.size(); - - for(std::size_t vert{}; vert < length; ++vert) { - matrix.erase(vert, vert); - } - - for(std::size_t vj{}; vj < length; ++vj) { - for(std::size_t vi{}; vi < length; ++vi) { - if(matrix.contains(vi, vj)) { - for(std::size_t vk{}; vk < length; ++vk) { - if(matrix.contains(vj, vk)) { - matrix.erase(vi, vk); - } - } - } - } - } - } - -public: - /*! @brief Allocator type. */ - using allocator_type = Allocator; - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - /*! @brief Iterable task list. */ - using iterable = iterable_adaptor<typename task_container_type::const_iterator>; - /*! @brief Adjacency matrix type. */ - using graph_type = adjacency_matrix_type; - - /*! @brief Default constructor. */ - basic_flow() - : basic_flow{allocator_type{}} {} - - /** - * @brief Constructs a flow builder with a given allocator. - * @param allocator The allocator to use. - */ - explicit basic_flow(const allocator_type &allocator) - : index{0u, allocator}, - vertices{allocator}, - deps{allocator} {} - - /*! @brief Default copy constructor. */ - basic_flow(const basic_flow &) = default; - - /** - * @brief Allocator-extended copy constructor. - * @param other The instance to copy from. - * @param allocator The allocator to use. - */ - basic_flow(const basic_flow &other, const allocator_type &allocator) - : index{other.index.first(), allocator}, - vertices{other.vertices, allocator}, - deps{other.deps, allocator}, - sync_on{other.sync_on} {} - - /*! @brief Default move constructor. */ - basic_flow(basic_flow &&) noexcept = default; - - /** - * @brief Allocator-extended move constructor. - * @param other The instance to move from. - * @param allocator The allocator to use. - */ - basic_flow(basic_flow &&other, const allocator_type &allocator) - : index{other.index.first(), allocator}, - vertices{std::move(other.vertices), allocator}, - deps{std::move(other.deps), allocator}, - sync_on{other.sync_on} {} - - /*! @brief Default destructor. */ - ~basic_flow() noexcept = default; - - /** - * @brief Default copy assignment operator. - * @return This flow builder. - */ - basic_flow &operator=(const basic_flow &) = default; - - /** - * @brief Default move assignment operator. - * @return This flow builder. - */ - basic_flow &operator=(basic_flow &&) noexcept = default; - - /** - * @brief Returns the associated allocator. - * @return The associated allocator. - */ - [[nodiscard]] constexpr allocator_type get_allocator() const noexcept { - return allocator_type{index.second()}; - } - - /** - * @brief Returns the identifier at specified location. - * @param pos Position of the identifier to return. - * @return The requested identifier. - */ - [[nodiscard]] id_type operator[](const size_type pos) const { - return vertices.cbegin()[pos]; - } - - /*! @brief Clears the flow builder. */ - void clear() noexcept { - index.first() = {}; - vertices.clear(); - deps.clear(); - sync_on = {}; - } - - /** - * @brief Exchanges the contents with those of a given flow builder. - * @param other Flow builder to exchange the content with. - */ - void swap(basic_flow &other) { - using std::swap; - std::swap(index, other.index); - std::swap(vertices, other.vertices); - std::swap(deps, other.deps); - std::swap(sync_on, other.sync_on); - } - - /** - * @brief Returns true if a flow builder contains no tasks, false otherwise. - * @return True if the flow builder contains no tasks, false otherwise. - */ - [[nodiscard]] bool empty() const noexcept { - return vertices.empty(); - } - - /** - * @brief Returns the number of tasks. - * @return The number of tasks. - */ - [[nodiscard]] size_type size() const noexcept { - return vertices.size(); - } - - /** - * @brief Binds a task to a flow builder. - * @param value Task identifier. - * @return This flow builder. - */ - basic_flow &bind(const id_type value) { - sync_on += (sync_on == vertices.size()); - const auto it = vertices.emplace(value).first; - index.first() = size_type(it - vertices.begin()); - return *this; - } - - /** - * @brief Turns the current task into a sync point. - * @return This flow builder. - */ - basic_flow &sync() { - ENTT_ASSERT(index.first() < vertices.size(), "Invalid node"); - sync_on = index.first(); - - for(const auto &elem: deps) { - elem.second.emplace_back(sync_on, true); - } - - return *this; - } - - /** - * @brief Assigns a resource to the current task with a given access mode. - * @param res Resource identifier. - * @param is_rw Access mode. - * @return This flow builder. - */ - basic_flow &set(const id_type res, bool is_rw = false) { - emplace(res, is_rw); - return *this; - } - - /** - * @brief Assigns a read-only resource to the current task. - * @param res Resource identifier. - * @return This flow builder. - */ - basic_flow &ro(const id_type res) { - emplace(res, false); - return *this; - } - - /** - * @brief Assigns a range of read-only resources to the current task. - * @tparam It Type of input iterator. - * @param first An iterator to the first element of the range of elements. - * @param last An iterator past the last element of the range of elements. - * @return This flow builder. - */ - template<typename It> - std::enable_if_t<std::is_same_v<std::remove_const_t<typename std::iterator_traits<It>::value_type>, id_type>, basic_flow &> - ro(It first, It last) { - for(; first != last; ++first) { - emplace(*first, false); - } - - return *this; - } - - /** - * @brief Assigns a writable resource to the current task. - * @param res Resource identifier. - * @return This flow builder. - */ - basic_flow &rw(const id_type res) { - emplace(res, true); - return *this; - } - - /** - * @brief Assigns a range of writable resources to the current task. - * @tparam It Type of input iterator. - * @param first An iterator to the first element of the range of elements. - * @param last An iterator past the last element of the range of elements. - * @return This flow builder. - */ - template<typename It> - std::enable_if_t<std::is_same_v<std::remove_const_t<typename std::iterator_traits<It>::value_type>, id_type>, basic_flow &> - rw(It first, It last) { - for(; first != last; ++first) { - emplace(*first, true); - } - - return *this; - } - - /** - * @brief Generates a task graph for the current content. - * @return The adjacency matrix of the task graph. - */ - [[nodiscard]] graph_type graph() const { - graph_type matrix{vertices.size(), get_allocator()}; - - setup_graph(matrix); - transitive_closure(matrix); - transitive_reduction(matrix); - - return matrix; - } - -private: - compressed_pair<size_type, allocator_type> index; - task_container_type vertices; - deps_container_type deps; - size_type sync_on{}; -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/graph/fwd.hpp b/deps/entt/include/entt/graph/fwd.hpp deleted file mode 100644 index 963082f..0000000 --- a/deps/entt/include/entt/graph/fwd.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef ENTT_GRAPH_FWD_HPP -#define ENTT_GRAPH_FWD_HPP - -#include <cstddef> -#include <memory> -#include "../core/fwd.hpp" - -namespace entt { - -/*! @brief Undirected graph category tag. */ -struct directed_tag {}; - -/*! @brief Directed graph category tag. */ -struct undirected_tag: directed_tag {}; - -template<typename, typename = std::allocator<std::size_t>> -class adjacency_matrix; - -template<typename = std::allocator<id_type>> -class basic_flow; - -/*! @brief Alias declaration for the most common use case. */ -using flow = basic_flow<>; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/locator/locator.hpp b/deps/entt/include/entt/locator/locator.hpp deleted file mode 100644 index dd80b5b..0000000 --- a/deps/entt/include/entt/locator/locator.hpp +++ /dev/null @@ -1,158 +0,0 @@ -#ifndef ENTT_LOCATOR_LOCATOR_HPP -#define ENTT_LOCATOR_LOCATOR_HPP - -#include <memory> -#include <utility> -#include "../config/config.h" - -namespace entt { - -/** - * @brief Service locator, nothing more. - * - * A service locator is used to do what it promises: locate services.<br/> - * Usually service locators are tightly bound to the services they expose and - * thus it's hard to define a general purpose class to do that. This tiny class - * tries to fill the gap and to get rid of the burden of defining a different - * specific locator for each application. - * - * @note - * Users shouldn't retain references to a service. The recommended way is to - * retrieve the service implementation currently set each and every time the - * need for it arises. The risk is to incur in unexpected behaviors otherwise. - * - * @tparam Service Service type. - */ -template<typename Service> -class locator final { - class service_handle { - friend class locator<Service>; - std::shared_ptr<Service> value{}; - }; - -public: - /*! @brief Service type. */ - using type = Service; - /*! @brief Service node type. */ - using node_type = service_handle; - - /*! @brief Default constructor, deleted on purpose. */ - locator() = delete; - - /*! @brief Default copy constructor, deleted on purpose. */ - locator(const locator &) = delete; - - /*! @brief Default destructor, deleted on purpose. */ - ~locator() noexcept = delete; - - /** - * @brief Default copy assignment operator, deleted on purpose. - * @return This locator. - */ - locator &operator=(const locator &) = delete; - - /** - * @brief Checks whether a service locator contains a value. - * @return True if the service locator contains a value, false otherwise. - */ - [[nodiscard]] static bool has_value() noexcept { - return (service != nullptr); - } - - /** - * @brief Returns a reference to a valid service, if any. - * - * @warning - * Invoking this function can result in undefined behavior if the service - * hasn't been set yet. - * - * @return A reference to the service currently set, if any. - */ - [[nodiscard]] static Service &value() noexcept { - ENTT_ASSERT(has_value(), "Service not available"); - return *service; - } - - /** - * @brief Returns a service if available or sets it from a fallback type. - * - * Arguments are used only if a service doesn't already exist. In all other - * cases, they are discarded. - * - * @tparam Args Types of arguments to use to construct the fallback service. - * @tparam Type Fallback service type. - * @param args Parameters to use to construct the fallback service. - * @return A reference to a valid service. - */ - template<typename Type = Service, typename... Args> - [[nodiscard]] static Service &value_or(Args &&...args) { - return service ? *service : emplace<Type>(std::forward<Args>(args)...); - } - - /** - * @brief Sets or replaces a service. - * @tparam Type Service type. - * @tparam Args Types of arguments to use to construct the service. - * @param args Parameters to use to construct the service. - * @return A reference to a valid service. - */ - template<typename Type = Service, typename... Args> - static Service &emplace(Args &&...args) { - service = std::make_shared<Type>(std::forward<Args>(args)...); - return *service; - } - - /** - * @brief Sets or replaces a service using a given allocator. - * @tparam Type Service type. - * @tparam Allocator Type of allocator used to manage memory and elements. - * @tparam Args Types of arguments to use to construct the service. - * @param alloc The allocator to use. - * @param args Parameters to use to construct the service. - * @return A reference to a valid service. - */ - template<typename Type = Service, typename Allocator, typename... Args> - static Service &emplace(std::allocator_arg_t, Allocator alloc, Args &&...args) { - service = std::allocate_shared<Type>(alloc, std::forward<Args>(args)...); - return *service; - } - - /** - * @brief Returns a handle to the underlying service. - * @return A handle to the underlying service. - */ - static node_type handle() noexcept { - node_type node{}; - node.value = service; - return node; - } - - /** - * @brief Resets or replaces a service. - * @param other Optional handle with which to replace the service. - */ - static void reset(const node_type &other = {}) noexcept { - service = other.value; - } - - /** - * @brief Resets or replaces a service. - * @tparam Type Service type. - * @tparam Deleter Deleter type. - * @param elem A pointer to a service to manage. - * @param deleter A deleter to use to destroy the service. - */ - template<typename Type, typename Deleter = std::default_delete<Type>> - static void reset(Type *elem, Deleter deleter = {}) { - service = std::shared_ptr<Service>{elem, std::move(deleter)}; - } - -private: - // std::shared_ptr because of its type erased allocator which is useful here - // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) - inline static std::shared_ptr<Service> service{}; -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/meta/adl_pointer.hpp b/deps/entt/include/entt/meta/adl_pointer.hpp deleted file mode 100644 index 5bb768a..0000000 --- a/deps/entt/include/entt/meta/adl_pointer.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef ENTT_META_ADL_POINTER_HPP -#define ENTT_META_ADL_POINTER_HPP - -namespace entt { - -/** - * @brief ADL based lookup function for dereferencing meta pointer-like types. - * @tparam Type Element type. - * @param value A pointer-like object. - * @return The value returned from the dereferenced pointer. - */ -template<typename Type> -decltype(auto) dereference_meta_pointer_like(const Type &value) { - return *value; -} - -/** - * @brief Fake ADL based lookup function for meta pointer-like types. - * @tparam Type Element type. - */ -template<typename Type> -struct adl_meta_pointer_like { - /** - * @brief Uses the default ADL based lookup method to resolve the call. - * @param value A pointer-like object. - * @return The value returned from the dereferenced pointer. - */ - static decltype(auto) dereference(const Type &value) { - return dereference_meta_pointer_like(value); - } -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/meta/container.hpp b/deps/entt/include/entt/meta/container.hpp deleted file mode 100644 index ca645a9..0000000 --- a/deps/entt/include/entt/meta/container.hpp +++ /dev/null @@ -1,388 +0,0 @@ -// IWYU pragma: always_keep - -#ifndef ENTT_META_CONTAINER_HPP -#define ENTT_META_CONTAINER_HPP - -#include <array> -#include <deque> -#include <iterator> -#include <list> -#include <map> -#include <set> -#include <type_traits> -#include <unordered_map> -#include <unordered_set> -#include <vector> -#include "../container/dense_map.hpp" -#include "../container/dense_set.hpp" -#include "context.hpp" -#include "meta.hpp" -#include "type_traits.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename, typename = void> -struct fixed_size_sequence_container: std::true_type {}; - -template<typename Type> -struct fixed_size_sequence_container<Type, std::void_t<decltype(&Type::clear)>>: std::false_type {}; - -template<typename Type> -inline constexpr bool fixed_size_sequence_container_v = fixed_size_sequence_container<Type>::value; - -template<typename, typename = void> -struct key_only_associative_container: std::true_type {}; - -template<typename Type> -struct key_only_associative_container<Type, std::void_t<typename Type::mapped_type>>: std::false_type {}; - -template<typename Type> -inline constexpr bool key_only_associative_container_v = key_only_associative_container<Type>::value; - -template<typename, typename = void> -struct reserve_aware_container: std::false_type {}; - -template<typename Type> -struct reserve_aware_container<Type, std::void_t<decltype(&Type::reserve)>>: std::true_type {}; - -template<typename Type> -inline constexpr bool reserve_aware_container_v = reserve_aware_container<Type>::value; - -} // namespace internal -/*! @endcond */ - -/** - * @brief General purpose implementation of meta sequence container traits. - * @tparam Type Type of underlying sequence container. - */ -template<typename Type> -struct basic_meta_sequence_container_traits { - static_assert(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>, "Unexpected type"); - - /*! @brief Unsigned integer type. */ - using size_type = typename meta_sequence_container::size_type; - /*! @brief Meta iterator type. */ - using iterator = typename meta_sequence_container::iterator; - - /*! @brief True in case of key-only containers, false otherwise. */ - static constexpr bool fixed_size = internal::fixed_size_sequence_container_v<Type>; - - /** - * @brief Returns the number of elements in a container. - * @param container Opaque pointer to a container of the given type. - * @return Number of elements. - */ - [[nodiscard]] static size_type size(const void *container) { - return static_cast<const Type *>(container)->size(); - } - - /** - * @brief Clears a container. - * @param container Opaque pointer to a container of the given type. - * @return True in case of success, false otherwise. - */ - [[nodiscard]] static bool clear([[maybe_unused]] void *container) { - if constexpr(fixed_size) { - return false; - } else { - static_cast<Type *>(container)->clear(); - return true; - } - } - - /** - * @brief Increases the capacity of a container. - * @param container Opaque pointer to a container of the given type. - * @param sz Desired capacity. - * @return True in case of success, false otherwise. - */ - [[nodiscard]] static bool reserve([[maybe_unused]] void *container, [[maybe_unused]] const size_type sz) { - if constexpr(internal::reserve_aware_container_v<Type>) { - static_cast<Type *>(container)->reserve(sz); - return true; - } else { - return false; - } - } - - /** - * @brief Resizes a container. - * @param container Opaque pointer to a container of the given type. - * @param sz The new number of elements. - * @return True in case of success, false otherwise. - */ - [[nodiscard]] static bool resize([[maybe_unused]] void *container, [[maybe_unused]] const size_type sz) { - if constexpr(fixed_size || !std::is_default_constructible_v<typename Type::value_type>) { - return false; - } else { - static_cast<Type *>(container)->resize(sz); - return true; - } - } - - /** - * @brief Returns a possibly const iterator to the beginning. - * @param area The context to pass to the newly created iterator. - * @param container Opaque pointer to a container of the given type. - * @param as_const Const opaque pointer fallback. - * @return An iterator to the first element of the container. - */ - static iterator begin(const meta_ctx &area, void *container, const void *as_const) { - return container ? iterator{area, static_cast<Type *>(container)->begin()} - : iterator{area, static_cast<const Type *>(as_const)->begin()}; - } - - /** - * @brief Returns a possibly const iterator to the end. - * @param area The context to pass to the newly created iterator. - * @param container Opaque pointer to a container of the given type. - * @param as_const Const opaque pointer fallback. - * @return An iterator that is past the last element of the container. - */ - static iterator end(const meta_ctx &area, void *container, const void *as_const) { - return container ? iterator{area, static_cast<Type *>(container)->end()} - : iterator{area, static_cast<const Type *>(as_const)->end()}; - } - - /** - * @brief Assigns one element to a container and constructs its object from - * a given opaque instance. - * @param area The context to pass to the newly created iterator. - * @param container Opaque pointer to a container of the given type. - * @param value Optional opaque instance of the object to construct (as - * value type). - * @param cref Optional opaque instance of the object to construct (as - * decayed const reference type). - * @param it Iterator before which the element will be inserted. - * @return A possibly invalid iterator to the inserted element. - */ - [[nodiscard]] static iterator insert([[maybe_unused]] const meta_ctx &area, [[maybe_unused]] void *container, [[maybe_unused]] const void *value, [[maybe_unused]] const void *cref, [[maybe_unused]] const iterator &it) { - if constexpr(fixed_size) { - return iterator{}; - } else { - auto *const non_const = any_cast<typename Type::iterator>(&it.base()); - return {area, static_cast<Type *>(container)->insert( - non_const ? *non_const : any_cast<const typename Type::const_iterator &>(it.base()), - value ? *static_cast<const typename Type::value_type *>(value) : *static_cast<const std::remove_reference_t<typename Type::const_reference> *>(cref))}; - } - } - - /** - * @brief Erases an element from a container. - * @param area The context to pass to the newly created iterator. - * @param container Opaque pointer to a container of the given type. - * @param it An opaque iterator to the element to erase. - * @return A possibly invalid iterator following the last removed element. - */ - [[nodiscard]] static iterator erase([[maybe_unused]] const meta_ctx &area, [[maybe_unused]] void *container, [[maybe_unused]] const iterator &it) { - if constexpr(fixed_size) { - return iterator{}; - } else { - auto *const non_const = any_cast<typename Type::iterator>(&it.base()); - return {area, static_cast<Type *>(container)->erase(non_const ? *non_const : any_cast<const typename Type::const_iterator &>(it.base()))}; - } - } -}; - -/** - * @brief General purpose implementation of meta associative container traits. - * @tparam Type Type of underlying associative container. - */ -template<typename Type> -struct basic_meta_associative_container_traits { - static_assert(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>, "Unexpected type"); - - /*! @brief Unsigned integer type. */ - using size_type = typename meta_associative_container::size_type; - /*! @brief Meta iterator type. */ - using iterator = typename meta_associative_container::iterator; - - /*! @brief True in case of key-only containers, false otherwise. */ - static constexpr bool key_only = internal::key_only_associative_container_v<Type>; - - /** - * @brief Returns the number of elements in a container. - * @param container Opaque pointer to a container of the given type. - * @return Number of elements. - */ - [[nodiscard]] static size_type size(const void *container) { - return static_cast<const Type *>(container)->size(); - } - - /** - * @brief Clears a container. - * @param container Opaque pointer to a container of the given type. - * @return True in case of success, false otherwise. - */ - [[nodiscard]] static bool clear(void *container) { - static_cast<Type *>(container)->clear(); - return true; - } - - /** - * @brief Increases the capacity of a container. - * @param container Opaque pointer to a container of the given type. - * @param sz Desired capacity. - * @return True in case of success, false otherwise. - */ - [[nodiscard]] static bool reserve([[maybe_unused]] void *container, [[maybe_unused]] const size_type sz) { - if constexpr(internal::reserve_aware_container_v<Type>) { - static_cast<Type *>(container)->reserve(sz); - return true; - } else { - return false; - } - } - - /** - * @brief Returns a possibly const iterator to the beginning. - * @param area The context to pass to the newly created iterator. - * @param container Opaque pointer to a container of the given type. - * @param as_const Const opaque pointer fallback. - * @return An iterator to the first element of the container. - */ - static iterator begin(const meta_ctx &area, void *container, const void *as_const) { - return container ? iterator{area, std::bool_constant<key_only>{}, static_cast<Type *>(container)->begin()} - : iterator{area, std::bool_constant<key_only>{}, static_cast<const Type *>(as_const)->begin()}; - } - - /** - * @brief Returns a possibly const iterator to the end. - * @param area The context to pass to the newly created iterator. - * @param container Opaque pointer to a container of the given type. - * @param as_const Const opaque pointer fallback. - * @return An iterator that is past the last element of the container. - */ - static iterator end(const meta_ctx &area, void *container, const void *as_const) { - return container ? iterator{area, std::bool_constant<key_only>{}, static_cast<Type *>(container)->end()} - : iterator{area, std::bool_constant<key_only>{}, static_cast<const Type *>(as_const)->end()}; - } - - /** - * @brief Inserts an element into a container, if the key does not exist. - * @param container Opaque pointer to a container of the given type. - * @param key An opaque key value of an element to insert. - * @param value Optional opaque value to insert (key-value containers). - * @return True if the insertion took place, false otherwise. - */ - [[nodiscard]] static bool insert(void *container, const void *key, [[maybe_unused]] const void *value) { - if constexpr(key_only) { - return static_cast<Type *>(container)->insert(*static_cast<const typename Type::key_type *>(key)).second; - } else { - return static_cast<Type *>(container)->emplace(*static_cast<const typename Type::key_type *>(key), *static_cast<const typename Type::mapped_type *>(value)).second; - } - } - - /** - * @brief Removes an element from a container. - * @param container Opaque pointer to a container of the given type. - * @param key An opaque key value of an element to remove. - * @return Number of elements removed (either 0 or 1). - */ - [[nodiscard]] static size_type erase(void *container, const void *key) { - return static_cast<Type *>(container)->erase(*static_cast<const typename Type::key_type *>(key)); - } - - /** - * @brief Finds an element with a given key. - * @param area The context to pass to the newly created iterator. - * @param container Opaque pointer to a container of the given type. - * @param as_const Const opaque pointer fallback. - * @param key Opaque key value of an element to search for. - * @return An iterator to the element with the given key, if any. - */ - static iterator find(const meta_ctx &area, void *container, const void *as_const, const void *key) { - return container ? iterator{area, std::bool_constant<key_only>{}, static_cast<Type *>(container)->find(*static_cast<const typename Type::key_type *>(key))} - : iterator{area, std::bool_constant<key_only>{}, static_cast<const Type *>(as_const)->find(*static_cast<const typename Type::key_type *>(key))}; - } -}; - -/** - * @brief Meta sequence container traits for `std::vector`s of any type. - * @tparam Args Template arguments for the container. - */ -template<typename... Args> -struct meta_sequence_container_traits<std::vector<Args...>> - : basic_meta_sequence_container_traits<std::vector<Args...>> {}; - -/** - * @brief Meta sequence container traits for `std::array`s of any type. - * @tparam Type Template arguments for the container. - * @tparam N Template arguments for the container. - */ -template<typename Type, auto N> -struct meta_sequence_container_traits<std::array<Type, N>> - : basic_meta_sequence_container_traits<std::array<Type, N>> {}; - -/** - * @brief Meta sequence container traits for `std::list`s of any type. - * @tparam Args Template arguments for the container. - */ -template<typename... Args> -struct meta_sequence_container_traits<std::list<Args...>> - : basic_meta_sequence_container_traits<std::list<Args...>> {}; - -/** - * @brief Meta sequence container traits for `std::deque`s of any type. - * @tparam Args Template arguments for the container. - */ -template<typename... Args> -struct meta_sequence_container_traits<std::deque<Args...>> - : basic_meta_sequence_container_traits<std::deque<Args...>> {}; - -/** - * @brief Meta associative container traits for `std::map`s of any type. - * @tparam Args Template arguments for the container. - */ -template<typename... Args> -struct meta_associative_container_traits<std::map<Args...>> - : basic_meta_associative_container_traits<std::map<Args...>> {}; - -/** - * @brief Meta associative container traits for `std::unordered_map`s of any - * type. - * @tparam Args Template arguments for the container. - */ -template<typename... Args> -struct meta_associative_container_traits<std::unordered_map<Args...>> - : basic_meta_associative_container_traits<std::unordered_map<Args...>> {}; - -/** - * @brief Meta associative container traits for `std::set`s of any type. - * @tparam Args Template arguments for the container. - */ -template<typename... Args> -struct meta_associative_container_traits<std::set<Args...>> - : basic_meta_associative_container_traits<std::set<Args...>> {}; - -/** - * @brief Meta associative container traits for `std::unordered_set`s of any - * type. - * @tparam Args Template arguments for the container. - */ -template<typename... Args> -struct meta_associative_container_traits<std::unordered_set<Args...>> - : basic_meta_associative_container_traits<std::unordered_set<Args...>> {}; - -/** - * @brief Meta associative container traits for `dense_map`s of any type. - * @tparam Args Template arguments for the container. - */ -template<typename... Args> -struct meta_associative_container_traits<dense_map<Args...>> - : basic_meta_associative_container_traits<dense_map<Args...>> {}; - -/** - * @brief Meta associative container traits for `dense_set`s of any type. - * @tparam Args Template arguments for the container. - */ -template<typename... Args> -struct meta_associative_container_traits<dense_set<Args...>> - : basic_meta_associative_container_traits<dense_set<Args...>> {}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/meta/context.hpp b/deps/entt/include/entt/meta/context.hpp deleted file mode 100644 index cb26a72..0000000 --- a/deps/entt/include/entt/meta/context.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef ENTT_META_CTX_HPP -#define ENTT_META_CTX_HPP - -#include "../container/dense_map.hpp" -#include "../core/fwd.hpp" -#include "../core/utility.hpp" - -namespace entt { - -class meta_ctx; - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -struct meta_type_node; - -struct meta_context { - dense_map<id_type, meta_type_node, identity> value{}; - - [[nodiscard]] inline static meta_context &from(meta_ctx &ctx); - [[nodiscard]] inline static const meta_context &from(const meta_ctx &ctx); -}; - -} // namespace internal -/*! @endcond */ - -/*! @brief Disambiguation tag for constructors and the like. */ -class meta_ctx_arg_t final {}; - -/*! @brief Constant of type meta_context_arg_t used to disambiguate calls. */ -inline constexpr meta_ctx_arg_t meta_ctx_arg{}; - -/*! @brief Opaque meta context type. */ -class meta_ctx: private internal::meta_context { - // attorney idiom like model to access the base class - friend struct internal::meta_context; -}; - -/*! @cond TURN_OFF_DOXYGEN */ -[[nodiscard]] inline internal::meta_context &internal::meta_context::from(meta_ctx &ctx) { - return ctx; -} - -[[nodiscard]] inline const internal::meta_context &internal::meta_context::from(const meta_ctx &ctx) { - return ctx; -} -/*! @endcond */ - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/meta/factory.hpp b/deps/entt/include/entt/meta/factory.hpp deleted file mode 100644 index 1732d25..0000000 --- a/deps/entt/include/entt/meta/factory.hpp +++ /dev/null @@ -1,668 +0,0 @@ -#ifndef ENTT_META_FACTORY_HPP -#define ENTT_META_FACTORY_HPP - -#include <cstddef> -#include <cstdint> -#include <functional> -#include <memory> -#include <tuple> -#include <type_traits> -#include <utility> -#include "../config/config.h" -#include "../core/bit.hpp" -#include "../core/fwd.hpp" -#include "../core/type_info.hpp" -#include "../core/type_traits.hpp" -#include "../locator/locator.hpp" -#include "context.hpp" -#include "meta.hpp" -#include "node.hpp" -#include "policy.hpp" -#include "range.hpp" -#include "resolve.hpp" -#include "utility.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -class basic_meta_factory { - using invoke_type = std::remove_pointer_t<decltype(meta_func_node::invoke)>; - - auto *find_overload() { - auto *curr = &details->func[bucket]; - - while(curr->invoke != invoke) { - curr = curr->next.get(); - } - - return curr; - } - -protected: - void type(const id_type id) noexcept { - auto &&elem = meta_context::from(*ctx).value[parent]; - ENTT_ASSERT(elem.id == id || !resolve(*ctx, id), "Duplicate identifier"); - invoke = nullptr; - bucket = parent; - elem.id = id; - } - - void base(const id_type id, meta_base_node node) { - details->base.insert_or_assign(id, node); - invoke = nullptr; - bucket = parent; - } - - void conv(const id_type id, meta_conv_node node) { - details->conv.insert_or_assign(id, node); - invoke = nullptr; - bucket = parent; - } - - void ctor(const id_type id, meta_ctor_node node) { - details->ctor.insert_or_assign(id, node); - invoke = nullptr; - bucket = parent; - } - - void dtor(meta_dtor_node node) { - meta_context::from(*ctx).value[parent].dtor = node; - invoke = nullptr; - bucket = parent; - } - - void data(const id_type id, meta_data_node node) { - if(auto it = details->data.find(id); it == details->data.end()) { - details->data.insert_or_assign(id, std::move(node)); - } else if(it->second.set != node.set || it->second.get != node.get) { - it->second = std::move(node); - } - - invoke = nullptr; - bucket = id; - } - - void func(const id_type id, meta_func_node node) { - if(auto it = details->func.find(id); it == details->func.end()) { - auto &&elem = details->func.insert_or_assign(id, std::move(node)).first; - invoke = elem->second.invoke; - bucket = id; - } else { - auto *curr = &it->second; - - while(curr->invoke != node.invoke && curr->next) { - curr = curr->next.get(); - } - - if(curr->invoke == node.invoke) { - invoke = curr->invoke; - } else { - invoke = node.invoke; - curr->next = std::make_shared<meta_func_node>(); - *curr->next = std::move(node); - } - - bucket = id; - } - } - - void prop(const id_type key, meta_prop_node value) { - if(bucket == parent) { - details->prop[key] = std::move(value); - } else if(invoke == nullptr) { - details->data[bucket].prop[key] = std::move(value); - } else { - find_overload()->prop[key] = std::move(value); - } - } - - void traits(const meta_traits value) { - if(bucket == parent) { - meta_context::from(*ctx).value[bucket].traits |= value; - } else if(invoke == nullptr) { - details->data[bucket].traits |= value; - } else { - find_overload()->traits |= value; - } - } - - void custom(meta_custom_node node) { - if(bucket == parent) { - meta_context::from(*ctx).value[bucket].custom = std::move(node); - } else if(invoke == nullptr) { - details->data[bucket].custom = std::move(node); - } else { - find_overload()->custom = std::move(node); - } - } - -public: - basic_meta_factory(const id_type id, meta_ctx &area) - : ctx{&area}, - parent{id}, - bucket{id} { - auto &&elem = meta_context::from(*ctx).value[parent]; - - if(!elem.details) { - elem.details = std::make_shared<meta_type_descriptor>(); - } - - details = elem.details.get(); - } - -private: - meta_ctx *ctx{}; - id_type parent{}; - id_type bucket{}; - invoke_type *invoke{}; - meta_type_descriptor *details{}; -}; - -} // namespace internal -/*! @endcond */ - -/** - * @brief Meta factory to be used for reflection purposes. - * @tparam Type Reflected type for which the factory was created. - */ -template<typename Type> -class meta_factory: private internal::basic_meta_factory { - using base_type = internal::basic_meta_factory; - - template<typename Setter, auto Getter, typename Policy, std::size_t... Index> - void data(const id_type id, std::index_sequence<Index...>) noexcept { - using data_type = std::invoke_result_t<decltype(Getter), Type &>; - using args_type = type_list<typename meta_function_helper_t<Type, decltype(value_list_element_v<Index, Setter>)>::args_type...>; - static_assert(Policy::template value<data_type>, "Invalid return type for the given policy"); - - base_type::data( - id, - internal::meta_data_node{ - /* this is never static */ - (std::is_member_object_pointer_v<decltype(value_list_element_v<Index, Setter>)> && ... && std::is_const_v<std::remove_reference_t<data_type>>) ? internal::meta_traits::is_const : internal::meta_traits::is_none, - Setter::size, - &internal::resolve<std::remove_cv_t<std::remove_reference_t<data_type>>>, - &meta_arg<type_list<type_list_element_t<type_list_element_t<Index, args_type>::size != 1u, type_list_element_t<Index, args_type>>...>>, - +[](meta_handle instance, meta_any value) { return (meta_setter<Type, value_list_element_v<Index, Setter>>(*instance.operator->(), value.as_ref()) || ...); }, - &meta_getter<Type, Getter, Policy>}); - } - -public: - /*! @brief Default constructor. */ - meta_factory() noexcept - : internal::basic_meta_factory{type_id<Type>(), locator<meta_ctx>::value_or()} {} - - /** - * @brief Context aware constructor. - * @param area The context into which to construct meta types. - */ - meta_factory(meta_ctx &area) noexcept - : internal::basic_meta_factory{type_id<Type>().hash(), area} {} - - /** - * @brief Assigns a custom unique identifier to a meta type. - * @param id A custom unique identifier. - * @return A meta factory for the given type. - */ - meta_factory type(const id_type id) noexcept { - base_type::type(id); - return *this; - } - - /** - * @brief Assigns a meta base to a meta type. - * - * A reflected base class must be a real base class of the reflected type. - * - * @tparam Base Type of the base class to assign to the meta type. - * @return A meta factory for the parent type. - */ - template<typename Base> - meta_factory base() noexcept { - static_assert(!std::is_same_v<Type, Base> && std::is_base_of_v<Base, Type>, "Invalid base type"); - auto *const op = +[](const void *instance) noexcept { return static_cast<const void *>(static_cast<const Base *>(static_cast<const Type *>(instance))); }; - base_type::base(type_id<Base>().hash(), internal::meta_base_node{&internal::resolve<Base>, op}); - return *this; - } - - /** - * @brief Assigns a meta conversion function to a meta type. - * - * Conversion functions can be either free functions or member - * functions.<br/> - * In case of free functions, they must accept a const reference to an - * instance of the parent type as an argument. In case of member functions, - * they should have no arguments at all. - * - * @tparam Candidate The actual function to use for the conversion. - * @return A meta factory for the parent type. - */ - template<auto Candidate> - auto conv() noexcept { - using conv_type = std::remove_cv_t<std::remove_reference_t<std::invoke_result_t<decltype(Candidate), Type &>>>; - auto *const op = +[](const meta_ctx &area, const void *instance) { return forward_as_meta(area, std::invoke(Candidate, *static_cast<const Type *>(instance))); }; - base_type::conv(type_id<conv_type>().hash(), internal::meta_conv_node{op}); - return *this; - } - - /** - * @brief Assigns a meta conversion function to a meta type. - * - * The given type must be such that an instance of the reflected type can be - * converted to it. - * - * @tparam To Type of the conversion function to assign to the meta type. - * @return A meta factory for the parent type. - */ - template<typename To> - meta_factory conv() noexcept { - using conv_type = std::remove_cv_t<std::remove_reference_t<To>>; - auto *const op = +[](const meta_ctx &area, const void *instance) { return forward_as_meta(area, static_cast<To>(*static_cast<const Type *>(instance))); }; - base_type::conv(type_id<conv_type>().hash(), internal::meta_conv_node{op}); - return *this; - } - - /** - * @brief Assigns a meta constructor to a meta type. - * - * Both member functions and free function can be assigned to meta types in - * the role of constructors. All that is required is that they return an - * instance of the underlying type.<br/> - * From a client's point of view, nothing changes if a constructor of a meta - * type is a built-in one or not. - * - * @tparam Candidate The actual function to use as a constructor. - * @tparam Policy Optional policy (no policy set by default). - * @return A meta factory for the parent type. - */ - template<auto Candidate, typename Policy = as_is_t> - meta_factory ctor() noexcept { - using descriptor = meta_function_helper_t<Type, decltype(Candidate)>; - static_assert(Policy::template value<typename descriptor::return_type>, "Invalid return type for the given policy"); - static_assert(std::is_same_v<std::remove_cv_t<std::remove_reference_t<typename descriptor::return_type>>, Type>, "The function doesn't return an object of the required type"); - base_type::ctor(type_id<typename descriptor::args_type>().hash(), internal::meta_ctor_node{descriptor::args_type::size, &meta_arg<typename descriptor::args_type>, &meta_construct<Type, Candidate, Policy>}); - return *this; - } - - /** - * @brief Assigns a meta constructor to a meta type. - * - * A meta constructor is uniquely identified by the types of its arguments - * and is such that there exists an actual constructor of the underlying - * type that can be invoked with parameters whose types are those given. - * - * @tparam Args Types of arguments to use to construct an instance. - * @return A meta factory for the parent type. - */ - template<typename... Args> - meta_factory ctor() noexcept { - // default constructor is already implicitly generated, no need for redundancy - if constexpr(sizeof...(Args) != 0u) { - using descriptor = meta_function_helper_t<Type, Type (*)(Args...)>; - base_type::ctor(type_id<typename descriptor::args_type>().hash(), internal::meta_ctor_node{descriptor::args_type::size, &meta_arg<typename descriptor::args_type>, &meta_construct<Type, Args...>}); - } - - return *this; - } - - /** - * @brief Assigns a meta destructor to a meta type. - * - * Both free functions and member functions can be assigned to meta types in - * the role of destructors.<br/> - * The signature of a free function should be identical to the following: - * - * @code{.cpp} - * void(Type &); - * @endcode - * - * Member functions should not take arguments instead.<br/> - * The purpose is to give users the ability to free up resources that - * require special treatment before an object is actually destroyed. - * - * @tparam Func The actual function to use as a destructor. - * @return A meta factory for the parent type. - */ - template<auto Func> - meta_factory dtor() noexcept { - static_assert(std::is_invocable_v<decltype(Func), Type &>, "The function doesn't accept an object of the type provided"); - auto *const op = +[](void *instance) { std::invoke(Func, *static_cast<Type *>(instance)); }; - base_type::dtor(internal::meta_dtor_node{op}); - return *this; - } - - /** - * @brief Assigns a meta data to a meta type. - * - * Both data members and static and global variables, as well as constants - * of any kind, can be assigned to a meta type.<br/> - * From a client's point of view, all the variables associated with the - * reflected object will appear as if they were part of the type itself. - * - * @tparam Data The actual variable to attach to the meta type. - * @tparam Policy Optional policy (no policy set by default). - * @param id Unique identifier. - * @return A meta factory for the parent type. - */ - template<auto Data, typename Policy = as_is_t> - meta_factory data(const id_type id) noexcept { - if constexpr(std::is_member_object_pointer_v<decltype(Data)>) { - using data_type = std::invoke_result_t<decltype(Data), Type &>; - static_assert(Policy::template value<data_type>, "Invalid return type for the given policy"); - - base_type::data( - id, - internal::meta_data_node{ - /* this is never static */ - std::is_const_v<std::remove_reference_t<data_type>> ? internal::meta_traits::is_const : internal::meta_traits::is_none, - 1u, - &internal::resolve<std::remove_cv_t<std::remove_reference_t<data_type>>>, - &meta_arg<type_list<std::remove_cv_t<std::remove_reference_t<data_type>>>>, - &meta_setter<Type, Data>, - &meta_getter<Type, Data, Policy>}); - } else { - using data_type = std::remove_pointer_t<decltype(Data)>; - - if constexpr(std::is_pointer_v<decltype(Data)>) { - static_assert(Policy::template value<decltype(*Data)>, "Invalid return type for the given policy"); - } else { - static_assert(Policy::template value<data_type>, "Invalid return type for the given policy"); - } - - base_type::data( - id, - internal::meta_data_node{ - ((std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<data_type>>> || std::is_const_v<std::remove_reference_t<data_type>>) ? internal::meta_traits::is_const : internal::meta_traits::is_none) | internal::meta_traits::is_static, - 1u, - &internal::resolve<std::remove_cv_t<std::remove_reference_t<data_type>>>, - &meta_arg<type_list<std::remove_cv_t<std::remove_reference_t<data_type>>>>, - &meta_setter<Type, Data>, - &meta_getter<Type, Data, Policy>}); - } - - return *this; - } - - /** - * @brief Assigns a meta data to a meta type by means of its setter and - * getter. - * - * Setters and getters can be either free functions, member functions or a - * mix of them.<br/> - * In case of free functions, setters and getters must accept a reference to - * an instance of the parent type as their first argument. A setter has then - * an extra argument of a type convertible to that of the parameter to - * set.<br/> - * In case of member functions, getters have no arguments at all, while - * setters has an argument of a type convertible to that of the parameter to - * set. - * - * @tparam Setter The actual function to use as a setter. - * @tparam Getter The actual function to use as a getter. - * @tparam Policy Optional policy (no policy set by default). - * @param id Unique identifier. - * @return A meta factory for the parent type. - */ - template<auto Setter, auto Getter, typename Policy = as_is_t> - meta_factory data(const id_type id) noexcept { - using data_type = std::invoke_result_t<decltype(Getter), Type &>; - static_assert(Policy::template value<data_type>, "Invalid return type for the given policy"); - - if constexpr(std::is_same_v<decltype(Setter), std::nullptr_t>) { - base_type::data( - id, - internal::meta_data_node{ - /* this is never static */ - internal::meta_traits::is_const, - 0u, - &internal::resolve<std::remove_cv_t<std::remove_reference_t<data_type>>>, - &meta_arg<type_list<>>, - &meta_setter<Type, Setter>, - &meta_getter<Type, Getter, Policy>}); - } else { - using args_type = typename meta_function_helper_t<Type, decltype(Setter)>::args_type; - - base_type::data( - id, - internal::meta_data_node{ - /* this is never static nor const */ - internal::meta_traits::is_none, - 1u, - &internal::resolve<std::remove_cv_t<std::remove_reference_t<data_type>>>, - &meta_arg<type_list<type_list_element_t<args_type::size != 1u, args_type>>>, - &meta_setter<Type, Setter>, - &meta_getter<Type, Getter, Policy>}); - } - - return *this; - } - - /** - * @brief Assigns a meta data to a meta type by means of its setters and - * getter. - * - * Multi-setter support for meta data members. All setters are tried in the - * order of definition before returning to the caller.<br/> - * Setters can be either free functions, member functions or a mix of them - * and are provided via a `value_list` type. - * - * @sa data - * - * @tparam Setter The actual functions to use as setters. - * @tparam Getter The actual getter function. - * @tparam Policy Optional policy (no policy set by default). - * @param id Unique identifier. - * @return A meta factory for the parent type. - */ - template<typename Setter, auto Getter, typename Policy = as_is_t> - meta_factory data(const id_type id) noexcept { - data<Setter, Getter, Policy>(id, std::make_index_sequence<Setter::size>{}); - return *this; - } - - /** - * @brief Assigns a meta function to a meta type. - * - * Both member functions and free functions can be assigned to a meta - * type.<br/> - * From a client's point of view, all the functions associated with the - * reflected object will appear as if they were part of the type itself. - * - * @tparam Candidate The actual function to attach to the meta type. - * @tparam Policy Optional policy (no policy set by default). - * @param id Unique identifier. - * @return A meta factory for the parent type. - */ - template<auto Candidate, typename Policy = as_is_t> - meta_factory func(const id_type id) noexcept { - using descriptor = meta_function_helper_t<Type, decltype(Candidate)>; - static_assert(Policy::template value<typename descriptor::return_type>, "Invalid return type for the given policy"); - - base_type::func( - id, - internal::meta_func_node{ - (descriptor::is_const ? internal::meta_traits::is_const : internal::meta_traits::is_none) | (descriptor::is_static ? internal::meta_traits::is_static : internal::meta_traits::is_none), - descriptor::args_type::size, - &internal::resolve<std::conditional_t<std::is_same_v<Policy, as_void_t>, void, std::remove_cv_t<std::remove_reference_t<typename descriptor::return_type>>>>, - &meta_arg<typename descriptor::args_type>, - &meta_invoke<Type, Candidate, Policy>}); - - return *this; - } - - /** - * @brief Assigns a property to the last created meta object. - * - * Both the key and the value (if any) must be at least copy constructible. - * - * @tparam Value Optional type of the property value. - * @param id Property key. - * @param value Optional property value. - * @return A meta factory for the parent type. - */ - template<typename... Value> - meta_factory prop(id_type id, [[maybe_unused]] Value &&...value) { - if constexpr(sizeof...(Value) == 0u) { - base_type::prop(id, internal::meta_prop_node{&internal::resolve<void>}); - } else { - base_type::prop(id, internal::meta_prop_node{&internal::resolve<std::decay_t<Value>>..., std::make_shared<std::decay_t<Value>>(std::forward<Value>(value))...}); - } - - return *this; - } - - /** - * @brief Sets traits on the last created meta object. - * - * The assigned value must be an enum and intended as a bitmask. - * - * @tparam Value Type of the traits value. - * @param value Traits value. - * @return A meta factory for the parent type. - */ - template<typename Value> - meta_factory traits(const Value value) { - static_assert(std::is_enum_v<Value>, "Invalid enum type"); - base_type::traits(internal::user_to_meta_traits(value)); - return *this; - } - - /** - * @brief Sets user defined data that will never be used by the library. - * @tparam Value Type of user defined data to store. - * @tparam Args Types of arguments to use to construct the user data. - * @param args Parameters to use to initialize the user data. - * @return A meta factory for the parent type. - */ - template<typename Value, typename... Args> - meta_factory custom(Args &&...args) { - base_type::custom(internal::meta_custom_node{type_id<Value>().hash(), std::make_shared<Value>(std::forward<Args>(args)...)}); - return *this; - } -}; - -/** - * @brief Utility function to use for reflection. - * - * This is the point from which everything starts.<br/> - * By invoking this function with a type that is not yet reflected, a meta type - * is created to which it will be possible to attach meta objects through a - * dedicated factory. - * - * @tparam Type Type to reflect. - * @param ctx The context into which to construct meta types. - * @return A meta factory for the given type. - */ -template<typename Type> -[[nodiscard]] auto meta(meta_ctx &ctx) noexcept { - auto &&context = internal::meta_context::from(ctx); - // make sure the type exists in the context before returning a factory - context.value.try_emplace(type_id<Type>().hash(), internal::resolve<Type>(context)); - return meta_factory<Type>{ctx}; -} - -/** - * @brief Utility function to use for reflection. - * - * This is the point from which everything starts.<br/> - * By invoking this function with a type that is not yet reflected, a meta type - * is created to which it will be possible to attach meta objects through a - * dedicated factory. - * - * @tparam Type Type to reflect. - * @return A meta factory for the given type. - */ -template<typename Type> -[[nodiscard]] auto meta() noexcept { - return meta<Type>(locator<meta_ctx>::value_or()); -} - -/** - * @brief Resets a type and all its parts. - * - * Resets a type and all its data members, member functions and properties, as - * well as its constructors, destructors and conversion functions if any.<br/> - * Base classes aren't reset but the link between the two types is removed. - * - * The type is also removed from the set of searchable types. - * - * @param id Unique identifier. - * @param ctx The context from which to reset meta types. - */ -inline void meta_reset(meta_ctx &ctx, const id_type id) noexcept { - auto &&context = internal::meta_context::from(ctx); - - for(auto it = context.value.begin(); it != context.value.end();) { - if(it->second.id == id) { - it = context.value.erase(it); - } else { - ++it; - } - } -} - -/** - * @brief Resets a type and all its parts. - * - * Resets a type and all its data members, member functions and properties, as - * well as its constructors, destructors and conversion functions if any.<br/> - * Base classes aren't reset but the link between the two types is removed. - * - * The type is also removed from the set of searchable types. - * - * @param id Unique identifier. - */ -inline void meta_reset(const id_type id) noexcept { - meta_reset(locator<meta_ctx>::value_or(), id); -} - -/** - * @brief Resets a type and all its parts. - * - * @sa meta_reset - * - * @tparam Type Type to reset. - * @param ctx The context from which to reset meta types. - */ -template<typename Type> -void meta_reset(meta_ctx &ctx) noexcept { - internal::meta_context::from(ctx).value.erase(type_id<Type>().hash()); -} - -/** - * @brief Resets a type and all its parts. - * - * @sa meta_reset - * - * @tparam Type Type to reset. - */ -template<typename Type> -void meta_reset() noexcept { - meta_reset<Type>(locator<meta_ctx>::value_or()); -} - -/** - * @brief Resets all meta types. - * - * @sa meta_reset - * - * @param ctx The context from which to reset meta types. - */ -inline void meta_reset(meta_ctx &ctx) noexcept { - internal::meta_context::from(ctx).value.clear(); -} - -/** - * @brief Resets all meta types. - * - * @sa meta_reset - */ -inline void meta_reset() noexcept { - meta_reset(locator<meta_ctx>::value_or()); -} - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/meta/fwd.hpp b/deps/entt/include/entt/meta/fwd.hpp deleted file mode 100644 index 09d1051..0000000 --- a/deps/entt/include/entt/meta/fwd.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef ENTT_META_FWD_HPP -#define ENTT_META_FWD_HPP - -namespace entt { - -class meta_sequence_container; - -class meta_associative_container; - -class meta_any; - -struct meta_handle; - -struct meta_prop; - -struct meta_custom; - -struct meta_data; - -struct meta_func; - -class meta_type; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/meta/meta.hpp b/deps/entt/include/entt/meta/meta.hpp deleted file mode 100644 index b7b120a..0000000 --- a/deps/entt/include/entt/meta/meta.hpp +++ /dev/null @@ -1,2026 +0,0 @@ -#ifndef ENTT_META_META_HPP -#define ENTT_META_META_HPP - -#include <array> -#include <cstddef> -#include <iterator> -#include <memory> -#include <type_traits> -#include <utility> -#include "../config/config.h" -#include "../core/any.hpp" -#include "../core/fwd.hpp" -#include "../core/iterator.hpp" -#include "../core/type_info.hpp" -#include "../core/type_traits.hpp" -#include "../core/utility.hpp" -#include "../locator/locator.hpp" -#include "adl_pointer.hpp" -#include "context.hpp" -#include "fwd.hpp" -#include "node.hpp" -#include "range.hpp" -#include "type_traits.hpp" - -namespace entt { - -class meta_any; -class meta_type; - -/*! @brief Proxy object for sequence containers. */ -class meta_sequence_container { - class meta_iterator; - -public: - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - /*! @brief Meta iterator type. */ - using iterator = meta_iterator; - - /*! @brief Default constructor. */ - meta_sequence_container() = default; - - /** - * @brief Context aware constructor. - * @param area The context from which to search for meta types. - */ - meta_sequence_container(const meta_ctx &area) noexcept - : ctx{&area} {} - - /** - * @brief Rebinds a proxy object to a sequence container type. - * @tparam Type Type of container to wrap. - * @param instance The container to wrap. - */ - template<typename Type> - void rebind(Type &instance) noexcept { - value_type_node = &internal::resolve<typename Type::value_type>; - const_reference_node = &internal::resolve<std::remove_const_t<std::remove_reference_t<typename Type::const_reference>>>; - size_fn = meta_sequence_container_traits<std::remove_const_t<Type>>::size; - clear_fn = meta_sequence_container_traits<std::remove_const_t<Type>>::clear; - reserve_fn = meta_sequence_container_traits<std::remove_const_t<Type>>::reserve; - resize_fn = meta_sequence_container_traits<std::remove_const_t<Type>>::resize; - begin_fn = meta_sequence_container_traits<std::remove_const_t<Type>>::begin; - end_fn = meta_sequence_container_traits<std::remove_const_t<Type>>::end; - insert_fn = meta_sequence_container_traits<std::remove_const_t<Type>>::insert; - erase_fn = meta_sequence_container_traits<std::remove_const_t<Type>>::erase; - const_only = std::is_const_v<Type>; - data = &instance; - } - - [[nodiscard]] inline meta_type value_type() const noexcept; - [[nodiscard]] inline size_type size() const noexcept; - inline bool resize(const size_type); - inline bool clear(); - inline bool reserve(const size_type); - [[nodiscard]] inline iterator begin(); - [[nodiscard]] inline iterator end(); - inline iterator insert(const iterator &, meta_any); - inline iterator erase(const iterator &); - [[nodiscard]] inline meta_any operator[](const size_type); - [[nodiscard]] inline explicit operator bool() const noexcept; - -private: - const meta_ctx *ctx{&locator<meta_ctx>::value_or()}; - internal::meta_type_node (*value_type_node)(const internal::meta_context &){}; - internal::meta_type_node (*const_reference_node)(const internal::meta_context &){}; - size_type (*size_fn)(const void *){}; - bool (*clear_fn)(void *){}; - bool (*reserve_fn)(void *, const size_type){}; - bool (*resize_fn)(void *, const size_type){}; - iterator (*begin_fn)(const meta_ctx &, void *, const void *){}; - iterator (*end_fn)(const meta_ctx &, void *, const void *){}; - iterator (*insert_fn)(const meta_ctx &, void *, const void *, const void *, const iterator &){}; - iterator (*erase_fn)(const meta_ctx &, void *, const iterator &){}; - const void *data{}; - bool const_only{}; -}; - -/*! @brief Proxy object for associative containers. */ -class meta_associative_container { - class meta_iterator; - -public: - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - /*! @brief Meta iterator type. */ - using iterator = meta_iterator; - - /*! @brief Default constructor. */ - meta_associative_container() = default; - - /** - * @brief Context aware constructor. - * @param area The context from which to search for meta types. - */ - meta_associative_container(const meta_ctx &area) noexcept - : ctx{&area} {} - - /** - * @brief Rebinds a proxy object to an associative container type. - * @tparam Type Type of container to wrap. - * @param instance The container to wrap. - */ - template<typename Type> - void rebind(Type &instance) noexcept { - key_type_node = &internal::resolve<typename Type::key_type>; - value_type_node = &internal::resolve<typename Type::value_type>; - - if constexpr(!meta_associative_container_traits<std::remove_const_t<Type>>::key_only) { - mapped_type_node = &internal::resolve<typename Type::mapped_type>; - } - - size_fn = &meta_associative_container_traits<std::remove_const_t<Type>>::size; - clear_fn = &meta_associative_container_traits<std::remove_const_t<Type>>::clear; - reserve_fn = &meta_associative_container_traits<std::remove_const_t<Type>>::reserve; - begin_fn = &meta_associative_container_traits<std::remove_const_t<Type>>::begin; - end_fn = &meta_associative_container_traits<std::remove_const_t<Type>>::end; - insert_fn = &meta_associative_container_traits<std::remove_const_t<Type>>::insert; - erase_fn = &meta_associative_container_traits<std::remove_const_t<Type>>::erase; - find_fn = &meta_associative_container_traits<std::remove_const_t<Type>>::find; - const_only = std::is_const_v<Type>; - data = &instance; - } - - [[nodiscard]] inline meta_type key_type() const noexcept; - [[nodiscard]] inline meta_type mapped_type() const noexcept; - [[nodiscard]] inline meta_type value_type() const noexcept; - [[nodiscard]] inline size_type size() const noexcept; - inline bool clear(); - inline bool reserve(const size_type); - [[nodiscard]] inline iterator begin(); - [[nodiscard]] inline iterator end(); - inline bool insert(meta_any, meta_any); - inline size_type erase(meta_any); - [[nodiscard]] inline iterator find(meta_any); - [[nodiscard]] inline explicit operator bool() const noexcept; - -private: - const meta_ctx *ctx{&locator<meta_ctx>::value_or()}; - internal::meta_type_node (*key_type_node)(const internal::meta_context &){}; - internal::meta_type_node (*mapped_type_node)(const internal::meta_context &){}; - internal::meta_type_node (*value_type_node)(const internal::meta_context &){}; - size_type (*size_fn)(const void *){}; - bool (*clear_fn)(void *){}; - bool (*reserve_fn)(void *, const size_type){}; - iterator (*begin_fn)(const meta_ctx &, void *, const void *){}; - iterator (*end_fn)(const meta_ctx &, void *, const void *){}; - bool (*insert_fn)(void *, const void *, const void *){}; - size_type (*erase_fn)(void *, const void *){}; - iterator (*find_fn)(const meta_ctx &, void *, const void *, const void *){}; - const void *data{}; - bool const_only{}; -}; - -/*! @brief Possible modes of a meta any object. */ -using meta_any_policy = any_policy; - -/*! @brief Opaque wrapper for values of any type. */ -class meta_any { - using vtable_type = void(const internal::meta_traits op, const bool, const void *, void *); - - template<typename Type> - static std::enable_if_t<std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, Type>> basic_vtable([[maybe_unused]] const internal::meta_traits req, [[maybe_unused]] const bool const_only, [[maybe_unused]] const void *value, [[maybe_unused]] void *other) { - if constexpr(is_meta_pointer_like_v<Type>) { - if(req == internal::meta_traits::is_meta_pointer_like) { - if constexpr(std::is_function_v<typename std::pointer_traits<Type>::element_type>) { - static_cast<meta_any *>(other)->emplace<Type>(*static_cast<const Type *>(value)); - } else if constexpr(!std::is_void_v<std::remove_const_t<typename std::pointer_traits<Type>::element_type>>) { - using in_place_type = decltype(adl_meta_pointer_like<Type>::dereference(*static_cast<const Type *>(value))); - - if constexpr(std::is_constructible_v<bool, Type>) { - if(const auto &pointer_like = *static_cast<const Type *>(value); pointer_like) { - static_cast<meta_any *>(other)->emplace<in_place_type>(adl_meta_pointer_like<Type>::dereference(pointer_like)); - } - } else { - static_cast<meta_any *>(other)->emplace<in_place_type>(adl_meta_pointer_like<Type>::dereference(*static_cast<const Type *>(value))); - } - } - } - } - - if constexpr(is_complete_v<meta_sequence_container_traits<Type>>) { - if(req == internal::meta_traits::is_meta_sequence_container) { - const_only ? static_cast<meta_sequence_container *>(other)->rebind(*static_cast<const Type *>(value)) : static_cast<meta_sequence_container *>(other)->rebind(*static_cast<Type *>(const_cast<void *>(value))); - } - } - - if constexpr(is_complete_v<meta_associative_container_traits<Type>>) { - if(req == internal::meta_traits::is_meta_associative_container) { - const_only ? static_cast<meta_associative_container *>(other)->rebind(*static_cast<const Type *>(value)) : static_cast<meta_associative_container *>(other)->rebind(*static_cast<Type *>(const_cast<void *>(value))); - } - } - } - - void release() { - if(node.dtor.dtor && (storage.policy() == any_policy::owner)) { - node.dtor.dtor(storage.data()); - } - } - - meta_any(const meta_any &other, any ref) noexcept - : storage{std::move(ref)}, - ctx{other.ctx}, - node{storage ? other.node : internal::meta_type_node{}}, - vtable{storage ? other.vtable : &basic_vtable<void>} {} - -public: - /*! Default constructor. */ - meta_any() = default; - - /** - * @brief Context aware constructor. - * @param area The context from which to search for meta types. - */ - meta_any(meta_ctx_arg_t, const meta_ctx &area) - : ctx{&area} {} - - /** - * @brief Constructs a wrapper by directly initializing the new object. - * @tparam Type Type of object to use to initialize the wrapper. - * @tparam Args Types of arguments to use to construct the new instance. - * @param args Parameters to use to construct the instance. - */ - template<typename Type, typename... Args> - explicit meta_any(std::in_place_type_t<Type>, Args &&...args) - : meta_any{locator<meta_ctx>::value_or(), std::in_place_type<Type>, std::forward<Args>(args)...} {} - - /** - * @brief Constructs a wrapper by directly initializing the new object. - * @tparam Type Type of object to use to initialize the wrapper. - * @tparam Args Types of arguments to use to construct the new instance. - * @param area The context from which to search for meta types. - * @param args Parameters to use to construct the instance. - */ - template<typename Type, typename... Args> - explicit meta_any(const meta_ctx &area, std::in_place_type_t<Type>, Args &&...args) - : storage{std::in_place_type<Type>, std::forward<Args>(args)...}, - ctx{&area}, - node{internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx))}, - vtable{&basic_vtable<std::remove_cv_t<std::remove_reference_t<Type>>>} {} - - /** - * @brief Constructs a wrapper from a given value. - * @tparam Type Type of object to use to initialize the wrapper. - * @param value An instance of an object to use to initialize the wrapper. - */ - template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>> - meta_any(Type &&value) - : meta_any{locator<meta_ctx>::value_or(), std::forward<Type>(value)} {} - - /** - * @brief Constructs a wrapper from a given value. - * @tparam Type Type of object to use to initialize the wrapper. - * @param area The context from which to search for meta types. - * @param value An instance of an object to use to initialize the wrapper. - */ - template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>> - meta_any(const meta_ctx &area, Type &&value) - : meta_any{area, std::in_place_type<std::decay_t<Type>>, std::forward<Type>(value)} {} - - /** - * @brief Context aware copy constructor. - * @param area The context from which to search for meta types. - * @param other The instance to copy from. - */ - meta_any(const meta_ctx &area, const meta_any &other) - : storage{other.storage}, - ctx{&area}, - node{other.node.resolve ? other.node.resolve(internal::meta_context::from(*ctx)) : other.node}, - vtable{other.vtable} {} - - /** - * @brief Context aware move constructor. - * @param area The context from which to search for meta types. - * @param other The instance to move from. - */ - meta_any(const meta_ctx &area, meta_any &&other) - : storage{std::move(other.storage)}, - ctx{&area}, - node{other.node.resolve ? std::exchange(other.node, internal::meta_type_node{}).resolve(internal::meta_context::from(*ctx)) : std::exchange(other.node, internal::meta_type_node{})}, - vtable{std::exchange(other.vtable, &basic_vtable<void>)} {} - - /** - * @brief Copy constructor. - * @param other The instance to copy from. - */ - meta_any(const meta_any &other) = default; - - /** - * @brief Move constructor. - * @param other The instance to move from. - */ - meta_any(meta_any &&other) noexcept - : storage{std::move(other.storage)}, - ctx{other.ctx}, - node{std::exchange(other.node, internal::meta_type_node{})}, - vtable{std::exchange(other.vtable, &basic_vtable<void>)} {} - - /*! @brief Frees the internal storage, whatever it means. */ - ~meta_any() noexcept { - release(); - } - - /** - * @brief Copy assignment operator. - * @param other The instance to copy from. - * @return This meta any object. - */ - meta_any &operator=(const meta_any &other) { - if(this != &other) { - release(); - storage = other.storage; - ctx = other.ctx; - node = other.node; - vtable = other.vtable; - } - - return *this; - } - - /** - * @brief Move assignment operator. - * @param other The instance to move from. - * @return This meta any object. - */ - meta_any &operator=(meta_any &&other) noexcept { - ENTT_ASSERT(this != &other, "Self move assignment"); - - release(); - storage = std::move(other.storage); - ctx = other.ctx; - node = std::exchange(other.node, internal::meta_type_node{}); - vtable = std::exchange(other.vtable, &basic_vtable<void>); - return *this; - } - - /** - * @brief Value assignment operator. - * @tparam Type Type of object to use to initialize the wrapper. - * @param value An instance of an object to use to initialize the wrapper. - * @return This meta any object. - */ - template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_any>>> - meta_any &operator=(Type &&value) { - emplace<std::decay_t<Type>>(std::forward<Type>(value)); - return *this; - } - - /*! @copydoc any::type */ - [[nodiscard]] inline meta_type type() const noexcept; - - /*! @copydoc any::data */ - [[nodiscard]] const void *data() const noexcept { - return storage.data(); - } - - /*! @copydoc any::data */ - [[nodiscard]] void *data() noexcept { - return storage.data(); - } - - /** - * @brief Invokes the underlying function, if possible. - * @tparam Args Types of arguments to use to invoke the function. - * @param id Unique identifier. - * @param args Parameters to use to invoke the function. - * @return A wrapper containing the returned value, if any. - */ - template<typename... Args> - meta_any invoke(const id_type id, Args &&...args) const; - - /*! @copydoc invoke */ - template<typename... Args> - meta_any invoke(const id_type id, Args &&...args); - - /** - * @brief Sets the value of a given variable. - * @tparam Type Type of value to assign. - * @param id Unique identifier. - * @param value Parameter to use to set the underlying variable. - * @return True in case of success, false otherwise. - */ - template<typename Type> - bool set(const id_type id, Type &&value); - - /** - * @brief Gets the value of a given variable. - * @param id Unique identifier. - * @return A wrapper containing the value of the underlying variable. - */ - [[nodiscard]] meta_any get(const id_type id) const; - - /*! @copydoc get */ - [[nodiscard]] meta_any get(const id_type id); - - /** - * @brief Tries to cast an instance to a given type. - * @tparam Type Type to which to cast the instance. - * @return A (possibly null) pointer to the contained instance. - */ - template<typename Type> - [[nodiscard]] const Type *try_cast() const { - const auto other = internal::resolve<std::remove_cv_t<Type>>(internal::meta_context::from(*ctx)); - return static_cast<const Type *>(internal::try_cast(internal::meta_context::from(*ctx), node, other, data())); - } - - /*! @copydoc try_cast */ - template<typename Type> - [[nodiscard]] Type *try_cast() { - if constexpr(std::is_const_v<Type>) { - return std::as_const(*this).try_cast<std::remove_const_t<Type>>(); - } else { - const auto other = internal::resolve<std::remove_cv_t<Type>>(internal::meta_context::from(*ctx)); - return static_cast<Type *>(const_cast<void *>(internal::try_cast(internal::meta_context::from(*ctx), node, other, data()))); - } - } - - /** - * @brief Tries to cast an instance to a given type. - * @tparam Type Type to which to cast the instance. - * @return A reference to the contained instance. - */ - template<typename Type> - [[nodiscard]] Type cast() const { - auto *const instance = try_cast<std::remove_reference_t<Type>>(); - ENTT_ASSERT(instance, "Invalid instance"); - return static_cast<Type>(*instance); - } - - /*! @copydoc cast */ - template<typename Type> - [[nodiscard]] Type cast() { - // forces const on non-reference types to make them work also with wrappers for const references - auto *const instance = try_cast<std::remove_reference_t<const Type>>(); - ENTT_ASSERT(instance, "Invalid instance"); - return static_cast<Type>(*instance); - } - - /** - * @brief Converts an object in such a way that a given cast becomes viable. - * @param type Meta type to which the cast is requested. - * @return A valid meta any object if there exists a viable conversion, an - * invalid one otherwise. - */ - [[nodiscard]] meta_any allow_cast(const meta_type &type) const; - - /** - * @brief Converts an object in such a way that a given cast becomes viable. - * @param type Meta type to which the cast is requested. - * @return True if there exists a viable conversion, false otherwise. - */ - [[nodiscard]] bool allow_cast(const meta_type &type) { - if(auto other = std::as_const(*this).allow_cast(type); other) { - if((other.storage.policy() == any_policy::owner)) { - std::swap(*this, other); - } - - return true; - } - - return false; - } - - /** - * @brief Converts an object in such a way that a given cast becomes viable. - * @tparam Type Type to which the cast is requested. - * @return A valid meta any object if there exists a viable conversion, an - * invalid one otherwise. - */ - template<typename Type> - [[nodiscard]] meta_any allow_cast() const { - if constexpr(std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>) { - return meta_any{meta_ctx_arg, *ctx}; - } else { - auto other = internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx)); - return allow_cast(meta_type{*ctx, other}); - } - } - - /** - * @brief Converts an object in such a way that a given cast becomes viable. - * @tparam Type Type to which the cast is requested. - * @return True if there exists a viable conversion, false otherwise. - */ - template<typename Type> - [[nodiscard]] bool allow_cast() { - auto other = internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx)); - return allow_cast(meta_type{*ctx, other}) && (!(std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>) || storage.data() != nullptr); - } - - /*! @copydoc any::emplace */ - template<typename Type, typename... Args> - void emplace(Args &&...args) { - release(); - storage.emplace<Type>(std::forward<Args>(args)...); - node = internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(internal::meta_context::from(*ctx)); - vtable = &basic_vtable<std::remove_cv_t<std::remove_reference_t<Type>>>; - } - - /*! @copydoc any::assign */ - bool assign(const meta_any &other); - - /*! @copydoc any::assign */ - bool assign(meta_any &&other); - - /*! @copydoc any::reset */ - void reset() { - release(); - storage.reset(); - node = {}; - vtable = &basic_vtable<void>; - } - - /** - * @brief Returns a sequence container proxy. - * @return A sequence container proxy for the underlying object. - */ - [[nodiscard]] meta_sequence_container as_sequence_container() noexcept { - meta_sequence_container proxy{*ctx}; - vtable(internal::meta_traits::is_meta_sequence_container, policy() == meta_any_policy::cref, std::as_const(*this).data(), &proxy); - return proxy; - } - - /*! @copydoc as_sequence_container */ - [[nodiscard]] meta_sequence_container as_sequence_container() const noexcept { - meta_sequence_container proxy{*ctx}; - vtable(internal::meta_traits::is_meta_sequence_container, true, data(), &proxy); - return proxy; - } - - /** - * @brief Returns an associative container proxy. - * @return An associative container proxy for the underlying object. - */ - [[nodiscard]] meta_associative_container as_associative_container() noexcept { - meta_associative_container proxy{*ctx}; - vtable(internal::meta_traits::is_meta_associative_container, policy() == meta_any_policy::cref, std::as_const(*this).data(), &proxy); - return proxy; - } - - /*! @copydoc as_associative_container */ - [[nodiscard]] meta_associative_container as_associative_container() const noexcept { - meta_associative_container proxy{*ctx}; - vtable(internal::meta_traits::is_meta_associative_container, true, data(), &proxy); - return proxy; - } - - /** - * @brief Indirection operator for dereferencing opaque objects. - * @return A wrapper that shares a reference to an unmanaged object if the - * wrapped element is dereferenceable, an invalid meta any otherwise. - */ - [[nodiscard]] meta_any operator*() const noexcept { - meta_any ret{meta_ctx_arg, *ctx}; - vtable(internal::meta_traits::is_meta_pointer_like, true, storage.data(), &ret); - return ret; - } - - /** - * @brief Returns false if a wrapper is invalid, true otherwise. - * @return False if the wrapper is invalid, true otherwise. - */ - [[nodiscard]] explicit operator bool() const noexcept { - return !(node.info == nullptr); - } - - /*! @copydoc any::operator== */ - [[nodiscard]] bool operator==(const meta_any &other) const noexcept { - return (ctx == other.ctx) && ((!node.info && !other.node.info) || (node.info && other.node.info && *node.info == *other.node.info && storage == other.storage)); - } - - /*! @copydoc any::operator!= */ - [[nodiscard]] bool operator!=(const meta_any &other) const noexcept { - return !(*this == other); - } - - /*! @copydoc any::as_ref */ - [[nodiscard]] meta_any as_ref() noexcept { - return meta_any{*this, storage.as_ref()}; - } - - /*! @copydoc any::as_ref */ - [[nodiscard]] meta_any as_ref() const noexcept { - return meta_any{*this, storage.as_ref()}; - } - - /** - * @brief Returns the current mode of a meta any object. - * @return The current mode of the meta any object. - */ - [[nodiscard]] meta_any_policy policy() const noexcept { - return storage.policy(); - } - -private: - any storage{}; - const meta_ctx *ctx{&locator<meta_ctx>::value_or()}; - internal::meta_type_node node{}; - vtable_type *vtable{&basic_vtable<void>}; -}; - -/** - * @brief Forwards its argument and avoids copies for lvalue references. - * @tparam Type Type of argument to use to construct the new instance. - * @param value Parameter to use to construct the instance. - * @param ctx The context from which to search for meta types. - * @return A properly initialized and not necessarily owning wrapper. - */ -template<typename Type> -[[nodiscard]] meta_any forward_as_meta(const meta_ctx &ctx, Type &&value) { - return meta_any{ctx, std::in_place_type<Type &&>, std::forward<Type>(value)}; -} - -/** - * @brief Forwards its argument and avoids copies for lvalue references. - * @tparam Type Type of argument to use to construct the new instance. - * @param value Parameter to use to construct the instance. - * @return A properly initialized and not necessarily owning wrapper. - */ -template<typename Type> -[[nodiscard]] meta_any forward_as_meta(Type &&value) { - return forward_as_meta(locator<meta_ctx>::value_or(), std::forward<Type>(value)); -} - -/** - * @brief Opaque pointers to instances of any type. - * - * A handle doesn't perform copies and isn't responsible for the contained - * object. It doesn't prolong the lifetime of the pointed instance. - */ -struct meta_handle { - /*! Default constructor. */ - meta_handle() = default; - - /** - * @brief Context aware constructor. - * @param area The context from which to search for meta types. - */ - meta_handle(meta_ctx_arg_t, const meta_ctx &area) - : any{meta_ctx_arg, area} {} - - /** - * @brief Creates a handle that points to an unmanaged object. - * @param value An instance of an object to use to initialize the handle. - */ - meta_handle(meta_any &value) - : any{value.as_ref()} {} - - /** - * @brief Creates a handle that points to an unmanaged object. - * @param value An instance of an object to use to initialize the handle. - */ - meta_handle(const meta_any &value) - : any{value.as_ref()} {} - - /** - * @brief Creates a handle that points to an unmanaged object. - * @tparam Type Type of object to use to initialize the handle. - * @param ctx The context from which to search for meta types. - * @param value An instance of an object to use to initialize the handle. - */ - template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_handle>>> - meta_handle(const meta_ctx &ctx, Type &value) - : any{ctx, std::in_place_type<Type &>, value} {} - - /** - * @brief Creates a handle that points to an unmanaged object. - * @tparam Type Type of object to use to initialize the handle. - * @param value An instance of an object to use to initialize the handle. - */ - template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::decay_t<Type>, meta_handle>>> - meta_handle(Type &value) - : meta_handle{locator<meta_ctx>::value_or(), value} {} - - /** - * @brief Context aware copy constructor. - * @param area The context from which to search for meta types. - * @param other The instance to copy from. - */ - meta_handle(const meta_ctx &area, const meta_handle &other) - : any{area, other.any} {} - - /** - * @brief Context aware move constructor. - * @param area The context from which to search for meta types. - * @param other The instance to move from. - */ - meta_handle(const meta_ctx &area, meta_handle &&other) - : any{area, std::move(other.any)} {} - - /*! @brief Default copy constructor, deleted on purpose. */ - meta_handle(const meta_handle &) = delete; - - /*! @brief Default move constructor. */ - meta_handle(meta_handle &&) = default; - - /*! @brief Default destructor. */ - ~meta_handle() noexcept = default; - - /** - * @brief Default copy assignment operator, deleted on purpose. - * @return This meta handle. - */ - meta_handle &operator=(const meta_handle &) = delete; - - /** - * @brief Default move assignment operator. - * @return This meta handle. - */ - meta_handle &operator=(meta_handle &&) = default; - - /** - * @brief Returns false if a handle is invalid, true otherwise. - * @return False if the handle is invalid, true otherwise. - */ - [[nodiscard]] explicit operator bool() const noexcept { - return static_cast<bool>(any); - } - - /*! @copydoc meta_any::operator== */ - [[nodiscard]] bool operator==(const meta_handle &other) const noexcept { - return (any == other.any); - } - - /*! @copydoc meta_any::operator!= */ - [[nodiscard]] bool operator!=(const meta_handle &other) const noexcept { - return !(*this == other); - } - - /** - * @brief Access operator for accessing the contained opaque object. - * @return A wrapper that shares a reference to an unmanaged object. - */ - [[nodiscard]] meta_any *operator->() { - return &any; - } - - /*! @copydoc operator-> */ - [[nodiscard]] const meta_any *operator->() const { - return &any; - } - -private: - meta_any any{meta_ctx_arg, locator<meta_ctx>::value_or()}; -}; - -/*! @brief Opaque wrapper for properties of any type. */ -struct meta_prop { - /*! @brief Default constructor. */ - meta_prop() noexcept = default; - - /** - * @brief Context aware constructor for meta objects. - * @param area The context from which to search for meta types. - * @param curr The underlying node with which to construct the instance. - */ - meta_prop(const meta_ctx &area, const internal::meta_prop_node &curr) noexcept - : node{&curr}, - ctx{&area} {} - - /** - * @brief Returns the stored value by const reference. - * @return A wrapper containing the value stored with the property. - */ - [[nodiscard]] meta_any value() const { - return node->value ? node->type(internal::meta_context::from(*ctx)).from_void(*ctx, nullptr, node->value.get()) : meta_any{meta_ctx_arg, *ctx}; - } - - /** - * @brief Returns the stored value by reference. - * @return A wrapper containing the value stored with the property. - */ - [[nodiscard]] meta_any value() { - return node->value ? node->type(internal::meta_context::from(*ctx)).from_void(*ctx, node->value.get(), nullptr) : meta_any{meta_ctx_arg, *ctx}; - } - - /** - * @brief Returns true if an object is valid, false otherwise. - * @return True if the object is valid, false otherwise. - */ - [[nodiscard]] explicit operator bool() const noexcept { - return (node != nullptr); - } - - /** - * @brief Checks if two objects refer to the same type. - * @param other The object with which to compare. - * @return True if the objects refer to the same type, false otherwise. - */ - [[nodiscard]] bool operator==(const meta_prop &other) const noexcept { - return (ctx == other.ctx && node == other.node); - } - -private: - const internal::meta_prop_node *node{}; - const meta_ctx *ctx{}; -}; - -/** - * @brief Checks if two objects refer to the same type. - * @param lhs An object, either valid or not. - * @param rhs An object, either valid or not. - * @return False if the objects refer to the same node, true otherwise. - */ -[[nodiscard]] inline bool operator!=(const meta_prop &lhs, const meta_prop &rhs) noexcept { - return !(lhs == rhs); -} - -/*! @brief Opaque wrapper for user defined data of any type. */ -struct meta_custom { - /*! @brief Default constructor. */ - meta_custom() noexcept = default; - - /** - * @brief Basic constructor for meta objects. - * @param curr The underlying node with which to construct the instance. - */ - meta_custom(internal::meta_custom_node curr) noexcept - : node{std::move(curr)} {} - - /** - * @brief Generic conversion operator. - * @tparam Type Type to which conversion is requested. - */ - template<typename Type> - [[nodiscard]] operator Type *() const noexcept { - return (type_id<Type>().hash() == node.type) ? std::static_pointer_cast<Type>(node.value).get() : nullptr; - } - - /** - * @brief Generic conversion operator. - * @tparam Type Type to which conversion is requested. - */ - template<typename Type> - [[nodiscard]] operator Type &() const noexcept { - ENTT_ASSERT(type_id<Type>().hash() == node.type, "Invalid type"); - return *std::static_pointer_cast<Type>(node.value); - } - -private: - internal::meta_custom_node node{}; -}; - -/*! @brief Opaque wrapper for data members. */ -struct meta_data { - /*! @brief Unsigned integer type. */ - using size_type = typename internal::meta_data_node::size_type; - - /*! @brief Default constructor. */ - meta_data() noexcept = default; - - /** - * @brief Context aware constructor for meta objects. - * @param area The context from which to search for meta types. - * @param curr The underlying node with which to construct the instance. - */ - meta_data(const meta_ctx &area, const internal::meta_data_node &curr) noexcept - : node{&curr}, - ctx{&area} {} - - /** - * @brief Returns the number of setters available. - * @return The number of setters available. - */ - [[nodiscard]] size_type arity() const noexcept { - return node->arity; - } - - /** - * @brief Indicates whether a data member is constant or not. - * @return True if the data member is constant, false otherwise. - */ - [[nodiscard]] bool is_const() const noexcept { - return static_cast<bool>(node->traits & internal::meta_traits::is_const); - } - - /** - * @brief Indicates whether a data member is static or not. - * @return True if the data member is static, false otherwise. - */ - [[nodiscard]] bool is_static() const noexcept { - return static_cast<bool>(node->traits & internal::meta_traits::is_static); - } - - /*! @copydoc meta_any::type */ - [[nodiscard]] inline meta_type type() const noexcept; - - /** - * @brief Sets the value of a given variable. - * @tparam Type Type of value to assign. - * @param instance An opaque instance of the underlying type. - * @param value Parameter to use to set the underlying variable. - * @return True in case of success, false otherwise. - */ - template<typename Type> - // NOLINTNEXTLINE(modernize-use-nodiscard) - bool set(meta_handle instance, Type &&value) const { - return node->set && node->set(meta_handle{*ctx, std::move(instance)}, meta_any{*ctx, std::forward<Type>(value)}); - } - - /** - * @brief Gets the value of a given variable. - * @param instance An opaque instance of the underlying type. - * @return A wrapper containing the value of the underlying variable. - */ - [[nodiscard]] meta_any get(meta_handle instance) const { - return node->get(*ctx, meta_handle{*ctx, std::move(instance)}); - } - - /** - * @brief Returns the type accepted by the i-th setter. - * @param index Index of the setter of which to return the accepted type. - * @return The type accepted by the i-th setter. - */ - [[nodiscard]] inline meta_type arg(const size_type index) const noexcept; - - /** - * @brief Returns a range to visit registered meta properties. - * @return An iterable range to visit registered meta properties. - */ - [[nodiscard]] meta_range<meta_prop, typename decltype(internal::meta_data_node::prop)::const_iterator> prop() const noexcept { - return {{*ctx, node->prop.cbegin()}, {*ctx, node->prop.cend()}}; - } - - /** - * @brief Lookup utility for meta properties. - * @param key The key to use to search for a property. - * @return The registered meta property for the given key, if any. - */ - [[nodiscard]] meta_prop prop(const id_type key) const { - const auto it = node->prop.find(key); - return it != node->prop.cend() ? meta_prop{*ctx, it->second} : meta_prop{}; - } - - /** - * @brief Returns all meta traits for a given meta object. - * @tparam Type The type to convert the meta traits to. - * @return The registered meta traits, if any. - */ - template<typename Type> - [[nodiscard]] Type traits() const noexcept { - return internal::meta_to_user_traits<Type>(node->traits); - } - - /** - * @brief Returns user defined data for a given meta object. - * @return User defined arbitrary data. - */ - [[nodiscard]] meta_custom custom() const noexcept { - return {node->custom}; - } - - /** - * @brief Returns true if an object is valid, false otherwise. - * @return True if the object is valid, false otherwise. - */ - [[nodiscard]] explicit operator bool() const noexcept { - return (node != nullptr); - } - - /*! @copydoc meta_prop::operator== */ - [[nodiscard]] bool operator==(const meta_data &other) const noexcept { - return (ctx == other.ctx && node == other.node); - } - -private: - const internal::meta_data_node *node{}; - const meta_ctx *ctx{}; -}; - -/** - * @brief Checks if two objects refer to the same type. - * @param lhs An object, either valid or not. - * @param rhs An object, either valid or not. - * @return False if the objects refer to the same node, true otherwise. - */ -[[nodiscard]] inline bool operator!=(const meta_data &lhs, const meta_data &rhs) noexcept { - return !(lhs == rhs); -} - -/*! @brief Opaque wrapper for member functions. */ -struct meta_func { - /*! @brief Unsigned integer type. */ - using size_type = typename internal::meta_func_node::size_type; - - /*! @brief Default constructor. */ - meta_func() noexcept = default; - - /** - * @brief Context aware constructor for meta objects. - * @param area The context from which to search for meta types. - * @param curr The underlying node with which to construct the instance. - */ - meta_func(const meta_ctx &area, const internal::meta_func_node &curr) noexcept - : node{&curr}, - ctx{&area} {} - - /** - * @brief Returns the number of arguments accepted by a member function. - * @return The number of arguments accepted by the member function. - */ - [[nodiscard]] size_type arity() const noexcept { - return node->arity; - } - - /** - * @brief Indicates whether a member function is constant or not. - * @return True if the member function is constant, false otherwise. - */ - [[nodiscard]] bool is_const() const noexcept { - return static_cast<bool>(node->traits & internal::meta_traits::is_const); - } - - /** - * @brief Indicates whether a member function is static or not. - * @return True if the member function is static, false otherwise. - */ - [[nodiscard]] bool is_static() const noexcept { - return static_cast<bool>(node->traits & internal::meta_traits::is_static); - } - - /** - * @brief Returns the return type of a member function. - * @return The return type of the member function. - */ - [[nodiscard]] inline meta_type ret() const noexcept; - - /** - * @brief Returns the type of the i-th argument of a member function. - * @param index Index of the argument of which to return the type. - * @return The type of the i-th argument of a member function. - */ - [[nodiscard]] inline meta_type arg(const size_type index) const noexcept; - - /** - * @brief Invokes the underlying function, if possible. - * @param instance An opaque instance of the underlying type. - * @param args Parameters to use to invoke the function. - * @param sz Number of parameters to use to invoke the function. - * @return A wrapper containing the returned value, if any. - */ - meta_any invoke(meta_handle instance, meta_any *const args, const size_type sz) const { - return sz == arity() ? node->invoke(*ctx, meta_handle{*ctx, std::move(instance)}, args) : meta_any{meta_ctx_arg, *ctx}; - } - - /** - * @copybrief invoke - * @tparam Args Types of arguments to use to invoke the function. - * @param instance An opaque instance of the underlying type. - * @param args Parameters to use to invoke the function. - * @return A wrapper containing the returned value, if any. - */ - template<typename... Args> - // NOLINTNEXTLINE(modernize-use-nodiscard) - meta_any invoke(meta_handle instance, Args &&...args) const { - std::array<meta_any, sizeof...(Args)> arguments{meta_any{*ctx, std::forward<Args>(args)}...}; - return invoke(std::move(instance), arguments.data(), sizeof...(Args)); - } - - /*! @copydoc meta_data::prop */ - [[nodiscard]] meta_range<meta_prop, typename decltype(internal::meta_func_node::prop)::const_iterator> prop() const noexcept { - return {{*ctx, node->prop.cbegin()}, {*ctx, node->prop.cend()}}; - } - - /** - * @brief Lookup utility for meta properties. - * @param key The key to use to search for a property. - * @return The registered meta property for the given key, if any. - */ - [[nodiscard]] meta_prop prop(const id_type key) const { - const auto it = node->prop.find(key); - return it != node->prop.cend() ? meta_prop{*ctx, it->second} : meta_prop{}; - } - - /*! @copydoc meta_data::traits */ - template<typename Type> - [[nodiscard]] Type traits() const noexcept { - return internal::meta_to_user_traits<Type>(node->traits); - } - - /*! @copydoc meta_data::custom */ - [[nodiscard]] meta_custom custom() const noexcept { - return {node->custom}; - } - - /** - * @brief Returns the next overload of a given function, if any. - * @return The next overload of the given function, if any. - */ - [[nodiscard]] meta_func next() const { - return node->next ? meta_func{*ctx, *node->next} : meta_func{}; - } - - /** - * @brief Returns true if an object is valid, false otherwise. - * @return True if the object is valid, false otherwise. - */ - [[nodiscard]] explicit operator bool() const noexcept { - return (node != nullptr); - } - - /*! @copydoc meta_prop::operator== */ - [[nodiscard]] bool operator==(const meta_func &other) const noexcept { - return (ctx == other.ctx && node == other.node); - } - -private: - const internal::meta_func_node *node{}; - const meta_ctx *ctx{}; -}; - -/** - * @brief Checks if two objects refer to the same type. - * @param lhs An object, either valid or not. - * @param rhs An object, either valid or not. - * @return False if the objects refer to the same node, true otherwise. - */ -[[nodiscard]] inline bool operator!=(const meta_func &lhs, const meta_func &rhs) noexcept { - return !(lhs == rhs); -} - -/*! @brief Opaque wrapper for types. */ -class meta_type { - template<typename Func> - [[nodiscard]] auto lookup(meta_any *const args, const typename internal::meta_type_node::size_type sz, [[maybe_unused]] bool constness, Func next) const { - decltype(next()) candidate = nullptr; - size_type same{}; - bool ambiguous{}; - - for(auto curr = next(); curr; curr = next()) { - if constexpr(std::is_same_v<std::decay_t<decltype(*curr)>, internal::meta_func_node>) { - if(constness && !static_cast<bool>(curr->traits & internal::meta_traits::is_const)) { - continue; - } - } - - if(curr->arity == sz) { - size_type match{}; - size_type pos{}; - - // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) - waiting for C++20 (and std::span) - for(; pos < sz && args[pos]; ++pos) { - const auto other = curr->arg(*ctx, pos); - const auto type = args[pos].type(); - - if(const auto &info = other.info(); info == type.info()) { - ++match; - } else if(!((type.node.details && (type.node.details->base.contains(info.hash()) || type.node.details->conv.contains(info.hash()))) || (type.node.conversion_helper && other.node.conversion_helper))) { - break; - } - } - // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic) - - if(pos == sz) { - if(!candidate || match > same) { - candidate = curr; - same = match; - ambiguous = false; - } else if(match == same) { - if constexpr(std::is_same_v<std::decay_t<decltype(*curr)>, internal::meta_func_node>) { - if(static_cast<bool>(curr->traits & internal::meta_traits::is_const) != static_cast<bool>(candidate->traits & internal::meta_traits::is_const)) { - candidate = static_cast<bool>(candidate->traits & internal::meta_traits::is_const) ? curr : candidate; - ambiguous = false; - continue; - } - } - - ambiguous = true; - } - } - } - } - - return ambiguous ? nullptr : candidate; - } - -public: - /*! @brief Unsigned integer type. */ - using size_type = typename internal::meta_type_node::size_type; - - /*! @brief Default constructor. */ - meta_type() noexcept = default; - - /** - * @brief Context aware constructor for meta objects. - * @param area The context from which to search for meta types. - * @param curr The underlying node with which to construct the instance. - */ - meta_type(const meta_ctx &area, internal::meta_type_node curr) noexcept - : node{std::move(curr)}, - ctx{&area} {} - - /** - * @brief Context aware constructor for meta objects. - * @param area The context from which to search for meta types. - * @param curr The underlying node with which to construct the instance. - */ - meta_type(const meta_ctx &area, const internal::meta_base_node &curr) noexcept - : meta_type{area, curr.type(internal::meta_context::from(area))} {} - - /** - * @brief Returns the type info object of the underlying type. - * @return The type info object of the underlying type. - */ - [[nodiscard]] const type_info &info() const noexcept { - return *node.info; - } - - /** - * @brief Returns the identifier assigned to a type. - * @return The identifier assigned to the type. - */ - [[nodiscard]] id_type id() const noexcept { - return node.id; - } - - /** - * @brief Returns the size of the underlying type if known. - * @return The size of the underlying type if known, 0 otherwise. - */ - [[nodiscard]] size_type size_of() const noexcept { - return node.size_of; - } - - /** - * @brief Checks whether a type refers to an arithmetic type or not. - * @return True if the underlying type is an arithmetic type, false - * otherwise. - */ - [[nodiscard]] bool is_arithmetic() const noexcept { - return static_cast<bool>(node.traits & internal::meta_traits::is_arithmetic); - } - - /** - * @brief Checks whether a type refers to an integral type or not. - * @return True if the underlying type is an integral type, false otherwise. - */ - [[nodiscard]] bool is_integral() const noexcept { - return static_cast<bool>(node.traits & internal::meta_traits::is_integral); - } - - /** - * @brief Checks whether a type refers to a signed type or not. - * @return True if the underlying type is a signed type, false otherwise. - */ - [[nodiscard]] bool is_signed() const noexcept { - return static_cast<bool>(node.traits & internal::meta_traits::is_signed); - } - - /** - * @brief Checks whether a type refers to an array type or not. - * @return True if the underlying type is an array type, false otherwise. - */ - [[nodiscard]] bool is_array() const noexcept { - return static_cast<bool>(node.traits & internal::meta_traits::is_array); - } - - /** - * @brief Checks whether a type refers to an enum or not. - * @return True if the underlying type is an enum, false otherwise. - */ - [[nodiscard]] bool is_enum() const noexcept { - return static_cast<bool>(node.traits & internal::meta_traits::is_enum); - } - - /** - * @brief Checks whether a type refers to a class or not. - * @return True if the underlying type is a class, false otherwise. - */ - [[nodiscard]] bool is_class() const noexcept { - return static_cast<bool>(node.traits & internal::meta_traits::is_class); - } - - /** - * @brief Checks whether a type refers to a pointer or not. - * @return True if the underlying type is a pointer, false otherwise. - */ - [[nodiscard]] bool is_pointer() const noexcept { - return static_cast<bool>(node.traits & internal::meta_traits::is_pointer); - } - - /** - * @brief Provides the type for which the pointer is defined. - * @return The type for which the pointer is defined or this type if it - * doesn't refer to a pointer type. - */ - [[nodiscard]] meta_type remove_pointer() const noexcept { - return {*ctx, node.remove_pointer(internal::meta_context::from(*ctx))}; - } - - /** - * @brief Checks whether a type is a pointer-like type or not. - * @return True if the underlying type is pointer-like, false otherwise. - */ - [[nodiscard]] bool is_pointer_like() const noexcept { - return static_cast<bool>(node.traits & internal::meta_traits::is_meta_pointer_like); - } - - /** - * @brief Checks whether a type refers to a sequence container or not. - * @return True if the type is a sequence container, false otherwise. - */ - [[nodiscard]] bool is_sequence_container() const noexcept { - return static_cast<bool>(node.traits & internal::meta_traits::is_meta_sequence_container); - } - - /** - * @brief Checks whether a type refers to an associative container or not. - * @return True if the type is an associative container, false otherwise. - */ - [[nodiscard]] bool is_associative_container() const noexcept { - return static_cast<bool>(node.traits & internal::meta_traits::is_meta_associative_container); - } - - /** - * @brief Checks whether a type refers to a recognized class template - * specialization or not. - * @return True if the type is a recognized class template specialization, - * false otherwise. - */ - [[nodiscard]] bool is_template_specialization() const noexcept { - return (node.templ.arity != 0u); - } - - /** - * @brief Returns the number of template arguments. - * @return The number of template arguments. - */ - [[nodiscard]] size_type template_arity() const noexcept { - return node.templ.arity; - } - - /** - * @brief Returns a tag for the class template of the underlying type. - * @return The tag for the class template of the underlying type. - */ - [[nodiscard]] inline meta_type template_type() const noexcept { - return node.templ.type ? meta_type{*ctx, node.templ.type(internal::meta_context::from(*ctx))} : meta_type{}; - } - - /** - * @brief Returns the type of the i-th template argument of a type. - * @param index Index of the template argument of which to return the type. - * @return The type of the i-th template argument of a type. - */ - [[nodiscard]] inline meta_type template_arg(const size_type index) const noexcept { - return index < template_arity() ? meta_type{*ctx, node.templ.arg(internal::meta_context::from(*ctx), index)} : meta_type{}; - } - - /** - * @brief Checks if a type supports direct casting to another type. - * @param other The meta type to test for. - * @return True if direct casting is allowed, false otherwise. - */ - [[nodiscard]] bool can_cast(const meta_type &other) const noexcept { - // casting this is UB in all cases but we aren't going to use the resulting pointer, so... - return (internal::try_cast(internal::meta_context::from(*ctx), node, other.node, this) != nullptr); - } - - /** - * @brief Checks if a type supports conversion it to another type. - * @param other The meta type to test for. - * @return True if the conversion is allowed, false otherwise. - */ - [[nodiscard]] bool can_convert(const meta_type &other) const noexcept { - return (internal::try_convert(internal::meta_context::from(*ctx), node, other.info(), other.is_arithmetic() || other.is_enum(), nullptr, [](const void *, auto &&...args) { return ((static_cast<void>(args), 1) + ... + 0u); }) != 0u); - } - - /** - * @brief Returns a range to visit registered top-level base meta types. - * @return An iterable range to visit registered top-level base meta types. - */ - [[nodiscard]] meta_range<meta_type, typename decltype(internal::meta_type_descriptor::base)::const_iterator> base() const noexcept { - using range_type = meta_range<meta_type, typename decltype(internal::meta_type_descriptor::base)::const_iterator>; - return node.details ? range_type{{*ctx, node.details->base.cbegin()}, {*ctx, node.details->base.cend()}} : range_type{}; - } - - /** - * @brief Returns a range to visit registered top-level meta data. - * @return An iterable range to visit registered top-level meta data. - */ - [[nodiscard]] meta_range<meta_data, typename decltype(internal::meta_type_descriptor::data)::const_iterator> data() const noexcept { - using range_type = meta_range<meta_data, typename decltype(internal::meta_type_descriptor::data)::const_iterator>; - return node.details ? range_type{{*ctx, node.details->data.cbegin()}, {*ctx, node.details->data.cend()}} : range_type{}; - } - - /** - * @brief Lookup utility for meta data (bases are also visited). - * @param id Unique identifier. - * @return The registered meta data for the given identifier, if any. - */ - [[nodiscard]] meta_data data(const id_type id) const { - const auto *elem = internal::look_for<&internal::meta_type_descriptor::data>(internal::meta_context::from(*ctx), node, id); - return elem ? meta_data{*ctx, *elem} : meta_data{}; - } - - /** - * @brief Returns a range to visit registered top-level functions. - * @return An iterable range to visit registered top-level functions. - */ - [[nodiscard]] meta_range<meta_func, typename decltype(internal::meta_type_descriptor::func)::const_iterator> func() const noexcept { - using return_type = meta_range<meta_func, typename decltype(internal::meta_type_descriptor::func)::const_iterator>; - return node.details ? return_type{{*ctx, node.details->func.cbegin()}, {*ctx, node.details->func.cend()}} : return_type{}; - } - - /** - * @brief Lookup utility for meta functions (bases are also visited). - * - * In case of overloaded functions, a random one is returned. - * - * @param id Unique identifier. - * @return The registered meta function for the given identifier, if any. - */ - [[nodiscard]] meta_func func(const id_type id) const { - const auto *elem = internal::look_for<&internal::meta_type_descriptor::func>(internal::meta_context::from(*ctx), node, id); - return elem ? meta_func{*ctx, *elem} : meta_func{}; - } - - /** - * @brief Creates an instance of the underlying type, if possible. - * @param args Parameters to use to construct the instance. - * @param sz Number of parameters to use to construct the instance. - * @return A wrapper containing the new instance, if any. - */ - [[nodiscard]] meta_any construct(meta_any *const args, const size_type sz) const { - if(node.details) { - if(const auto *candidate = lookup(args, sz, false, [first = node.details->ctor.cbegin(), last = node.details->ctor.cend()]() mutable { return first == last ? nullptr : &(first++)->second; }); candidate) { - return candidate->invoke(*ctx, args); - } - } - - if(sz == 0u && node.default_constructor) { - return node.default_constructor(*ctx); - } - - return meta_any{meta_ctx_arg, *ctx}; - } - - /** - * @copybrief construct - * @tparam Args Types of arguments to use to construct the instance. - * @param args Parameters to use to construct the instance. - * @return A wrapper containing the new instance, if any. - */ - template<typename... Args> - [[nodiscard]] meta_any construct(Args &&...args) const { - std::array<meta_any, sizeof...(Args)> arguments{meta_any{*ctx, std::forward<Args>(args)}...}; - return construct(arguments.data(), sizeof...(Args)); - } - - /** - * @brief Wraps an opaque element of the underlying type. - * @param elem A valid pointer to an element of the underlying type. - * @return A wrapper that references the given instance. - */ - [[nodiscard]] meta_any from_void(void *elem) const { - return (elem && node.from_void) ? node.from_void(*ctx, elem, nullptr) : meta_any{meta_ctx_arg, *ctx}; - } - - /*! @copydoc from_void */ - [[nodiscard]] meta_any from_void(const void *elem) const { - return (elem && node.from_void) ? node.from_void(*ctx, nullptr, elem) : meta_any{meta_ctx_arg, *ctx}; - } - - /** - * @brief Invokes a function given an identifier, if possible. - * @param id Unique identifier. - * @param instance An opaque instance of the underlying type. - * @param args Parameters to use to invoke the function. - * @param sz Number of parameters to use to invoke the function. - * @return A wrapper containing the returned value, if any. - */ - meta_any invoke(const id_type id, meta_handle instance, meta_any *const args, const size_type sz) const { - if(node.details) { - if(auto it = node.details->func.find(id); it != node.details->func.cend()) { - if(const auto *candidate = lookup(args, sz, instance && (instance->data() == nullptr), [curr = &it->second]() mutable { return curr ? std::exchange(curr, curr->next.get()) : nullptr; }); candidate) { - return candidate->invoke(*ctx, meta_handle{*ctx, std::move(instance)}, args); - } - } - } - - for(auto &&curr: base()) { - if(auto elem = curr.second.invoke(id, *instance.operator->(), args, sz); elem) { - return elem; - } - } - - return meta_any{meta_ctx_arg, *ctx}; - } - - /** - * @copybrief invoke - * @param id Unique identifier. - * @tparam Args Types of arguments to use to invoke the function. - * @param instance An opaque instance of the underlying type. - * @param args Parameters to use to invoke the function. - * @return A wrapper containing the returned value, if any. - */ - template<typename... Args> - // NOLINTNEXTLINE(modernize-use-nodiscard) - meta_any invoke(const id_type id, meta_handle instance, Args &&...args) const { - std::array<meta_any, sizeof...(Args)> arguments{meta_any{*ctx, std::forward<Args>(args)}...}; - return invoke(id, std::move(instance), arguments.data(), sizeof...(Args)); - } - - /** - * @brief Sets the value of a given variable. - * @tparam Type Type of value to assign. - * @param id Unique identifier. - * @param instance An opaque instance of the underlying type. - * @param value Parameter to use to set the underlying variable. - * @return True in case of success, false otherwise. - */ - template<typename Type> - bool set(const id_type id, meta_handle instance, Type &&value) const { - const auto candidate = data(id); - return candidate && candidate.set(std::move(instance), std::forward<Type>(value)); - } - - /** - * @brief Gets the value of a given variable. - * @param id Unique identifier. - * @param instance An opaque instance of the underlying type. - * @return A wrapper containing the value of the underlying variable. - */ - [[nodiscard]] meta_any get(const id_type id, meta_handle instance) const { - const auto candidate = data(id); - return candidate ? candidate.get(std::move(instance)) : meta_any{meta_ctx_arg, *ctx}; - } - - /** - * @brief Returns a range to visit registered top-level meta properties. - * @return An iterable range to visit registered top-level meta properties. - */ - [[nodiscard]] meta_range<meta_prop, typename decltype(internal::meta_type_descriptor::prop)::const_iterator> prop() const noexcept { - using range_type = meta_range<meta_prop, typename decltype(internal::meta_type_descriptor::prop)::const_iterator>; - return node.details ? range_type{{*ctx, node.details->prop.cbegin()}, {*ctx, node.details->prop.cend()}} : range_type{}; - } - - /** - * @brief Lookup utility for meta properties (bases are also visited). - * @param key The key to use to search for a property. - * @return The registered meta property for the given key, if any. - */ - [[nodiscard]] meta_prop prop(const id_type key) const { - const auto *elem = internal::look_for<&internal::meta_type_descriptor::prop>(internal::meta_context::from(*ctx), node, key); - return elem ? meta_prop{*ctx, *elem} : meta_prop{}; - } - - /*! @copydoc meta_data::traits */ - template<typename Type> - [[nodiscard]] Type traits() const noexcept { - return internal::meta_to_user_traits<Type>(node.traits); - } - - /*! @copydoc meta_data::custom */ - [[nodiscard]] meta_custom custom() const noexcept { - return {node.custom}; - } - - /** - * @brief Returns true if an object is valid, false otherwise. - * @return True if the object is valid, false otherwise. - */ - [[nodiscard]] explicit operator bool() const noexcept { - return !(ctx == nullptr); - } - - /*! @copydoc meta_prop::operator== */ - [[nodiscard]] bool operator==(const meta_type &other) const noexcept { - return (ctx == other.ctx) && ((!node.info && !other.node.info) || (node.info && other.node.info && *node.info == *other.node.info)); - } - -private: - internal::meta_type_node node{}; - const meta_ctx *ctx{}; -}; - -/** - * @brief Checks if two objects refer to the same type. - * @param lhs An object, either valid or not. - * @param rhs An object, either valid or not. - * @return False if the objects refer to the same node, true otherwise. - */ -[[nodiscard]] inline bool operator!=(const meta_type &lhs, const meta_type &rhs) noexcept { - return !(lhs == rhs); -} - -[[nodiscard]] inline meta_type meta_any::type() const noexcept { - return node.info ? meta_type{*ctx, node} : meta_type{}; -} - -template<typename... Args> -// NOLINTNEXTLINE(modernize-use-nodiscard) -meta_any meta_any::invoke(const id_type id, Args &&...args) const { - return type().invoke(id, *this, std::forward<Args>(args)...); -} - -template<typename... Args> -meta_any meta_any::invoke(const id_type id, Args &&...args) { - return type().invoke(id, *this, std::forward<Args>(args)...); -} - -template<typename Type> -bool meta_any::set(const id_type id, Type &&value) { - return type().set(id, *this, std::forward<Type>(value)); -} - -[[nodiscard]] inline meta_any meta_any::get(const id_type id) const { - return type().get(id, *this); -} - -[[nodiscard]] inline meta_any meta_any::get(const id_type id) { - return type().get(id, *this); -} - -[[nodiscard]] inline meta_any meta_any::allow_cast(const meta_type &type) const { - return internal::try_convert(internal::meta_context::from(*ctx), node, type.info(), type.is_arithmetic() || type.is_enum(), data(), [this, &type]([[maybe_unused]] const void *instance, auto &&...args) { - if constexpr((std::is_same_v<std::remove_const_t<std::remove_reference_t<decltype(args)>>, internal::meta_type_node> || ...)) { - return (args.from_void(*ctx, nullptr, instance), ...); - } else if constexpr((std::is_same_v<std::remove_const_t<std::remove_reference_t<decltype(args)>>, internal::meta_conv_node> || ...)) { - return (args.conv(*ctx, instance), ...); - } else if constexpr((std::is_same_v<std::remove_const_t<std::remove_reference_t<decltype(args)>>, decltype(internal::meta_type_node::conversion_helper)> || ...)) { - // exploits the fact that arithmetic types and enums are also default constructible - auto other = type.construct(); - const auto value = (args(nullptr, instance), ...); - other.node.conversion_helper(other.data(), &value); - return other; - } else { - // forwards to force a compile-time error in case of available arguments - return meta_any{meta_ctx_arg, *ctx, std::forward<decltype(args)>(args)...}; - } - }); -} - -inline bool meta_any::assign(const meta_any &other) { - auto value = other.allow_cast({*ctx, node}); - return value && storage.assign(value.storage); -} - -inline bool meta_any::assign(meta_any &&other) { - if(*node.info == *other.node.info) { - return storage.assign(std::move(other.storage)); - } - - return assign(std::as_const(other)); -} - -[[nodiscard]] inline meta_type meta_data::type() const noexcept { - return meta_type{*ctx, node->type(internal::meta_context::from(*ctx))}; -} - -[[nodiscard]] inline meta_type meta_data::arg(const size_type index) const noexcept { - return index < arity() ? node->arg(*ctx, index) : meta_type{}; -} - -[[nodiscard]] inline meta_type meta_func::ret() const noexcept { - return meta_type{*ctx, node->ret(internal::meta_context::from(*ctx))}; -} - -[[nodiscard]] inline meta_type meta_func::arg(const size_type index) const noexcept { - return index < arity() ? node->arg(*ctx, index) : meta_type{}; -} - -/*! @cond TURN_OFF_DOXYGEN */ -class meta_sequence_container::meta_iterator final { - using vtable_type = void(const void *, const std::ptrdiff_t, meta_any *); - - template<typename It> - static void basic_vtable(const void *value, const std::ptrdiff_t offset, meta_any *other) { - const auto &it = *static_cast<const It *>(value); - other ? other->emplace<decltype(*it)>(*it) : std::advance(const_cast<It &>(it), offset); - } - -public: - using value_type = meta_any; - using pointer = input_iterator_pointer<value_type>; - using reference = value_type; - using difference_type = std::ptrdiff_t; - using iterator_category = std::input_iterator_tag; - using iterator_concept = std::bidirectional_iterator_tag; - - meta_iterator() = default; - - template<typename It> - meta_iterator(const meta_ctx &area, It iter) noexcept - : ctx{&area}, - vtable{&basic_vtable<It>}, - handle{iter} {} - - meta_iterator &operator++() noexcept { - vtable(handle.data(), 1, nullptr); - return *this; - } - - meta_iterator operator++(int value) noexcept { - meta_iterator orig = *this; - vtable(handle.data(), ++value, nullptr); - return orig; - } - - meta_iterator &operator--() noexcept { - vtable(handle.data(), -1, nullptr); - return *this; - } - - meta_iterator operator--(int value) noexcept { - meta_iterator orig = *this; - vtable(handle.data(), --value, nullptr); - return orig; - } - - [[nodiscard]] reference operator*() const { - reference other{meta_ctx_arg, *ctx}; - vtable(handle.data(), 0, &other); - return other; - } - - [[nodiscard]] pointer operator->() const { - return operator*(); - } - - [[nodiscard]] explicit operator bool() const noexcept { - return static_cast<bool>(handle); - } - - [[nodiscard]] bool operator==(const meta_iterator &other) const noexcept { - return handle == other.handle; - } - - [[nodiscard]] bool operator!=(const meta_iterator &other) const noexcept { - return !(*this == other); - } - - [[nodiscard]] const any &base() const noexcept { - return handle; - } - -private: - const meta_ctx *ctx{&locator<meta_ctx>::value_or()}; - vtable_type *vtable{}; - any handle{}; -}; - -class meta_associative_container::meta_iterator final { - using vtable_type = void(const void *, std::pair<meta_any, meta_any> *); - - template<bool KeyOnly, typename It> - static void basic_vtable(const void *value, std::pair<meta_any, meta_any> *other) { - if(const auto &it = *static_cast<const It *>(value); other) { - if constexpr(KeyOnly) { - other->first.emplace<decltype(*it)>(*it); - } else { - other->first.emplace<decltype((it->first))>(it->first); - other->second.emplace<decltype((it->second))>(it->second); - } - } else { - ++const_cast<It &>(it); - } - } - -public: - using value_type = std::pair<meta_any, meta_any>; - using pointer = input_iterator_pointer<value_type>; - using reference = value_type; - using difference_type = std::ptrdiff_t; - using iterator_category = std::input_iterator_tag; - using iterator_concept = std::forward_iterator_tag; - - meta_iterator() = default; - - template<bool KeyOnly, typename It> - meta_iterator(const meta_ctx &area, std::bool_constant<KeyOnly>, It iter) noexcept - : ctx{&area}, - vtable{&basic_vtable<KeyOnly, It>}, - handle{iter} {} - - meta_iterator &operator++() noexcept { - vtable(handle.data(), nullptr); - return *this; - } - - meta_iterator operator++(int) noexcept { - meta_iterator orig = *this; - vtable(handle.data(), nullptr); - return orig; - } - - [[nodiscard]] reference operator*() const { - reference other{{meta_ctx_arg, *ctx}, {meta_ctx_arg, *ctx}}; - vtable(handle.data(), &other); - return other; - } - - [[nodiscard]] pointer operator->() const { - return operator*(); - } - - [[nodiscard]] explicit operator bool() const noexcept { - return static_cast<bool>(handle); - } - - [[nodiscard]] bool operator==(const meta_iterator &other) const noexcept { - return handle == other.handle; - } - - [[nodiscard]] bool operator!=(const meta_iterator &other) const noexcept { - return !(*this == other); - } - -private: - const meta_ctx *ctx{&locator<meta_ctx>::value_or()}; - vtable_type *vtable{}; - any handle{}; -}; -/*! @endcond */ - -/** - * @brief Returns the meta value type of a container. - * @return The meta value type of the container. - */ -[[nodiscard]] inline meta_type meta_sequence_container::value_type() const noexcept { - return value_type_node ? meta_type{*ctx, value_type_node(internal::meta_context::from(*ctx))} : meta_type{}; -} - -/** - * @brief Returns the size of a container. - * @return The size of the container. - */ -[[nodiscard]] inline meta_sequence_container::size_type meta_sequence_container::size() const noexcept { - return size_fn(data); -} - -/** - * @brief Resizes a container to contain a given number of elements. - * @param sz The new size of the container. - * @return True in case of success, false otherwise. - */ -inline bool meta_sequence_container::resize(const size_type sz) { - return !const_only && resize_fn(const_cast<void *>(data), sz); -} - -/** - * @brief Clears the content of a container. - * @return True in case of success, false otherwise. - */ -inline bool meta_sequence_container::clear() { - return !const_only && clear_fn(const_cast<void *>(data)); -} - -/** - * @brief Reserves storage for at least the given number of elements. - * @param sz The new capacity of the container. - * @return True in case of success, false otherwise. - */ -inline bool meta_sequence_container::reserve(const size_type sz) { - return !const_only && reserve_fn(const_cast<void *>(data), sz); -} - -/** - * @brief Returns an iterator to the first element of a container. - * @return An iterator to the first element of the container. - */ -[[nodiscard]] inline meta_sequence_container::iterator meta_sequence_container::begin() { - return begin_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data); -} - -/** - * @brief Returns an iterator that is past the last element of a container. - * @return An iterator that is past the last element of the container. - */ -[[nodiscard]] inline meta_sequence_container::iterator meta_sequence_container::end() { - return end_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data); -} - -/** - * @brief Inserts an element at a specified location of a container. - * @param it Iterator before which the element will be inserted. - * @param value Element value to insert. - * @return A possibly invalid iterator to the inserted element. - */ -inline meta_sequence_container::iterator meta_sequence_container::insert(const iterator &it, meta_any value) { - // this abomination is necessary because only on macos value_type and const_reference are different types for std::vector<bool> - if(const auto vtype = value_type_node(internal::meta_context::from(*ctx)); !const_only && (value.allow_cast({*ctx, vtype}) || value.allow_cast({*ctx, const_reference_node(internal::meta_context::from(*ctx))}))) { - const bool is_value_type = (value.type().info() == *vtype.info); - return insert_fn(*ctx, const_cast<void *>(data), is_value_type ? std::as_const(value).data() : nullptr, is_value_type ? nullptr : std::as_const(value).data(), it); - } - - return iterator{}; -} - -/** - * @brief Removes a given element from a container. - * @param it Iterator to the element to remove. - * @return A possibly invalid iterator following the last removed element. - */ -inline meta_sequence_container::iterator meta_sequence_container::erase(const iterator &it) { - return const_only ? iterator{} : erase_fn(*ctx, const_cast<void *>(data), it); -} - -/** - * @brief Returns a reference to the element at a given location of a container. - * @param pos The position of the element to return. - * @return A reference to the requested element properly wrapped. - */ -[[nodiscard]] inline meta_any meta_sequence_container::operator[](const size_type pos) { - auto it = begin(); - it.operator++(static_cast<int>(pos) - 1); - return *it; -} - -/** - * @brief Returns false if a proxy is invalid, true otherwise. - * @return False if the proxy is invalid, true otherwise. - */ -[[nodiscard]] inline meta_sequence_container::operator bool() const noexcept { - return (data != nullptr); -} - -/** - * @brief Returns the meta key type of a container. - * @return The meta key type of the a container. - */ -[[nodiscard]] inline meta_type meta_associative_container::key_type() const noexcept { - return key_type_node ? meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))} : meta_type{}; -} - -/** - * @brief Returns the meta mapped type of a container. - * @return The meta mapped type of the a container. - */ -[[nodiscard]] inline meta_type meta_associative_container::mapped_type() const noexcept { - return mapped_type_node ? meta_type{*ctx, mapped_type_node(internal::meta_context::from(*ctx))} : meta_type{}; -} - -/*! @copydoc meta_sequence_container::value_type */ -[[nodiscard]] inline meta_type meta_associative_container::value_type() const noexcept { - return value_type_node ? meta_type{*ctx, value_type_node(internal::meta_context::from(*ctx))} : meta_type{}; -} - -/*! @copydoc meta_sequence_container::size */ -[[nodiscard]] inline meta_associative_container::size_type meta_associative_container::size() const noexcept { - return size_fn(data); -} - -/*! @copydoc meta_sequence_container::clear */ -inline bool meta_associative_container::clear() { - return !const_only && clear_fn(const_cast<void *>(data)); -} - -/*! @copydoc meta_sequence_container::reserve */ -inline bool meta_associative_container::reserve(const size_type sz) { - return !const_only && reserve_fn(const_cast<void *>(data), sz); -} - -/*! @copydoc meta_sequence_container::begin */ -[[nodiscard]] inline meta_associative_container::iterator meta_associative_container::begin() { - return begin_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data); -} - -/*! @copydoc meta_sequence_container::end */ -[[nodiscard]] inline meta_associative_container::iterator meta_associative_container::end() { - return end_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data); -} - -/** - * @brief Inserts a key-only or key/value element into a container. - * @param key The key of the element to insert. - * @param value The value of the element to insert, if needed. - * @return A bool denoting whether the insertion took place. - */ -inline bool meta_associative_container::insert(meta_any key, meta_any value = {}) { - return !const_only && key.allow_cast(meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))}) - && (!mapped_type_node || value.allow_cast(meta_type{*ctx, mapped_type_node(internal::meta_context::from(*ctx))})) - && insert_fn(const_cast<void *>(data), std::as_const(key).data(), std::as_const(value).data()); -} - -/** - * @brief Removes the specified element from a container. - * @param key The key of the element to remove. - * @return A bool denoting whether the removal took place. - */ -inline meta_associative_container::size_type meta_associative_container::erase(meta_any key) { - return (!const_only && key.allow_cast(meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))})) ? erase_fn(const_cast<void *>(data), std::as_const(key).data()) : 0u; -} - -/** - * @brief Returns an iterator to the element with a given key, if any. - * @param key The key of the element to search. - * @return An iterator to the element with the given key, if any. - */ -[[nodiscard]] inline meta_associative_container::iterator meta_associative_container::find(meta_any key) { - return key.allow_cast(meta_type{*ctx, key_type_node(internal::meta_context::from(*ctx))}) ? find_fn(*ctx, const_only ? nullptr : const_cast<void *>(data), data, std::as_const(key).data()) : iterator{}; -} - -/** - * @brief Returns false if a proxy is invalid, true otherwise. - * @return False if the proxy is invalid, true otherwise. - */ -[[nodiscard]] inline meta_associative_container::operator bool() const noexcept { - return (data != nullptr); -} - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/meta/node.hpp b/deps/entt/include/entt/meta/node.hpp deleted file mode 100644 index 5c4e25c..0000000 --- a/deps/entt/include/entt/meta/node.hpp +++ /dev/null @@ -1,298 +0,0 @@ -#ifndef ENTT_META_NODE_HPP -#define ENTT_META_NODE_HPP - -#include <cstddef> -#include <memory> -#include <type_traits> -#include <utility> -#include "../config/config.h" -#include "../container/dense_map.hpp" -#include "../core/attribute.h" -#include "../core/bit.hpp" -#include "../core/enum.hpp" -#include "../core/fwd.hpp" -#include "../core/type_info.hpp" -#include "../core/type_traits.hpp" -#include "../core/utility.hpp" -#include "context.hpp" -#include "type_traits.hpp" - -namespace entt { - -class meta_any; -class meta_type; -struct meta_handle; - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -enum class meta_traits : std::uint32_t { - is_none = 0x0000, - is_const = 0x0001, - is_static = 0x0002, - is_arithmetic = 0x0004, - is_integral = 0x0008, - is_signed = 0x0010, - is_array = 0x0020, - is_enum = 0x0040, - is_class = 0x0080, - is_pointer = 0x0100, - is_meta_pointer_like = 0x0200, - is_meta_sequence_container = 0x0400, - is_meta_associative_container = 0x0800, - _user_defined_traits = 0xFFFF, - _entt_enum_as_bitmask = 0xFFFF -}; - -template<typename Type> -[[nodiscard]] auto meta_to_user_traits(const meta_traits traits) noexcept { - static_assert(std::is_enum_v<Type>, "Invalid enum type"); - constexpr auto shift = popcount(static_cast<std::underlying_type_t<meta_traits>>(meta_traits::_user_defined_traits)); - return Type{static_cast<std::underlying_type_t<Type>>(static_cast<std::underlying_type_t<meta_traits>>(traits) >> shift)}; -} - -template<typename Type> -[[nodiscard]] auto user_to_meta_traits(const Type value) noexcept { - static_assert(std::is_enum_v<Type>, "Invalid enum type"); - constexpr auto shift = popcount(static_cast<std::underlying_type_t<meta_traits>>(meta_traits::_user_defined_traits)); - const auto traits = static_cast<std::underlying_type_t<internal::meta_traits>>(static_cast<std::underlying_type_t<Type>>(value)); - ENTT_ASSERT(traits < ((~static_cast<std::underlying_type_t<meta_traits>>(meta_traits::_user_defined_traits)) >> shift), "Invalid traits"); - return meta_traits{traits << shift}; -} - -struct meta_type_node; - -struct meta_custom_node { - id_type type{}; - std::shared_ptr<void> value{}; -}; - -struct meta_prop_node { - meta_type_node (*type)(const meta_context &) noexcept {}; - std::shared_ptr<void> value{}; -}; - -struct meta_base_node { - meta_type_node (*type)(const meta_context &) noexcept {}; - const void *(*cast)(const void *) noexcept {}; -}; - -struct meta_conv_node { - meta_any (*conv)(const meta_ctx &, const void *){}; -}; - -struct meta_ctor_node { - using size_type = std::size_t; - - size_type arity{0u}; - meta_type (*arg)(const meta_ctx &, const size_type) noexcept {}; - meta_any (*invoke)(const meta_ctx &, meta_any *const){}; -}; - -struct meta_dtor_node { - void (*dtor)(void *){}; -}; - -struct meta_data_node { - using size_type = std::size_t; - - meta_traits traits{meta_traits::is_none}; - size_type arity{0u}; - meta_type_node (*type)(const meta_context &) noexcept {}; - meta_type (*arg)(const meta_ctx &, const size_type) noexcept {}; - bool (*set)(meta_handle, meta_any){}; - meta_any (*get)(const meta_ctx &, meta_handle){}; - meta_custom_node custom{}; - dense_map<id_type, meta_prop_node, identity> prop{}; -}; - -struct meta_func_node { - using size_type = std::size_t; - - meta_traits traits{meta_traits::is_none}; - size_type arity{0u}; - meta_type_node (*ret)(const meta_context &) noexcept {}; - meta_type (*arg)(const meta_ctx &, const size_type) noexcept {}; - meta_any (*invoke)(const meta_ctx &, meta_handle, meta_any *const){}; - std::shared_ptr<meta_func_node> next{}; - meta_custom_node custom{}; - dense_map<id_type, meta_prop_node, identity> prop{}; -}; - -struct meta_template_node { - using size_type = std::size_t; - - size_type arity{0u}; - meta_type_node (*type)(const meta_context &) noexcept {}; - meta_type_node (*arg)(const meta_context &, const size_type) noexcept {}; -}; - -struct meta_type_descriptor { - dense_map<id_type, meta_ctor_node, identity> ctor{}; - dense_map<id_type, meta_base_node, identity> base{}; - dense_map<id_type, meta_conv_node, identity> conv{}; - dense_map<id_type, meta_data_node, identity> data{}; - dense_map<id_type, meta_func_node, identity> func{}; - dense_map<id_type, meta_prop_node, identity> prop{}; -}; - -struct meta_type_node { - using size_type = std::size_t; - - const type_info *info{}; - id_type id{}; - meta_traits traits{meta_traits::is_none}; - size_type size_of{0u}; - meta_type_node (*resolve)(const meta_context &) noexcept {}; - meta_type_node (*remove_pointer)(const meta_context &) noexcept {}; - meta_any (*default_constructor)(const meta_ctx &){}; - double (*conversion_helper)(void *, const void *){}; - meta_any (*from_void)(const meta_ctx &, void *, const void *){}; - meta_template_node templ{}; - meta_dtor_node dtor{}; - meta_custom_node custom{}; - std::shared_ptr<meta_type_descriptor> details{}; -}; - -template<auto Member> -auto *look_for(const meta_context &context, const meta_type_node &node, const id_type id) { - if(node.details) { - if(const auto it = (node.details.get()->*Member).find(id); it != (node.details.get()->*Member).cend()) { - return &it->second; - } - - for(auto &&curr: node.details->base) { - if(auto *elem = look_for<Member>(context, curr.second.type(context), id); elem) { - return elem; - } - } - } - - return static_cast<typename std::remove_reference_t<decltype(node.details.get()->*Member)>::mapped_type *>(nullptr); -} - -template<typename Type> -meta_type_node resolve(const meta_context &) noexcept; - -template<typename... Args> -[[nodiscard]] auto meta_arg_node(const meta_context &context, type_list<Args...>, [[maybe_unused]] const std::size_t index) noexcept { - [[maybe_unused]] std::size_t pos{}; - meta_type_node (*value)(const meta_context &) noexcept = nullptr; - ((value = (pos++ == index ? &resolve<std::remove_cv_t<std::remove_reference_t<Args>>> : value)), ...); - ENTT_ASSERT(value != nullptr, "Out of bounds"); - return value(context); -} - -[[nodiscard]] inline const void *try_cast(const meta_context &context, const meta_type_node &from, const meta_type_node &to, const void *instance) noexcept { - if(from.info && to.info && *from.info == *to.info) { - return instance; - } - - if(from.details) { - for(auto &&curr: from.details->base) { - if(const void *elem = try_cast(context, curr.second.type(context), to, curr.second.cast(instance)); elem) { - return elem; - } - } - } - - return nullptr; -} - -template<typename Func> -[[nodiscard]] inline auto try_convert(const meta_context &context, const meta_type_node &from, const type_info &to, const bool arithmetic_or_enum, const void *instance, Func func) { - if(from.info && *from.info == to) { - return func(instance, from); - } - - if(from.details) { - if(auto it = from.details->conv.find(to.hash()); it != from.details->conv.cend()) { - return func(instance, it->second); - } - - for(auto &&curr: from.details->base) { - if(auto other = try_convert(context, curr.second.type(context), to, arithmetic_or_enum, curr.second.cast(instance), func); other) { - return other; - } - } - } - - if(from.conversion_helper && arithmetic_or_enum) { - return func(instance, from.conversion_helper); - } - - return func(instance); -} - -[[nodiscard]] inline const meta_type_node *try_resolve(const meta_context &context, const type_info &info) noexcept { - const auto it = context.value.find(info.hash()); - return it != context.value.end() ? &it->second : nullptr; -} - -template<typename Type> -[[nodiscard]] meta_type_node resolve(const meta_context &context) noexcept { - static_assert(std::is_same_v<Type, std::remove_const_t<std::remove_reference_t<Type>>>, "Invalid type"); - - if(auto *elem = try_resolve(context, type_id<Type>()); elem) { - return *elem; - } - - meta_type_node node{ - &type_id<Type>(), - type_id<Type>().hash(), - (std::is_arithmetic_v<Type> ? meta_traits::is_arithmetic : meta_traits::is_none) - | (std::is_integral_v<Type> ? meta_traits::is_integral : meta_traits::is_none) - | (std::is_signed_v<Type> ? meta_traits::is_signed : meta_traits::is_none) - | (std::is_array_v<Type> ? meta_traits::is_array : meta_traits::is_none) - | (std::is_enum_v<Type> ? meta_traits::is_enum : meta_traits::is_none) - | (std::is_class_v<Type> ? meta_traits::is_class : meta_traits::is_none) - | (std::is_pointer_v<Type> ? meta_traits::is_pointer : meta_traits::is_none) - | (is_meta_pointer_like_v<Type> ? meta_traits::is_meta_pointer_like : meta_traits::is_none) - | (is_complete_v<meta_sequence_container_traits<Type>> ? meta_traits::is_meta_sequence_container : meta_traits::is_none) - | (is_complete_v<meta_associative_container_traits<Type>> ? meta_traits::is_meta_associative_container : meta_traits::is_none), - size_of_v<Type>, - &resolve<Type>, - &resolve<std::remove_cv_t<std::remove_pointer_t<Type>>>}; - - if constexpr(std::is_default_constructible_v<Type>) { - node.default_constructor = +[](const meta_ctx &ctx) { - return meta_any{ctx, std::in_place_type<Type>}; - }; - } - - if constexpr(std::is_arithmetic_v<Type>) { - node.conversion_helper = +[](void *lhs, const void *rhs) { - return lhs ? static_cast<double>(*static_cast<Type *>(lhs) = static_cast<Type>(*static_cast<const double *>(rhs))) : static_cast<double>(*static_cast<const Type *>(rhs)); - }; - } else if constexpr(std::is_enum_v<Type>) { - node.conversion_helper = +[](void *lhs, const void *rhs) { - return lhs ? static_cast<double>(*static_cast<Type *>(lhs) = static_cast<Type>(static_cast<std::underlying_type_t<Type>>(*static_cast<const double *>(rhs)))) : static_cast<double>(*static_cast<const Type *>(rhs)); - }; - } - - if constexpr(!std::is_void_v<Type> && !std::is_function_v<Type>) { - node.from_void = +[](const meta_ctx &ctx, void *elem, const void *celem) { - if(elem) { - return meta_any{ctx, std::in_place_type<std::decay_t<Type> &>, *static_cast<std::decay_t<Type> *>(elem)}; - } - - return meta_any{ctx, std::in_place_type<const std::decay_t<Type> &>, *static_cast<const std::decay_t<Type> *>(celem)}; - }; - } - - if constexpr(is_complete_v<meta_template_traits<Type>>) { - node.templ = meta_template_node{ - meta_template_traits<Type>::args_type::size, - &resolve<typename meta_template_traits<Type>::class_type>, - +[](const meta_context &area, const std::size_t index) noexcept { return meta_arg_node(area, typename meta_template_traits<Type>::args_type{}, index); }}; - } - - return node; -} - -} // namespace internal -/*! @endcond */ - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/meta/pointer.hpp b/deps/entt/include/entt/meta/pointer.hpp deleted file mode 100644 index e90b0a1..0000000 --- a/deps/entt/include/entt/meta/pointer.hpp +++ /dev/null @@ -1,51 +0,0 @@ -// IWYU pragma: always_keep - -#ifndef ENTT_META_POINTER_HPP -#define ENTT_META_POINTER_HPP - -#include <memory> -#include <type_traits> -#include "type_traits.hpp" - -namespace entt { - -/** - * @brief Makes plain pointers pointer-like types for the meta system. - * @tparam Type Element type. - */ -template<typename Type> -struct is_meta_pointer_like<Type *> - : std::true_type {}; - -/** - * @brief Partial specialization used to reject pointers to arrays. - * @tparam Type Type of elements of the array. - * @tparam N Number of elements of the array. - */ -template<typename Type, std::size_t N> -// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays) -struct is_meta_pointer_like<Type (*)[N]> - : std::false_type {}; - -/** - * @brief Makes `std::shared_ptr`s of any type pointer-like types for the meta - * system. - * @tparam Type Element type. - */ -template<typename Type> -struct is_meta_pointer_like<std::shared_ptr<Type>> - : std::true_type {}; - -/** - * @brief Makes `std::unique_ptr`s of any type pointer-like types for the meta - * system. - * @tparam Type Element type. - * @tparam Args Other arguments. - */ -template<typename Type, typename... Args> -struct is_meta_pointer_like<std::unique_ptr<Type, Args...>> - : std::true_type {}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/meta/policy.hpp b/deps/entt/include/entt/meta/policy.hpp deleted file mode 100644 index b939599..0000000 --- a/deps/entt/include/entt/meta/policy.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef ENTT_META_POLICY_HPP -#define ENTT_META_POLICY_HPP - -#include <type_traits> - -namespace entt { - -/*! @brief Empty class type used to request the _as ref_ policy. */ -struct as_ref_t final { - /*! @cond TURN_OFF_DOXYGEN */ - template<typename Type> - static constexpr bool value = std::is_reference_v<Type> && !std::is_const_v<std::remove_reference_t<Type>>; - /*! @endcond */ -}; - -/*! @brief Empty class type used to request the _as cref_ policy. */ -struct as_cref_t final { - /*! @cond TURN_OFF_DOXYGEN */ - template<typename Type> - static constexpr bool value = std::is_reference_v<Type>; - /*! @endcond */ -}; - -/*! @brief Empty class type used to request the _as-is_ policy. */ -struct as_is_t final { - /*! @cond TURN_OFF_DOXYGEN */ - template<typename> - static constexpr bool value = true; - /*! @endcond */ -}; - -/*! @brief Empty class type used to request the _as void_ policy. */ -struct as_void_t final { - /*! @cond TURN_OFF_DOXYGEN */ - template<typename> - static constexpr bool value = true; - /*! @endcond */ -}; - -/** - * @brief Provides the member constant `value` to true if a type also is a meta - * policy, false otherwise. - * @tparam Type Type to check. - */ -template<typename Type> -struct is_meta_policy - : std::bool_constant<std::is_same_v<Type, as_ref_t> || std::is_same_v<Type, as_cref_t> || std::is_same_v<Type, as_is_t> || std::is_same_v<Type, as_void_t>> {}; - -/** - * @brief Helper variable template. - * @tparam Type Type to check. - */ -template<typename Type> -inline constexpr bool is_meta_policy_v = is_meta_policy<Type>::value; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/meta/range.hpp b/deps/entt/include/entt/meta/range.hpp deleted file mode 100644 index f53b572..0000000 --- a/deps/entt/include/entt/meta/range.hpp +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef ENTT_META_RANGE_HPP -#define ENTT_META_RANGE_HPP - -#include <cstddef> -#include <iterator> -#include <utility> -#include "../core/fwd.hpp" -#include "../core/iterator.hpp" -#include "context.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename Type, typename It> -struct meta_range_iterator final { - using value_type = std::pair<id_type, Type>; - using pointer = input_iterator_pointer<value_type>; - using reference = value_type; - using difference_type = std::ptrdiff_t; - using iterator_category = std::input_iterator_tag; - using iterator_concept = std::random_access_iterator_tag; - - constexpr meta_range_iterator() noexcept - : it{}, - ctx{} {} - - constexpr meta_range_iterator(const meta_ctx &area, const It iter) noexcept - : it{iter}, - ctx{&area} {} - - constexpr meta_range_iterator &operator++() noexcept { - return ++it, *this; - } - - constexpr meta_range_iterator operator++(int) noexcept { - meta_range_iterator orig = *this; - return ++(*this), orig; - } - - constexpr meta_range_iterator &operator--() noexcept { - return --it, *this; - } - - constexpr meta_range_iterator operator--(int) noexcept { - meta_range_iterator orig = *this; - return operator--(), orig; - } - - constexpr meta_range_iterator &operator+=(const difference_type value) noexcept { - it += value; - return *this; - } - - constexpr meta_range_iterator operator+(const difference_type value) const noexcept { - meta_range_iterator copy = *this; - return (copy += value); - } - - constexpr meta_range_iterator &operator-=(const difference_type value) noexcept { - return (*this += -value); - } - - constexpr meta_range_iterator operator-(const difference_type value) const noexcept { - return (*this + -value); - } - - [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept { - return {it[value].first, Type{*ctx, it[value].second}}; - } - - [[nodiscard]] constexpr pointer operator->() const noexcept { - return operator*(); - } - - [[nodiscard]] constexpr reference operator*() const noexcept { - return operator[](0); - } - - template<typename... Args> - friend constexpr std::ptrdiff_t operator-(const meta_range_iterator<Args...> &, const meta_range_iterator<Args...> &) noexcept; - - template<typename... Args> - friend constexpr bool operator==(const meta_range_iterator<Args...> &, const meta_range_iterator<Args...> &) noexcept; - - template<typename... Args> - friend constexpr bool operator<(const meta_range_iterator<Args...> &, const meta_range_iterator<Args...> &) noexcept; - -private: - It it; - const meta_ctx *ctx; -}; - -template<typename... Args> -[[nodiscard]] constexpr std::ptrdiff_t operator-(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept { - return lhs.it - rhs.it; -} - -template<typename... Args> -[[nodiscard]] constexpr bool operator==(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept { - return lhs.it == rhs.it; -} - -template<typename... Args> -[[nodiscard]] constexpr bool operator!=(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept { - return !(lhs == rhs); -} - -template<typename... Args> -[[nodiscard]] constexpr bool operator<(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept { - return lhs.it < rhs.it; -} - -template<typename... Args> -[[nodiscard]] constexpr bool operator>(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept { - return rhs < lhs; -} - -template<typename... Args> -[[nodiscard]] constexpr bool operator<=(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept { - return !(lhs > rhs); -} - -template<typename... Args> -[[nodiscard]] constexpr bool operator>=(const meta_range_iterator<Args...> &lhs, const meta_range_iterator<Args...> &rhs) noexcept { - return !(lhs < rhs); -} - -} // namespace internal -/*! @endcond */ - -/** - * @brief Iterable range to use to iterate all types of meta objects. - * @tparam Type Type of meta objects returned. - * @tparam It Type of forward iterator. - */ -template<typename Type, typename It> -using meta_range = iterable_adaptor<internal::meta_range_iterator<Type, It>>; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/meta/resolve.hpp b/deps/entt/include/entt/meta/resolve.hpp deleted file mode 100644 index 9360db5..0000000 --- a/deps/entt/include/entt/meta/resolve.hpp +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef ENTT_META_RESOLVE_HPP -#define ENTT_META_RESOLVE_HPP - -#include <type_traits> -#include "../core/type_info.hpp" -#include "../locator/locator.hpp" -#include "context.hpp" -#include "meta.hpp" -#include "node.hpp" -#include "range.hpp" - -namespace entt { - -/** - * @brief Returns the meta type associated with a given type. - * @tparam Type Type to use to search for a meta type. - * @param ctx The context from which to search for meta types. - * @return The meta type associated with the given type, if any. - */ -template<typename Type> -[[nodiscard]] meta_type resolve(const meta_ctx &ctx) noexcept { - auto &&context = internal::meta_context::from(ctx); - return {ctx, internal::resolve<std::remove_cv_t<std::remove_reference_t<Type>>>(context)}; -} - -/** - * @brief Returns the meta type associated with a given type. - * @tparam Type Type to use to search for a meta type. - * @return The meta type associated with the given type, if any. - */ -template<typename Type> -[[nodiscard]] meta_type resolve() noexcept { - return resolve<Type>(locator<meta_ctx>::value_or()); -} - -/** - * @brief Returns a range to use to visit all meta types. - * @param ctx The context from which to search for meta types. - * @return An iterable range to use to visit all meta types. - */ -[[nodiscard]] inline meta_range<meta_type, typename decltype(internal::meta_context::value)::const_iterator> resolve(const meta_ctx &ctx) noexcept { - auto &&context = internal::meta_context::from(ctx); - return {{ctx, context.value.cbegin()}, {ctx, context.value.cend()}}; -} - -/** - * @brief Returns a range to use to visit all meta types. - * @return An iterable range to use to visit all meta types. - */ -[[nodiscard]] inline meta_range<meta_type, typename decltype(internal::meta_context::value)::const_iterator> resolve() noexcept { - return resolve(locator<meta_ctx>::value_or()); -} - -/** - * @brief Returns the meta type associated with a given identifier, if any. - * @param ctx The context from which to search for meta types. - * @param id Unique identifier. - * @return The meta type associated with the given identifier, if any. - */ -[[nodiscard]] inline meta_type resolve(const meta_ctx &ctx, const id_type id) noexcept { - for(auto &&curr: resolve(ctx)) { - if(curr.second.id() == id) { - return curr.second; - } - } - - return meta_type{}; -} - -/** - * @brief Returns the meta type associated with a given identifier, if any. - * @param id Unique identifier. - * @return The meta type associated with the given identifier, if any. - */ -[[nodiscard]] inline meta_type resolve(const id_type id) noexcept { - return resolve(locator<meta_ctx>::value_or(), id); -} - -/** - * @brief Returns the meta type associated with a given type info object. - * @param ctx The context from which to search for meta types. - * @param info The type info object of the requested type. - * @return The meta type associated with the given type info object, if any. - */ -[[nodiscard]] inline meta_type resolve(const meta_ctx &ctx, const type_info &info) noexcept { - auto &&context = internal::meta_context::from(ctx); - const auto *elem = internal::try_resolve(context, info); - return elem ? meta_type{ctx, *elem} : meta_type{}; -} - -/** - * @brief Returns the meta type associated with a given type info object. - * @param info The type info object of the requested type. - * @return The meta type associated with the given type info object, if any. - */ -[[nodiscard]] inline meta_type resolve(const type_info &info) noexcept { - return resolve(locator<meta_ctx>::value_or(), info); -} - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/meta/template.hpp b/deps/entt/include/entt/meta/template.hpp deleted file mode 100644 index 5eab2af..0000000 --- a/deps/entt/include/entt/meta/template.hpp +++ /dev/null @@ -1,29 +0,0 @@ -// IWYU pragma: always_keep - -#ifndef ENTT_META_TEMPLATE_HPP -#define ENTT_META_TEMPLATE_HPP - -#include "../core/type_traits.hpp" - -namespace entt { - -/*! @brief Utility class to disambiguate class templates. */ -template<template<typename...> class> -struct meta_class_template_tag {}; - -/** - * @brief General purpose traits class for generating meta template information. - * @tparam Clazz Type of class template. - * @tparam Args Types of template arguments. - */ -template<template<typename...> class Clazz, typename... Args> -struct meta_template_traits<Clazz<Args...>> { - /*! @brief Wrapped class template. */ - using class_type = meta_class_template_tag<Clazz>; - /*! @brief List of template arguments. */ - using args_type = type_list<Args...>; -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/meta/type_traits.hpp b/deps/entt/include/entt/meta/type_traits.hpp deleted file mode 100644 index 9ba167f..0000000 --- a/deps/entt/include/entt/meta/type_traits.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef ENTT_META_TYPE_TRAITS_HPP -#define ENTT_META_TYPE_TRAITS_HPP - -#include <type_traits> -#include <utility> - -namespace entt { - -/** - * @brief Traits class template to be specialized to enable support for meta - * template information. - */ -template<typename> -struct meta_template_traits; - -/** - * @brief Traits class template to be specialized to enable support for meta - * sequence containers. - */ -template<typename> -struct meta_sequence_container_traits; - -/** - * @brief Traits class template to be specialized to enable support for meta - * associative containers. - */ -template<typename> -struct meta_associative_container_traits; - -/** - * @brief Provides the member constant `value` to true if a given type is a - * pointer-like type from the point of view of the meta system, false otherwise. - */ -template<typename> -struct is_meta_pointer_like: std::false_type {}; - -/** - * @brief Partial specialization to ensure that const pointer-like types are - * also accepted. - * @tparam Type Potentially pointer-like type. - */ -template<typename Type> -struct is_meta_pointer_like<const Type>: is_meta_pointer_like<Type> {}; - -/** - * @brief Helper variable template. - * @tparam Type Potentially pointer-like type. - */ -template<typename Type> -inline constexpr auto is_meta_pointer_like_v = is_meta_pointer_like<Type>::value; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/meta/utility.hpp b/deps/entt/include/entt/meta/utility.hpp deleted file mode 100644 index b2e45c6..0000000 --- a/deps/entt/include/entt/meta/utility.hpp +++ /dev/null @@ -1,539 +0,0 @@ -#ifndef ENTT_META_UTILITY_HPP -#define ENTT_META_UTILITY_HPP - -#include <cstddef> -#include <functional> -#include <type_traits> -#include <utility> -#include "../core/type_traits.hpp" -#include "../locator/locator.hpp" -#include "meta.hpp" -#include "node.hpp" -#include "policy.hpp" - -namespace entt { - -/** - * @brief Meta function descriptor traits. - * @tparam Ret Function return type. - * @tparam Args Function arguments. - * @tparam Static Function staticness. - * @tparam Const Function constness. - */ -template<typename Ret, typename Args, bool Static, bool Const> -struct meta_function_descriptor_traits { - /*! @brief Meta function return type. */ - using return_type = Ret; - /*! @brief Meta function arguments. */ - using args_type = Args; - - /*! @brief True if the meta function is static, false otherwise. */ - static constexpr bool is_static = Static; - /*! @brief True if the meta function is const, false otherwise. */ - static constexpr bool is_const = Const; -}; - -/*! @brief Primary template isn't defined on purpose. */ -template<typename, typename> -struct meta_function_descriptor; - -/** - * @brief Meta function descriptor. - * @tparam Type Reflected type to which the meta function is associated. - * @tparam Ret Function return type. - * @tparam Class Actual owner of the member function. - * @tparam Args Function arguments. - */ -template<typename Type, typename Ret, typename Class, typename... Args> -struct meta_function_descriptor<Type, Ret (Class::*)(Args...) const> - : meta_function_descriptor_traits< - Ret, - std::conditional_t<std::is_base_of_v<Class, Type>, type_list<Args...>, type_list<const Class &, Args...>>, - !std::is_base_of_v<Class, Type>, - true> {}; - -/** - * @brief Meta function descriptor. - * @tparam Type Reflected type to which the meta function is associated. - * @tparam Ret Function return type. - * @tparam Class Actual owner of the member function. - * @tparam Args Function arguments. - */ -template<typename Type, typename Ret, typename Class, typename... Args> -struct meta_function_descriptor<Type, Ret (Class::*)(Args...)> - : meta_function_descriptor_traits< - Ret, - std::conditional_t<std::is_base_of_v<Class, Type>, type_list<Args...>, type_list<Class &, Args...>>, - !std::is_base_of_v<Class, Type>, - false> {}; - -/** - * @brief Meta function descriptor. - * @tparam Type Reflected type to which the meta data is associated. - * @tparam Class Actual owner of the data member. - * @tparam Ret Data member type. - */ -template<typename Type, typename Ret, typename Class> -struct meta_function_descriptor<Type, Ret Class::*> - : meta_function_descriptor_traits< - Ret &, - std::conditional_t<std::is_base_of_v<Class, Type>, type_list<>, type_list<Class &>>, - !std::is_base_of_v<Class, Type>, - false> {}; - -/** - * @brief Meta function descriptor. - * @tparam Type Reflected type to which the meta function is associated. - * @tparam Ret Function return type. - * @tparam MaybeType First function argument. - * @tparam Args Other function arguments. - */ -template<typename Type, typename Ret, typename MaybeType, typename... Args> -struct meta_function_descriptor<Type, Ret (*)(MaybeType, Args...)> - : meta_function_descriptor_traits< - Ret, - std::conditional_t< - std::is_same_v<std::remove_cv_t<std::remove_reference_t<MaybeType>>, Type> || std::is_base_of_v<std::remove_cv_t<std::remove_reference_t<MaybeType>>, Type>, - type_list<Args...>, - type_list<MaybeType, Args...>>, - !(std::is_same_v<std::remove_cv_t<std::remove_reference_t<MaybeType>>, Type> || std::is_base_of_v<std::remove_cv_t<std::remove_reference_t<MaybeType>>, Type>), - std::is_const_v<std::remove_reference_t<MaybeType>> && (std::is_same_v<std::remove_cv_t<std::remove_reference_t<MaybeType>>, Type> || std::is_base_of_v<std::remove_cv_t<std::remove_reference_t<MaybeType>>, Type>)> {}; - -/** - * @brief Meta function descriptor. - * @tparam Type Reflected type to which the meta function is associated. - * @tparam Ret Function return type. - */ -template<typename Type, typename Ret> -struct meta_function_descriptor<Type, Ret (*)()> - : meta_function_descriptor_traits< - Ret, - type_list<>, - true, - false> {}; - -/** - * @brief Meta function helper. - * - * Converts a function type to be associated with a reflected type into its meta - * function descriptor. - * - * @tparam Type Reflected type to which the meta function is associated. - * @tparam Candidate The actual function to associate with the reflected type. - */ -template<typename Type, typename Candidate> -class meta_function_helper { - template<typename Ret, typename... Args, typename Class> - static constexpr meta_function_descriptor<Type, Ret (Class::*)(Args...) const> get_rid_of_noexcept(Ret (Class::*)(Args...) const); - - template<typename Ret, typename... Args, typename Class> - static constexpr meta_function_descriptor<Type, Ret (Class::*)(Args...)> get_rid_of_noexcept(Ret (Class::*)(Args...)); - - template<typename Ret, typename Class> - static constexpr meta_function_descriptor<Type, Ret Class::*> get_rid_of_noexcept(Ret Class::*); - - template<typename Ret, typename... Args> - static constexpr meta_function_descriptor<Type, Ret (*)(Args...)> get_rid_of_noexcept(Ret (*)(Args...)); - - template<typename Class> - static constexpr meta_function_descriptor<Class, decltype(&Class::operator())> get_rid_of_noexcept(Class); - -public: - /*! @brief The meta function descriptor of the given function. */ - using type = decltype(get_rid_of_noexcept(std::declval<Candidate>())); -}; - -/** - * @brief Helper type. - * @tparam Type Reflected type to which the meta function is associated. - * @tparam Candidate The actual function to associate with the reflected type. - */ -template<typename Type, typename Candidate> -using meta_function_helper_t = typename meta_function_helper<Type, Candidate>::type; - -/** - * @brief Wraps a value depending on the given policy. - * - * This function always returns a wrapped value in the requested context.<br/> - * Therefore, if the passed value is itself a wrapped object with a different - * context, it undergoes a rebinding to the requested context. - * - * @tparam Policy Optional policy (no policy set by default). - * @tparam Type Type of value to wrap. - * @param ctx The context from which to search for meta types. - * @param value Value to wrap. - * @return A meta any containing the returned value, if any. - */ -template<typename Policy = as_is_t, typename Type> -[[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_dispatch(const meta_ctx &ctx, [[maybe_unused]] Type &&value) { - if constexpr(std::is_same_v<Policy, as_void_t>) { - return meta_any{ctx, std::in_place_type<void>}; - } else if constexpr(std::is_same_v<Policy, as_ref_t>) { - return meta_any{ctx, std::in_place_type<Type>, value}; - } else if constexpr(std::is_same_v<Policy, as_cref_t>) { - static_assert(std::is_lvalue_reference_v<Type>, "Invalid type"); - return meta_any{ctx, std::in_place_type<const std::remove_reference_t<Type> &>, std::as_const(value)}; - } else { - return meta_any{ctx, std::forward<Type>(value)}; - } -} - -/** - * @brief Wraps a value depending on the given policy. - * @tparam Policy Optional policy (no policy set by default). - * @tparam Type Type of value to wrap. - * @param value Value to wrap. - * @return A meta any containing the returned value, if any. - */ -template<typename Policy = as_is_t, typename Type> -[[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_dispatch(Type &&value) { - return meta_dispatch<Policy, Type>(locator<meta_ctx>::value_or(), std::forward<Type>(value)); -} - -/** - * @brief Returns the meta type of the i-th element of a list of arguments. - * @tparam Type Type list of the actual types of arguments. - * @param ctx The context from which to search for meta types. - * @param index The index of the element for which to return the meta type. - * @return The meta type of the i-th element of the list of arguments. - */ -template<typename Type> -[[nodiscard]] static meta_type meta_arg(const meta_ctx &ctx, const std::size_t index) noexcept { - auto &&context = internal::meta_context::from(ctx); - return {ctx, internal::meta_arg_node(context, Type{}, index)}; -} - -/** - * @brief Returns the meta type of the i-th element of a list of arguments. - * @tparam Type Type list of the actual types of arguments. - * @param index The index of the element for which to return the meta type. - * @return The meta type of the i-th element of the list of arguments. - */ -template<typename Type> -[[nodiscard]] static meta_type meta_arg(const std::size_t index) noexcept { - return meta_arg<Type>(locator<meta_ctx>::value_or(), index); -} - -/** - * @brief Sets the value of a given variable. - * @tparam Type Reflected type to which the variable is associated. - * @tparam Data The actual variable to set. - * @param instance An opaque instance of the underlying type, if required. - * @param value Parameter to use to set the variable. - * @return True in case of success, false otherwise. - */ -template<typename Type, auto Data> -[[nodiscard]] bool meta_setter([[maybe_unused]] meta_handle instance, [[maybe_unused]] meta_any value) { - if constexpr(!std::is_same_v<decltype(Data), Type> && !std::is_same_v<decltype(Data), std::nullptr_t>) { - if constexpr(std::is_member_function_pointer_v<decltype(Data)> || std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>>) { - using descriptor = meta_function_helper_t<Type, decltype(Data)>; - using data_type = type_list_element_t<descriptor::is_static, typename descriptor::args_type>; - - if(auto *const clazz = instance->try_cast<Type>(); clazz && value.allow_cast<data_type>()) { - std::invoke(Data, *clazz, value.cast<data_type>()); - return true; - } - } else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) { - using data_type = std::remove_reference_t<typename meta_function_helper_t<Type, decltype(Data)>::return_type>; - - if constexpr(!std::is_array_v<data_type> && !std::is_const_v<data_type>) { - if(auto *const clazz = instance->try_cast<Type>(); clazz && value.allow_cast<data_type>()) { - std::invoke(Data, *clazz) = value.cast<data_type>(); - return true; - } - } - } else { - using data_type = std::remove_reference_t<decltype(*Data)>; - - if constexpr(!std::is_array_v<data_type> && !std::is_const_v<data_type>) { - if(value.allow_cast<data_type>()) { - *Data = value.cast<data_type>(); - return true; - } - } - } - } - - return false; -} - -/** - * @brief Gets the value of a given variable. - * - * @warning - * The context provided is used only for the return type.<br/> - * It's up to the caller to bind the arguments to the right context(s). - * - * @tparam Type Reflected type to which the variable is associated. - * @tparam Data The actual variable to get. - * @tparam Policy Optional policy (no policy set by default). - * @param ctx The context from which to search for meta types. - * @param instance An opaque instance of the underlying type, if required. - * @return A meta any containing the value of the underlying variable. - */ -template<typename Type, auto Data, typename Policy = as_is_t> -[[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_getter(const meta_ctx &ctx, [[maybe_unused]] meta_handle instance) { - if constexpr(std::is_member_pointer_v<decltype(Data)> || std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>>) { - if constexpr(!std::is_array_v<std::remove_cv_t<std::remove_reference_t<std::invoke_result_t<decltype(Data), Type &>>>>) { - if constexpr(std::is_invocable_v<decltype(Data), Type &>) { - if(auto *clazz = instance->try_cast<Type>(); clazz) { - return meta_dispatch<Policy>(ctx, std::invoke(Data, *clazz)); - } - } - - if constexpr(std::is_invocable_v<decltype(Data), const Type &>) { - if(auto *fallback = instance->try_cast<const Type>(); fallback) { - return meta_dispatch<Policy>(ctx, std::invoke(Data, *fallback)); - } - } - } - - return meta_any{meta_ctx_arg, ctx}; - } else if constexpr(std::is_pointer_v<decltype(Data)>) { - if constexpr(std::is_array_v<std::remove_pointer_t<decltype(Data)>>) { - return meta_any{meta_ctx_arg, ctx}; - } else { - return meta_dispatch<Policy>(ctx, *Data); - } - } else { - return meta_dispatch<Policy>(ctx, Data); - } -} - -/** - * @brief Gets the value of a given variable. - * @tparam Type Reflected type to which the variable is associated. - * @tparam Data The actual variable to get. - * @tparam Policy Optional policy (no policy set by default). - * @param instance An opaque instance of the underlying type, if required. - * @return A meta any containing the value of the underlying variable. - */ -template<typename Type, auto Data, typename Policy = as_is_t> -[[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_getter(meta_handle instance) { - return meta_getter<Type, Data, Policy>(locator<meta_ctx>::value_or(), std::move(instance)); -} - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename Policy, typename Candidate, typename... Args> -[[nodiscard]] meta_any meta_invoke_with_args(const meta_ctx &ctx, Candidate &&candidate, Args &&...args) { - if constexpr(std::is_void_v<decltype(std::invoke(std::forward<Candidate>(candidate), args...))>) { - std::invoke(std::forward<Candidate>(candidate), args...); - return meta_any{ctx, std::in_place_type<void>}; - } else { - return meta_dispatch<Policy>(ctx, std::invoke(std::forward<Candidate>(candidate), args...)); - } -} - -template<typename Type, typename Policy, typename Candidate, std::size_t... Index> -[[nodiscard]] meta_any meta_invoke(const meta_ctx &ctx, [[maybe_unused]] meta_handle instance, Candidate &&candidate, [[maybe_unused]] meta_any *const args, std::index_sequence<Index...>) { - using descriptor = meta_function_helper_t<Type, std::remove_reference_t<Candidate>>; - - // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) - waiting for C++20 (and std::span) - if constexpr(std::is_invocable_v<std::remove_reference_t<Candidate>, const Type &, type_list_element_t<Index, typename descriptor::args_type>...>) { - if(const auto *const clazz = instance->try_cast<const Type>(); clazz && ((args + Index)->allow_cast<type_list_element_t<Index, typename descriptor::args_type>>() && ...)) { - return meta_invoke_with_args<Policy>(ctx, std::forward<Candidate>(candidate), *clazz, (args + Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...); - } - } else if constexpr(std::is_invocable_v<std::remove_reference_t<Candidate>, Type &, type_list_element_t<Index, typename descriptor::args_type>...>) { - if(auto *const clazz = instance->try_cast<Type>(); clazz && ((args + Index)->allow_cast<type_list_element_t<Index, typename descriptor::args_type>>() && ...)) { - return meta_invoke_with_args<Policy>(ctx, std::forward<Candidate>(candidate), *clazz, (args + Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...); - } - } else { - if(((args + Index)->allow_cast<type_list_element_t<Index, typename descriptor::args_type>>() && ...)) { - return meta_invoke_with_args<Policy>(ctx, std::forward<Candidate>(candidate), (args + Index)->cast<type_list_element_t<Index, typename descriptor::args_type>>()...); - } - } - // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic) - - return meta_any{meta_ctx_arg, ctx}; -} - -template<typename Type, typename... Args, std::size_t... Index> -[[nodiscard]] meta_any meta_construct(const meta_ctx &ctx, meta_any *const args, std::index_sequence<Index...>) { - // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) - waiting for C++20 (and std::span) - if(((args + Index)->allow_cast<Args>() && ...)) { - return meta_any{ctx, std::in_place_type<Type>, (args + Index)->cast<Args>()...}; - } - // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic) - - return meta_any{meta_ctx_arg, ctx}; -} - -} // namespace internal -/*! @endcond */ - -/** - * @brief Tries to _invoke_ an object given a list of erased parameters. - * - * @warning - * The context provided is used only for the return type.<br/> - * It's up to the caller to bind the arguments to the right context(s). - * - * @tparam Type Reflected type to which the object to _invoke_ is associated. - * @tparam Policy Optional policy (no policy set by default). - * @param ctx The context from which to search for meta types. - * @tparam Candidate The type of the actual object to _invoke_. - * @param instance An opaque instance of the underlying type, if required. - * @param candidate The actual object to _invoke_. - * @param args Parameters to use to _invoke_ the object. - * @return A meta any containing the returned value, if any. - */ -template<typename Type, typename Policy = as_is_t, typename Candidate> -[[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_invoke(const meta_ctx &ctx, meta_handle instance, Candidate &&candidate, meta_any *const args) { - return internal::meta_invoke<Type, Policy>(ctx, std::move(instance), std::forward<Candidate>(candidate), args, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<Candidate>>::args_type::size>{}); -} - -/** - * @brief Tries to _invoke_ an object given a list of erased parameters. - * @tparam Type Reflected type to which the object to _invoke_ is associated. - * @tparam Policy Optional policy (no policy set by default). - * @tparam Candidate The type of the actual object to _invoke_. - * @param instance An opaque instance of the underlying type, if required. - * @param candidate The actual object to _invoke_. - * @param args Parameters to use to _invoke_ the object. - * @return A meta any containing the returned value, if any. - */ -template<typename Type, typename Policy = as_is_t, typename Candidate> -[[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_invoke(meta_handle instance, Candidate &&candidate, meta_any *const args) { - return meta_invoke<Type, Policy>(locator<meta_ctx>::value_or(), std::move(instance), std::forward<Candidate>(candidate), args); -} - -/** - * @brief Tries to invoke a function given a list of erased parameters. - * - * @warning - * The context provided is used only for the return type.<br/> - * It's up to the caller to bind the arguments to the right context(s). - * - * @tparam Type Reflected type to which the function is associated. - * @tparam Candidate The actual function to invoke. - * @tparam Policy Optional policy (no policy set by default). - * @param ctx The context from which to search for meta types. - * @param instance An opaque instance of the underlying type, if required. - * @param args Parameters to use to invoke the function. - * @return A meta any containing the returned value, if any. - */ -template<typename Type, auto Candidate, typename Policy = as_is_t> -[[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_invoke(const meta_ctx &ctx, meta_handle instance, meta_any *const args) { - return internal::meta_invoke<Type, Policy>(ctx, std::move(instance), Candidate, args, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<decltype(Candidate)>>::args_type::size>{}); -} - -/** - * @brief Tries to invoke a function given a list of erased parameters. - * @tparam Type Reflected type to which the function is associated. - * @tparam Candidate The actual function to invoke. - * @tparam Policy Optional policy (no policy set by default). - * @param instance An opaque instance of the underlying type, if required. - * @param args Parameters to use to invoke the function. - * @return A meta any containing the returned value, if any. - */ -template<typename Type, auto Candidate, typename Policy = as_is_t> -[[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_invoke(meta_handle instance, meta_any *const args) { - return meta_invoke<Type, Candidate, Policy>(locator<meta_ctx>::value_or(), std::move(instance), args); -} - -/** - * @brief Tries to construct an instance given a list of erased parameters. - * - * @warning - * The context provided is used only for the return type.<br/> - * It's up to the caller to bind the arguments to the right context(s). - * - * @tparam Type Actual type of the instance to construct. - * @tparam Args Types of arguments expected. - * @param ctx The context from which to search for meta types. - * @param args Parameters to use to construct the instance. - * @return A meta any containing the new instance, if any. - */ -template<typename Type, typename... Args> -[[nodiscard]] meta_any meta_construct(const meta_ctx &ctx, meta_any *const args) { - return internal::meta_construct<Type, Args...>(ctx, args, std::index_sequence_for<Args...>{}); -} - -/** - * @brief Tries to construct an instance given a list of erased parameters. - * @tparam Type Actual type of the instance to construct. - * @tparam Args Types of arguments expected. - * @param args Parameters to use to construct the instance. - * @return A meta any containing the new instance, if any. - */ -template<typename Type, typename... Args> -[[nodiscard]] meta_any meta_construct(meta_any *const args) { - return meta_construct<Type, Args...>(locator<meta_ctx>::value_or(), args); -} - -/** - * @brief Tries to construct an instance given a list of erased parameters. - * - * @warning - * The context provided is used only for the return type.<br/> - * It's up to the caller to bind the arguments to the right context(s). - * - * @tparam Type Reflected type to which the object to _invoke_ is associated. - * @tparam Policy Optional policy (no policy set by default). - * @tparam Candidate The type of the actual object to _invoke_. - * @param ctx The context from which to search for meta types. - * @param candidate The actual object to _invoke_. - * @param args Parameters to use to _invoke_ the object. - * @return A meta any containing the returned value, if any. - */ -template<typename Type, typename Policy = as_is_t, typename Candidate> -[[nodiscard]] meta_any meta_construct(const meta_ctx &ctx, Candidate &&candidate, meta_any *const args) { - if constexpr(meta_function_helper_t<Type, Candidate>::is_static || std::is_class_v<std::remove_cv_t<std::remove_reference_t<Candidate>>>) { - return internal::meta_invoke<Type, Policy>(ctx, {}, std::forward<Candidate>(candidate), args, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<Candidate>>::args_type::size>{}); - } else { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - waiting for C++20 (and std::span) - return internal::meta_invoke<Type, Policy>(ctx, *args, std::forward<Candidate>(candidate), args + 1u, std::make_index_sequence<meta_function_helper_t<Type, std::remove_reference_t<Candidate>>::args_type::size>{}); - } -} - -/** - * @brief Tries to construct an instance given a list of erased parameters. - * @tparam Type Reflected type to which the object to _invoke_ is associated. - * @tparam Policy Optional policy (no policy set by default). - * @tparam Candidate The type of the actual object to _invoke_. - * @param candidate The actual object to _invoke_. - * @param args Parameters to use to _invoke_ the object. - * @return A meta any containing the returned value, if any. - */ -template<typename Type, typename Policy = as_is_t, typename Candidate> -[[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_construct(Candidate &&candidate, meta_any *const args) { - return meta_construct<Type, Policy>(locator<meta_ctx>::value_or(), std::forward<Candidate>(candidate), args); -} - -/** - * @brief Tries to construct an instance given a list of erased parameters. - * - * @warning - * The context provided is used only for the return type.<br/> - * It's up to the caller to bind the arguments to the right context(s). - * - * @tparam Type Reflected type to which the function is associated. - * @tparam Candidate The actual function to invoke. - * @tparam Policy Optional policy (no policy set by default). - * @param ctx The context from which to search for meta types. - * @param args Parameters to use to invoke the function. - * @return A meta any containing the returned value, if any. - */ -template<typename Type, auto Candidate, typename Policy = as_is_t> -[[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_construct(const meta_ctx &ctx, meta_any *const args) { - return meta_construct<Type, Policy>(ctx, Candidate, args); -} - -/** - * @brief Tries to construct an instance given a list of erased parameters. - * @tparam Type Reflected type to which the function is associated. - * @tparam Candidate The actual function to invoke. - * @tparam Policy Optional policy (no policy set by default). - * @param args Parameters to use to invoke the function. - * @return A meta any containing the returned value, if any. - */ -template<typename Type, auto Candidate, typename Policy = as_is_t> -[[nodiscard]] std::enable_if_t<is_meta_policy_v<Policy>, meta_any> meta_construct(meta_any *const args) { - return meta_construct<Type, Candidate, Policy>(locator<meta_ctx>::value_or(), args); -} - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/platform/android-ndk-r17.hpp b/deps/entt/include/entt/platform/android-ndk-r17.hpp deleted file mode 100644 index 5696123..0000000 --- a/deps/entt/include/entt/platform/android-ndk-r17.hpp +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef ENTT_PLATFORM_ANDROID_NDK_R17_HPP -#define ENTT_PLATFORM_ANDROID_NDK_R17_HPP - -/** - * @cond TURN_OFF_DOXYGEN - * Internal details not to be documented. - */ - -#ifdef __ANDROID__ -# include <android/ndk-version.h> -# if __NDK_MAJOR__ == 17 - -# include <functional> -# include <type_traits> -# include <utility> - -namespace std { - -namespace internal { - -template<typename Func, typename... Args> -constexpr auto is_invocable(int) -> decltype(std::invoke(std::declval<Func>(), std::declval<Args>()...), std::true_type{}); - -template<typename, typename...> -constexpr std::false_type is_invocable(...); - -template<typename Ret, typename Func, typename... Args> -constexpr auto is_invocable_r(int) --> std::enable_if_t<decltype(std::is_convertible_v<decltype(std::invoke(std::declval<Func>(), std::declval<Args>()...)), Ret>, std::true_type>; - - -template<typename, typename, typename...> -constexpr std::false_type is_invocable_r(...); - -} // namespace internal - -template<typename Func, typename... Args> -struct is_invocable: decltype(internal::is_invocable<Func, Args...>(0)) {}; - -template<typename Func, typename... Argsv> -inline constexpr bool is_invocable_v = std::is_invocable<Func, Args...>::value; - -template<typename Ret, typename Func, typename... Args> -struct is_invocable_r: decltype(internal::is_invocable_r<Ret, Func, Args...>(0)) {}; - -template<typename Ret, typename Func, typename... Args> -inline constexpr bool is_invocable_r_v = std::is_invocable_r<Ret, Func, Args...>::value; - -template<typename Func, typename... Args> -struct invoke_result { - using type = decltype(std::invoke(std::declval<Func>(), std::declval<Args>()...)); -}; - -template<typename Func, typename... Args> -using invoke_result_t = typename std::invoke_result<Func, Args...>::type; - -} // namespace std - -# endif -#endif - -/** - * Internal details not to be documented. - * @endcond - */ - -#endif diff --git a/deps/entt/include/entt/poly/fwd.hpp b/deps/entt/include/entt/poly/fwd.hpp deleted file mode 100644 index 34b096d..0000000 --- a/deps/entt/include/entt/poly/fwd.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef ENTT_POLY_FWD_HPP -#define ENTT_POLY_FWD_HPP - -#include <cstddef> - -namespace entt { - -// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays) -template<typename, std::size_t Len = sizeof(double[2]), std::size_t = alignof(double[2])> -class basic_poly; - -/** - * @brief Alias declaration for the most common use case. - * @tparam Concept Concept descriptor. - */ -template<typename Concept> -using poly = basic_poly<Concept>; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/poly/poly.hpp b/deps/entt/include/entt/poly/poly.hpp deleted file mode 100644 index 977148a..0000000 --- a/deps/entt/include/entt/poly/poly.hpp +++ /dev/null @@ -1,310 +0,0 @@ -#ifndef ENTT_POLY_POLY_HPP -#define ENTT_POLY_POLY_HPP - -#include <cstddef> -#include <functional> -#include <tuple> -#include <type_traits> -#include <utility> -#include "../core/any.hpp" -#include "../core/type_info.hpp" -#include "../core/type_traits.hpp" -#include "fwd.hpp" - -namespace entt { - -/*! @brief Inspector class used to infer the type of the virtual table. */ -struct poly_inspector { - /** - * @brief Generic conversion operator (definition only). - * @tparam Type Type to which conversion is requested. - */ - template<typename Type> - operator Type &&() const; - - /** - * @brief Dummy invocation function (definition only). - * @tparam Member Index of the function to invoke. - * @tparam Args Types of arguments to pass to the function. - * @param args The arguments to pass to the function. - * @return A poly inspector convertible to any type. - */ - template<std::size_t Member, typename... Args> - [[nodiscard]] poly_inspector invoke(Args &&...args) const; - - /*! @copydoc invoke */ - template<std::size_t Member, typename... Args> - [[nodiscard]] poly_inspector invoke(Args &&...args); -}; - -/** - * @brief Static virtual table factory. - * @tparam Concept Concept descriptor. - * @tparam Len Size of the storage reserved for the small buffer optimization. - * @tparam Align Alignment requirement. - */ -template<typename Concept, std::size_t Len, std::size_t Align> -class poly_vtable { - using inspector = typename Concept::template type<poly_inspector>; - - template<typename Ret, typename... Args> - static auto vtable_entry(Ret (*)(inspector &, Args...)) -> Ret (*)(basic_any<Len, Align> &, Args...); - - template<typename Ret, typename... Args> - static auto vtable_entry(Ret (*)(const inspector &, Args...)) -> Ret (*)(const basic_any<Len, Align> &, Args...); - - template<typename Ret, typename... Args> - static auto vtable_entry(Ret (*)(Args...)) -> Ret (*)(const basic_any<Len, Align> &, Args...); - - template<typename Ret, typename... Args> - static auto vtable_entry(Ret (inspector::*)(Args...)) -> Ret (*)(basic_any<Len, Align> &, Args...); - - template<typename Ret, typename... Args> - static auto vtable_entry(Ret (inspector::*)(Args...) const) -> Ret (*)(const basic_any<Len, Align> &, Args...); - - template<auto... Candidate> - static auto make_vtable(value_list<Candidate...>) noexcept - -> decltype(std::make_tuple(vtable_entry(Candidate)...)); - - template<typename... Func> - [[nodiscard]] static constexpr auto make_vtable(type_list<Func...>) noexcept { - if constexpr(sizeof...(Func) == 0u) { - return decltype(make_vtable(typename Concept::template impl<inspector>{})){}; - } else if constexpr((std::is_function_v<Func> && ...)) { - return decltype(std::make_tuple(vtable_entry(std::declval<Func inspector::*>())...)){}; - } - } - - template<typename Type, auto Candidate, typename Ret, typename Any, typename... Args> - static void fill_vtable_entry(Ret (*&entry)(Any &, Args...)) noexcept { - if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Args...>) { - entry = +[](Any &, Args... args) -> Ret { - return std::invoke(Candidate, std::forward<Args>(args)...); - }; - } else { - entry = +[](Any &instance, Args... args) -> Ret { - return static_cast<Ret>(std::invoke(Candidate, any_cast<constness_as_t<Type, Any> &>(instance), std::forward<Args>(args)...)); - }; - } - } - - template<typename Type, auto... Index> - [[nodiscard]] static auto fill_vtable(std::index_sequence<Index...>) noexcept { - vtable_type impl{}; - (fill_vtable_entry<Type, value_list_element_v<Index, typename Concept::template impl<Type>>>(std::get<Index>(impl)), ...); - return impl; - } - - using vtable_type = decltype(make_vtable(Concept{})); - static constexpr bool is_mono_v = std::tuple_size_v<vtable_type> == 1u; - -public: - /*! @brief Virtual table type. */ - using type = std::conditional_t<is_mono_v, std::tuple_element_t<0u, vtable_type>, const vtable_type *>; - - /** - * @brief Returns a static virtual table for a specific concept and type. - * @tparam Type The type for which to generate the virtual table. - * @return A static virtual table for the given concept and type. - */ - template<typename Type> - [[nodiscard]] static type instance() noexcept { - static_assert(std::is_same_v<Type, std::decay_t<Type>>, "Type differs from its decayed form"); - static const vtable_type vtable = fill_vtable<Type>(std::make_index_sequence<Concept::template impl<Type>::size>{}); - - if constexpr(is_mono_v) { - return std::get<0>(vtable); - } else { - return &vtable; - } - } -}; - -/** - * @brief Poly base class used to inject functionalities into concepts. - * @tparam Poly The outermost poly class. - */ -template<typename Poly> -struct poly_base { - /** - * @brief Invokes a function from the static virtual table. - * @tparam Member Index of the function to invoke. - * @tparam Args Types of arguments to pass to the function. - * @param self A reference to the poly object that made the call. - * @param args The arguments to pass to the function. - * @return The return value of the invoked function, if any. - */ - template<std::size_t Member, typename... Args> - [[nodiscard]] decltype(auto) invoke(const poly_base &self, Args &&...args) const { - const auto &poly = static_cast<const Poly &>(self); - - if constexpr(std::is_function_v<std::remove_pointer_t<decltype(poly.vtable)>>) { - return poly.vtable(poly.storage, std::forward<Args>(args)...); - } else { - return std::get<Member>(*poly.vtable)(poly.storage, std::forward<Args>(args)...); - } - } - - /*! @copydoc invoke */ - template<std::size_t Member, typename... Args> - [[nodiscard]] decltype(auto) invoke(poly_base &self, Args &&...args) { - auto &poly = static_cast<Poly &>(self); - - if constexpr(std::is_function_v<std::remove_pointer_t<decltype(poly.vtable)>>) { - static_assert(Member == 0u, "Unknown member"); - return poly.vtable(poly.storage, std::forward<Args>(args)...); - } else { - return std::get<Member>(*poly.vtable)(poly.storage, std::forward<Args>(args)...); - } - } -}; - -/** - * @brief Shortcut for calling `poly_base<Type>::invoke`. - * @tparam Member Index of the function to invoke. - * @tparam Poly A fully defined poly object. - * @tparam Args Types of arguments to pass to the function. - * @param self A reference to the poly object that made the call. - * @param args The arguments to pass to the function. - * @return The return value of the invoked function, if any. - */ -template<std::size_t Member, typename Poly, typename... Args> -decltype(auto) poly_call(Poly &&self, Args &&...args) { - return std::forward<Poly>(self).template invoke<Member>(self, std::forward<Args>(args)...); -} - -/** - * @brief Static polymorphism made simple and within everyone's reach. - * - * Static polymorphism is a very powerful tool in C++, albeit sometimes - * cumbersome to obtain.<br/> - * This class aims to make it simple and easy to use. - * - * @note - * Both deduced and defined static virtual tables are supported.<br/> - * Moreover, the `poly` class template also works with unmanaged objects. - * - * @tparam Concept Concept descriptor. - * @tparam Len Size of the storage reserved for the small buffer optimization. - * @tparam Align Optional alignment requirement. - */ -template<typename Concept, std::size_t Len, std::size_t Align> -class basic_poly: private Concept::template type<poly_base<basic_poly<Concept, Len, Align>>> { - friend struct poly_base<basic_poly>; - -public: - /*! @brief Concept type. */ - using concept_type = typename Concept::template type<poly_base<basic_poly>>; - /*! @brief Virtual table type. */ - using vtable_type = typename poly_vtable<Concept, Len, Align>::type; - - /*! @brief Default constructor. */ - basic_poly() noexcept = default; - - /** - * @brief Constructs a poly by directly initializing the new object. - * @tparam Type Type of object to use to initialize the poly. - * @tparam Args Types of arguments to use to construct the new instance. - * @param args Parameters to use to construct the instance. - */ - template<typename Type, typename... Args> - explicit basic_poly(std::in_place_type_t<Type>, Args &&...args) - : storage{std::in_place_type<Type>, std::forward<Args>(args)...}, - vtable{poly_vtable<Concept, Len, Align>::template instance<std::remove_cv_t<std::remove_reference_t<Type>>>()} {} - - /** - * @brief Constructs a poly from a given value. - * @tparam Type Type of object to use to initialize the poly. - * @param value An instance of an object to use to initialize the poly. - */ - template<typename Type, typename = std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Type>>, basic_poly>>> - basic_poly(Type &&value) noexcept - : basic_poly{std::in_place_type<std::remove_cv_t<std::remove_reference_t<Type>>>, std::forward<Type>(value)} {} - - /** - * @brief Returns the object type if any, `type_id<void>()` otherwise. - * @return The object type if any, `type_id<void>()` otherwise. - */ - [[nodiscard]] const type_info &type() const noexcept { - return storage.type(); - } - - /** - * @brief Returns an opaque pointer to the contained instance. - * @return An opaque pointer the contained instance, if any. - */ - [[nodiscard]] const void *data() const noexcept { - return storage.data(); - } - - /*! @copydoc data */ - [[nodiscard]] void *data() noexcept { - return storage.data(); - } - - /** - * @brief Replaces the contained object by creating a new instance directly. - * @tparam Type Type of object to use to initialize the poly. - * @tparam Args Types of arguments to use to construct the new instance. - * @param args Parameters to use to construct the instance. - */ - template<typename Type, typename... Args> - void emplace(Args &&...args) { - storage.template emplace<Type>(std::forward<Args>(args)...); - vtable = poly_vtable<Concept, Len, Align>::template instance<std::remove_cv_t<std::remove_reference_t<Type>>>(); - } - - /*! @brief Destroys contained object */ - void reset() { - storage.reset(); - vtable = {}; - } - - /** - * @brief Returns false if a poly is empty, true otherwise. - * @return False if the poly is empty, true otherwise. - */ - [[nodiscard]] explicit operator bool() const noexcept { - return static_cast<bool>(storage); - } - - /** - * @brief Returns a pointer to the underlying concept. - * @return A pointer to the underlying concept. - */ - [[nodiscard]] concept_type *operator->() noexcept { - return this; - } - - /*! @copydoc operator-> */ - [[nodiscard]] const concept_type *operator->() const noexcept { - return this; - } - - /** - * @brief Aliasing constructor. - * @return A poly that shares a reference to an unmanaged object. - */ - [[nodiscard]] basic_poly as_ref() noexcept { - basic_poly ref{}; - ref.storage = storage.as_ref(); - ref.vtable = vtable; - return ref; - } - - /*! @copydoc as_ref */ - [[nodiscard]] basic_poly as_ref() const noexcept { - basic_poly ref{}; - ref.storage = storage.as_ref(); - ref.vtable = vtable; - return ref; - } - -private: - basic_any<Len, Align> storage{}; - vtable_type vtable{}; -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/process/fwd.hpp b/deps/entt/include/entt/process/fwd.hpp deleted file mode 100644 index 6d033a3..0000000 --- a/deps/entt/include/entt/process/fwd.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef ENTT_PROCESS_FWD_HPP -#define ENTT_PROCESS_FWD_HPP - -#include <cstdint> -#include <memory> - -namespace entt { - -template<typename, typename> -class process; - -template<typename = std::uint32_t, typename = std::allocator<void>> -class basic_scheduler; - -/*! @brief Alias declaration for the most common use case. */ -using scheduler = basic_scheduler<>; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/process/process.hpp b/deps/entt/include/entt/process/process.hpp deleted file mode 100644 index e95ad0c..0000000 --- a/deps/entt/include/entt/process/process.hpp +++ /dev/null @@ -1,354 +0,0 @@ -#ifndef ENTT_PROCESS_PROCESS_HPP -#define ENTT_PROCESS_PROCESS_HPP - -#include <cstdint> -#include <type_traits> -#include <utility> -#include "fwd.hpp" - -namespace entt { - -/** - * @brief Base class for processes. - * - * This class stays true to the CRTP idiom. Derived classes must specify what's - * the intended type for elapsed times.<br/> - * A process should expose publicly the following member functions whether - * required: - * - * * @code{.cpp} - * void update(Delta, void *); - * @endcode - * - * It's invoked once per tick until a process is explicitly aborted or it - * terminates either with or without errors. Even though it's not mandatory to - * declare this member function, as a rule of thumb each process should at - * least define it to work properly. The `void *` parameter is an opaque - * pointer to user data (if any) forwarded directly to the process during an - * update. - * - * * @code{.cpp} - * void init(); - * @endcode - * - * It's invoked when the process joins the running queue of a scheduler. This - * happens as soon as it's attached to the scheduler if the process is a top - * level one, otherwise when it replaces its parent if the process is a - * continuation. - * - * * @code{.cpp} - * void succeeded(); - * @endcode - * - * It's invoked in case of success, immediately after an update and during the - * same tick. - * - * * @code{.cpp} - * void failed(); - * @endcode - * - * It's invoked in case of errors, immediately after an update and during the - * same tick. - * - * * @code{.cpp} - * void aborted(); - * @endcode - * - * It's invoked only if a process is explicitly aborted. There is no guarantee - * that it executes in the same tick, this depends solely on whether the - * process is aborted immediately or not. - * - * Derived classes can change the internal state of a process by invoking the - * `succeed` and `fail` protected member functions and even pause or unpause the - * process itself. - * - * @sa scheduler - * - * @tparam Derived Actual type of process that extends the class template. - * @tparam Delta Type to use to provide elapsed time. - */ -template<typename Derived, typename Delta> -class process { - enum class state : std::uint8_t { - uninitialized = 0, - running, - paused, - succeeded, - failed, - aborted, - finished, - rejected - }; - - template<typename Target = Derived> - auto next(std::integral_constant<state, state::uninitialized>) - -> decltype(std::declval<Target>().init(), void()) { - static_cast<Target *>(this)->init(); - } - - template<typename Target = Derived> - auto next(std::integral_constant<state, state::running>, Delta delta, void *data) - -> decltype(std::declval<Target>().update(delta, data), void()) { - static_cast<Target *>(this)->update(delta, data); - } - - template<typename Target = Derived> - auto next(std::integral_constant<state, state::succeeded>) - -> decltype(std::declval<Target>().succeeded(), void()) { - static_cast<Target *>(this)->succeeded(); - } - - template<typename Target = Derived> - auto next(std::integral_constant<state, state::failed>) - -> decltype(std::declval<Target>().failed(), void()) { - static_cast<Target *>(this)->failed(); - } - - template<typename Target = Derived> - auto next(std::integral_constant<state, state::aborted>) - -> decltype(std::declval<Target>().aborted(), void()) { - static_cast<Target *>(this)->aborted(); - } - - template<typename... Args> - void next(Args &&...) const noexcept {} - -protected: - /** - * @brief Terminates a process with success if it's still alive. - * - * The function is idempotent and it does nothing if the process isn't - * alive. - */ - void succeed() noexcept { - if(alive()) { - current = state::succeeded; - } - } - - /** - * @brief Terminates a process with errors if it's still alive. - * - * The function is idempotent and it does nothing if the process isn't - * alive. - */ - void fail() noexcept { - if(alive()) { - current = state::failed; - } - } - - /** - * @brief Stops a process if it's in a running state. - * - * The function is idempotent and it does nothing if the process isn't - * running. - */ - void pause() noexcept { - if(current == state::running) { - current = state::paused; - } - } - - /** - * @brief Restarts a process if it's paused. - * - * The function is idempotent and it does nothing if the process isn't - * paused. - */ - void unpause() noexcept { - if(current == state::paused) { - current = state::running; - } - } - -public: - /*! @brief Type used to provide elapsed time. */ - using delta_type = Delta; - - /*! @brief Default constructor. */ - constexpr process() = default; - - /*! @brief Default copy constructor. */ - process(const process &) = default; - - /*! @brief Default move constructor. */ - process(process &&) noexcept = default; - - /** - * @brief Default copy assignment operator. - * @return This process. - */ - process &operator=(const process &) = default; - - /** - * @brief Default move assignment operator. - * @return This process. - */ - process &operator=(process &&) noexcept = default; - - /*! @brief Default destructor. */ - virtual ~process() noexcept { - static_assert(std::is_base_of_v<process, Derived>, "Incorrect use of the class template"); - } - - /** - * @brief Aborts a process if it's still alive. - * - * The function is idempotent and it does nothing if the process isn't - * alive. - * - * @param immediate Requests an immediate operation. - */ - void abort(const bool immediate = false) { - if(alive()) { - current = state::aborted; - - if(immediate) { - tick({}); - } - } - } - - /** - * @brief Returns true if a process is either running or paused. - * @return True if the process is still alive, false otherwise. - */ - [[nodiscard]] bool alive() const noexcept { - return current == state::running || current == state::paused; - } - - /** - * @brief Returns true if a process is already terminated. - * @return True if the process is terminated, false otherwise. - */ - [[nodiscard]] bool finished() const noexcept { - return current == state::finished; - } - - /** - * @brief Returns true if a process is currently paused. - * @return True if the process is paused, false otherwise. - */ - [[nodiscard]] bool paused() const noexcept { - return current == state::paused; - } - - /** - * @brief Returns true if a process terminated with errors. - * @return True if the process terminated with errors, false otherwise. - */ - [[nodiscard]] bool rejected() const noexcept { - return current == state::rejected; - } - - /** - * @brief Updates a process and its internal state if required. - * @param delta Elapsed time. - * @param data Optional data. - */ - void tick(const Delta delta, void *data = nullptr) { - switch(current) { - case state::uninitialized: - next(std::integral_constant<state, state::uninitialized>{}); - current = state::running; - break; - case state::running: - next(std::integral_constant<state, state::running>{}, delta, data); - break; - default: - // suppress warnings - break; - } - - // if it's dead, it must be notified and removed immediately - switch(current) { - case state::succeeded: - next(std::integral_constant<state, state::succeeded>{}); - current = state::finished; - break; - case state::failed: - next(std::integral_constant<state, state::failed>{}); - current = state::rejected; - break; - case state::aborted: - next(std::integral_constant<state, state::aborted>{}); - current = state::rejected; - break; - default: - // suppress warnings - break; - } - } - -private: - state current{state::uninitialized}; -}; - -/** - * @brief Adaptor for lambdas and functors to turn them into processes. - * - * Lambdas and functors can't be used directly with a scheduler for they are not - * properly defined processes with managed life cycles.<br/> - * This class helps in filling the gap and turning lambdas and functors into - * full featured processes usable by a scheduler. - * - * The signature of the function call operator should be equivalent to the - * following: - * - * @code{.cpp} - * void(Delta delta, void *data, auto succeed, auto fail); - * @endcode - * - * Where: - * - * * `delta` is the elapsed time. - * * `data` is an opaque pointer to user data if any, `nullptr` otherwise. - * * `succeed` is a function to call when a process terminates with success. - * * `fail` is a function to call when a process terminates with errors. - * - * The signature of the function call operator of both `succeed` and `fail` - * is equivalent to the following: - * - * @code{.cpp} - * void(); - * @endcode - * - * Usually users shouldn't worry about creating adaptors. A scheduler will - * create them internally each and avery time a lambda or a functor is used as - * a process. - * - * @sa process - * @sa scheduler - * - * @tparam Func Actual type of process. - * @tparam Delta Type to use to provide elapsed time. - */ -template<typename Func, typename Delta> -struct process_adaptor: process<process_adaptor<Func, Delta>, Delta>, private Func { - /** - * @brief Constructs a process adaptor from a lambda or a functor. - * @tparam Args Types of arguments to use to initialize the actual process. - * @param args Parameters to use to initialize the actual process. - */ - template<typename... Args> - process_adaptor(Args &&...args) - : Func{std::forward<Args>(args)...} {} - - /** - * @brief Updates a process and its internal state if required. - * @param delta Elapsed time. - * @param data Optional data. - */ - void update(const Delta delta, void *data) { - Func::operator()( - delta, - data, - [this]() { this->succeed(); }, - [this]() { this->fail(); }); - } -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/process/scheduler.hpp b/deps/entt/include/entt/process/scheduler.hpp deleted file mode 100644 index 770059d..0000000 --- a/deps/entt/include/entt/process/scheduler.hpp +++ /dev/null @@ -1,364 +0,0 @@ -#ifndef ENTT_PROCESS_SCHEDULER_HPP -#define ENTT_PROCESS_SCHEDULER_HPP - -#include <cstddef> -#include <memory> -#include <type_traits> -#include <utility> -#include <vector> -#include "../config/config.h" -#include "../core/compressed_pair.hpp" -#include "fwd.hpp" -#include "process.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename Delta> -struct basic_process_handler { - virtual ~basic_process_handler() noexcept = default; - - virtual bool update(const Delta, void *) = 0; - virtual void abort(const bool) = 0; - - // std::shared_ptr because of its type erased allocator which is useful here - std::shared_ptr<basic_process_handler> next; -}; - -template<typename Delta, typename Type> -struct process_handler final: basic_process_handler<Delta> { - template<typename... Args> - process_handler(Args &&...args) - : process{std::forward<Args>(args)...} {} - - bool update(const Delta delta, void *data) override { - if(process.tick(delta, data); process.rejected()) { - this->next.reset(); - } - - return (process.rejected() || process.finished()); - } - - void abort(const bool immediate) override { - process.abort(immediate); - } - - Type process; -}; - -} // namespace internal -/*! @endcond */ - -/** - * @brief Cooperative scheduler for processes. - * - * A cooperative scheduler runs processes and helps managing their life cycles. - * - * Each process is invoked once per tick. If a process terminates, it's - * removed automatically from the scheduler and it's never invoked again.<br/> - * A process can also have a child. In this case, the process is replaced with - * its child when it terminates if it returns with success. In case of errors, - * both the process and its child are discarded. - * - * Example of use (pseudocode): - * - * @code{.cpp} - * scheduler.attach([](auto delta, void *, auto succeed, auto fail) { - * // code - * }).then<my_process>(arguments...); - * @endcode - * - * In order to invoke all scheduled processes, call the `update` member function - * passing it the elapsed time to forward to the tasks. - * - * @sa process - * - * @tparam Delta Type to use to provide elapsed time. - * @tparam Allocator Type of allocator used to manage memory and elements. - */ -template<typename Delta, typename Allocator> -class basic_scheduler { - template<typename Type> - using handler_type = internal::process_handler<Delta, Type>; - - // std::shared_ptr because of its type erased allocator which is useful here - using process_type = std::shared_ptr<internal::basic_process_handler<Delta>>; - - using alloc_traits = std::allocator_traits<Allocator>; - using container_allocator = typename alloc_traits::template rebind_alloc<process_type>; - using container_type = std::vector<process_type, container_allocator>; - -public: - /*! @brief Allocator type. */ - using allocator_type = Allocator; - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - /*! @brief Unsigned integer type. */ - using delta_type = Delta; - - /*! @brief Default constructor. */ - basic_scheduler() - : basic_scheduler{allocator_type{}} {} - - /** - * @brief Constructs a scheduler with a given allocator. - * @param allocator The allocator to use. - */ - explicit basic_scheduler(const allocator_type &allocator) - : handlers{allocator, allocator} {} - - /*! @brief Default copy constructor, deleted on purpose. */ - basic_scheduler(const basic_scheduler &) = delete; - - /** - * @brief Move constructor. - * @param other The instance to move from. - */ - basic_scheduler(basic_scheduler &&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. - */ - basic_scheduler(basic_scheduler &&other, const allocator_type &allocator) - : handlers{container_type{std::move(other.handlers.first()), allocator}, allocator} { - ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a scheduler is not allowed"); - } - - /*! @brief Default destructor. */ - ~basic_scheduler() noexcept = default; - - /** - * @brief Default copy assignment operator, deleted on purpose. - * @return This process scheduler. - */ - basic_scheduler &operator=(const basic_scheduler &) = delete; - - /** - * @brief Move assignment operator. - * @param other The instance to move from. - * @return This process scheduler. - */ - basic_scheduler &operator=(basic_scheduler &&other) noexcept { - ENTT_ASSERT(alloc_traits::is_always_equal::value || get_allocator() == other.get_allocator(), "Copying a scheduler is not allowed"); - handlers = std::move(other.handlers); - return *this; - } - - /** - * @brief Exchanges the contents with those of a given scheduler. - * @param other Scheduler to exchange the content with. - */ - void swap(basic_scheduler &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 Number of processes currently scheduled. - * @return Number of processes currently scheduled. - */ - [[nodiscard]] size_type size() const noexcept { - return handlers.first().size(); - } - - /** - * @brief Returns true if at least a process is currently scheduled. - * @return True if there are scheduled processes, false otherwise. - */ - [[nodiscard]] bool empty() const noexcept { - return handlers.first().empty(); - } - - /** - * @brief Discards all scheduled processes. - * - * Processes aren't aborted. They are discarded along with their children - * and never executed again. - */ - void clear() { - handlers.first().clear(); - } - - /** - * @brief Schedules a process for the next tick. - * - * Returned value can be used to attach a continuation for the last process. - * The continutation is scheduled automatically when the process terminates - * and only if the process returns with success. - * - * Example of use (pseudocode): - * - * @code{.cpp} - * // schedules a task in the form of a process class - * scheduler.attach<my_process>(arguments...) - * // appends a child in the form of a lambda function - * .then([](auto delta, void *, auto succeed, auto fail) { - * // code - * }) - * // appends a child in the form of another process class - * .then<my_other_process>(); - * @endcode - * - * @tparam Proc Type of process to schedule. - * @tparam Args Types of arguments to use to initialize the process. - * @param args Parameters to use to initialize the process. - * @return This process scheduler. - */ - template<typename Proc, typename... Args> - basic_scheduler &attach(Args &&...args) { - static_assert(std::is_base_of_v<process<Proc, Delta>, Proc>, "Invalid process type"); - auto &ref = handlers.first().emplace_back(std::allocate_shared<handler_type<Proc>>(handlers.second(), std::forward<Args>(args)...)); - // forces the process to exit the uninitialized state - ref->update({}, nullptr); - return *this; - } - - /** - * @brief Schedules a process for the next tick. - * - * A process can be either a lambda or a functor. The scheduler wraps both - * of them in a process adaptor internally.<br/> - * The signature of the function call operator should be equivalent to the - * following: - * - * @code{.cpp} - * void(Delta delta, void *data, auto succeed, auto fail); - * @endcode - * - * Where: - * - * * `delta` is the elapsed time. - * * `data` is an opaque pointer to user data if any, `nullptr` otherwise. - * * `succeed` is a function to call when a process terminates with success. - * * `fail` is a function to call when a process terminates with errors. - * - * The signature of the function call operator of both `succeed` and `fail` - * is equivalent to the following: - * - * @code{.cpp} - * void(); - * @endcode - * - * Returned value can be used to attach a continuation for the last process. - * The continutation is scheduled automatically when the process terminates - * and only if the process returns with success. - * - * Example of use (pseudocode): - * - * @code{.cpp} - * // schedules a task in the form of a lambda function - * scheduler.attach([](auto delta, void *, auto succeed, auto fail) { - * // code - * }) - * // appends a child in the form of another lambda function - * .then([](auto delta, void *, auto succeed, auto fail) { - * // code - * }) - * // appends a child in the form of a process class - * .then<my_process>(arguments...); - * @endcode - * - * @sa process_adaptor - * - * @tparam Func Type of process to schedule. - * @param func Either a lambda or a functor to use as a process. - * @return This process scheduler. - */ - template<typename Func> - basic_scheduler &attach(Func &&func) { - using Proc = process_adaptor<std::decay_t<Func>, Delta>; - return attach<Proc>(std::forward<Func>(func)); - } - - /** - * @brief Sets a process as a continuation of the last scheduled process. - * @tparam Proc Type of process to use as a continuation. - * @tparam Args Types of arguments to use to initialize the process. - * @param args Parameters to use to initialize the process. - * @return This process scheduler. - */ - template<typename Proc, typename... Args> - basic_scheduler &then(Args &&...args) { - static_assert(std::is_base_of_v<process<Proc, Delta>, Proc>, "Invalid process type"); - ENTT_ASSERT(!handlers.first().empty(), "Process not available"); - auto *curr = handlers.first().back().get(); - for(; curr->next; curr = curr->next.get()) {} - curr->next = std::allocate_shared<handler_type<Proc>>(handlers.second(), std::forward<Args>(args)...); - return *this; - } - - /** - * @brief Sets a process as a continuation of the last scheduled process. - * @tparam Func Type of process to use as a continuation. - * @param func Either a lambda or a functor to use as a process. - * @return This process scheduler. - */ - template<typename Func> - basic_scheduler &then(Func &&func) { - using Proc = process_adaptor<std::decay_t<Func>, Delta>; - return then<Proc>(std::forward<Func>(func)); - } - - /** - * @brief Updates all scheduled processes. - * - * All scheduled processes are executed in no specific order.<br/> - * If a process terminates with success, it's replaced with its child, if - * any. Otherwise, if a process terminates with an error, it's removed along - * with its child. - * - * @param delta Elapsed time. - * @param data Optional data. - */ - void update(const delta_type delta, void *data = nullptr) { - for(auto next = handlers.first().size(); next; --next) { - if(const auto pos = next - 1u; handlers.first()[pos]->update(delta, data)) { - // updating might spawn/reallocate, cannot hold refs until here - if(auto &curr = handlers.first()[pos]; curr->next) { - curr = std::move(curr->next); - // forces the process to exit the uninitialized state - curr->update({}, nullptr); - } else { - curr = std::move(handlers.first().back()); - handlers.first().pop_back(); - } - } - } - } - - /** - * @brief Aborts all scheduled processes. - * - * Unless an immediate operation is requested, the abort is scheduled for - * the next tick. Processes won't be executed anymore in any case.<br/> - * Once a process is fully aborted and thus finished, it's discarded along - * with its child, if any. - * - * @param immediate Requests an immediate operation. - */ - void abort(const bool immediate = false) { - for(auto &&curr: handlers.first()) { - curr->abort(immediate); - } - } - -private: - compressed_pair<container_type, allocator_type> handlers; -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/resource/cache.hpp b/deps/entt/include/entt/resource/cache.hpp deleted file mode 100644 index 4650c63..0000000 --- a/deps/entt/include/entt/resource/cache.hpp +++ /dev/null @@ -1,413 +0,0 @@ -#ifndef ENTT_RESOURCE_RESOURCE_CACHE_HPP -#define ENTT_RESOURCE_RESOURCE_CACHE_HPP - -#include <cstddef> -#include <functional> -#include <iterator> -#include <memory> -#include <tuple> -#include <type_traits> -#include <utility> -#include "../container/dense_map.hpp" -#include "../core/compressed_pair.hpp" -#include "../core/fwd.hpp" -#include "../core/iterator.hpp" -#include "../core/utility.hpp" -#include "fwd.hpp" -#include "loader.hpp" -#include "resource.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename Type, typename It> -class resource_cache_iterator final { - template<typename, typename> - friend class resource_cache_iterator; - -public: - using value_type = std::pair<id_type, resource<Type>>; - using pointer = input_iterator_pointer<value_type>; - using reference = value_type; - using difference_type = std::ptrdiff_t; - using iterator_category = std::input_iterator_tag; - using iterator_concept = std::random_access_iterator_tag; - - constexpr resource_cache_iterator() noexcept = default; - - constexpr resource_cache_iterator(const It iter) noexcept - : it{iter} {} - - template<typename Other, typename = std::enable_if_t<!std::is_same_v<It, Other> && std::is_constructible_v<It, Other>>> - constexpr resource_cache_iterator(const resource_cache_iterator<std::remove_const_t<Type>, Other> &other) noexcept - : it{other.it} {} - - constexpr resource_cache_iterator &operator++() noexcept { - return ++it, *this; - } - - constexpr resource_cache_iterator operator++(int) noexcept { - resource_cache_iterator orig = *this; - return ++(*this), orig; - } - - constexpr resource_cache_iterator &operator--() noexcept { - return --it, *this; - } - - constexpr resource_cache_iterator operator--(int) noexcept { - resource_cache_iterator orig = *this; - return operator--(), orig; - } - - constexpr resource_cache_iterator &operator+=(const difference_type value) noexcept { - it += value; - return *this; - } - - constexpr resource_cache_iterator operator+(const difference_type value) const noexcept { - resource_cache_iterator copy = *this; - return (copy += value); - } - - constexpr resource_cache_iterator &operator-=(const difference_type value) noexcept { - return (*this += -value); - } - - constexpr resource_cache_iterator operator-(const difference_type value) const noexcept { - return (*this + -value); - } - - [[nodiscard]] constexpr reference operator[](const difference_type value) const noexcept { - return {it[value].first, resource<Type>{it[value].second}}; - } - - [[nodiscard]] constexpr reference operator*() const noexcept { - return operator[](0); - } - - [[nodiscard]] constexpr pointer operator->() const noexcept { - return operator*(); - } - - template<typename... Lhs, typename... Rhs> - friend constexpr std::ptrdiff_t operator-(const resource_cache_iterator<Lhs...> &, const resource_cache_iterator<Rhs...> &) noexcept; - - template<typename... Lhs, typename... Rhs> - friend constexpr bool operator==(const resource_cache_iterator<Lhs...> &, const resource_cache_iterator<Rhs...> &) noexcept; - - template<typename... Lhs, typename... Rhs> - friend constexpr bool operator<(const resource_cache_iterator<Lhs...> &, const resource_cache_iterator<Rhs...> &) noexcept; - -private: - It it; -}; - -template<typename... Lhs, typename... Rhs> -[[nodiscard]] constexpr std::ptrdiff_t operator-(const resource_cache_iterator<Lhs...> &lhs, const resource_cache_iterator<Rhs...> &rhs) noexcept { - return lhs.it - rhs.it; -} - -template<typename... Lhs, typename... Rhs> -[[nodiscard]] constexpr bool operator==(const resource_cache_iterator<Lhs...> &lhs, const resource_cache_iterator<Rhs...> &rhs) noexcept { - return lhs.it == rhs.it; -} - -template<typename... Lhs, typename... Rhs> -[[nodiscard]] constexpr bool operator!=(const resource_cache_iterator<Lhs...> &lhs, const resource_cache_iterator<Rhs...> &rhs) noexcept { - return !(lhs == rhs); -} - -template<typename... Lhs, typename... Rhs> -[[nodiscard]] constexpr bool operator<(const resource_cache_iterator<Lhs...> &lhs, const resource_cache_iterator<Rhs...> &rhs) noexcept { - return lhs.it < rhs.it; -} - -template<typename... Lhs, typename... Rhs> -[[nodiscard]] constexpr bool operator>(const resource_cache_iterator<Lhs...> &lhs, const resource_cache_iterator<Rhs...> &rhs) noexcept { - return rhs < lhs; -} - -template<typename... Lhs, typename... Rhs> -[[nodiscard]] constexpr bool operator<=(const resource_cache_iterator<Lhs...> &lhs, const resource_cache_iterator<Rhs...> &rhs) noexcept { - return !(lhs > rhs); -} - -template<typename... Lhs, typename... Rhs> -[[nodiscard]] constexpr bool operator>=(const resource_cache_iterator<Lhs...> &lhs, const resource_cache_iterator<Rhs...> &rhs) noexcept { - return !(lhs < rhs); -} - -} // namespace internal -/*! @endcond */ - -/** - * @brief Basic cache for resources of any type. - * @tparam Type Type of resources managed by a cache. - * @tparam Loader Type of loader used to create the resources. - * @tparam Allocator Type of allocator used to manage memory and elements. - */ -template<typename Type, typename Loader, typename Allocator> -class resource_cache { - using alloc_traits = std::allocator_traits<Allocator>; - static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type"); - using container_allocator = typename alloc_traits::template rebind_alloc<std::pair<const id_type, typename Loader::result_type>>; - using container_type = dense_map<id_type, typename Loader::result_type, identity, std::equal_to<>, container_allocator>; - -public: - /*! @brief Allocator type. */ - using allocator_type = Allocator; - /*! @brief Resource type. */ - using value_type = Type; - /*! @brief Unsigned integer type. */ - using size_type = std::size_t; - /*! @brief Loader type. */ - using loader_type = Loader; - /*! @brief Input iterator type. */ - using iterator = internal::resource_cache_iterator<Type, typename container_type::iterator>; - /*! @brief Constant input iterator type. */ - using const_iterator = internal::resource_cache_iterator<const Type, typename container_type::const_iterator>; - - /*! @brief Default constructor. */ - resource_cache() - : resource_cache{loader_type{}} {} - - /** - * @brief Constructs an empty cache with a given allocator. - * @param allocator The allocator to use. - */ - explicit resource_cache(const allocator_type &allocator) - : resource_cache{loader_type{}, allocator} {} - - /** - * @brief Constructs an empty cache with a given allocator and loader. - * @param callable The loader to use. - * @param allocator The allocator to use. - */ - explicit resource_cache(const loader_type &callable, const allocator_type &allocator = allocator_type{}) - : pool{container_type{allocator}, callable} {} - - /*! @brief Default copy constructor. */ - resource_cache(const resource_cache &) = default; - - /** - * @brief Allocator-extended copy constructor. - * @param other The instance to copy from. - * @param allocator The allocator to use. - */ - resource_cache(const resource_cache &other, const allocator_type &allocator) - : pool{std::piecewise_construct, std::forward_as_tuple(other.pool.first(), allocator), std::forward_as_tuple(other.pool.second())} {} - - /*! @brief Default move constructor. */ - resource_cache(resource_cache &&) noexcept = default; - - /** - * @brief Allocator-extended move constructor. - * @param other The instance to move from. - * @param allocator The allocator to use. - */ - resource_cache(resource_cache &&other, const allocator_type &allocator) - : pool{std::piecewise_construct, std::forward_as_tuple(std::move(other.pool.first()), allocator), std::forward_as_tuple(std::move(other.pool.second()))} {} - - /*! @brief Default destructor. */ - ~resource_cache() noexcept = default; - - /** - * @brief Default copy assignment operator. - * @return This cache. - */ - resource_cache &operator=(const resource_cache &) = default; - - /** - * @brief Default move assignment operator. - * @return This cache. - */ - resource_cache &operator=(resource_cache &&) noexcept = default; - - /** - * @brief Returns the associated allocator. - * @return The associated allocator. - */ - [[nodiscard]] constexpr allocator_type get_allocator() const noexcept { - return pool.first().get_allocator(); - } - - /** - * @brief Returns an iterator to the beginning. - * - * If the cache is empty, the returned iterator will be equal to `end()`. - * - * @return An iterator to the first instance of the internal cache. - */ - [[nodiscard]] const_iterator cbegin() const noexcept { - return pool.first().begin(); - } - - /*! @copydoc cbegin */ - [[nodiscard]] const_iterator begin() const noexcept { - return cbegin(); - } - - /*! @copydoc begin */ - [[nodiscard]] iterator begin() noexcept { - return pool.first().begin(); - } - - /** - * @brief Returns an iterator to the end. - * @return An iterator to the element following the last instance of the - * internal cache. - */ - [[nodiscard]] const_iterator cend() const noexcept { - return pool.first().end(); - } - - /*! @copydoc cend */ - [[nodiscard]] const_iterator end() const noexcept { - return cend(); - } - - /*! @copydoc end */ - [[nodiscard]] iterator end() noexcept { - return pool.first().end(); - } - - /** - * @brief Returns true if a cache contains no resources, false otherwise. - * @return True if the cache contains no resources, false otherwise. - */ - [[nodiscard]] bool empty() const noexcept { - return pool.first().empty(); - } - - /** - * @brief Number of resources managed by a cache. - * @return Number of resources currently stored. - */ - [[nodiscard]] size_type size() const noexcept { - return pool.first().size(); - } - - /*! @brief Clears a cache. */ - void clear() noexcept { - pool.first().clear(); - } - - /** - * @brief Loads a resource, if its identifier does not exist. - * - * Arguments are forwarded directly to the loader and _consumed_ only if the - * resource doesn't already exist. - * - * @warning - * If the resource isn't loaded correctly, the returned handle could be - * invalid and any use of it will result in undefined behavior. - * - * @tparam Args Types of arguments to use to load the resource if required. - * @param id Unique resource identifier. - * @param args Arguments to use to load the resource if required. - * @return A pair consisting of an iterator to the inserted element (or to - * the element that prevented the insertion) and a bool denoting whether the - * insertion took place. - */ - template<typename... Args> - std::pair<iterator, bool> load(const id_type id, Args &&...args) { - if(auto it = pool.first().find(id); it != pool.first().end()) { - return {it, false}; - } - - return pool.first().emplace(id, pool.second()(std::forward<Args>(args)...)); - } - - /** - * @brief Force loads a resource, if its identifier does not exist. - * @copydetails load - */ - template<typename... Args> - std::pair<iterator, bool> force_load(const id_type id, Args &&...args) { - return {pool.first().insert_or_assign(id, pool.second()(std::forward<Args>(args)...)).first, true}; - } - - /** - * @brief Returns a handle for a given resource identifier. - * - * @warning - * There is no guarantee that the returned handle is valid.<br/> - * If it is not, any use will result in indefinite behavior. - * - * @param id Unique resource identifier. - * @return A handle for the given resource. - */ - [[nodiscard]] resource<const value_type> operator[](const id_type id) const { - if(auto it = pool.first().find(id); it != pool.first().cend()) { - return resource<const value_type>{it->second}; - } - - return {}; - } - - /*! @copydoc operator[] */ - [[nodiscard]] resource<value_type> operator[](const id_type id) { - if(auto it = pool.first().find(id); it != pool.first().end()) { - return resource<value_type>{it->second}; - } - - return {}; - } - - /** - * @brief Checks if a cache contains a given identifier. - * @param id Unique resource identifier. - * @return True if the cache contains the resource, false otherwise. - */ - [[nodiscard]] bool contains(const id_type id) const { - return pool.first().contains(id); - } - - /** - * @brief Removes an element from a given position. - * @param pos An iterator to the element to remove. - * @return An iterator following the removed element. - */ - iterator erase(const_iterator pos) { - const auto it = pool.first().begin(); - return pool.first().erase(it + (pos - const_iterator{it})); - } - - /** - * @brief Removes the given elements from a cache. - * @param first An iterator to the first element of the range of elements. - * @param last An iterator past the last element of the range of elements. - * @return An iterator following the last removed element. - */ - iterator erase(const_iterator first, const_iterator last) { - const auto it = pool.first().begin(); - return pool.first().erase(it + (first - const_iterator{it}), it + (last - const_iterator{it})); - } - - /** - * @brief Removes the given elements from a cache. - * @param id Unique resource identifier. - * @return Number of resources erased (either 0 or 1). - */ - size_type erase(const id_type id) { - return pool.first().erase(id); - } - - /** - * @brief Returns the loader used to create resources. - * @return The loader used to create resources. - */ - [[nodiscard]] loader_type loader() const { - return pool.second(); - } - -private: - compressed_pair<container_type, loader_type> pool; -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/resource/fwd.hpp b/deps/entt/include/entt/resource/fwd.hpp deleted file mode 100644 index ed63da5..0000000 --- a/deps/entt/include/entt/resource/fwd.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef ENTT_RESOURCE_FWD_HPP -#define ENTT_RESOURCE_FWD_HPP - -#include <memory> - -namespace entt { - -template<typename> -struct resource_loader; - -template<typename Type, typename = resource_loader<Type>, typename = std::allocator<Type>> -class resource_cache; - -template<typename> -class resource; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/resource/loader.hpp b/deps/entt/include/entt/resource/loader.hpp deleted file mode 100644 index f59d748..0000000 --- a/deps/entt/include/entt/resource/loader.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef ENTT_RESOURCE_LOADER_HPP -#define ENTT_RESOURCE_LOADER_HPP - -#include <memory> -#include <utility> -#include "fwd.hpp" - -namespace entt { - -/** - * @brief Transparent loader for shared resources. - * @tparam Type Type of resources created by the loader. - */ -template<typename Type> -struct resource_loader { - /*! @brief Result type. */ - using result_type = std::shared_ptr<Type>; - - /** - * @brief Constructs a shared pointer to a resource from its arguments. - * @tparam Args Types of arguments to use to construct the resource. - * @param args Parameters to use to construct the resource. - * @return A shared pointer to a resource of the given type. - */ - template<typename... Args> - result_type operator()(Args &&...args) const { - return std::make_shared<Type>(std::forward<Args>(args)...); - } -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/resource/resource.hpp b/deps/entt/include/entt/resource/resource.hpp deleted file mode 100644 index 323d738..0000000 --- a/deps/entt/include/entt/resource/resource.hpp +++ /dev/null @@ -1,259 +0,0 @@ -#ifndef ENTT_RESOURCE_RESOURCE_HPP -#define ENTT_RESOURCE_RESOURCE_HPP - -#include <memory> -#include <type_traits> -#include <utility> -#include "fwd.hpp" - -namespace entt { - -/** - * @brief Basic resource handle. - * - * A handle wraps a resource and extends its lifetime. It also shares the same - * resource with all other handles constructed from the same element.<br/> - * As a rule of thumb, resources should never be copied nor moved. Handles are - * the way to go to push references around. - * - * @tparam Type Type of resource managed by a handle. - */ -template<typename Type> -class resource { - template<typename> - friend class resource; - - template<typename Other> - static constexpr bool is_acceptable_v = !std::is_same_v<Type, Other> && std::is_constructible_v<Type &, Other &>; - -public: - /*! @brief Resource type. */ - using element_type = Type; - /*! @brief Handle type. */ - using handle_type = std::shared_ptr<element_type>; - - /*! @brief Default constructor. */ - resource() noexcept - : value{} {} - - /** - * @brief Creates a new resource handle. - * @param res A handle to a resource. - */ - explicit resource(handle_type res) noexcept - : value{std::move(res)} {} - - /*! @brief Default copy constructor. */ - resource(const resource &) noexcept = default; - - /*! @brief Default move constructor. */ - resource(resource &&) noexcept = default; - - /** - * @brief Aliasing constructor. - * @tparam Other Type of resource managed by the received handle. - * @param other The handle with which to share ownership information. - * @param res Unrelated and unmanaged resources. - */ - template<typename Other> - resource(const resource<Other> &other, element_type &res) noexcept - : value{other.value, std::addressof(res)} {} - - /** - * @brief Copy constructs a handle which shares ownership of the resource. - * @tparam Other Type of resource managed by the received handle. - * @param other The handle to copy from. - */ - template<typename Other, typename = std::enable_if_t<is_acceptable_v<Other>>> - resource(const resource<Other> &other) noexcept - : value{other.value} {} - - /** - * @brief Move constructs a handle which takes ownership of the resource. - * @tparam Other Type of resource managed by the received handle. - * @param other The handle to move from. - */ - template<typename Other, typename = std::enable_if_t<is_acceptable_v<Other>>> - resource(resource<Other> &&other) noexcept - : value{std::move(other.value)} {} - - /*! @brief Default destructor. */ - ~resource() noexcept = default; - - /** - * @brief Default copy assignment operator. - * @return This resource handle. - */ - resource &operator=(const resource &) noexcept = default; - - /** - * @brief Default move assignment operator. - * @return This resource handle. - */ - resource &operator=(resource &&) noexcept = default; - - /** - * @brief Copy assignment operator from foreign handle. - * @tparam Other Type of resource managed by the received handle. - * @param other The handle to copy from. - * @return This resource handle. - */ - template<typename Other, typename = std::enable_if_t<is_acceptable_v<Other>>> - resource &operator=(const resource<Other> &other) noexcept { - value = other.value; - return *this; - } - - /** - * @brief Move assignment operator from foreign handle. - * @tparam Other Type of resource managed by the received handle. - * @param other The handle to move from. - * @return This resource handle. - */ - template<typename Other, typename = std::enable_if_t<is_acceptable_v<Other>>> - resource &operator=(resource<Other> &&other) noexcept { - value = std::move(other.value); - return *this; - } - - /** - * @brief Returns a reference to the managed resource. - * - * @warning - * The behavior is undefined if the handle doesn't contain a resource. - * - * @return A reference to the managed resource. - */ - [[nodiscard]] element_type &operator*() const noexcept { - return *value; - } - - /*! @copydoc operator* */ - [[nodiscard]] operator element_type &() const noexcept { - return *value; - } - - /** - * @brief Returns a pointer to the managed resource. - * @return A pointer to the managed resource. - */ - [[nodiscard]] element_type *operator->() const noexcept { - return value.get(); - } - - /** - * @brief Returns true if a handle contains a resource, false otherwise. - * @return True if the handle contains a resource, false otherwise. - */ - [[nodiscard]] explicit operator bool() const noexcept { - return static_cast<bool>(value); - } - - /*! @brief Releases the ownership of the managed resource. */ - void reset() { - value.reset(); - } - - /** - * @brief Replaces the managed resource. - * @param other A handle to a resource. - */ - void reset(handle_type other) { - value = std::move(other); - } - - /** - * @brief Returns the underlying resource handle. - * @return The underlying resource handle. - */ - [[nodiscard]] const handle_type &handle() const noexcept { - return value; - } - -private: - handle_type value; -}; - -/** - * @brief Compares two handles. - * @tparam Lhs Type of resource managed by the first handle. - * @tparam Rhs Type of resource managed by the second handle. - * @param lhs A valid handle. - * @param rhs A valid handle. - * @return True if both handles refer to the same resource, false otherwise. - */ -template<typename Lhs, typename Rhs> -[[nodiscard]] bool operator==(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept { - return (std::addressof(*lhs) == std::addressof(*rhs)); -} - -/** - * @brief Compares two handles. - * @tparam Lhs Type of resource managed by the first handle. - * @tparam Rhs Type of resource managed by the second handle. - * @param lhs A valid handle. - * @param rhs A valid handle. - * @return False if both handles refer to the same resource, true otherwise. - */ -template<typename Lhs, typename Rhs> -[[nodiscard]] bool operator!=(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept { - return !(lhs == rhs); -} - -/** - * @brief Compares two handles. - * @tparam Lhs Type of resource managed by the first handle. - * @tparam Rhs Type of resource managed by the second handle. - * @param lhs A valid handle. - * @param rhs A valid handle. - * @return True if the first handle is less than the second, false otherwise. - */ -template<typename Lhs, typename Rhs> -[[nodiscard]] bool operator<(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept { - return (std::addressof(*lhs) < std::addressof(*rhs)); -} - -/** - * @brief Compares two handles. - * @tparam Lhs Type of resource managed by the first handle. - * @tparam Rhs Type of resource managed by the second handle. - * @param lhs A valid handle. - * @param rhs A valid handle. - * @return True if the first handle is greater than the second, false otherwise. - */ -template<typename Lhs, typename Rhs> -[[nodiscard]] bool operator>(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept { - return rhs < lhs; -} - -/** - * @brief Compares two handles. - * @tparam Lhs Type of resource managed by the first handle. - * @tparam Rhs Type of resource managed by the second handle. - * @param lhs A valid handle. - * @param rhs A valid handle. - * @return True if the first handle is less than or equal to the second, false - * otherwise. - */ -template<typename Lhs, typename Rhs> -[[nodiscard]] bool operator<=(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept { - return !(lhs > rhs); -} - -/** - * @brief Compares two handles. - * @tparam Lhs Type of resource managed by the first handle. - * @tparam Rhs Type of resource managed by the second handle. - * @param lhs A valid handle. - * @param rhs A valid handle. - * @return True if the first handle is greater than or equal to the second, - * false otherwise. - */ -template<typename Lhs, typename Rhs> -[[nodiscard]] bool operator>=(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept { - return !(lhs < rhs); -} - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/signal/delegate.hpp b/deps/entt/include/entt/signal/delegate.hpp deleted file mode 100644 index 0060649..0000000 --- a/deps/entt/include/entt/signal/delegate.hpp +++ /dev/null @@ -1,323 +0,0 @@ -#ifndef ENTT_SIGNAL_DELEGATE_HPP -#define ENTT_SIGNAL_DELEGATE_HPP - -#include <cstddef> -#include <functional> -#include <tuple> -#include <type_traits> -#include <utility> -#include "../config/config.h" -#include "../core/type_traits.hpp" -#include "fwd.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template<typename Ret, typename... Args> -constexpr auto function_pointer(Ret (*)(Args...)) -> Ret (*)(Args...); - -template<typename Ret, typename Type, typename... Args, typename Other> -constexpr auto function_pointer(Ret (*)(Type, Args...), Other &&) -> Ret (*)(Args...); - -template<typename Class, typename Ret, typename... Args, typename... Other> -constexpr auto function_pointer(Ret (Class::*)(Args...), Other &&...) -> Ret (*)(Args...); - -template<typename Class, typename Ret, typename... Args, typename... Other> -constexpr auto function_pointer(Ret (Class::*)(Args...) const, Other &&...) -> Ret (*)(Args...); - -template<typename Class, typename Type, typename... Other> -constexpr auto function_pointer(Type Class::*, Other &&...) -> Type (*)(); - -template<typename... Type> -using function_pointer_t = decltype(function_pointer(std::declval<Type>()...)); - -template<typename... Class, typename Ret, typename... Args> -[[nodiscard]] constexpr auto index_sequence_for(Ret (*)(Args...)) { - return std::index_sequence_for<Class..., Args...>{}; -} - -} // 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<typename> -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<typename Ret, typename... Args> -class delegate<Ret(Args...)> { - template<auto Candidate, std::size_t... Index> - [[nodiscard]] auto wrap(std::index_sequence<Index...>) noexcept { - return [](const void *, Args... args) -> Ret { - [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...); - [[maybe_unused]] constexpr auto offset = !std::is_invocable_r_v<Ret, decltype(Candidate), type_list_element_t<Index, type_list<Args...>>...> * (sizeof...(Args) - sizeof...(Index)); - return static_cast<Ret>(std::invoke(Candidate, std::forward<type_list_element_t<Index + offset, type_list<Args...>>>(std::get<Index + offset>(arguments))...)); - }; - } - - template<auto Candidate, typename Type, std::size_t... Index> - [[nodiscard]] auto wrap(Type &, std::index_sequence<Index...>) noexcept { - return [](const void *payload, Args... args) -> Ret { - Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload)); - [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...); - [[maybe_unused]] constexpr auto offset = !std::is_invocable_r_v<Ret, decltype(Candidate), Type &, type_list_element_t<Index, type_list<Args...>>...> * (sizeof...(Args) - sizeof...(Index)); - return static_cast<Ret>(std::invoke(Candidate, *curr, std::forward<type_list_element_t<Index + offset, type_list<Args...>>>(std::get<Index + offset>(arguments))...)); - }; - } - - template<auto Candidate, typename Type, std::size_t... Index> - [[nodiscard]] auto wrap(Type *, std::index_sequence<Index...>) noexcept { - return [](const void *payload, Args... args) -> Ret { - Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload)); - [[maybe_unused]] const auto arguments = std::forward_as_tuple(std::forward<Args>(args)...); - [[maybe_unused]] constexpr auto offset = !std::is_invocable_r_v<Ret, decltype(Candidate), Type *, type_list_element_t<Index, type_list<Args...>>...> * (sizeof...(Args) - sizeof...(Index)); - return static_cast<Ret>(std::invoke(Candidate, curr, std::forward<type_list_element_t<Index + offset, type_list<Args...>>>(std::get<Index + offset>(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<auto Candidate, typename... Type> - delegate(connect_arg_t<Candidate>, Type &&...value_or_instance) noexcept { - connect<Candidate>(std::forward<Type>(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<auto Candidate> - void connect() noexcept { - instance = nullptr; - - if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Args...>) { - fn = [](const void *, Args... args) -> Ret { - return Ret(std::invoke(Candidate, std::forward<Args>(args)...)); - }; - } else if constexpr(std::is_member_pointer_v<decltype(Candidate)>) { - fn = wrap<Candidate>(internal::index_sequence_for<type_list_element_t<0, type_list<Args...>>>(internal::function_pointer_t<decltype(Candidate)>{})); - } else { - fn = wrap<Candidate>(internal::index_sequence_for(internal::function_pointer_t<decltype(Candidate)>{})); - } - } - - /** - * @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.<br/> - * 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<auto Candidate, typename Type> - void connect(Type &value_or_instance) noexcept { - instance = &value_or_instance; - - if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Type &, Args...>) { - fn = [](const void *payload, Args... args) -> Ret { - Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload)); - return Ret(std::invoke(Candidate, *curr, std::forward<Args>(args)...)); - }; - } else { - fn = wrap<Candidate>(value_or_instance, internal::index_sequence_for(internal::function_pointer_t<decltype(Candidate), Type>{})); - } - } - - /** - * @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<auto Candidate, typename Type> - void connect(Type *value_or_instance) noexcept { - instance = value_or_instance; - - if constexpr(std::is_invocable_r_v<Ret, decltype(Candidate), Type *, Args...>) { - fn = [](const void *payload, Args... args) -> Ret { - Type *curr = static_cast<Type *>(const_cast<constness_as_t<void, Type> *>(payload)); - return Ret(std::invoke(Candidate, curr, std::forward<Args>(args)...)); - }; - } else { - fn = wrap<Candidate>(value_or_instance, internal::index_sequence_for(internal::function_pointer_t<decltype(Candidate), Type>{})); - } - } - - /** - * @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.<br/> - * 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<bool>(*this), "Uninitialized delegate"); - return fn(instance, std::forward<Args>(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<Ret(Args...)> &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<typename Ret, typename... Args> -[[nodiscard]] bool operator!=(const delegate<Ret(Args...)> &lhs, const delegate<Ret(Args...)> &rhs) noexcept { - return !(lhs == rhs); -} - -/** - * @brief Deduction guide. - * @tparam Candidate Function or member to connect to the delegate. - */ -template<auto Candidate> -delegate(connect_arg_t<Candidate>) -> delegate<std::remove_pointer_t<internal::function_pointer_t<decltype(Candidate)>>>; - -/** - * @brief Deduction guide. - * @tparam Candidate Function or member to connect to the delegate. - * @tparam Type Type of class or type of payload. - */ -template<auto Candidate, typename Type> -delegate(connect_arg_t<Candidate>, Type &&) -> delegate<std::remove_pointer_t<internal::function_pointer_t<decltype(Candidate), Type>>>; - -/** - * @brief Deduction guide. - * @tparam Ret Return type of a function type. - * @tparam Args Types of arguments of a function type. - */ -template<typename Ret, typename... Args> -delegate(Ret (*)(const void *, Args...), const void * = nullptr) -> delegate<Ret(Args...)>; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/signal/dispatcher.hpp b/deps/entt/include/entt/signal/dispatcher.hpp deleted file mode 100644 index fbd758e..0000000 --- a/deps/entt/include/entt/signal/dispatcher.hpp +++ /dev/null @@ -1,397 +0,0 @@ -#ifndef ENTT_SIGNAL_DISPATCHER_HPP -#define ENTT_SIGNAL_DISPATCHER_HPP - -#include <cstddef> -#include <functional> -#include <memory> -#include <type_traits> -#include <utility> -#include <vector> -#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<typename Type, typename Allocator> -class dispatcher_handler final: public basic_dispatcher_handler { - static_assert(std::is_same_v<Type, std::decay_t<Type>>, "Invalid type"); - - using alloc_traits = std::allocator_traits<Allocator>; - using signal_type = sigh<void(Type &), Allocator>; - using container_type = std::vector<Type, typename alloc_traits::template rebind_alloc<Type>>; - -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<typename... Args> - void enqueue(Args &&...args) { - if constexpr(std::is_aggregate_v<Type> && (sizeof...(Args) != 0u || !std::is_default_constructible_v<Type>)) { - events.push_back(Type{std::forward<Args>(args)...}); - } else { - events.emplace_back(std::forward<Args>(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.<br/> - * 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<typename Allocator> -class basic_dispatcher { - template<typename Type> - using handler_type = internal::dispatcher_handler<Type, Allocator>; - - using key_type = id_type; - // std::shared_ptr because of its type erased allocator which is useful here - using mapped_type = std::shared_ptr<internal::basic_dispatcher_handler>; - - using alloc_traits = std::allocator_traits<Allocator>; - using container_allocator = typename alloc_traits::template rebind_alloc<std::pair<const key_type, mapped_type>>; - using container_type = dense_map<key_type, mapped_type, identity, std::equal_to<>, container_allocator>; - - template<typename Type> - [[nodiscard]] handler_type<Type> &assure(const id_type id) { - static_assert(std::is_same_v<Type, std::decay_t<Type>>, "Non-decayed types not allowed"); - auto &&ptr = pools.first()[id]; - - if(!ptr) { - const auto &allocator = get_allocator(); - ptr = std::allocate_shared<handler_type<Type>>(allocator, allocator); - } - - return static_cast<handler_type<Type> &>(*ptr); - } - - template<typename Type> - [[nodiscard]] const handler_type<Type> *assure(const id_type id) const { - static_assert(std::is_same_v<Type, std::decay_t<Type>>, "Non-decayed types not allowed"); - - if(auto it = pools.first().find(id); it != pools.first().cend()) { - return static_cast<const handler_type<Type> *>(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<typename Type> - [[nodiscard]] size_type size(const id_type id = type_hash<Type>::value()) const noexcept { - const auto *cpool = assure<std::decay_t<Type>>(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<typename Type> - [[nodiscard]] auto sink(const id_type id = type_hash<Type>::value()) { - return assure<Type>(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<typename Type> - void trigger(Type &&value = {}) { - trigger(type_hash<std::decay_t<Type>>::value(), std::forward<Type>(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<typename Type> - void trigger(const id_type id, Type &&value = {}) { - assure<std::decay_t<Type>>(id).trigger(std::forward<Type>(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<typename Type, typename... Args> - void enqueue(Args &&...args) { - enqueue_hint<Type>(type_hash<Type>::value(), std::forward<Args>(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<typename Type> - void enqueue(Type &&value) { - enqueue_hint(type_hash<std::decay_t<Type>>::value(), std::forward<Type>(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<typename Type, typename... Args> - void enqueue_hint(const id_type id, Args &&...args) { - assure<Type>(id).enqueue(std::forward<Args>(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<typename Type> - void enqueue_hint(const id_type id, Type &&value) { - assure<std::decay_t<Type>>(id).enqueue(std::forward<Type>(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<typename Type> - 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<typename Type> - 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<typename Type> - void clear(const id_type id = type_hash<Type>::value()) { - assure<Type>(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<typename Type> - void update(const id_type id = type_hash<Type>::value()) { - assure<Type>(id).publish(); - } - - /*! @brief Delivers all the pending events. */ - void update() const { - for(auto &&cpool: pools.first()) { - cpool.second->publish(); - } - } - -private: - compressed_pair<container_type, allocator_type> pools; -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/signal/emitter.hpp b/deps/entt/include/entt/signal/emitter.hpp deleted file mode 100644 index de69ed4..0000000 --- a/deps/entt/include/entt/signal/emitter.hpp +++ /dev/null @@ -1,182 +0,0 @@ -#ifndef ENTT_SIGNAL_EMITTER_HPP -#define ENTT_SIGNAL_EMITTER_HPP - -#include <functional> -#include <type_traits> -#include <utility> -#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<my_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.<br/> - * 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<typename Derived, typename Allocator> -class emitter { - using key_type = id_type; - using mapped_type = std::function<void(void *)>; - - using alloc_traits = std::allocator_traits<Allocator>; - using container_allocator = typename alloc_traits::template rebind_alloc<std::pair<const key_type, mapped_type>>; - using container_type = dense_map<key_type, mapped_type, identity, std::equal_to<>, 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<emitter<Derived, Allocator>, 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<typename Type> - void publish(Type &&value) { - if(const auto id = type_id<Type>().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<typename Type> - void on(std::function<void(Type &, Derived &)> func) { - handlers.first().insert_or_assign(type_id<Type>().hash(), [func = std::move(func), this](void *value) { - func(*static_cast<Type *>(value), static_cast<Derived &>(*this)); - }); - } - - /** - * @brief Disconnects a listener from the event emitter. - * @tparam Type Type of event of the listener. - */ - template<typename Type> - void erase() { - handlers.first().erase(type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::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<typename Type> - [[nodiscard]] bool contains() const { - return handlers.first().contains(type_hash<std::remove_cv_t<std::remove_reference_t<Type>>>::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<container_type, allocator_type> handlers; -}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/signal/fwd.hpp b/deps/entt/include/entt/signal/fwd.hpp deleted file mode 100644 index b0964b6..0000000 --- a/deps/entt/include/entt/signal/fwd.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef ENTT_SIGNAL_FWD_HPP -#define ENTT_SIGNAL_FWD_HPP - -#include <memory> - -namespace entt { - -template<typename> -class delegate; - -template<typename = std::allocator<void>> -class basic_dispatcher; - -template<typename, typename = std::allocator<void>> -class emitter; - -class connection; - -struct scoped_connection; - -template<typename> -class sink; - -template<typename Type, typename = std::allocator<void>> -class sigh; - -/*! @brief Alias declaration for the most common use case. */ -using dispatcher = basic_dispatcher<>; - -/*! @brief Disambiguation tag for constructors and the like. */ -template<auto> -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<auto Candidate> -inline constexpr connect_arg_t<Candidate> connect_arg{}; - -} // namespace entt - -#endif diff --git a/deps/entt/include/entt/signal/sigh.hpp b/deps/entt/include/entt/signal/sigh.hpp deleted file mode 100644 index 38da4a2..0000000 --- a/deps/entt/include/entt/signal/sigh.hpp +++ /dev/null @@ -1,471 +0,0 @@ -#ifndef ENTT_SIGNAL_SIGH_HPP -#define ENTT_SIGNAL_SIGH_HPP - -#include <cstddef> -#include <memory> -#include <type_traits> -#include <utility> -#include <vector> -#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<typename Type> -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<typename Type, typename Allocator> -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<typename Ret, typename... Args, typename Allocator> -class sigh<Ret(Args...), Allocator> { - friend class sink<sigh<Ret(Args...), Allocator>>; - - using alloc_traits = std::allocator_traits<Allocator>; - using delegate_type = delegate<Ret(Args...)>; - using container_type = std::vector<delegate_type, typename alloc_traits::template rebind_alloc<delegate_type>>; - -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<sigh<Ret(Args...), Allocator>>; - - /*! @brief Default constructor. */ - sigh() noexcept(std::is_nothrow_default_constructible_v<allocator_type> && std::is_nothrow_constructible_v<container_type, const allocator_type &>) - : 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<container_type, const allocator_type &>) - : calls{allocator} {} - - /** - * @brief Copy constructor. - * @param other The instance to copy from. - */ - sigh(const sigh &other) noexcept(std::is_nothrow_copy_constructible_v<container_type>) - : 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<container_type, const container_type &, const allocator_type &>) - : calls{other.calls, allocator} {} - - /** - * @brief Move constructor. - * @param other The instance to move from. - */ - sigh(sigh &&other) noexcept(std::is_nothrow_move_constructible_v<container_type>) - : 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<container_type, container_type &&, const allocator_type &>) - : 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<container_type>) { - 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<container_type>) { - 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<container_type>) { - 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<typename Func> - void collect(Func func, Args... args) const { - for(auto pos = calls.size(); pos; --pos) { - if constexpr(std::is_void_v<Ret> || !std::is_invocable_v<Func, Ret>) { - calls[pos - 1u](args...); - - if constexpr(std::is_invocable_r_v<bool, Func>) { - if(func()) { - break; - } - } else { - func(); - } - } else { - if constexpr(std::is_invocable_r_v<bool, Func, Ret>) { - 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<typename> - friend class sink; - - connection(delegate<void(void *)> 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<bool>(disconnect); - } - - /*! @brief Breaks the connection. */ - void release() { - if(disconnect) { - disconnect(signal); - disconnect.reset(); - } - } - -private: - delegate<void(void *)> 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.<br/> - * 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<bool>(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.<br/> - * 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<typename Ret, typename... Args, typename Allocator> -class sink<sigh<Ret(Args...), Allocator>> { - using signal_type = sigh<Ret(Args...), Allocator>; - using delegate_type = typename signal_type::delegate_type; - using difference_type = typename signal_type::container_type::difference_type; - - template<auto Candidate, typename Type> - static void release(Type value_or_instance, void *signal) { - sink{*static_cast<signal_type *>(signal)}.disconnect<Candidate>(value_or_instance); - } - - template<auto Candidate> - static void release(void *signal) { - sink{*static_cast<signal_type *>(signal)}.disconnect<Candidate>(); - } - - template<typename Func> - 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<Ret(Args...), Allocator> &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<auto Candidate, typename... Type> - connection connect(Type &&...value_or_instance) { - disconnect<Candidate>(value_or_instance...); - - delegate_type call{}; - call.template connect<Candidate>(value_or_instance...); - signal->calls.push_back(std::move(call)); - - delegate<void(void *)> conn{}; - conn.template connect<&release<Candidate, Type...>>(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<auto Candidate, typename... Type> - void disconnect(Type &&...value_or_instance) { - delegate_type call{}; - call.template connect<Candidate>(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<typename Ret, typename... Args, typename Allocator> -sink(sigh<Ret(Args...), Allocator> &) -> sink<sigh<Ret(Args...), Allocator>>; - -} // namespace entt - -#endif |
