added support for free/member functions to meta_conv
This commit is contained in:
6
TODO
6
TODO
@@ -17,14 +17,10 @@
|
||||
* add take functionality, eg registry.take(entity, other); where it takes the entity and all its components from registry and move them to other
|
||||
* add opaque input iterators to views and groups that return tuples <entity, T &...> (proxy), multi-pass guaranteed
|
||||
* add fast lane for raw iterations, extend mt doc to describe allowed add/remove with pre-allocations on fast lanes
|
||||
* review 64 bit id: user defined area + dedicated member on the registry to set it
|
||||
* early out in views using bitmasks with bloom filter like access based on modulus
|
||||
- standard each, use bitmask to speed up the whole thing and avoid accessing the pools to test for the page
|
||||
- iterator based each with a couple of iterators passed from outside (use bitmask + has)
|
||||
* stable component handle that isn't affected by reallocations
|
||||
* multi component registry::remove and some others?
|
||||
* can I use opaque connection also for the emitter?
|
||||
* built-in support for dual (or N-) buffering
|
||||
* meta: opaque references and pointers
|
||||
|
||||
TODO
|
||||
* registry::sort also for types that are part of a group (untracked items only)
|
||||
|
||||
@@ -244,8 +244,8 @@ public:
|
||||
type,
|
||||
nullptr,
|
||||
&internal::meta_info<To>::resolve,
|
||||
[](void *instance) -> meta_any {
|
||||
return static_cast<To>(*static_cast<Type *>(instance));
|
||||
[](const void *instance) -> meta_any {
|
||||
return static_cast<To>(*static_cast<const Type *>(instance));
|
||||
},
|
||||
[]() ENTT_NOEXCEPT -> meta_conv {
|
||||
return &node;
|
||||
@@ -260,12 +260,50 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assigns a meta conversion function to a meta type.
|
||||
*
|
||||
* Conversion functions can be either free functions or member
|
||||
* functions.<br/>
|
||||
* In case of free functions, they must accept a reference to an instance of
|
||||
* the parent type as an argument. Otherwise, they must accept no arguments
|
||||
* at all.
|
||||
*
|
||||
* @tparam Candidate The actual function to use for the conversion.
|
||||
* @return A meta factory for the parent type.
|
||||
*/
|
||||
template<auto Candidate>
|
||||
meta_factory conv() ENTT_NOEXCEPT {
|
||||
using conv_type = std::invoke_result_t<decltype(Candidate), Type &>;
|
||||
auto * const type = internal::meta_info<Type>::resolve();
|
||||
|
||||
static internal::meta_conv_node node{
|
||||
&internal::meta_info<Type>::template conv<conv_type>,
|
||||
type,
|
||||
nullptr,
|
||||
&internal::meta_info<conv_type>::resolve,
|
||||
[](const void *instance) -> meta_any {
|
||||
return std::invoke(Candidate, *static_cast<const Type *>(instance));
|
||||
},
|
||||
[]() ENTT_NOEXCEPT -> meta_conv {
|
||||
return &node;
|
||||
}
|
||||
};
|
||||
|
||||
node.next = type->conv;
|
||||
ENTT_ASSERT((!internal::meta_info<Type>::template conv<conv_type>));
|
||||
internal::meta_info<Type>::template conv<conv_type> = &node;
|
||||
type->conv = &node;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assigns a meta constructor to a meta type.
|
||||
*
|
||||
* Free functions can be assigned to meta types in the role of
|
||||
* constructors. All that is required is that they return an instance of the
|
||||
* underlying type.<br/>
|
||||
* Free functions can be assigned to meta types in the role of constructors.
|
||||
* All that is required is that they return an instance of the underlying
|
||||
* type.<br/>
|
||||
* From a client's point of view, nothing changes if a constructor of a meta
|
||||
* type is a built-in one or a free function.
|
||||
*
|
||||
|
||||
@@ -63,7 +63,7 @@ struct meta_conv_node {
|
||||
meta_type_node * const parent;
|
||||
meta_conv_node * next;
|
||||
meta_type_node *(* const type)() ENTT_NOEXCEPT;
|
||||
meta_any(* const conv)(void *);
|
||||
meta_any(* const conv)(const void *);
|
||||
meta_conv(* const meta)() ENTT_NOEXCEPT;
|
||||
};
|
||||
|
||||
@@ -982,7 +982,7 @@ public:
|
||||
* @param instance The instance to convert.
|
||||
* @return An opaque pointer to the instance to convert.
|
||||
*/
|
||||
meta_any convert(void *instance) const ENTT_NOEXCEPT {
|
||||
meta_any convert(const void *instance) const ENTT_NOEXCEPT {
|
||||
return node->conv(instance);
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,9 @@ struct derived_type: base_type {
|
||||
: i{value}, c{character}
|
||||
{}
|
||||
|
||||
int f() const { return i; }
|
||||
static char g(const derived_type &type) { return type.c; }
|
||||
|
||||
const int i{};
|
||||
const char c{};
|
||||
};
|
||||
@@ -144,7 +147,9 @@ struct Meta: public ::testing::Test {
|
||||
entt::reflect<derived_type>("derived"_hs, std::make_pair(properties::prop_int, 99))
|
||||
.base<base_type>()
|
||||
.ctor<const base_type &, int, char>(std::make_pair(properties::prop_bool, false))
|
||||
.ctor<&derived_factory>(std::make_pair(properties::prop_int, 42));
|
||||
.ctor<&derived_factory>(std::make_pair(properties::prop_int, 42))
|
||||
.conv<&derived_type::f>()
|
||||
.conv<&derived_type::g>();
|
||||
|
||||
entt::reflect<empty_type>("empty"_hs)
|
||||
.dtor<&empty_type::destroy>();
|
||||
@@ -849,6 +854,38 @@ TEST_F(Meta, MetaConv) {
|
||||
ASSERT_EQ(any.cast<int>(), 3);
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaConvAsFreeFunctions) {
|
||||
auto conv = entt::resolve<derived_type>().conv<int>();
|
||||
derived_type derived{derived_type{}, 42, 'c'};
|
||||
|
||||
ASSERT_TRUE(conv);
|
||||
ASSERT_NE(conv, entt::meta_conv{});
|
||||
ASSERT_EQ(conv.parent(), entt::resolve<derived_type>());
|
||||
ASSERT_EQ(conv.type(), entt::resolve<int>());
|
||||
|
||||
auto any = conv.convert(&derived);
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(any.cast<int>(), 42);
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaConvAsMemberFunctions) {
|
||||
auto conv = entt::resolve<derived_type>().conv<char>();
|
||||
derived_type derived{derived_type{}, 42, 'c'};
|
||||
|
||||
ASSERT_TRUE(conv);
|
||||
ASSERT_NE(conv, entt::meta_conv{});
|
||||
ASSERT_EQ(conv.parent(), entt::resolve<derived_type>());
|
||||
ASSERT_EQ(conv.type(), entt::resolve<char>());
|
||||
|
||||
auto any = conv.convert(&derived);
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.type(), entt::resolve<char>());
|
||||
ASSERT_EQ(any.cast<char>(), 'c');
|
||||
}
|
||||
|
||||
TEST_F(Meta, MetaCtor) {
|
||||
auto ctor = entt::resolve<derived_type>().ctor<const base_type &, int, char>();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user