meta: added minimal class template support to meta_type

This commit is contained in:
Michele Caini
2021-02-09 17:18:24 +01:00
parent b90b71c8c0
commit 5e4c63736b
4 changed files with 96 additions and 11 deletions

1
TODO
View File

@@ -18,6 +18,7 @@
- ...
WIP:
* HP: meta func/ctor size -> arity
* HP: as_ref should be a qualified function, not a global one (no breaking change, ADL makes it work anyway)
* HP: merge view and view pack
* HP: invalid view auto-refresh

View File

@@ -688,8 +688,8 @@ struct meta_ctor {
/**
* @brief Returns the type of the i-th argument of a constructor.
* @param index The index of the argument of which to return the type.
* @return The type of the i-th argument of a constructor, if any.
* @param index Index of the argument of which to return the type.
* @return The type of the i-th argument of a constructor.
*/
[[nodiscard]] meta_type arg(size_type index) const ENTT_NOEXCEPT;
@@ -900,8 +900,8 @@ struct meta_func {
/**
* @brief Returns the type of the i-th argument of a member function.
* @param index The index of the argument of which to return the type.
* @return The type of the i-th argument of a member function, if any.
* @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(size_type index) const ENTT_NOEXCEPT;
@@ -1163,6 +1163,44 @@ public:
return node->is_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->template_info.is_template_specialization;
}
/**
* @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->template_info.template_arity;
}
/**
* @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 is_template_specialization() ? node->template_info.template_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(size_type index) const ENTT_NOEXCEPT {
return index < template_arity() ? node->template_info.template_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.

View File

@@ -2,6 +2,7 @@
#define ENTT_META_NODE_HPP
#include <array>
#include <cstddef>
#include <type_traits>
#include <utility>
@@ -17,6 +18,11 @@
namespace entt {
/*! @brief Utility class to disambiguate class templates. */
template<template<typename...> typename>
struct meta_class_template_tag {};
class meta_any;
class meta_type;
struct meta_handle;
@@ -96,6 +102,15 @@ struct meta_func_node {
};
struct meta_template_info {
using size_type = std::size_t;
const bool is_template_specialization;
const size_type template_arity;
meta_type_node *(* const template_type)() ENTT_NOEXCEPT;
meta_type_node *(* const template_arg)(const size_type) ENTT_NOEXCEPT;
};
struct meta_type_node {
using size_type = std::size_t;
const type_info info;
@@ -117,8 +132,9 @@ struct meta_type_node {
const bool is_pointer_like;
const bool is_sequence_container;
const bool is_associative_container;
meta_template_info template_info;
const size_type rank;
size_type(* const extent)(const size_type);
size_type(* const extent)(const size_type) ENTT_NOEXCEPT ;
meta_type_node *(* const remove_pointer)() ENTT_NOEXCEPT;
meta_type_node *(* const remove_extent)() ENTT_NOEXCEPT;
meta_ctor_node *def_ctor{nullptr};
@@ -157,15 +173,15 @@ class ENTT_API meta_node {
static_assert(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>, "Invalid type");
template<std::size_t... Index>
[[nodiscard]] static auto extent(const meta_type_node::size_type dim, std::index_sequence<Index...>) {
[[nodiscard]] static auto extent(const meta_type_node::size_type dim, std::index_sequence<Index...>) ENTT_NOEXCEPT {
meta_type_node::size_type ext{};
((ext = (dim == Index ? std::extent_v<Type, Index> : ext)), ...);
return ext;
}
[[nodiscard]] static meta_ctor_node * meta_default_constructor([[maybe_unused]] meta_type_node *type) {
[[nodiscard]] static meta_ctor_node * meta_default_constructor([[maybe_unused]] meta_type_node *type) ENTT_NOEXCEPT {
if constexpr(std::is_default_constructible_v<Type>) {
static internal::meta_ctor_node node{
static meta_ctor_node node{
type,
nullptr,
nullptr,
@@ -180,8 +196,24 @@ class ENTT_API meta_node {
}
}
template<template<typename...> typename Clazz, typename... Args>
[[nodiscard]] static meta_template_info template_info(type_identity<Clazz<Args...>>) ENTT_NOEXCEPT {
return {
true,
sizeof...(Args),
&meta_node<meta_class_template_tag<Clazz>>::resolve,
[](const std::size_t index) ENTT_NOEXCEPT {
return std::array<meta_type_node *, sizeof...(Args)>{{internal::meta_info<Args>::resolve()...}}[index];
}
};
}
[[nodiscard]] static meta_template_info template_info(...) ENTT_NOEXCEPT {
return { false, 0u, nullptr, nullptr };
}
public:
[[nodiscard]] static internal::meta_type_node * resolve() ENTT_NOEXCEPT {
[[nodiscard]] static meta_type_node * resolve() ENTT_NOEXCEPT {
static meta_type_node node{
type_id<Type>(),
{},
@@ -202,10 +234,11 @@ public:
is_meta_pointer_like_v<Type>,
has_meta_sequence_container_traits_v<Type>,
has_meta_associative_container_traits_v<Type>,
template_info(type_identity<Type>{}),
std::rank_v<Type>,
[](meta_type_node::size_type dim) { return extent(dim, std::make_index_sequence<std::rank_v<Type>>{}); },
[](meta_type_node::size_type dim) ENTT_NOEXCEPT { return extent(dim, std::make_index_sequence<std::rank_v<Type>>{}); },
&meta_node<std::remove_cv_t<std::remove_pointer_t<Type>>>::resolve,
&meta_node<std::remove_cv_t<std::remove_extent_t<Type>>>::resolve,
&meta_node<std::remove_cv_t<std::remove_reference_t<std::remove_extent_t<Type>>>>::resolve,
meta_default_constructor(&node),
meta_default_constructor(&node)
};

View File

@@ -599,3 +599,16 @@ TEST_F(MetaType, ResetAndReRegistrationAfterReset) {
ASSERT_TRUE(entt::resolve<property_t>().data("rand"_hs).prop(property_t::value));
ASSERT_TRUE(entt::resolve<property_t>().data("rand"_hs).prop(property_t::random));
}
TEST_F(MetaType, ClassTemplate) {
ASSERT_FALSE(entt::resolve<int>().is_template_specialization());
ASSERT_EQ(entt::resolve<int>().template_arity(), 0u);
ASSERT_EQ(entt::resolve<int>().template_type(), entt::meta_type{});
ASSERT_EQ(entt::resolve<int>().template_arg(0u), entt::meta_type{});
ASSERT_TRUE(entt::resolve<std::shared_ptr<int>>().is_template_specialization());
ASSERT_EQ(entt::resolve<std::shared_ptr<int>>().template_arity(), 1u);
ASSERT_EQ(entt::resolve<std::shared_ptr<int>>().template_type(), entt::resolve<entt::meta_class_template_tag<std::shared_ptr>>());
ASSERT_EQ(entt::resolve<std::shared_ptr<int>>().template_arg(0u), entt::resolve<int>());
ASSERT_EQ(entt::resolve<std::shared_ptr<int>>().template_arg(1u), entt::meta_type{});
}