meta: iterable base types as instances of meta_type

This commit is contained in:
Michele Caini
2021-01-15 14:34:27 +01:00
parent 997dd433b3
commit 0ec755fccf
4 changed files with 53 additions and 15 deletions

View File

@@ -309,11 +309,8 @@ The meta objects that compose a meta type are accessed in the following ways:
auto base = entt::resolve<derived_type>().base("base"_hs);
```
The returned type is `meta_base` and may be invalid if there is no meta base
object associated with the given identifier.<br/>
Meta bases aren't meant to be used directly, even though they are freely
accessible. They expose only a few methods to use to know the meta type of the
base class and to convert a raw pointer between types.
The returned type is `meta_type` and may be invalid if there is no meta base
object associated with the given identifier.
All the objects thus obtained as well as the meta types can be explicitly
converted to a boolean value to check if they are valid:
@@ -325,7 +322,7 @@ if(auto func = entt::resolve<my_type>().func("member"_hs); func) {
```
Furthermore, all them are also returned by specific overloads that provide the
caller with iterable objects. As an example:
caller with iterable ranges of top-level elements. As an example:
```cpp
for(auto data = entt::resolve<my_type>().data()) {
@@ -345,11 +342,8 @@ member function in its API. Destructors are invoked implicitly by `meta_any`
behind the scenes and users have not to deal with them explicitly. Furthermore,
they have no name, cannot be searched and wouldn't have member functions to
expose anyway.<br/>
Similarly, conversion functions and base types aren't directly accessible. They
are used internally by `meta_any` and the meta objects when needed.<br/>
It wouldn't make sense to give direct access to these elements and to open the
doors to the possibility of making mistakes. On the other side, the library
already offers enough ways to use them correctly.
Similarly, conversion functions aren't directly accessible. They are used
internally by `meta_any` and the meta objects when needed.
Meta types and meta objects in general contain much more than what is said: a
plethora of functions in addition to those listed whose purposes and uses go

View File

@@ -1180,6 +1180,8 @@ class meta_type {
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;
@@ -1188,6 +1190,14 @@ public:
: node{curr}
{}
/**
* @brief Constructs an instance from a given base node.
* @param curr The base node with which to construct the instance.
*/
meta_type(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.
@@ -1366,6 +1376,23 @@ public:
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::meta_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.

View File

@@ -11,9 +11,10 @@ namespace entt {
/**
* @brief Iterable range to use to iterate all types of meta objects.
* @tparam Type Type of meta objects iterated.
* @tparam Type Type of meta objects returned.
* @tparam Node Type of meta nodes iterated.
*/
template<typename Type>
template<typename Type, typename Node = typename Type::node_type>
class meta_range {
struct range_iterator {
using difference_type = std::ptrdiff_t;
@@ -21,7 +22,7 @@ class meta_range {
using pointer = void;
using reference = value_type;
using iterator_category = std::input_iterator_tag;
using node_type = typename Type::node_type;
using node_type = Node;
range_iterator() ENTT_NOEXCEPT = default;
@@ -56,7 +57,7 @@ class meta_range {
public:
/*! @brief Node type. */
using node_type = typename Type::node_type;
using node_type = Node;
/*! @brief Input iterator type. */
using iterator = range_iterator;

View File

@@ -251,6 +251,22 @@ TEST_F(MetaType, RemoveExtent) {
ASSERT_EQ(entt::resolve<derived_t>().remove_extent(), entt::resolve<derived_t>());
}
TEST_F(MetaType, Base) {
using namespace entt::literals;
auto type = entt::resolve<derived_t>();
bool iterate = false;
for(auto curr: type.base()) {
ASSERT_EQ(curr, entt::resolve<base_t>());
iterate = true;
}
ASSERT_TRUE(iterate);
ASSERT_EQ(type.base("base"_hs), entt::resolve<base_t>());
ASSERT_FALSE(type.base("esabe"_hs));
}
TEST_F(MetaType, Ctor) {
auto type = entt::resolve<clazz_t>();
int counter{};