Skip to content

Commit

Permalink
Merge branch 'wip' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
friflo authored Dec 2, 2024
2 parents 9457283 + f96b373 commit dd65189
Show file tree
Hide file tree
Showing 21 changed files with 500 additions and 145 deletions.
5 changes: 2 additions & 3 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,8 @@ TODO:
* refine the storage fallback mechanism for views (ie alloc?)
* don't pass reactive storage by default to callback
* runtime types support for meta for types that aren't backed by C++ types
* dtor, traits and custom should be part of meta descriptor maybe (?)
* dtor, traits and custom should be part of meta descriptor (update meta_factory tests then)
* allow attaching const values of non-Type type to meta types
* built-in no-pagination storage - no_pagination page size as limits::max
* meta_any ownership construction and from_void
* meta_factory() isn't fully tested yet
* entt::meta isn't required anymore, we can do everything with entt::meta_factory and avoid symbol duplication
* sparse_set shrink_to_fit argument for sparse array shrink policy (none, empty, deep, whatever)
50 changes: 25 additions & 25 deletions docs/md/meta.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@ identifier is required, it's likely that a user defined literal is used as
follows:

```cpp
auto factory = entt::meta<my_type>().type("reflected_type"_hs);
entt::meta_factory<my_type>{}.type("reflected_type"_hs);
```

For what it's worth, this is completely equivalent to:

```cpp
auto factory = entt::meta<my_type>().type(42u);
entt::meta_factory<my_type>{}.type(42u);
```

Obviously, human-readable identifiers are more convenient to use and highly
Expand All @@ -65,10 +65,10 @@ recommended.

Reflection always starts from actual C++ types. Users cannot reflect _imaginary_
types.<br/>
The `meta` function is where it all starts:
The `meta_factory` class is where it all starts:

```cpp
auto factory = entt::meta<my_type>();
entt::meta_factory<my_type> factory{};
```

The returned value is a _factory object_ to use to continue building the meta
Expand All @@ -79,7 +79,7 @@ runtime type identification system built-in in `EnTT`.<br/>
However, it's also possible to assign custom identifiers to meta types:

```cpp
auto factory = entt::meta<my_type>().type("reflected_type"_hs);
entt::meta_factory<my_type>{}.type("reflected_type"_hs);
```

Identifiers are used to _retrieve_ meta types at runtime by _name_ other than by
Expand All @@ -98,15 +98,15 @@ generally used to create the following:
function or an actual constructor:

```cpp
entt::meta<my_type>().ctor<int, char>().ctor<&factory>();
entt::meta_factory<my_type>{}.ctor<int, char>().ctor<&factory>();
```

Meta default constructors are implicitly generated, if possible.

* _Destructors_. Both free functions and member functions are valid destructors:

```cpp
entt::meta<my_type>().dtor<&destroy>();
entt::meta_factory<my_type>{}.dtor<&destroy>();
```

The purpose is to offer the possibility to free up resources that require
Expand All @@ -120,7 +120,7 @@ generally used to create the following:
type appear as if they were part of the type itself:

```cpp
entt::meta<my_type>()
entt::meta_factory<my_type>{}
.data<&my_type::static_variable>("static"_hs)
.data<&my_type::data_member>("member"_hs)
.data<&global_variable>("global"_hs);
Expand All @@ -133,13 +133,13 @@ generally used to create the following:
convenient to create read-only properties from a non-const data member:

```cpp
entt::meta<my_type>().data<nullptr, &my_type::data_member>("member"_hs);
entt::meta_factory<my_type>{}.data<nullptr, &my_type::data_member>("member"_hs);
```

Multiple setters are also supported by means of a `value_list` object:

```cpp
entt::meta<my_type>().data<entt::value_list<&from_int, &from_string>, &my_type::data_member>("member"_hs);
entt::meta_factory<my_type>{}.data<entt::value_list<&from_int, &from_string>, &my_type::data_member>("member"_hs);
```

* _Member functions_. Meta member functions are actual member functions of the
Expand All @@ -148,7 +148,7 @@ generally used to create the following:
were part of the type itself:

```cpp
entt::meta<my_type>()
entt::meta_factory<my_type>{}
.func<&my_type::static_function>("static"_hs)
.func<&my_type::member_function>("member"_hs)
.func<&free_function>("free"_hs);
Expand All @@ -163,7 +163,7 @@ generally used to create the following:
derived from it:

```cpp
entt::meta<derived_type>().base<base_type>();
entt::meta_factory<derived_type>{}.base<base_type>();
```

The reflection system tracks the relationship and allows for implicit casts at
Expand All @@ -174,7 +174,7 @@ generally used to create the following:
that are implicitly performed by the reflection system when required:

```cpp
entt::meta<double>().conv<int>();
entt::meta_factory<double>{}.conv<int>();
```

This is everything users need to create meta types. Refer to the inline
Expand Down Expand Up @@ -669,7 +669,7 @@ If this were to be translated into explicit registrations with the reflection
system, it would result in a long series of instructions such as the following:

```cpp
entt::meta<int>()
entt::meta_factory<int>{}
.conv<bool>()
.conv<char>()
// ...
Expand All @@ -683,7 +683,7 @@ underlying types and offers what it takes to do the same for scoped enums. It
would result in the following if it were to be done explicitly:

```cpp
entt::meta<my_enum>()
entt::meta_factory<my_enum>{}
.conv<std::underlying_type_t<my_enum>>();
```

Expand Down Expand Up @@ -776,7 +776,7 @@ There are a few alternatives available at the moment:
thus making it appear as if its type were `void`:

```cpp
entt::meta<my_type>().func<&my_type::member_function, entt::as_void_t>("member"_hs);
entt::meta_factory<my_type>{}.func<&my_type::member_function, entt::as_void_t>("member"_hs);
```

If the use with functions is obvious, perhaps less so is use with constructors
Expand All @@ -792,7 +792,7 @@ There are a few alternatives available at the moment:
the wrapper itself:

```cpp
entt::meta<my_type>().data<&my_type::data_member, entt::as_ref_t>("member"_hs);
entt::meta_factory<my_type>{}.data<&my_type::data_member, entt::as_ref_t>("member"_hs);
```

These policies work with constructors (for example, when objects are taken
Expand All @@ -819,11 +819,11 @@ between enums and classes in C++ directly in the space of the reflected types.
Exposing constant values or elements from an enum is quite simple:

```cpp
entt::meta<my_enum>()
entt::meta_factory<my_enum>{}
.data<my_enum::a_value>("a_value"_hs)
.data<my_enum::another_value>("another_value"_hs);

entt::meta<int>().data<2048>("max_int"_hs);
entt::meta_factory<int>{}.data<2048>("max_int"_hs);
```

Accessing them is trivial as well. It's a matter of doing the following, as with
Expand Down Expand Up @@ -859,7 +859,7 @@ and meta functions.
User-defined traits are set via a meta factory:

```cpp
entt::meta<my_type>().traits(my_traits::required | my_traits::hidden);
entt::meta_factory<my_type>{}.traits(my_traits::required | my_traits::hidden);
```

In the example above, `EnTT` bitmask enum support is used but any integral value
Expand All @@ -872,7 +872,7 @@ Likewise, users can also set traits on meta objects later if needed, as long as
the factory is reset to the meta object of interest:

```cpp
entt::meta<my_type>()
entt::meta_factory<my_type>{}
.data<&my_type::data_member, entt::as_ref_t>("member"_hs)
.traits(my_traits::internal);
```
Expand All @@ -893,7 +893,7 @@ correctly.
Custom arbitrary data are set via a meta factory:

```cpp
entt::meta<my_type>().custom<type_data>("name");
entt::meta_factory<my_type>{}.custom<type_data>("name");
```

The way to do this is by specifying the data type to the `custom` function and
Expand All @@ -906,7 +906,7 @@ Likewise, users can also set custom data on meta objects later if needed, as
long as the factory is reset to the meta object of interest:

```cpp
entt::meta<my_type>()
entt::meta_factory<my_type>{}
.func<&my_type::member_function>("member"_hs)
.custom<function_data>("tooltip");
```
Expand Down Expand Up @@ -976,11 +976,11 @@ If _replacing_ the default context isn't enough, `EnTT` also offers the ability
to use multiple and externally managed contexts with the runtime reflection
system.<br/>
For example, to create new meta types within a context other than the default
one, simply pass it as an argument to the `meta` call:
one, simply pass it as an argument to the `meta_factory` constructor:
```cpp
entt::meta_ctx context{};
auto factory = entt::meta<my_type>(context).type("reflected_type"_hs);
entt::meta_factory<my_type>{context}.type("reflected_type"_hs);
```

By doing so, the new meta type isn't available in the default context but is
Expand Down
3 changes: 2 additions & 1 deletion src/entt/entity/sparse_set.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,8 @@ class basic_sparse_set {

static constexpr auto max_size = static_cast<std::size_t>(traits_type::to_entity(null));

[[nodiscard]] auto policy_to_head() const noexcept {
// it could be auto but gcc complains and emits a warning due to a false positive
[[nodiscard]] std::size_t policy_to_head() const noexcept {
return static_cast<size_type>(max_size * static_cast<decltype(max_size)>(mode != deletion_policy::swap_only));
}

Expand Down
26 changes: 11 additions & 15 deletions src/entt/meta/factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,17 +119,16 @@ class basic_meta_factory {
}

public:
basic_meta_factory(const id_type id, meta_ctx &area)
basic_meta_factory(meta_ctx &area, meta_type_node node)
: ctx{&area},
parent{id},
bucket{id} {
auto &&elem = meta_context::from(*ctx).value[parent];

if(!elem.details) {
elem.details = std::make_shared<meta_type_descriptor>();
parent{node.info->hash()},
bucket{parent} {
if(!node.details) {
node.details = std::make_shared<meta_type_descriptor>();
}

details = elem.details.get();
details = node.details.get();
meta_context::from(*ctx).value.try_emplace(parent, std::move(node));
}

private:
Expand Down Expand Up @@ -172,14 +171,14 @@ class meta_factory: private internal::basic_meta_factory {
public:
/*! @brief Default constructor. */
meta_factory() noexcept
: internal::basic_meta_factory{type_id<Type>().hash(), locator<meta_ctx>::value_or()} {}
: meta_factory{locator<meta_ctx>::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<Type>().hash(), area} {}
: base_type{area, internal::resolve<Type>(internal::meta_context::from(area))} {}

/**
* @brief Assigns a custom unique identifier to a meta type.
Expand Down Expand Up @@ -515,10 +514,7 @@ class meta_factory: private internal::basic_meta_factory {
* @return A meta factory for the given type.
*/
template<typename Type>
[[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<Type>().hash(), internal::resolve<Type>(context));
[[nodiscard]] [[deprecated("use meta_factory directly instead")]] auto meta(meta_ctx &ctx) noexcept {
return meta_factory<Type>{ctx};
}

Expand All @@ -534,7 +530,7 @@ template<typename Type>
* @return A meta factory for the given type.
*/
template<typename Type>
[[nodiscard]] auto meta() noexcept {
[[nodiscard]] [[deprecated("use meta_factory directly instead")]] auto meta() noexcept {
return meta<Type>(locator<meta_ctx>::value_or());
}

Expand Down
6 changes: 3 additions & 3 deletions test/entt/meta/meta_any.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,16 @@ struct MetaAny: ::testing::Test {
void SetUp() override {
using namespace entt::literals;

entt::meta<empty>()
entt::meta_factory<empty>{}
.type("empty"_hs)
.dtor<empty::destroy>();

entt::meta<fat>()
entt::meta_factory<fat>{}
.type("fat"_hs)
.base<empty>()
.dtor<fat::destroy>();

entt::meta<clazz>()
entt::meta_factory<clazz>{}
.type("clazz"_hs)
.data<&clazz::value>("value"_hs)
.func<&clazz::member>("member"_hs)
Expand Down
8 changes: 4 additions & 4 deletions test/entt/meta/meta_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,18 @@ struct MetaBase: ::testing::Test {
void SetUp() override {
using namespace entt::literals;

entt::meta<base_1>()
entt::meta_factory<base_1>{}
.data<&base_1::value_1>("value_1"_hs);

entt::meta<base_2>()
entt::meta_factory<base_2>{}
.conv<int>()
.data<&base_2::value_2>("value_2"_hs);

entt::meta<base_3>()
entt::meta_factory<base_3>{}
.base<base_2>()
.data<&base_3::value_3>("value_3"_hs);

entt::meta<derived>()
entt::meta_factory<derived>{}
.type("derived"_hs)
.base<base_1>()
.base<base_3>()
Expand Down
20 changes: 10 additions & 10 deletions test/entt/meta/meta_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,41 +78,41 @@ class MetaContext: public ::testing::Test {
static void init_global_context() {
using namespace entt::literals;

entt::meta<int>()
entt::meta_factory<int>{}
.data<global_marker>("marker"_hs);

entt::meta<argument>()
entt::meta_factory<argument>{}
.conv<&argument::get>();

entt::meta<clazz>()
entt::meta_factory<clazz>{}
.type("foo"_hs)
.custom<int>(3)
.ctor<int>()
.data<&clazz::value>("value"_hs)
.data<&clazz::value>("rw"_hs)
.func<&clazz::func>("func"_hs);

entt::meta<template_clazz<int>>()
entt::meta_factory<template_clazz<int>>{}
.type("template"_hs);
}

void init_local_context() {
using namespace entt::literals;

entt::meta<int>(context)
entt::meta_factory<int>{context}
.data<local_marker>("marker"_hs);

entt::meta<test::empty>(context)
entt::meta_factory<test::empty>{context}
.type("quux"_hs);

entt::meta<argument>(context)
entt::meta_factory<argument>{context}
.conv<&argument::get_mul>();

entt::meta<base>(context)
entt::meta_factory<base>{context}
.data<&base::value>("char"_hs)
.func<&base::get>("get"_hs);

entt::meta<clazz>(context)
entt::meta_factory<clazz>{context}
.type("bar"_hs)
.custom<char>('c')
.base<base>()
Expand All @@ -122,7 +122,7 @@ class MetaContext: public ::testing::Test {
.data<&clazz::value>("rw"_hs)
.func<&clazz::cfunc>("func"_hs);

entt::meta<template_clazz<int, char>>(context)
entt::meta_factory<template_clazz<int, char>>{context}
.type("template"_hs);
}

Expand Down
Loading

0 comments on commit dd65189

Please sign in to comment.