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 use to visit top-level base meta types.
base overloadReturns the base meta type associated with a given identifier.
construct overloadCreates an instance of the underlying type, if possible.
ctor overloadReturns a range to use to visit top-level constructors.
ctor overloadReturns a constructor for a given list of types of arguments.
data overloadReturns a range to use to visit top-level data.
data overloadReturns the data associated with a given identifier.
extentThe number of elements along the given dimension of an array type.
func overloadReturns a range to use to visit top-level functions.
func overloadReturns the function associated with a given identifier.
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_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_floating_pointChecks whether a type refers to a floating-point type or not.
is_function_pointerChecks whether a type refers to a function pointer or not.
is_integralChecks whether a type refers to an integral type or not.
is_member_function_pointerChecks whether a type refers to a pointer to member function or not.
is_member_object_pointerChecks whether a type refers to a pointer to data member 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.
is_unionChecks whether a type refers to an union 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 use to visit top-level properties.
prop overloadReturns the property associated with a given key.
rankProvides the number of dimensions of an array type.
remove_extentProvides the type for which the array is defined.
remove_pointerProvides the type for which the pointer is defined.
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, if any.
template_typeReturns a tag for the class template of the underlying type.

Source

Lines 1024-1535 in src/entt/meta/meta.hpp.

class meta_type {
    [[nodiscard]] static bool can_cast_or_convert(const internal::meta_type_node *type, const type_info info) ENTT_NOEXCEPT {
        if(type->info == info) {
            return true;
        }

        for(const auto *curr = type->conv; curr; curr = curr->next) {
            if(curr->type->info == info) {
                return true;
            }
        }

        for(const auto *curr = type->base; curr; curr = curr->next) {
            if(can_cast_or_convert(curr->type, info)) {
                return true;
            }
        }

        return false;
    }

    template<typename... Args, auto... Index>
    [[nodiscard]] static const internal::meta_ctor_node * ctor(const internal::meta_ctor_node *curr, std::index_sequence<Index...>) {
        for(; curr; curr = curr->next) {
            if(curr->arity == sizeof...(Args) && (can_cast_or_convert(internal::meta_info<Args>::resolve(), curr->arg(Index).info()) && ...)) {
                return curr;
            }
        }

        return nullptr;
    }

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]] 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 integral type or not.
     * @return True if the underlying type is an integral type, false otherwise.
     */
    [[nodiscard]] bool is_integral() const ENTT_NOEXCEPT {
        return (node->traits & internal::meta_trait::IS_INTEGRAL);
    }

    /**
     * @brief Checks whether a type refers to a floating-point type or not.
     * @return True if the underlying type is a floating-point type, false
     * otherwise.
     */
    [[nodiscard]] bool is_floating_point() const ENTT_NOEXCEPT {
        return (node->traits & internal::meta_trait::IS_FLOATING_POINT);
    }

    /**
     * @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_trait::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_trait::IS_ENUM);
    }

    /**
     * @brief Checks whether a type refers to an union or not.
     * @return True if the underlying type is an union, false otherwise.
     */
    [[nodiscard]] bool is_union() const ENTT_NOEXCEPT {
        return (node->traits & internal::meta_trait::IS_UNION);
    }

    /**
     * @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_trait::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_trait::IS_POINTER);
    }

    /**
     * @brief Checks whether a type refers to a function pointer or not.
     * @return True if the underlying type is a function pointer, false
     * otherwise.
     */
    [[nodiscard]] bool is_function_pointer() const ENTT_NOEXCEPT {
        return (node->traits & internal::meta_trait::IS_FUNCTION_POINTER);
    }

    /**
     * @brief Checks whether a type refers to a pointer to data member or not.
     * @return True if the underlying type is a pointer to data member, false
     * otherwise.
     */
    [[nodiscard]] bool is_member_object_pointer() const ENTT_NOEXCEPT {
        return (node->traits & internal::meta_trait::IS_MEMBER_OBJECT_POINTER);
    }

    /**
     * @brief Checks whether a type refers to a pointer to member function or
     * not.
     * @return True if the underlying type is a pointer to member function,
     * false otherwise.
     */
    [[nodiscard]] bool is_member_function_pointer() const ENTT_NOEXCEPT {
        return (node->traits & internal::meta_trait::IS_MEMBER_FUNCTION_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_trait::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_trait::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_trait::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, if any.
     * @return The number of template arguments, if any.
     */
    [[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 Provides the number of dimensions of an array type.
     * @return The number of dimensions in case of array types, 0 otherwise.
     */
    [[nodiscard]] size_type rank() const ENTT_NOEXCEPT {
        return node->rank;
    }

    /**
     * @brief The number of elements along the given dimension of an array type.
     * @param dim The dimension of which to return the number of elements.
     * @return The number of elements along the given dimension in case of array
     * types, 0 otherwise.
     */
    [[nodiscard]] size_type extent(const size_type dim = {}) const ENTT_NOEXCEPT {
        return node->extent(dim);
    }

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

    /**
     * @brief Provides the type for which the array is defined.
     * @return The type for which the array is defined or this type if it
     * doesn't refer to an array type.
     */
    [[nodiscard]] meta_type remove_extent() const ENTT_NOEXCEPT {
        return node->remove_extent();
    }

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

    /**
     * @brief Returns the base meta type associated with a given identifier.
     * @param id Unique identifier.
     * @return The base meta type associated with the given identifier, if any.
     */
    [[nodiscard]] meta_type base(const id_type id) const {
        return internal::visit<&node_type::base>([id](const auto *curr) { return curr->type->id == id; }, node);
    }

    /**
     * @brief Returns a range to use to visit top-level constructors.
     * @return An iterable range to use to visit top-level constructors.
     */
    [[nodiscard]] meta_range<meta_ctor> ctor() const ENTT_NOEXCEPT {
        return node->ctor;
    }

    /**
     * @brief Returns a constructor for a given list of types of arguments.
     * @tparam Args Constructor arguments.
     * @return The requested constructor, if any.
     */
    template<typename... Args>
    [[nodiscard]] meta_ctor ctor() const {
        return ctor<Args...>(node->ctor, std::make_index_sequence<sizeof...(Args)>{});
    }

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

    /**
     * @brief Returns the data associated with a given identifier.
     *
     * The data of the base classes will also be visited, if any.
     *
     * @param id Unique identifier.
     * @return The data associated with the given identifier, if any.
     */
    [[nodiscard]] meta_data data(const id_type id) const {
        return internal::visit<&node_type::data>([id](const auto *curr) { return curr->id == id; }, node);
    }

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

    /**
     * @brief Returns the function associated with a given identifier.
     *
     * The functions of the base classes will also be visited, if any.<br/>
     * In the case of overloaded functions, the first one with the required
     * identifier will be returned.
     *
     * @param id Unique identifier.
     * @return The function associated with the given identifier, if any.
     */
    [[nodiscard]] meta_func func(const id_type id) const {
        return internal::visit<&node_type::func>([id](const auto *curr) { return curr->id == id; }, node);
    }

    /**
     * @brief Creates an instance of the underlying type, if possible.
     *
     * Parameters must be such that a cast or conversion to the required types
     * is possible. Otherwise, an empty and thus invalid wrapper is returned.
     *
     * @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 {
        for(auto *curr = node->ctor; curr; curr = curr->next) {
            if(curr->arity == sz) {
                if(auto ret = curr->invoke(args); ret) {
                    return ret;
                }
            }
        }

        return {};
    }

    /**
     * @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. Otherwise, invoking the underlying function results in an
     * undefined behavior.
     *
     * @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 internal::meta_func_node* candidate{};
        size_type extent{sz + 1u};
        bool ambiguous{};

        for(auto *it = internal::visit<&node_type::func>([id, sz](const auto *curr) { return curr->id == id && curr->arity == sz; }, node); it && it->id == id && it->arity == sz; it = it->next) {
            size_type direct{};
            size_type ext{};

            for(size_type next{}; next < sz && next == (direct + ext); ++next) {
                const auto type = args[next].type();
                const auto req = it->arg(next).info();
                type.info() == req ? ++direct : (ext += can_cast_or_convert(type.node, req));
            }

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

        return (candidate && !ambiguous) ? 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. Otherwise, invoking the setter results in an undefined
     * behavior.<br/>
     * The type of the value must be 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. Otherwise, invoking the getter results in an undefined behavior.
     *
     * @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 use to visit top-level properties.
     * @return An iterable range to use to visit top-level properties.
     */
    [[nodiscard]] meta_range<meta_prop> prop() const ENTT_NOEXCEPT {
        return node->prop;
    }

    /**
     * @brief Returns the property associated with a given key.
     *
     * Properties of the base classes will also be visited, if any.
     *
     * @param key The key to use to search for a property.
     * @return The property associated with the given key, if any.
     */
    [[nodiscard]] meta_prop prop(meta_any key) const {
        return internal::visit<&internal::meta_type_node::prop>([&key](const auto *curr) { return curr->id == 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