Class meta_type

Synopsis

#include <src/entt/meta/meta.hpp>

class meta_type

Description

Opaque wrapper for types.

Mentioned in

Methods

meta_type overloadConstructs an instance from a given node.
meta_type overloadConstructs an instance from a given base node.
base overloadReturns a range to visit registered top-level base meta types.
base overloadLookup function for registered base meta types.
construct overloadCreates an instance of the underlying type, if possible.
data overloadReturns a range to visit registered top-level meta data.
data overloadLookup function for registered meta data.
func overloadReturns a range to visit registered top-level functions.
func overloadLookup function for registered meta functions.
getGets the value of a given variable.
idReturns the identifier assigned to a type.
infoReturns the type info object of the underlying type.
invoke overloadInvokes a function given an identifier, if possible.
is_arithmeticChecks whether a type refers to an arithmetic type or not.
is_arrayChecks whether a type refers to an array type or not.
is_associative_containerChecks whether a type refers to an associative container or not.
is_classChecks whether a type refers to a class or not.
is_enumChecks whether a type refers to an enum or not.
is_pointerChecks whether a type refers to a pointer or not.
is_pointer_likeChecks whether a type is a pointer-like type or not.
is_sequence_containerChecks whether a type refers to a sequence container or not.
is_template_specializationChecks whether a type refers to a recognized class template specialization or not.
operator boolReturns true if an object is valid, false otherwise.
operator==Checks if two objects refer to the same type.
prop overloadReturns a range to visit registered top-level meta properties.
prop overloadLookup function for meta properties.
setSets the value of a given variable.
size_ofReturns the size of the underlying type if known.
template_argReturns the type of the i-th template argument of a type.
template_arityReturns the number of template arguments.
template_typeReturns a tag for the class template of the underlying type.

Source

Lines 949-1341 in src/entt/meta/meta.hpp.

class meta_type {
    template<auto Member, typename Pred>
    [[nodiscard]] std::decay_t<decltype(std::declval<internal::meta_type_node>().*Member)> lookup(meta_any *const args, const typename internal::meta_type_node::size_type sz, Pred pred) const {
        std::decay_t<decltype(node->*Member)> candidate{};
        size_type extent{sz + 1u};
        bool ambiguous{};

        for(auto *curr = (node->*Member); curr; curr = curr->next) {
            if(pred(curr) && curr->arity == sz) {
                size_type direct{};
                size_type ext{};

                for(size_type next{}; next < sz && next == (direct + ext) && args[next]; ++next) {
                    const auto type = args[next].type();
                    const auto other = curr->arg(next);

                    if(const auto &info = other.info(); info == type.info()) {
                        ++direct;
                    } else {
                        ext += internal::find_by<&node_type::base>(info, type.node)
                               || internal::find_by<&node_type::conv>(info, type.node)
                               || (type.node->conversion_helper && other.node->conversion_helper);
                    }
                }

                if((direct + ext) == sz) {
                    if(ext < extent) {
                        candidate = curr;
                        extent = ext;
                        ambiguous = false;
                    } else if(ext == extent) {
                        ambiguous = true;
                    }
                }
            }
        }

        return (candidate && !ambiguous) ? candidate : decltype(candidate){};
    }

public:
    /*! @brief Node type. */
    using node_type = internal::meta_type_node;
    /*! @brief Node type. */
    using base_node_type = internal::meta_base_node;
    /*! @brief Unsigned integer type. */
    using size_type = typename node_type::size_type;

    /*! @copydoc meta_prop::meta_prop */
    meta_type(const node_type *curr = nullptr) ENTT_NOEXCEPT
        : node{curr} {}

    /**
     * @brief Constructs an instance from a given base node.
     * @param curr The base node with which to construct the instance.
     */
    meta_type(const base_node_type *curr) ENTT_NOEXCEPT
        : node{curr ? curr->type : nullptr} {}

    /**
     * @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 ENTT_NOEXCEPT {
        return *node->info;
    }

    /**
     * @brief Returns the identifier assigned to a type.
     * @return The identifier assigned to the type.
     */
    [[nodiscard]] id_type id() const ENTT_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 ENTT_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 ENTT_NOEXCEPT {
        return !!(node->traits & internal::meta_traits::is_arithmetic);
    }

    /**
     * @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 ENTT_NOEXCEPT {
        return !!(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 ENTT_NOEXCEPT {
        return !!(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 ENTT_NOEXCEPT {
        return !!(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 ENTT_NOEXCEPT {
        return !!(node->traits & internal::meta_traits::is_pointer);
    }

    /**
     * @brief Checks whether a type is a pointer-like type or not.
     * @return True if the underlying type is a pointer-like one, false
     * otherwise.
     */
    [[nodiscard]] bool is_pointer_like() const ENTT_NOEXCEPT {
        return !!(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 ENTT_NOEXCEPT {
        return !!(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 ENTT_NOEXCEPT {
        return !!(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 ENTT_NOEXCEPT {
        return (node->templ != nullptr);
    }

    /**
     * @brief Returns the number of template arguments.
     * @return The number of template arguments.
     */
    [[nodiscard]] size_type template_arity() const ENTT_NOEXCEPT {
        return node->templ ? node->templ->arity : size_type{};
    }

    /**
     * @brief Returns a tag for the class template of the underlying type.
     *
     * @sa meta_class_template_tag
     *
     * @return The tag for the class template of the underlying type.
     */
    [[nodiscard]] inline meta_type template_type() const ENTT_NOEXCEPT {
        return node->templ ? node->templ->type : 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 ENTT_NOEXCEPT {
        return index < template_arity() ? node->templ->arg(index) : meta_type{};
    }

    /**
     * @brief Returns a range to visit registered top-level base meta types.
     * @return An iterable range to visit registered top-level base meta types.
     */
    [[nodiscard]] meta_range<meta_type, internal::meta_base_node> base() const ENTT_NOEXCEPT {
        return node->base;
    }

    /**
     * @brief Lookup function for registered base meta types.
     * @param id Unique identifier.
     * @return The registered base meta type for the given identifier, if any.
     */
    [[nodiscard]] meta_type base(const id_type id) const {
        return internal::find_by<&node_type::base>(id, node);
    }

    /**
     * @brief Returns a range to visit registered top-level meta data.
     * @return An iterable range to visit registered top-level meta data.
     */
    [[nodiscard]] meta_range<meta_data> data() const ENTT_NOEXCEPT {
        return node->data;
    }

    /**
     * @brief Lookup function for registered meta data.
     *
     * Registered meta data of base classes will also be 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 {
        return internal::find_by<&node_type::data>(id, node);
    }

    /**
     * @brief Returns a range to visit registered top-level functions.
     * @return An iterable range to visit registered top-level functions.
     */
    [[nodiscard]] meta_range<meta_func> func() const ENTT_NOEXCEPT {
        return node->func;
    }

    /**
     * @brief Lookup function for registered meta functions.
     *
     * Registered meta functions of base classes will also be visited.<br/>
     * In case of overloaded functions, the first one with the required
     * identifier will be 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 {
        return internal::find_by<&node_type::func>(id, node);
    }

    /**
     * @brief Creates an instance of the underlying type, if possible.
     *
     * Parameters are such that a cast or conversion to the required types is
     * possible. Otherwise, an empty and thus invalid wrapper is returned.<br/>
     * If suitable, the implicitly generated default constructor is used.
     *
     * @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 {
        const auto *candidate = lookup<&node_type::ctor>(args, sz, [](const auto *) { return true; });
        return candidate ? candidate->invoke(args) : ((!sz && node->default_constructor) ? node->default_constructor() : meta_any{});
    }

    /**
     * @copybrief construct
     *
     * @sa construct
     *
     * @tparam Args Types of arguments to use to construct the instance.
     * @param args Parameters to use to construct the instance.
     * @return A wrapper containing the new instance, if any.
     */
    template<typename... Args>
    [[nodiscard]] meta_any construct(Args &&...args) const {
        meta_any arguments[sizeof...(Args) + 1u]{std::forward<Args>(args)...};
        return construct(arguments, sizeof...(Args));
    }

    /**
     * @brief Invokes a function given an identifier, if possible.
     *
     * It must be possible to cast the instance to the parent type of the member
     * function.
     *
     * @sa meta_func::invoke
     *
     * @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 {
        const auto *candidate = lookup<&node_type::func>(args, sz, [id](const auto *curr) { return curr->id == id; });

        for(auto it = base().begin(), last = base().end(); it != last && !candidate; ++it) {
            candidate = it->lookup<&node_type::func>(args, sz, [id](const auto *curr) { return curr->id == id; });
        }

        return candidate ? candidate->invoke(std::move(instance), args) : meta_any{};
    }

    /**
     * @copybrief invoke
     *
     * @sa 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 new instance, if any.
     */
    template<typename... Args>
    meta_any invoke(const id_type id, meta_handle instance, Args &&...args) const {
        meta_any arguments[sizeof...(Args) + 1u]{std::forward<Args>(args)...};
        return invoke(id, std::move(instance), arguments, sizeof...(Args));
    }

    /**
     * @brief Sets the value of a given variable.
     *
     * It must be possible to cast the instance to the parent type of the data
     * member.<br/>
     * The type of the value is such that a cast or conversion to the type of
     * the variable is possible. Otherwise, invoking the setter does nothing.
     *
     * @tparam Type Type of value to assign.
     * @param id Unique identifier.
     * @param instance An opaque instance of the underlying type.
     * @param value Parameter to use to set the underlying variable.
     * @return True in case of success, false otherwise.
     */
    template<typename Type>
    bool set(const id_type id, meta_handle instance, Type &&value) const {
        const auto candidate = data(id);
        return candidate && candidate.set(std::move(instance), std::forward<Type>(value));
    }

    /**
     * @brief Gets the value of a given variable.
     *
     * It must be possible to cast the instance to the parent type of the data
     * member.
     *
     * @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{};
    }

    /**
     * @brief Returns a range to visit registered top-level meta properties.
     * @return An iterable range to visit registered top-level meta properties.
     */
    [[nodiscard]] meta_range<meta_prop> prop() const ENTT_NOEXCEPT {
        return node->prop;
    }

    /**
     * @brief Lookup function for meta properties.
     *
     * Properties of base classes 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(meta_any key) const {
        return internal::find_by<&internal::meta_type_node::prop>(key, node);
    }

    /**
     * @brief Returns true if an object is valid, false otherwise.
     * @return True if the object is valid, false otherwise.
     */
    [[nodiscard]] explicit operator bool() const ENTT_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_type &other) const ENTT_NOEXCEPT {
        return (!node && !other.node) || (node && other.node && *node->info == *other.node->info);
    }

private:
    const node_type *node;
};





Add Discussion

Log in to comment