Implemented shortcuts for meta-functions and meta-data
The shortcut for meta-functions allows invoking them directly from an instance of meta_type or meta_any. If the meta-function was not found or the arguments don't match its signature an invalid meta_any object is returned. The shortcut for meta-data allows getting and setting meta-data directly from an instance of meta_type of meta_any. If the meta_data was not found or getting/setting it failed and invalid meta_any object is returned. Signed-off-by: Innokentiy Alaytsev <alaitsev@gmail.com>
This commit is contained in:
committed by
Michele Caini
parent
c9f47ed89a
commit
5995adf8b6
@@ -296,6 +296,48 @@ public:
|
||||
return storage.data();
|
||||
}
|
||||
|
||||
/**
|
||||
* @copybrief invoke
|
||||
*
|
||||
* @sa invoke
|
||||
*
|
||||
* @param id identifier of function to invoke.
|
||||
* @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 meta any containing the new instance, if any.
|
||||
*/
|
||||
template<typename... Args>
|
||||
meta_any invoke(const id_type id, Args &&... args) const;
|
||||
|
||||
/**
|
||||
* @brief Sets the value of a given variable.
|
||||
*
|
||||
* It must be possible to cast the instance to the parent type of the meta
|
||||
* data. 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 identifier of the variable to set.
|
||||
* @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, Type &&value) const;
|
||||
|
||||
/**
|
||||
* @brief Gets the value of a given variable.
|
||||
*
|
||||
* It must be possible to cast the instance to the parent type of the meta
|
||||
* data. Otherwise, invoking the getter results in an undefined behavior.
|
||||
*
|
||||
* @param id identifier of the variable to get.
|
||||
* @return A meta any containing the value of the underlying variable.
|
||||
*/
|
||||
[[nodiscard]] meta_any get(const id_type id) const;
|
||||
|
||||
/**
|
||||
* @brief Tries to cast an instance to a given type.
|
||||
* @tparam Type Type to which to cast the instance.
|
||||
@@ -1305,6 +1347,80 @@ public:
|
||||
return construct(arguments.data(), sizeof...(Args));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Invokes the function with the given identifier, if possible.
|
||||
*
|
||||
* To invoke a meta function, the parameters must be such that a cast or
|
||||
* conversion to the required types is possible. Otherwise, an empty and
|
||||
* thus invalid wrapper is returned.<br/>
|
||||
* It must be possible to cast the instance to the parent type of the meta
|
||||
* function. Otherwise, invoking the underlying function results in an
|
||||
* undefined behavior.
|
||||
*
|
||||
* @param id identifier of function to invoke.
|
||||
* @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 meta any containing the returned value, if any.
|
||||
*/
|
||||
[[nodiscard]] meta_any invoke(const id_type id, meta_handle instance, meta_any * const args, const std::size_t sz) const {
|
||||
auto const f = func(id);
|
||||
return f ? f.invoke(instance, args, sz) : meta_any{};
|
||||
}
|
||||
|
||||
/**
|
||||
* @copybrief invoke
|
||||
*
|
||||
* @sa invoke
|
||||
*
|
||||
* @param id identifier of function to invoke.
|
||||
* @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 meta any containing the new instance, if any.
|
||||
*/
|
||||
template<typename... Args>
|
||||
meta_any invoke(const id_type id, meta_handle instance, Args &&... args) const {
|
||||
std::array<meta_any, sizeof...(Args)> arguments{std::forward<Args>(args)...};
|
||||
return invoke(id, instance, arguments.data(), sizeof...(Args));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the value of a given variable.
|
||||
*
|
||||
* It must be possible to cast the instance to the parent type of the meta
|
||||
* data. 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 identifier of the variable to set.
|
||||
* @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 {
|
||||
auto const d = data(id);
|
||||
return d ? d.set(std::move(instance), std::forward<Type>(value)) : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the value of a given variable.
|
||||
*
|
||||
* It must be possible to cast the instance to the parent type of the meta
|
||||
* data. Otherwise, invoking the getter results in an undefined behavior.
|
||||
*
|
||||
* @param id identifier of the variable to get.
|
||||
* @param instance An opaque instance of the underlying type.
|
||||
* @return A meta any containing the value of the underlying variable.
|
||||
*/
|
||||
[[nodiscard]] meta_any get(const id_type id, meta_handle instance) const {
|
||||
auto const d = data(id);
|
||||
return d ? d.get(std::move(instance)) : meta_any{};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns a range to use to visit top-level meta properties.
|
||||
* @return An iterable range to use to visit top-level meta properties.
|
||||
@@ -1409,6 +1525,23 @@ private:
|
||||
}
|
||||
|
||||
|
||||
template<typename... Args>
|
||||
meta_any meta_any::invoke(const id_type id, Args &&... args) const {
|
||||
return type().invoke(id, *this, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
||||
template<typename Type>
|
||||
bool meta_any::set(const id_type id, Type &&value) const {
|
||||
return type().set(id, *this, std::forward<Type>(value));
|
||||
}
|
||||
|
||||
|
||||
[[nodiscard]] inline meta_any meta_any::get(const id_type id) const {
|
||||
return type().get(id, *this);
|
||||
}
|
||||
|
||||
|
||||
[[nodiscard]] inline meta_type meta_base::parent() const ENTT_NOEXCEPT {
|
||||
return node->parent;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,17 @@
|
||||
#include <entt/meta/meta.hpp>
|
||||
#include <entt/meta/resolve.hpp>
|
||||
|
||||
|
||||
struct clazz_t {
|
||||
clazz_t() = default;
|
||||
|
||||
void member(int i) { value = i; }
|
||||
static void func() { c = 'd'; }
|
||||
|
||||
static inline char c = 'c';
|
||||
int value = 0;
|
||||
};
|
||||
|
||||
struct empty_t {
|
||||
virtual ~empty_t() = default;
|
||||
static void destroy(empty_t &) {
|
||||
@@ -46,6 +57,12 @@ struct MetaAny: ::testing::Test {
|
||||
entt::meta<double>().conv<int>();
|
||||
entt::meta<empty_t>().dtor<&empty_t::destroy>();
|
||||
entt::meta<fat_t>().base<empty_t>().dtor<&fat_t::destroy>();
|
||||
|
||||
entt::meta<clazz_t>()
|
||||
.type("clazz"_hs)
|
||||
.data<&clazz_t::value>("value"_hs)
|
||||
.func<&clazz_t::member>("member"_hs)
|
||||
.func<&clazz_t::func>("func"_hs);
|
||||
}
|
||||
|
||||
void SetUp() override {
|
||||
@@ -622,3 +639,32 @@ TEST_F(MetaAny, UnmanageableType) {
|
||||
ASSERT_TRUE(std::as_const(any).convert<unmanageable_t>());
|
||||
ASSERT_FALSE(std::as_const(any).convert<int>());
|
||||
}
|
||||
|
||||
TEST_F(MetaAny, FuncInvokeShortcut) {
|
||||
clazz_t instance;
|
||||
entt::meta_any any{std::ref(instance)};
|
||||
|
||||
ASSERT_TRUE(any.invoke("func"_hs));
|
||||
ASSERT_TRUE(any.invoke("member"_hs, 42));
|
||||
ASSERT_FALSE(any.invoke("non_existent"_hs, 42));
|
||||
|
||||
ASSERT_EQ(clazz_t::c, 'd');
|
||||
ASSERT_EQ(instance.value, 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaAny, DataAccessShortcut) {
|
||||
clazz_t instance;
|
||||
entt::meta_any any{std::ref(instance)};
|
||||
|
||||
ASSERT_TRUE(any.set("value"_hs, 42));
|
||||
|
||||
auto const value_any = any.get("value"_hs);
|
||||
|
||||
ASSERT_EQ(instance.value, 42);
|
||||
ASSERT_TRUE(value_any);
|
||||
ASSERT_TRUE(value_any.try_cast<int>());
|
||||
ASSERT_EQ(value_any.cast<int>(), 42);
|
||||
|
||||
ASSERT_FALSE(any.set("non_existent"_hs, 42));
|
||||
ASSERT_FALSE(any.get("non_existent"_hs));
|
||||
}
|
||||
|
||||
@@ -270,6 +270,9 @@ TEST_F(MetaType, Func) {
|
||||
ASSERT_TRUE(type.func("func"_hs));
|
||||
ASSERT_TRUE(type.func("member"_hs).invoke(instance));
|
||||
ASSERT_TRUE(type.func("func"_hs).invoke({}));
|
||||
|
||||
ASSERT_TRUE(type.invoke("member"_hs, instance));
|
||||
ASSERT_TRUE(type.invoke("func"_hs, {}));
|
||||
}
|
||||
|
||||
TEST_F(MetaType, Construct) {
|
||||
|
||||
Reference in New Issue
Block a user