From 61e5bcef2629e2d68b805a956a96fff264d4f74d Mon Sep 17 00:00:00 2001 From: untodesu Date: Sat, 28 Jun 2025 01:59:49 +0500 Subject: Restructure dependencies and update to C++20 - Nuked static_assert from almost everywhere in the project - Nuked binary dependency support. Might add one later though - Separated dependency headers into a separate include subdirectory - Grafted a thirdpartylegalnotices.txt generator from RITEG - Pushed development snapshot version to 2126 (26th week of 2025) --- deps/include/entt/meta/adl_pointer.hpp | 35 - deps/include/entt/meta/container.hpp | 388 ------ deps/include/entt/meta/context.hpp | 51 - deps/include/entt/meta/factory.hpp | 668 ----------- deps/include/entt/meta/fwd.hpp | 26 - deps/include/entt/meta/meta.hpp | 2026 -------------------------------- deps/include/entt/meta/node.hpp | 298 ----- deps/include/entt/meta/pointer.hpp | 51 - deps/include/entt/meta/policy.hpp | 58 - deps/include/entt/meta/range.hpp | 143 --- deps/include/entt/meta/resolve.hpp | 102 -- deps/include/entt/meta/template.hpp | 29 - deps/include/entt/meta/type_traits.hpp | 54 - deps/include/entt/meta/utility.hpp | 539 --------- 14 files changed, 4468 deletions(-) delete mode 100644 deps/include/entt/meta/adl_pointer.hpp delete mode 100644 deps/include/entt/meta/container.hpp delete mode 100644 deps/include/entt/meta/context.hpp delete mode 100644 deps/include/entt/meta/factory.hpp delete mode 100644 deps/include/entt/meta/fwd.hpp delete mode 100644 deps/include/entt/meta/meta.hpp delete mode 100644 deps/include/entt/meta/node.hpp delete mode 100644 deps/include/entt/meta/pointer.hpp delete mode 100644 deps/include/entt/meta/policy.hpp delete mode 100644 deps/include/entt/meta/range.hpp delete mode 100644 deps/include/entt/meta/resolve.hpp delete mode 100644 deps/include/entt/meta/template.hpp delete mode 100644 deps/include/entt/meta/type_traits.hpp delete mode 100644 deps/include/entt/meta/utility.hpp (limited to 'deps/include/entt/meta') diff --git a/deps/include/entt/meta/adl_pointer.hpp b/deps/include/entt/meta/adl_pointer.hpp deleted file mode 100644 index 2623d0e..0000000 --- a/deps/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 -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 -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/include/entt/meta/container.hpp b/deps/include/entt/meta/container.hpp deleted file mode 100644 index ee90c7d..0000000 --- a/deps/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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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 -struct fixed_size_sequence_container: std::true_type {}; - -template -struct fixed_size_sequence_container>: std::false_type {}; - -template -inline constexpr bool fixed_size_sequence_container_v = fixed_size_sequence_container::value; - -template -struct key_only_associative_container: std::true_type {}; - -template -struct key_only_associative_container>: std::false_type {}; - -template -inline constexpr bool key_only_associative_container_v = key_only_associative_container::value; - -template -struct reserve_aware_container: std::false_type {}; - -template -struct reserve_aware_container>: std::true_type {}; - -template -inline constexpr bool reserve_aware_container_v = reserve_aware_container::value; - -} // namespace internal -/*! @endcond */ - -/** - * @brief General purpose implementation of meta sequence container traits. - * @tparam Type Type of underlying sequence container. - */ -template -struct basic_meta_sequence_container_traits { - static_assert(std::is_same_v>>, "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; - - /** - * @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(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(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) { - static_cast(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) { - return false; - } else { - static_cast(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(container)->begin()} - : iterator{area, static_cast(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(container)->end()} - : iterator{area, static_cast(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(&it.base()); - return {area, static_cast(container)->insert( - non_const ? *non_const : any_cast(it.base()), - value ? *static_cast(value) : *static_cast *>(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(&it.base()); - return {area, static_cast(container)->erase(non_const ? *non_const : any_cast(it.base()))}; - } - } -}; - -/** - * @brief General purpose implementation of meta associative container traits. - * @tparam Type Type of underlying associative container. - */ -template -struct basic_meta_associative_container_traits { - static_assert(std::is_same_v>>, "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; - - /** - * @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(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(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) { - static_cast(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{}, static_cast(container)->begin()} - : iterator{area, std::bool_constant{}, static_cast(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{}, static_cast(container)->end()} - : iterator{area, std::bool_constant{}, static_cast(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(container)->insert(*static_cast(key)).second; - } else { - return static_cast(container)->emplace(*static_cast(key), *static_cast(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(container)->erase(*static_cast(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{}, static_cast(container)->find(*static_cast(key))} - : iterator{area, std::bool_constant{}, static_cast(as_const)->find(*static_cast(key))}; - } -}; - -/** - * @brief Meta sequence container traits for `std::vector`s of any type. - * @tparam Args Template arguments for the container. - */ -template -struct meta_sequence_container_traits> - : basic_meta_sequence_container_traits> {}; - -/** - * @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 -struct meta_sequence_container_traits> - : basic_meta_sequence_container_traits> {}; - -/** - * @brief Meta sequence container traits for `std::list`s of any type. - * @tparam Args Template arguments for the container. - */ -template -struct meta_sequence_container_traits> - : basic_meta_sequence_container_traits> {}; - -/** - * @brief Meta sequence container traits for `std::deque`s of any type. - * @tparam Args Template arguments for the container. - */ -template -struct meta_sequence_container_traits> - : basic_meta_sequence_container_traits> {}; - -/** - * @brief Meta associative container traits for `std::map`s of any type. - * @tparam Args Template arguments for the container. - */ -template -struct meta_associative_container_traits> - : basic_meta_associative_container_traits> {}; - -/** - * @brief Meta associative container traits for `std::unordered_map`s of any - * type. - * @tparam Args Template arguments for the container. - */ -template -struct meta_associative_container_traits> - : basic_meta_associative_container_traits> {}; - -/** - * @brief Meta associative container traits for `std::set`s of any type. - * @tparam Args Template arguments for the container. - */ -template -struct meta_associative_container_traits> - : basic_meta_associative_container_traits> {}; - -/** - * @brief Meta associative container traits for `std::unordered_set`s of any - * type. - * @tparam Args Template arguments for the container. - */ -template -struct meta_associative_container_traits> - : basic_meta_associative_container_traits> {}; - -/** - * @brief Meta associative container traits for `dense_map`s of any type. - * @tparam Args Template arguments for the container. - */ -template -struct meta_associative_container_traits> - : basic_meta_associative_container_traits> {}; - -/** - * @brief Meta associative container traits for `dense_set`s of any type. - * @tparam Args Template arguments for the container. - */ -template -struct meta_associative_container_traits> - : basic_meta_associative_container_traits> {}; - -} // namespace entt - -#endif diff --git a/deps/include/entt/meta/context.hpp b/deps/include/entt/meta/context.hpp deleted file mode 100644 index 920a6f1..0000000 --- a/deps/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 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/include/entt/meta/factory.hpp b/deps/include/entt/meta/factory.hpp deleted file mode 100644 index 3f61d69..0000000 --- a/deps/include/entt/meta/factory.hpp +++ /dev/null @@ -1,668 +0,0 @@ -#ifndef ENTT_META_FACTORY_HPP -#define ENTT_META_FACTORY_HPP - -#include -#include -#include -#include -#include -#include -#include -#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; - - 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(); - *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(); - } - - 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 -class meta_factory: private internal::basic_meta_factory { - using base_type = internal::basic_meta_factory; - - template - void data(const id_type id, std::index_sequence) noexcept { - using data_type = std::invoke_result_t; - using args_type = type_list)>::args_type...>; - static_assert(Policy::template value, "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)> && ... && std::is_const_v>) ? internal::meta_traits::is_const : internal::meta_traits::is_none, - Setter::size, - &internal::resolve>>, - &meta_arg::size != 1u, type_list_element_t>...>>, - +[](meta_handle instance, meta_any value) { return (meta_setter>(*instance.operator->(), value.as_ref()) || ...); }, - &meta_getter}); - } - -public: - /*! @brief Default constructor. */ - meta_factory() noexcept - : internal::basic_meta_factory{type_id(), locator::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().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 - meta_factory base() noexcept { - static_assert(!std::is_same_v && std::is_base_of_v, "Invalid base type"); - auto *const op = +[](const void *instance) noexcept { return static_cast(static_cast(static_cast(instance))); }; - base_type::base(type_id().hash(), internal::meta_base_node{&internal::resolve, op}); - return *this; - } - - /** - * @brief Assigns a meta conversion function to a meta type. - * - * Conversion functions can be either free functions or member - * functions.
- * 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 conv() noexcept { - using conv_type = std::remove_cv_t>>; - auto *const op = +[](const meta_ctx &area, const void *instance) { return forward_as_meta(area, std::invoke(Candidate, *static_cast(instance))); }; - base_type::conv(type_id().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 - meta_factory conv() noexcept { - using conv_type = std::remove_cv_t>; - auto *const op = +[](const meta_ctx &area, const void *instance) { return forward_as_meta(area, static_cast(*static_cast(instance))); }; - base_type::conv(type_id().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.
- * 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 - meta_factory ctor() noexcept { - using descriptor = meta_function_helper_t; - static_assert(Policy::template value, "Invalid return type for the given policy"); - static_assert(std::is_same_v>, Type>, "The function doesn't return an object of the required type"); - base_type::ctor(type_id().hash(), internal::meta_ctor_node{descriptor::args_type::size, &meta_arg, &meta_construct}); - 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 - 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; - base_type::ctor(type_id().hash(), internal::meta_ctor_node{descriptor::args_type::size, &meta_arg, &meta_construct}); - } - - 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.
- * The signature of a free function should be identical to the following: - * - * @code{.cpp} - * void(Type &); - * @endcode - * - * Member functions should not take arguments instead.
- * 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 - meta_factory dtor() noexcept { - static_assert(std::is_invocable_v, "The function doesn't accept an object of the type provided"); - auto *const op = +[](void *instance) { std::invoke(Func, *static_cast(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.
- * 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 - meta_factory data(const id_type id) noexcept { - if constexpr(std::is_member_object_pointer_v) { - using data_type = std::invoke_result_t; - static_assert(Policy::template value, "Invalid return type for the given policy"); - - base_type::data( - id, - internal::meta_data_node{ - /* this is never static */ - std::is_const_v> ? internal::meta_traits::is_const : internal::meta_traits::is_none, - 1u, - &internal::resolve>>, - &meta_arg>>>, - &meta_setter, - &meta_getter}); - } else { - using data_type = std::remove_pointer_t; - - if constexpr(std::is_pointer_v) { - static_assert(Policy::template value, "Invalid return type for the given policy"); - } else { - static_assert(Policy::template value, "Invalid return type for the given policy"); - } - - base_type::data( - id, - internal::meta_data_node{ - ((std::is_same_v>> || std::is_const_v>) ? internal::meta_traits::is_const : internal::meta_traits::is_none) | internal::meta_traits::is_static, - 1u, - &internal::resolve>>, - &meta_arg>>>, - &meta_setter, - &meta_getter}); - } - - 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.
- * 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.
- * 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 - meta_factory data(const id_type id) noexcept { - using data_type = std::invoke_result_t; - static_assert(Policy::template value, "Invalid return type for the given policy"); - - if constexpr(std::is_same_v) { - base_type::data( - id, - internal::meta_data_node{ - /* this is never static */ - internal::meta_traits::is_const, - 0u, - &internal::resolve>>, - &meta_arg>, - &meta_setter, - &meta_getter}); - } else { - using args_type = typename meta_function_helper_t::args_type; - - base_type::data( - id, - internal::meta_data_node{ - /* this is never static nor const */ - internal::meta_traits::is_none, - 1u, - &internal::resolve>>, - &meta_arg>>, - &meta_setter, - &meta_getter}); - } - - 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.
- * 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 - meta_factory data(const id_type id) noexcept { - data(id, std::make_index_sequence{}); - return *this; - } - - /** - * @brief Assigns a meta function to a meta type. - * - * Both member functions and free functions can be assigned to a meta - * type.
- * 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 - meta_factory func(const id_type id) noexcept { - using descriptor = meta_function_helper_t; - static_assert(Policy::template value, "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, void, std::remove_cv_t>>>, - &meta_arg, - &meta_invoke}); - - 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 - 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}); - } else { - base_type::prop(id, internal::meta_prop_node{&internal::resolve>..., std::make_shared>(std::forward(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 - meta_factory traits(const Value value) { - static_assert(std::is_enum_v, "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 - meta_factory custom(Args &&...args) { - base_type::custom(internal::meta_custom_node{type_id().hash(), std::make_shared(std::forward(args)...)}); - return *this; - } -}; - -/** - * @brief Utility function to use for reflection. - * - * This is the point from which everything starts.
- * 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 -[[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().hash(), internal::resolve(context)); - return meta_factory{ctx}; -} - -/** - * @brief Utility function to use for reflection. - * - * This is the point from which everything starts.
- * 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 -[[nodiscard]] auto meta() noexcept { - return meta(locator::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.
- * 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.
- * 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::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 -void meta_reset(meta_ctx &ctx) noexcept { - internal::meta_context::from(ctx).value.erase(type_id().hash()); -} - -/** - * @brief Resets a type and all its parts. - * - * @sa meta_reset - * - * @tparam Type Type to reset. - */ -template -void meta_reset() noexcept { - meta_reset(locator::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::value_or()); -} - -} // namespace entt - -#endif diff --git a/deps/include/entt/meta/fwd.hpp b/deps/include/entt/meta/fwd.hpp deleted file mode 100644 index 83be362..0000000 --- a/deps/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/include/entt/meta/meta.hpp b/deps/include/entt/meta/meta.hpp deleted file mode 100644 index 64419c1..0000000 --- a/deps/include/entt/meta/meta.hpp +++ /dev/null @@ -1,2026 +0,0 @@ -#ifndef ENTT_META_META_HPP -#define ENTT_META_META_HPP - -#include -#include -#include -#include -#include -#include -#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 - void rebind(Type &instance) noexcept { - value_type_node = &internal::resolve; - const_reference_node = &internal::resolve>>; - size_fn = meta_sequence_container_traits>::size; - clear_fn = meta_sequence_container_traits>::clear; - reserve_fn = meta_sequence_container_traits>::reserve; - resize_fn = meta_sequence_container_traits>::resize; - begin_fn = meta_sequence_container_traits>::begin; - end_fn = meta_sequence_container_traits>::end; - insert_fn = meta_sequence_container_traits>::insert; - erase_fn = meta_sequence_container_traits>::erase; - const_only = std::is_const_v; - 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::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 - void rebind(Type &instance) noexcept { - key_type_node = &internal::resolve; - value_type_node = &internal::resolve; - - if constexpr(!meta_associative_container_traits>::key_only) { - mapped_type_node = &internal::resolve; - } - - size_fn = &meta_associative_container_traits>::size; - clear_fn = &meta_associative_container_traits>::clear; - reserve_fn = &meta_associative_container_traits>::reserve; - begin_fn = &meta_associative_container_traits>::begin; - end_fn = &meta_associative_container_traits>::end; - insert_fn = &meta_associative_container_traits>::insert; - erase_fn = &meta_associative_container_traits>::erase; - find_fn = &meta_associative_container_traits>::find; - const_only = std::is_const_v; - 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::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 - static std::enable_if_t>, 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) { - if(req == internal::meta_traits::is_meta_pointer_like) { - if constexpr(std::is_function_v::element_type>) { - static_cast(other)->emplace(*static_cast(value)); - } else if constexpr(!std::is_void_v::element_type>>) { - using in_place_type = decltype(adl_meta_pointer_like::dereference(*static_cast(value))); - - if constexpr(std::is_constructible_v) { - if(const auto &pointer_like = *static_cast(value); pointer_like) { - static_cast(other)->emplace(adl_meta_pointer_like::dereference(pointer_like)); - } - } else { - static_cast(other)->emplace(adl_meta_pointer_like::dereference(*static_cast(value))); - } - } - } - } - - if constexpr(is_complete_v>) { - if(req == internal::meta_traits::is_meta_sequence_container) { - const_only ? static_cast(other)->rebind(*static_cast(value)) : static_cast(other)->rebind(*static_cast(const_cast(value))); - } - } - - if constexpr(is_complete_v>) { - if(req == internal::meta_traits::is_meta_associative_container) { - const_only ? static_cast(other)->rebind(*static_cast(value)) : static_cast(other)->rebind(*static_cast(const_cast(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} {} - -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 - explicit meta_any(std::in_place_type_t, Args &&...args) - : meta_any{locator::value_or(), std::in_place_type, std::forward(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 - explicit meta_any(const meta_ctx &area, std::in_place_type_t, Args &&...args) - : storage{std::in_place_type, std::forward(args)...}, - ctx{&area}, - node{internal::resolve>>(internal::meta_context::from(*ctx))}, - vtable{&basic_vtable>>} {} - - /** - * @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, meta_any>>> - meta_any(Type &&value) - : meta_any{locator::value_or(), std::forward(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, meta_any>>> - meta_any(const meta_ctx &area, Type &&value) - : meta_any{area, std::in_place_type>, std::forward(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)} {} - - /** - * @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)} {} - - /*! @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); - 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, meta_any>>> - meta_any &operator=(Type &&value) { - emplace>(std::forward(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 - meta_any invoke(const id_type id, Args &&...args) const; - - /*! @copydoc invoke */ - template - 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 - 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 - [[nodiscard]] const Type *try_cast() const { - const auto other = internal::resolve>(internal::meta_context::from(*ctx)); - return static_cast(internal::try_cast(internal::meta_context::from(*ctx), node, other, data())); - } - - /*! @copydoc try_cast */ - template - [[nodiscard]] Type *try_cast() { - if constexpr(std::is_const_v) { - return std::as_const(*this).try_cast>(); - } else { - const auto other = internal::resolve>(internal::meta_context::from(*ctx)); - return static_cast(const_cast(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 - [[nodiscard]] Type cast() const { - auto *const instance = try_cast>(); - ENTT_ASSERT(instance, "Invalid instance"); - return static_cast(*instance); - } - - /*! @copydoc cast */ - template - [[nodiscard]] Type cast() { - // forces const on non-reference types to make them work also with wrappers for const references - auto *const instance = try_cast>(); - ENTT_ASSERT(instance, "Invalid instance"); - return static_cast(*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 - [[nodiscard]] meta_any allow_cast() const { - if constexpr(std::is_reference_v && !std::is_const_v>) { - return meta_any{meta_ctx_arg, *ctx}; - } else { - auto other = internal::resolve>>(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 - [[nodiscard]] bool allow_cast() { - auto other = internal::resolve>>(internal::meta_context::from(*ctx)); - return allow_cast(meta_type{*ctx, other}) && (!(std::is_reference_v && !std::is_const_v>) || storage.data() != nullptr); - } - - /*! @copydoc any::emplace */ - template - void emplace(Args &&...args) { - release(); - storage.emplace(std::forward(args)...); - node = internal::resolve>>(internal::meta_context::from(*ctx)); - vtable = &basic_vtable>>; - } - - /*! @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; - } - - /** - * @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::value_or()}; - internal::meta_type_node node{}; - vtable_type *vtable{&basic_vtable}; -}; - -/** - * @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 -[[nodiscard]] meta_any forward_as_meta(const meta_ctx &ctx, Type &&value) { - return meta_any{ctx, std::in_place_type, std::forward(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 -[[nodiscard]] meta_any forward_as_meta(Type &&value) { - return forward_as_meta(locator::value_or(), std::forward(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, meta_handle>>> - meta_handle(const meta_ctx &ctx, Type &value) - : any{ctx, std::in_place_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, meta_handle>>> - meta_handle(Type &value) - : meta_handle{locator::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(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::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 - [[nodiscard]] operator Type *() const noexcept { - return (type_id().hash() == node.type) ? std::static_pointer_cast(node.value).get() : nullptr; - } - - /** - * @brief Generic conversion operator. - * @tparam Type Type to which conversion is requested. - */ - template - [[nodiscard]] operator Type &() const noexcept { - ENTT_ASSERT(type_id().hash() == node.type, "Invalid type"); - return *std::static_pointer_cast(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(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(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 - // 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(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 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 - [[nodiscard]] Type traits() const noexcept { - return internal::meta_to_user_traits(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(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(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 - // NOLINTNEXTLINE(modernize-use-nodiscard) - meta_any invoke(meta_handle instance, Args &&...args) const { - std::array arguments{meta_any{*ctx, std::forward(args)}...}; - return invoke(std::move(instance), arguments.data(), sizeof...(Args)); - } - - /*! @copydoc meta_data::prop */ - [[nodiscard]] meta_range 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 - [[nodiscard]] Type traits() const noexcept { - return internal::meta_to_user_traits(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 - [[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, internal::meta_func_node>) { - if(constness && !static_cast(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, internal::meta_func_node>) { - if(static_cast(curr->traits & internal::meta_traits::is_const) != static_cast(candidate->traits & internal::meta_traits::is_const)) { - candidate = static_cast(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(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(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(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(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(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(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(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(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(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(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(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 base() const noexcept { - using range_type = meta_range; - 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 data() const noexcept { - using range_type = meta_range; - 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 func() const noexcept { - using return_type = meta_range; - 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 - [[nodiscard]] meta_any construct(Args &&...args) const { - std::array arguments{meta_any{*ctx, std::forward(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 - // NOLINTNEXTLINE(modernize-use-nodiscard) - meta_any invoke(const id_type id, meta_handle instance, Args &&...args) const { - std::array arguments{meta_any{*ctx, std::forward(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 - 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(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 prop() const noexcept { - using range_type = meta_range; - 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 - [[nodiscard]] Type traits() const noexcept { - return internal::meta_to_user_traits(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 -// NOLINTNEXTLINE(modernize-use-nodiscard) -meta_any meta_any::invoke(const id_type id, Args &&...args) const { - return type().invoke(id, *this, std::forward(args)...); -} - -template -meta_any meta_any::invoke(const id_type id, Args &&...args) { - return type().invoke(id, *this, std::forward(args)...); -} - -template -bool meta_any::set(const id_type id, Type &&value) { - return type().set(id, *this, std::forward(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>, internal::meta_type_node> || ...)) { - return (args.from_void(*ctx, nullptr, instance), ...); - } else if constexpr((std::is_same_v>, internal::meta_conv_node> || ...)) { - return (args.conv(*ctx, instance), ...); - } else if constexpr((std::is_same_v>, 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(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 - static void basic_vtable(const void *value, const std::ptrdiff_t offset, meta_any *other) { - const auto &it = *static_cast(value); - other ? other->emplace(*it) : std::advance(const_cast(it), offset); - } - -public: - using value_type = meta_any; - using pointer = input_iterator_pointer; - 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 - meta_iterator(const meta_ctx &area, It iter) noexcept - : ctx{&area}, - vtable{&basic_vtable}, - 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(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::value_or()}; - vtable_type *vtable{}; - any handle{}; -}; - -class meta_associative_container::meta_iterator final { - using vtable_type = void(const void *, std::pair *); - - template - static void basic_vtable(const void *value, std::pair *other) { - if(const auto &it = *static_cast(value); other) { - if constexpr(KeyOnly) { - other->first.emplace(*it); - } else { - other->first.emplacefirst))>(it->first); - other->second.emplacesecond))>(it->second); - } - } else { - ++const_cast(it); - } - } - -public: - using value_type = std::pair; - using pointer = input_iterator_pointer; - 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 - meta_iterator(const meta_ctx &area, std::bool_constant, It iter) noexcept - : ctx{&area}, - vtable{&basic_vtable}, - 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(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::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(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(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(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(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(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 - 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(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(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(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(data)); -} - -/*! @copydoc meta_sequence_container::reserve */ -inline bool meta_associative_container::reserve(const size_type sz) { - return !const_only && reserve_fn(const_cast(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(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(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(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(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(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/include/entt/meta/node.hpp b/deps/include/entt/meta/node.hpp deleted file mode 100644 index fc680a3..0000000 --- a/deps/include/entt/meta/node.hpp +++ /dev/null @@ -1,298 +0,0 @@ -#ifndef ENTT_META_NODE_HPP -#define ENTT_META_NODE_HPP - -#include -#include -#include -#include -#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 -[[nodiscard]] auto meta_to_user_traits(const meta_traits traits) noexcept { - static_assert(std::is_enum_v, "Invalid enum type"); - constexpr auto shift = popcount(static_cast>(meta_traits::_user_defined_traits)); - return Type{static_cast>(static_cast>(traits) >> shift)}; -} - -template -[[nodiscard]] auto user_to_meta_traits(const Type value) noexcept { - static_assert(std::is_enum_v, "Invalid enum type"); - constexpr auto shift = popcount(static_cast>(meta_traits::_user_defined_traits)); - const auto traits = static_cast>(static_cast>(value)); - ENTT_ASSERT(traits < ((~static_cast>(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 value{}; -}; - -struct meta_prop_node { - meta_type_node (*type)(const meta_context &) noexcept {}; - std::shared_ptr 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 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 next{}; - meta_custom_node custom{}; - dense_map 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 ctor{}; - dense_map base{}; - dense_map conv{}; - dense_map data{}; - dense_map func{}; - dense_map 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 details{}; -}; - -template -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(context, curr.second.type(context), id); elem) { - return elem; - } - } - } - - return static_cast*Member)>::mapped_type *>(nullptr); -} - -template -meta_type_node resolve(const meta_context &) noexcept; - -template -[[nodiscard]] auto meta_arg_node(const meta_context &context, type_list, [[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>> : 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 -[[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 -[[nodiscard]] meta_type_node resolve(const meta_context &context) noexcept { - static_assert(std::is_same_v>>, "Invalid type"); - - if(auto *elem = try_resolve(context, type_id()); elem) { - return *elem; - } - - meta_type_node node{ - &type_id(), - type_id().hash(), - (std::is_arithmetic_v ? meta_traits::is_arithmetic : meta_traits::is_none) - | (std::is_integral_v ? meta_traits::is_integral : meta_traits::is_none) - | (std::is_signed_v ? meta_traits::is_signed : meta_traits::is_none) - | (std::is_array_v ? meta_traits::is_array : meta_traits::is_none) - | (std::is_enum_v ? meta_traits::is_enum : meta_traits::is_none) - | (std::is_class_v ? meta_traits::is_class : meta_traits::is_none) - | (std::is_pointer_v ? meta_traits::is_pointer : meta_traits::is_none) - | (is_meta_pointer_like_v ? meta_traits::is_meta_pointer_like : meta_traits::is_none) - | (is_complete_v> ? meta_traits::is_meta_sequence_container : meta_traits::is_none) - | (is_complete_v> ? meta_traits::is_meta_associative_container : meta_traits::is_none), - size_of_v, - &resolve, - &resolve>>}; - - if constexpr(std::is_default_constructible_v) { - node.default_constructor = +[](const meta_ctx &ctx) { - return meta_any{ctx, std::in_place_type}; - }; - } - - if constexpr(std::is_arithmetic_v) { - node.conversion_helper = +[](void *lhs, const void *rhs) { - return lhs ? static_cast(*static_cast(lhs) = static_cast(*static_cast(rhs))) : static_cast(*static_cast(rhs)); - }; - } else if constexpr(std::is_enum_v) { - node.conversion_helper = +[](void *lhs, const void *rhs) { - return lhs ? static_cast(*static_cast(lhs) = static_cast(static_cast>(*static_cast(rhs)))) : static_cast(*static_cast(rhs)); - }; - } - - if constexpr(!std::is_void_v && !std::is_function_v) { - node.from_void = +[](const meta_ctx &ctx, void *elem, const void *celem) { - if(elem) { - return meta_any{ctx, std::in_place_type &>, *static_cast *>(elem)}; - } - - return meta_any{ctx, std::in_place_type &>, *static_cast *>(celem)}; - }; - } - - if constexpr(is_complete_v>) { - node.templ = meta_template_node{ - meta_template_traits::args_type::size, - &resolve::class_type>, - +[](const meta_context &area, const std::size_t index) noexcept { return meta_arg_node(area, typename meta_template_traits::args_type{}, index); }}; - } - - return node; -} - -} // namespace internal -/*! @endcond */ - -} // namespace entt - -#endif diff --git a/deps/include/entt/meta/pointer.hpp b/deps/include/entt/meta/pointer.hpp deleted file mode 100644 index 093ce2d..0000000 --- a/deps/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 -#include -#include "type_traits.hpp" - -namespace entt { - -/** - * @brief Makes plain pointers pointer-like types for the meta system. - * @tparam Type Element type. - */ -template -struct is_meta_pointer_like - : 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 -// NOLINTNEXTLINE(cppcoreguidelines-avoid-c-arrays, modernize-avoid-c-arrays) -struct is_meta_pointer_like - : std::false_type {}; - -/** - * @brief Makes `std::shared_ptr`s of any type pointer-like types for the meta - * system. - * @tparam Type Element type. - */ -template -struct is_meta_pointer_like> - : 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 -struct is_meta_pointer_like> - : std::true_type {}; - -} // namespace entt - -#endif diff --git a/deps/include/entt/meta/policy.hpp b/deps/include/entt/meta/policy.hpp deleted file mode 100644 index 2974b89..0000000 --- a/deps/include/entt/meta/policy.hpp +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef ENTT_META_POLICY_HPP -#define ENTT_META_POLICY_HPP - -#include - -namespace entt { - -/*! @brief Empty class type used to request the _as ref_ policy. */ -struct as_ref_t final { - /*! @cond TURN_OFF_DOXYGEN */ - template - static constexpr bool value = std::is_reference_v && !std::is_const_v>; - /*! @endcond */ -}; - -/*! @brief Empty class type used to request the _as cref_ policy. */ -struct as_cref_t final { - /*! @cond TURN_OFF_DOXYGEN */ - template - static constexpr bool value = std::is_reference_v; - /*! @endcond */ -}; - -/*! @brief Empty class type used to request the _as-is_ policy. */ -struct as_is_t final { - /*! @cond TURN_OFF_DOXYGEN */ - template - 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 - 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 -struct is_meta_policy - : std::bool_constant || std::is_same_v || std::is_same_v || std::is_same_v> {}; - -/** - * @brief Helper variable template. - * @tparam Type Type to check. - */ -template -inline constexpr bool is_meta_policy_v = is_meta_policy::value; - -} // namespace entt - -#endif diff --git a/deps/include/entt/meta/range.hpp b/deps/include/entt/meta/range.hpp deleted file mode 100644 index 96e4664..0000000 --- a/deps/include/entt/meta/range.hpp +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef ENTT_META_RANGE_HPP -#define ENTT_META_RANGE_HPP - -#include -#include -#include -#include "../core/fwd.hpp" -#include "../core/iterator.hpp" -#include "context.hpp" - -namespace entt { - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template -struct meta_range_iterator final { - using value_type = std::pair; - using pointer = input_iterator_pointer; - 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 - friend constexpr std::ptrdiff_t operator-(const meta_range_iterator &, const meta_range_iterator &) noexcept; - - template - friend constexpr bool operator==(const meta_range_iterator &, const meta_range_iterator &) noexcept; - - template - friend constexpr bool operator<(const meta_range_iterator &, const meta_range_iterator &) noexcept; - -private: - It it; - const meta_ctx *ctx; -}; - -template -[[nodiscard]] constexpr std::ptrdiff_t operator-(const meta_range_iterator &lhs, const meta_range_iterator &rhs) noexcept { - return lhs.it - rhs.it; -} - -template -[[nodiscard]] constexpr bool operator==(const meta_range_iterator &lhs, const meta_range_iterator &rhs) noexcept { - return lhs.it == rhs.it; -} - -template -[[nodiscard]] constexpr bool operator!=(const meta_range_iterator &lhs, const meta_range_iterator &rhs) noexcept { - return !(lhs == rhs); -} - -template -[[nodiscard]] constexpr bool operator<(const meta_range_iterator &lhs, const meta_range_iterator &rhs) noexcept { - return lhs.it < rhs.it; -} - -template -[[nodiscard]] constexpr bool operator>(const meta_range_iterator &lhs, const meta_range_iterator &rhs) noexcept { - return rhs < lhs; -} - -template -[[nodiscard]] constexpr bool operator<=(const meta_range_iterator &lhs, const meta_range_iterator &rhs) noexcept { - return !(lhs > rhs); -} - -template -[[nodiscard]] constexpr bool operator>=(const meta_range_iterator &lhs, const meta_range_iterator &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 -using meta_range = iterable_adaptor>; - -} // namespace entt - -#endif diff --git a/deps/include/entt/meta/resolve.hpp b/deps/include/entt/meta/resolve.hpp deleted file mode 100644 index a9f2f93..0000000 --- a/deps/include/entt/meta/resolve.hpp +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef ENTT_META_RESOLVE_HPP -#define ENTT_META_RESOLVE_HPP - -#include -#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 -[[nodiscard]] meta_type resolve(const meta_ctx &ctx) noexcept { - auto &&context = internal::meta_context::from(ctx); - return {ctx, internal::resolve>>(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 -[[nodiscard]] meta_type resolve() noexcept { - return resolve(locator::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 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 resolve() noexcept { - return resolve(locator::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::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::value_or(), info); -} - -} // namespace entt - -#endif diff --git a/deps/include/entt/meta/template.hpp b/deps/include/entt/meta/template.hpp deleted file mode 100644 index a928b06..0000000 --- a/deps/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 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 class Clazz, typename... Args> -struct meta_template_traits> { - /*! @brief Wrapped class template. */ - using class_type = meta_class_template_tag; - /*! @brief List of template arguments. */ - using args_type = type_list; -}; - -} // namespace entt - -#endif diff --git a/deps/include/entt/meta/type_traits.hpp b/deps/include/entt/meta/type_traits.hpp deleted file mode 100644 index 7164065..0000000 --- a/deps/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 -#include - -namespace entt { - -/** - * @brief Traits class template to be specialized to enable support for meta - * template information. - */ -template -struct meta_template_traits; - -/** - * @brief Traits class template to be specialized to enable support for meta - * sequence containers. - */ -template -struct meta_sequence_container_traits; - -/** - * @brief Traits class template to be specialized to enable support for meta - * associative containers. - */ -template -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 -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 -struct is_meta_pointer_like: is_meta_pointer_like {}; - -/** - * @brief Helper variable template. - * @tparam Type Potentially pointer-like type. - */ -template -inline constexpr auto is_meta_pointer_like_v = is_meta_pointer_like::value; - -} // namespace entt - -#endif diff --git a/deps/include/entt/meta/utility.hpp b/deps/include/entt/meta/utility.hpp deleted file mode 100644 index 613d894..0000000 --- a/deps/include/entt/meta/utility.hpp +++ /dev/null @@ -1,539 +0,0 @@ -#ifndef ENTT_META_UTILITY_HPP -#define ENTT_META_UTILITY_HPP - -#include -#include -#include -#include -#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 -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 -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 -struct meta_function_descriptor - : meta_function_descriptor_traits< - Ret, - std::conditional_t, type_list, type_list>, - !std::is_base_of_v, - 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 -struct meta_function_descriptor - : meta_function_descriptor_traits< - Ret, - std::conditional_t, type_list, type_list>, - !std::is_base_of_v, - 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 -struct meta_function_descriptor - : meta_function_descriptor_traits< - Ret &, - std::conditional_t, type_list<>, type_list>, - !std::is_base_of_v, - 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 -struct meta_function_descriptor - : meta_function_descriptor_traits< - Ret, - std::conditional_t< - std::is_same_v>, Type> || std::is_base_of_v>, Type>, - type_list, - type_list>, - !(std::is_same_v>, Type> || std::is_base_of_v>, Type>), - std::is_const_v> && (std::is_same_v>, Type> || std::is_base_of_v>, Type>)> {}; - -/** - * @brief Meta function descriptor. - * @tparam Type Reflected type to which the meta function is associated. - * @tparam Ret Function return type. - */ -template -struct meta_function_descriptor - : 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 -class meta_function_helper { - template - static constexpr meta_function_descriptor get_rid_of_noexcept(Ret (Class::*)(Args...) const); - - template - static constexpr meta_function_descriptor get_rid_of_noexcept(Ret (Class::*)(Args...)); - - template - static constexpr meta_function_descriptor get_rid_of_noexcept(Ret Class::*); - - template - static constexpr meta_function_descriptor get_rid_of_noexcept(Ret (*)(Args...)); - - template - static constexpr meta_function_descriptor get_rid_of_noexcept(Class); - -public: - /*! @brief The meta function descriptor of the given function. */ - using type = decltype(get_rid_of_noexcept(std::declval())); -}; - -/** - * @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 -using meta_function_helper_t = typename meta_function_helper::type; - -/** - * @brief Wraps a value depending on the given policy. - * - * This function always returns a wrapped value in the requested context.
- * 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 -[[nodiscard]] std::enable_if_t, meta_any> meta_dispatch(const meta_ctx &ctx, [[maybe_unused]] Type &&value) { - if constexpr(std::is_same_v) { - return meta_any{ctx, std::in_place_type}; - } else if constexpr(std::is_same_v) { - return meta_any{ctx, std::in_place_type, value}; - } else if constexpr(std::is_same_v) { - static_assert(std::is_lvalue_reference_v, "Invalid type"); - return meta_any{ctx, std::in_place_type &>, std::as_const(value)}; - } else { - return meta_any{ctx, std::forward(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 -[[nodiscard]] std::enable_if_t, meta_any> meta_dispatch(Type &&value) { - return meta_dispatch(locator::value_or(), std::forward(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 -[[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 -[[nodiscard]] static meta_type meta_arg(const std::size_t index) noexcept { - return meta_arg(locator::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 -[[nodiscard]] bool meta_setter([[maybe_unused]] meta_handle instance, [[maybe_unused]] meta_any value) { - if constexpr(!std::is_same_v && !std::is_same_v) { - if constexpr(std::is_member_function_pointer_v || std::is_function_v>>) { - using descriptor = meta_function_helper_t; - using data_type = type_list_element_t; - - if(auto *const clazz = instance->try_cast(); clazz && value.allow_cast()) { - std::invoke(Data, *clazz, value.cast()); - return true; - } - } else if constexpr(std::is_member_object_pointer_v) { - using data_type = std::remove_reference_t::return_type>; - - if constexpr(!std::is_array_v && !std::is_const_v) { - if(auto *const clazz = instance->try_cast(); clazz && value.allow_cast()) { - std::invoke(Data, *clazz) = value.cast(); - return true; - } - } - } else { - using data_type = std::remove_reference_t; - - if constexpr(!std::is_array_v && !std::is_const_v) { - if(value.allow_cast()) { - *Data = value.cast(); - return true; - } - } - } - } - - return false; -} - -/** - * @brief Gets the value of a given variable. - * - * @warning - * The context provided is used only for the return type.
- * 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 -[[nodiscard]] std::enable_if_t, meta_any> meta_getter(const meta_ctx &ctx, [[maybe_unused]] meta_handle instance) { - if constexpr(std::is_member_pointer_v || std::is_function_v>>) { - if constexpr(!std::is_array_v>>>) { - if constexpr(std::is_invocable_v) { - if(auto *clazz = instance->try_cast(); clazz) { - return meta_dispatch(ctx, std::invoke(Data, *clazz)); - } - } - - if constexpr(std::is_invocable_v) { - if(auto *fallback = instance->try_cast(); fallback) { - return meta_dispatch(ctx, std::invoke(Data, *fallback)); - } - } - } - - return meta_any{meta_ctx_arg, ctx}; - } else if constexpr(std::is_pointer_v) { - if constexpr(std::is_array_v>) { - return meta_any{meta_ctx_arg, ctx}; - } else { - return meta_dispatch(ctx, *Data); - } - } else { - return meta_dispatch(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 -[[nodiscard]] std::enable_if_t, meta_any> meta_getter(meta_handle instance) { - return meta_getter(locator::value_or(), std::move(instance)); -} - -/*! @cond TURN_OFF_DOXYGEN */ -namespace internal { - -template -[[nodiscard]] meta_any meta_invoke_with_args(const meta_ctx &ctx, Candidate &&candidate, Args &&...args) { - if constexpr(std::is_void_v(candidate), args...))>) { - std::invoke(std::forward(candidate), args...); - return meta_any{ctx, std::in_place_type}; - } else { - return meta_dispatch(ctx, std::invoke(std::forward(candidate), args...)); - } -} - -template -[[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) { - using descriptor = meta_function_helper_t>; - - // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) - waiting for C++20 (and std::span) - if constexpr(std::is_invocable_v, const Type &, type_list_element_t...>) { - if(const auto *const clazz = instance->try_cast(); clazz && ((args + Index)->allow_cast>() && ...)) { - return meta_invoke_with_args(ctx, std::forward(candidate), *clazz, (args + Index)->cast>()...); - } - } else if constexpr(std::is_invocable_v, Type &, type_list_element_t...>) { - if(auto *const clazz = instance->try_cast(); clazz && ((args + Index)->allow_cast>() && ...)) { - return meta_invoke_with_args(ctx, std::forward(candidate), *clazz, (args + Index)->cast>()...); - } - } else { - if(((args + Index)->allow_cast>() && ...)) { - return meta_invoke_with_args(ctx, std::forward(candidate), (args + Index)->cast>()...); - } - } - // NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic) - - return meta_any{meta_ctx_arg, ctx}; -} - -template -[[nodiscard]] meta_any meta_construct(const meta_ctx &ctx, meta_any *const args, std::index_sequence) { - // NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) - waiting for C++20 (and std::span) - if(((args + Index)->allow_cast() && ...)) { - return meta_any{ctx, std::in_place_type, (args + Index)->cast()...}; - } - // 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.
- * 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 -[[nodiscard]] std::enable_if_t, meta_any> meta_invoke(const meta_ctx &ctx, meta_handle instance, Candidate &&candidate, meta_any *const args) { - return internal::meta_invoke(ctx, std::move(instance), std::forward(candidate), args, std::make_index_sequence>::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 -[[nodiscard]] std::enable_if_t, meta_any> meta_invoke(meta_handle instance, Candidate &&candidate, meta_any *const args) { - return meta_invoke(locator::value_or(), std::move(instance), std::forward(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.
- * 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 -[[nodiscard]] std::enable_if_t, meta_any> meta_invoke(const meta_ctx &ctx, meta_handle instance, meta_any *const args) { - return internal::meta_invoke(ctx, std::move(instance), Candidate, args, std::make_index_sequence>::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 -[[nodiscard]] std::enable_if_t, meta_any> meta_invoke(meta_handle instance, meta_any *const args) { - return meta_invoke(locator::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.
- * 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 -[[nodiscard]] meta_any meta_construct(const meta_ctx &ctx, meta_any *const args) { - return internal::meta_construct(ctx, args, std::index_sequence_for{}); -} - -/** - * @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 -[[nodiscard]] meta_any meta_construct(meta_any *const args) { - return meta_construct(locator::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.
- * 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 -[[nodiscard]] meta_any meta_construct(const meta_ctx &ctx, Candidate &&candidate, meta_any *const args) { - if constexpr(meta_function_helper_t::is_static || std::is_class_v>>) { - return internal::meta_invoke(ctx, {}, std::forward(candidate), args, std::make_index_sequence>::args_type::size>{}); - } else { - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - waiting for C++20 (and std::span) - return internal::meta_invoke(ctx, *args, std::forward(candidate), args + 1u, std::make_index_sequence>::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 -[[nodiscard]] std::enable_if_t, meta_any> meta_construct(Candidate &&candidate, meta_any *const args) { - return meta_construct(locator::value_or(), std::forward(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.
- * 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 -[[nodiscard]] std::enable_if_t, meta_any> meta_construct(const meta_ctx &ctx, meta_any *const args) { - return meta_construct(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 -[[nodiscard]] std::enable_if_t, meta_any> meta_construct(meta_any *const args) { - return meta_construct(locator::value_or(), args); -} - -} // namespace entt - -#endif -- cgit