|
@@ -2,9 +2,7 @@
|
|
|
#define ENTT_META_FACTORY_HPP
|
|
#define ENTT_META_FACTORY_HPP
|
|
|
|
|
|
|
|
|
|
|
|
|
-#include <array>
|
|
|
|
|
#include <cstddef>
|
|
#include <cstddef>
|
|
|
-#include <functional>
|
|
|
|
|
#include <tuple>
|
|
#include <tuple>
|
|
|
#include <type_traits>
|
|
#include <type_traits>
|
|
|
#include <utility>
|
|
#include <utility>
|
|
@@ -14,199 +12,12 @@
|
|
|
#include "../core/type_traits.hpp"
|
|
#include "../core/type_traits.hpp"
|
|
|
#include "meta.hpp"
|
|
#include "meta.hpp"
|
|
|
#include "policy.hpp"
|
|
#include "policy.hpp"
|
|
|
|
|
+#include "utility.hpp"
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace entt {
|
|
namespace entt {
|
|
|
|
|
|
|
|
|
|
|
|
|
-/**
|
|
|
|
|
- * @cond TURN_OFF_DOXYGEN
|
|
|
|
|
- * Internal details not to be documented.
|
|
|
|
|
- */
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-namespace internal {
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-template<typename, bool, bool>
|
|
|
|
|
-struct meta_function_helper;
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-template<typename Ret, typename... Args, bool Const, bool Static>
|
|
|
|
|
-struct meta_function_helper<Ret(Args...), Const, Static> {
|
|
|
|
|
- using return_type = Ret;
|
|
|
|
|
- using args_type = type_list<Args...>;
|
|
|
|
|
-
|
|
|
|
|
- static constexpr auto is_static = Static;
|
|
|
|
|
- static constexpr auto is_const = Const;
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-template<typename Type, typename Ret, typename... Args, typename Class>
|
|
|
|
|
-constexpr meta_function_helper<std::conditional_t<std::is_same_v<Type, Class>, Ret(Args...), Ret(Class &, Args...)>, true, !std::is_same_v<Type, Class>>
|
|
|
|
|
-to_meta_function_helper(Ret(Class:: *)(Args...) const);
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-template<typename Type, typename Ret, typename... Args, typename Class>
|
|
|
|
|
-constexpr meta_function_helper<std::conditional_t<std::is_same_v<Type, Class>, Ret(Args...), Ret(Class &, Args...)>, false, !std::is_same_v<Type, Class>>
|
|
|
|
|
-to_meta_function_helper(Ret(Class:: *)(Args...));
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-template<typename Type, typename Ret, typename... Args>
|
|
|
|
|
-constexpr meta_function_helper<Ret(Args...), false, true>
|
|
|
|
|
-to_meta_function_helper(Ret(*)(Args...));
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-template<typename Type>
|
|
|
|
|
-constexpr void to_meta_function_helper(...);
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-template<typename Type, typename Candidate>
|
|
|
|
|
-using meta_function_helper_t = decltype(to_meta_function_helper<Type>(std::declval<Candidate>()));
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-template<typename... Args>
|
|
|
|
|
-[[nodiscard]] static auto arg(type_list<Args...>, const std::size_t index) ENTT_NOEXCEPT {
|
|
|
|
|
- return std::array<meta_type_node *, sizeof...(Args)>{{meta_info<Args>::resolve()...}}[index];
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-template<typename Type, typename... Args, std::size_t... Index>
|
|
|
|
|
-[[nodiscard]] meta_any construct(meta_any * const args, std::index_sequence<Index...>) {
|
|
|
|
|
- if(((args+Index)->allow_cast<Args>() && ...)) {
|
|
|
|
|
- return Type{(args+Index)->cast<Args>()...};
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return {};
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-template<typename Type, auto Data>
|
|
|
|
|
-[[nodiscard]] bool setter([[maybe_unused]] meta_handle instance, [[maybe_unused]] meta_any value) {
|
|
|
|
|
- if constexpr(!std::is_same_v<decltype(Data), Type> && !std::is_same_v<decltype(Data), std::nullptr_t>) {
|
|
|
|
|
- if constexpr(std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>> || std::is_member_function_pointer_v<decltype(Data)>) {
|
|
|
|
|
- using helper_type = meta_function_helper_t<Type, decltype(Data)>;
|
|
|
|
|
- using data_type = type_list_element_t<!std::is_member_function_pointer_v<decltype(Data)>, typename helper_type::args_type>;
|
|
|
|
|
-
|
|
|
|
|
- if(auto * const clazz = instance->try_cast<Type>(); clazz) {
|
|
|
|
|
- if(value.allow_cast<data_type>()) {
|
|
|
|
|
- std::invoke(Data, *clazz, value.cast<data_type>());
|
|
|
|
|
- return true;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- } else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
|
|
|
|
|
- using data_type = std::remove_reference_t<decltype(std::declval<Type>().*Data)>;
|
|
|
|
|
-
|
|
|
|
|
- if constexpr(!std::is_array_v<data_type> && !std::is_const_v<data_type>) {
|
|
|
|
|
- if(auto * const clazz = instance->try_cast<Type>(); clazz) {
|
|
|
|
|
- if(value.allow_cast<data_type>()) {
|
|
|
|
|
- std::invoke(Data, clazz) = value.cast<data_type>();
|
|
|
|
|
- return true;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- using data_type = std::remove_reference_t<decltype(*Data)>;
|
|
|
|
|
-
|
|
|
|
|
- if constexpr(!std::is_array_v<data_type> && !std::is_const_v<data_type>) {
|
|
|
|
|
- if(value.allow_cast<data_type>()) {
|
|
|
|
|
- *Data = value.cast<data_type>();
|
|
|
|
|
- return true;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return false;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-template<typename Type, auto Data, typename Policy>
|
|
|
|
|
-[[nodiscard]] meta_any getter([[maybe_unused]] meta_handle instance) {
|
|
|
|
|
- [[maybe_unused]] auto dispatch = [](auto &&value) {
|
|
|
|
|
- if constexpr(std::is_same_v<Policy, as_void_t>) {
|
|
|
|
|
- return meta_any{std::in_place_type<void>, std::forward<decltype(value)>(value)};
|
|
|
|
|
- } else if constexpr(std::is_same_v<Policy, as_ref_t>) {
|
|
|
|
|
- return meta_any{std::reference_wrapper{std::forward<decltype(value)>(value)}};
|
|
|
|
|
- } else if constexpr(std::is_same_v<Policy, as_cref_t>) {
|
|
|
|
|
- return meta_any{std::cref(std::forward<decltype(value)>(value))};
|
|
|
|
|
- } else {
|
|
|
|
|
- static_assert(std::is_same_v<Policy, as_is_t>, "Policy not supported");
|
|
|
|
|
- return meta_any{std::forward<decltype(value)>(value)};
|
|
|
|
|
- }
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- if constexpr(std::is_function_v<std::remove_reference_t<std::remove_pointer_t<decltype(Data)>>> || std::is_member_function_pointer_v<decltype(Data)>) {
|
|
|
|
|
- auto * const clazz = instance->try_cast<std::conditional_t<std::is_invocable_v<decltype(Data), const Type &>, const Type, Type>>();
|
|
|
|
|
- return clazz ? dispatch(std::invoke(Data, *clazz)) : meta_any{};
|
|
|
|
|
- } else if constexpr(std::is_member_object_pointer_v<decltype(Data)>) {
|
|
|
|
|
- if constexpr(std::is_array_v<std::remove_cv_t<std::remove_reference_t<decltype(std::declval<Type>().*Data)>>>) {
|
|
|
|
|
- return meta_any{};
|
|
|
|
|
- } else {
|
|
|
|
|
- if(auto * clazz = instance->try_cast<Type>(); clazz) {
|
|
|
|
|
- return dispatch(std::invoke(Data, *clazz));
|
|
|
|
|
- } else {
|
|
|
|
|
- auto * fallback = instance->try_cast<const Type>();
|
|
|
|
|
- return fallback ? dispatch(std::invoke(Data, *fallback)) : meta_any{};
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- } else if constexpr(std::is_pointer_v<decltype(Data)>) {
|
|
|
|
|
- if constexpr(std::is_array_v<std::remove_pointer_t<decltype(Data)>>) {
|
|
|
|
|
- return meta_any{};
|
|
|
|
|
- } else {
|
|
|
|
|
- return dispatch(*Data);
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- return dispatch(Data);
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-template<typename Type, auto Candidate, typename Policy, std::size_t... Index>
|
|
|
|
|
-[[nodiscard]] meta_any invoke([[maybe_unused]] meta_handle instance, meta_any *args, std::index_sequence<Index...>) {
|
|
|
|
|
- using helper_type = meta_function_helper_t<Type, decltype(Candidate)>;
|
|
|
|
|
-
|
|
|
|
|
- auto dispatch = [](auto &&... params) {
|
|
|
|
|
- if constexpr(std::is_void_v<std::remove_cv_t<typename helper_type::return_type>> || std::is_same_v<Policy, as_void_t>) {
|
|
|
|
|
- std::invoke(Candidate, std::forward<decltype(params)>(params)...);
|
|
|
|
|
- return meta_any{std::in_place_type<void>};
|
|
|
|
|
- } else if constexpr(std::is_same_v<Policy, as_ref_t>) {
|
|
|
|
|
- return meta_any{std::reference_wrapper{std::invoke(Candidate, std::forward<decltype(params)>(params)...)}};
|
|
|
|
|
- } else if constexpr(std::is_same_v<Policy, as_cref_t>) {
|
|
|
|
|
- return meta_any{std::cref(std::invoke(Candidate, std::forward<decltype(params)>(params)...))};
|
|
|
|
|
- } else {
|
|
|
|
|
- static_assert(std::is_same_v<Policy, as_is_t>, "Policy not supported");
|
|
|
|
|
- return meta_any{std::invoke(Candidate, std::forward<decltype(params)>(params)...)};
|
|
|
|
|
- }
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- if constexpr(std::is_invocable_v<decltype(Candidate), const Type &, type_list_element_t<Index, typename helper_type::args_type>...>) {
|
|
|
|
|
- if(const auto * const clazz = instance->try_cast<const Type>(); clazz && ((args+Index)->allow_cast<type_list_element_t<Index, typename helper_type::args_type>>() && ...)) {
|
|
|
|
|
- return dispatch(*clazz, (args+Index)->cast<type_list_element_t<Index, typename helper_type::args_type>>()...);
|
|
|
|
|
- }
|
|
|
|
|
- } else if constexpr(std::is_invocable_v<decltype(Candidate), Type &, type_list_element_t<Index, typename helper_type::args_type>...>) {
|
|
|
|
|
- if(auto * const clazz = instance->try_cast<Type>(); clazz && ((args+Index)->allow_cast<type_list_element_t<Index, typename helper_type::args_type>>() && ...)) {
|
|
|
|
|
- return dispatch(*clazz, (args+Index)->cast<type_list_element_t<Index, typename helper_type::args_type>>()...);
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- if(((args+Index)->allow_cast<type_list_element_t<Index, typename helper_type::args_type>>() && ...)) {
|
|
|
|
|
- return dispatch((args+Index)->cast<type_list_element_t<Index, typename helper_type::args_type>>()...);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- return meta_any{};
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-/**
|
|
|
|
|
- * Internal details not to be documented.
|
|
|
|
|
- * @endcond
|
|
|
|
|
- */
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
/**
|
|
/**
|
|
|
* @brief Meta factory to be used for reflection purposes.
|
|
* @brief Meta factory to be used for reflection purposes.
|
|
|
*
|
|
*
|
|
@@ -477,20 +288,20 @@ public:
|
|
|
*/
|
|
*/
|
|
|
template<auto Candidate, typename Policy = as_is_t>
|
|
template<auto Candidate, typename Policy = as_is_t>
|
|
|
auto ctor() ENTT_NOEXCEPT {
|
|
auto ctor() ENTT_NOEXCEPT {
|
|
|
- using helper_type = internal::meta_function_helper_t<Type, decltype(Candidate)>;
|
|
|
|
|
- static_assert(std::is_same_v<std::remove_cv_t<std::remove_reference_t<typename helper_type::return_type>>, Type>, "The function doesn't return an object of the required type");
|
|
|
|
|
|
|
+ using descriptor = meta_function_helper_t<Type, decltype(Candidate)>;
|
|
|
|
|
+ static_assert(std::is_same_v<std::remove_cv_t<std::remove_reference_t<typename descriptor::return_type>>, Type>, "The function doesn't return an object of the required type");
|
|
|
auto * const type = internal::meta_info<Type>::resolve();
|
|
auto * const type = internal::meta_info<Type>::resolve();
|
|
|
|
|
|
|
|
static internal::meta_ctor_node node{
|
|
static internal::meta_ctor_node node{
|
|
|
type,
|
|
type,
|
|
|
nullptr,
|
|
nullptr,
|
|
|
nullptr,
|
|
nullptr,
|
|
|
- helper_type::args_type::size,
|
|
|
|
|
|
|
+ descriptor::args_type::size,
|
|
|
[](const typename internal::meta_ctor_node::size_type index) ENTT_NOEXCEPT {
|
|
[](const typename internal::meta_ctor_node::size_type index) ENTT_NOEXCEPT {
|
|
|
- return internal::arg(typename helper_type::args_type{}, index);
|
|
|
|
|
|
|
+ return meta_arg(typename descriptor::args_type{}, index);
|
|
|
},
|
|
},
|
|
|
[](meta_any * const any) {
|
|
[](meta_any * const any) {
|
|
|
- return internal::invoke<Type, Candidate, Policy>({}, any, std::make_index_sequence<helper_type::args_type::size>{});
|
|
|
|
|
|
|
+ return meta_invoke<Type, Candidate, Policy>({}, any, std::make_index_sequence<descriptor::args_type::size>{});
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -513,19 +324,19 @@ public:
|
|
|
*/
|
|
*/
|
|
|
template<typename... Args>
|
|
template<typename... Args>
|
|
|
auto ctor() ENTT_NOEXCEPT {
|
|
auto ctor() ENTT_NOEXCEPT {
|
|
|
- using helper_type = internal::meta_function_helper_t<Type, Type(*)(Args...)>;
|
|
|
|
|
|
|
+ using descriptor = meta_function_helper_t<Type, Type(*)(Args...)>;
|
|
|
auto * const type = internal::meta_info<Type>::resolve();
|
|
auto * const type = internal::meta_info<Type>::resolve();
|
|
|
|
|
|
|
|
static internal::meta_ctor_node node{
|
|
static internal::meta_ctor_node node{
|
|
|
type,
|
|
type,
|
|
|
nullptr,
|
|
nullptr,
|
|
|
nullptr,
|
|
nullptr,
|
|
|
- helper_type::args_type::size,
|
|
|
|
|
|
|
+ descriptor::args_type::size,
|
|
|
[](const typename internal::meta_ctor_node::size_type index) ENTT_NOEXCEPT {
|
|
[](const typename internal::meta_ctor_node::size_type index) ENTT_NOEXCEPT {
|
|
|
- return internal::arg(typename helper_type::args_type{}, index);
|
|
|
|
|
|
|
+ return meta_arg(typename descriptor::args_type{}, index);
|
|
|
},
|
|
},
|
|
|
[](meta_any * const any) {
|
|
[](meta_any * const any) {
|
|
|
- return internal::construct<Type, Args...>(any, std::make_index_sequence<helper_type::args_type::size>{});
|
|
|
|
|
|
|
+ return meta_construct<Type, Args...>(any, std::make_index_sequence<descriptor::args_type::size>{});
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
@@ -597,8 +408,8 @@ public:
|
|
|
std::is_same_v<Type, data_type> || std::is_const_v<data_type>,
|
|
std::is_same_v<Type, data_type> || std::is_const_v<data_type>,
|
|
|
true,
|
|
true,
|
|
|
&internal::meta_info<data_type>::resolve,
|
|
&internal::meta_info<data_type>::resolve,
|
|
|
- &internal::setter<Type, Data>,
|
|
|
|
|
- &internal::getter<Type, Data, Policy>
|
|
|
|
|
|
|
+ &meta_setter<Type, Data>,
|
|
|
|
|
+ &meta_getter<Type, Data, Policy>
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
ENTT_ASSERT(!exists(id, type->data));
|
|
ENTT_ASSERT(!exists(id, type->data));
|
|
@@ -644,8 +455,8 @@ public:
|
|
|
std::is_same_v<decltype(Setter), std::nullptr_t> || (std::is_member_object_pointer_v<decltype(Setter)> && std::is_const_v<underlying_type>),
|
|
std::is_same_v<decltype(Setter), std::nullptr_t> || (std::is_member_object_pointer_v<decltype(Setter)> && std::is_const_v<underlying_type>),
|
|
|
false,
|
|
false,
|
|
|
&internal::meta_info<underlying_type>::resolve,
|
|
&internal::meta_info<underlying_type>::resolve,
|
|
|
- &internal::setter<Type, Setter>,
|
|
|
|
|
- &internal::getter<Type, Getter, Policy>
|
|
|
|
|
|
|
+ &meta_setter<Type, Setter>,
|
|
|
|
|
+ &meta_getter<Type, Getter, Policy>
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
ENTT_ASSERT(!exists(id, type->data));
|
|
ENTT_ASSERT(!exists(id, type->data));
|
|
@@ -672,7 +483,7 @@ public:
|
|
|
*/
|
|
*/
|
|
|
template<auto Candidate, typename Policy = as_is_t>
|
|
template<auto Candidate, typename Policy = as_is_t>
|
|
|
auto func(const id_type id) ENTT_NOEXCEPT {
|
|
auto func(const id_type id) ENTT_NOEXCEPT {
|
|
|
- using helper_type = internal::meta_function_helper_t<Type, decltype(Candidate)>;
|
|
|
|
|
|
|
+ using descriptor = meta_function_helper_t<Type, decltype(Candidate)>;
|
|
|
auto * const type = internal::meta_info<Type>::resolve();
|
|
auto * const type = internal::meta_info<Type>::resolve();
|
|
|
|
|
|
|
|
static internal::meta_func_node node{
|
|
static internal::meta_func_node node{
|
|
@@ -680,15 +491,15 @@ public:
|
|
|
type,
|
|
type,
|
|
|
nullptr,
|
|
nullptr,
|
|
|
nullptr,
|
|
nullptr,
|
|
|
- helper_type::args_type::size,
|
|
|
|
|
- helper_type::is_const,
|
|
|
|
|
- helper_type::is_static,
|
|
|
|
|
- &internal::meta_info<std::conditional_t<std::is_same_v<Policy, as_void_t>, void, typename helper_type::return_type>>::resolve,
|
|
|
|
|
|
|
+ descriptor::args_type::size,
|
|
|
|
|
+ descriptor::is_const,
|
|
|
|
|
+ descriptor::is_static,
|
|
|
|
|
+ &internal::meta_info<std::conditional_t<std::is_same_v<Policy, as_void_t>, void, typename descriptor::return_type>>::resolve,
|
|
|
[](const typename internal::meta_func_node::size_type index) ENTT_NOEXCEPT {
|
|
[](const typename internal::meta_func_node::size_type index) ENTT_NOEXCEPT {
|
|
|
- return internal::arg(typename helper_type::args_type{}, index);
|
|
|
|
|
|
|
+ return meta_arg(typename descriptor::args_type{}, index);
|
|
|
},
|
|
},
|
|
|
[](meta_handle instance, meta_any *args) {
|
|
[](meta_handle instance, meta_any *args) {
|
|
|
- return internal::invoke<Type, Candidate, Policy>(std::move(instance), args, std::make_index_sequence<helper_type::args_type::size>{});
|
|
|
|
|
|
|
+ return meta_invoke<Type, Candidate, Policy>(std::move(instance), args, std::make_index_sequence<descriptor::args_type::size>{});
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|