meta: small review

This commit is contained in:
Michele Caini
2020-06-09 16:36:10 +02:00
parent b836be2c84
commit c00dcd31d6
5 changed files with 320 additions and 263 deletions

View File

@@ -20,7 +20,9 @@
#include "entity/utility.hpp"
#include "entity/view.hpp"
#include "locator/locator.hpp"
#include "meta/ctx.hpp"
#include "meta/factory.hpp"
#include "meta/internal.hpp"
#include "meta/meta.hpp"
#include "meta/resolve.hpp"
#include "meta/policy.hpp"

78
src/entt/meta/ctx.hpp Normal file
View File

@@ -0,0 +1,78 @@
#ifndef ENTT_META_CTX_HPP
#define ENTT_META_CTX_HPP
#include "../core/attribute.h"
#include "../config/config.h"
#include "internal.hpp"
namespace entt {
/**
* @cond TURN_OFF_DOXYGEN
* Internal details not to be documented.
*/
namespace internal {
struct ENTT_API meta_context {
// we could use the lines below but VS2017 returns with an ICE if combined with ENTT_API despite the code being valid C++
// inline static meta_type_node *local = nullptr;
// inline static meta_type_node **global = &local;
[[nodiscard]] static meta_type_node * & local() ENTT_NOEXCEPT {
static meta_type_node *chain = nullptr;
return chain;
}
[[nodiscard]] static meta_type_node ** & global() ENTT_NOEXCEPT {
static meta_type_node **chain = &local();
return chain;
}
static void detach(const meta_type_node *node) ENTT_NOEXCEPT {
auto **it = global();
while(*it && *it != node) {
it = &(*it)->next;
}
if(*it) {
*it = (*it)->next;
}
}
};
}
/**
* Internal details not to be documented.
* @endcond TURN_OFF_DOXYGEN
*/
/*! @brief Opaque container for a meta context. */
struct meta_ctx {
/**
* @brief Binds the meta system to a given context.
* @param other A valid context to which to bind.
*/
static void bind(meta_ctx other) ENTT_NOEXCEPT {
internal::meta_context::global() = other.ctx;
}
private:
internal::meta_type_node **ctx{&internal::meta_context::local()};
};
}
#endif

View File

@@ -13,6 +13,7 @@
#include "../core/type_info.hpp"
#include "../core/type_traits.hpp"
#include "../core/utility.hpp"
#include "internal.hpp"
#include "meta.hpp"
#include "policy.hpp"

237
src/entt/meta/internal.hpp Normal file
View File

@@ -0,0 +1,237 @@
#ifndef ENTT_META_INTERNAL_HPP
#define ENTT_META_INTERNAL_HPP
#include <cstddef>
#include <type_traits>
#include "../core/attribute.h"
#include "../config/config.h"
#include "../core/fwd.hpp"
#include "../core/type_info.hpp"
#include "../core/type_traits.hpp"
namespace entt {
class meta_any;
/**
* @cond TURN_OFF_DOXYGEN
* Internal details not to be documented.
*/
namespace internal {
struct meta_type_node;
struct meta_prop_node {
meta_prop_node * next;
meta_any(* const key)();
meta_any(* const value)();
};
struct meta_base_node {
meta_type_node * const parent;
meta_base_node * next;
meta_type_node *(* const type)() ENTT_NOEXCEPT;
void *(* const cast)(void *) ENTT_NOEXCEPT;
};
struct meta_conv_node {
meta_type_node * const parent;
meta_conv_node * next;
meta_type_node *(* const type)() ENTT_NOEXCEPT;
meta_any(* const conv)(const void *);
};
struct meta_ctor_node {
using size_type = std::size_t;
meta_type_node * const parent;
meta_ctor_node * next;
meta_prop_node * prop;
const size_type size;
meta_type_node *(* const arg)(size_type) ENTT_NOEXCEPT;
meta_any(* const invoke)(meta_any * const);
};
struct meta_dtor_node {
meta_type_node * const parent;
void(* const invoke)(void *);
};
struct meta_data_node {
id_type id;
meta_type_node * const parent;
meta_data_node * next;
meta_prop_node * prop;
const bool is_static;
meta_type_node *(* const type)() ENTT_NOEXCEPT;
bool(* const set)(meta_any, meta_any, meta_any);
meta_any(* const get)(meta_any, meta_any);
};
struct meta_func_node {
using size_type = std::size_t;
id_type id;
meta_type_node * const parent;
meta_func_node * next;
meta_prop_node * prop;
const size_type size;
const bool is_const;
const bool is_static;
meta_type_node *(* const ret)() ENTT_NOEXCEPT;
meta_type_node *(* const arg)(size_type) ENTT_NOEXCEPT;
meta_any(* const invoke)(meta_any, meta_any *);
};
struct meta_type_node {
using size_type = std::size_t;
const id_type type_id;
id_type id;
meta_type_node * next;
meta_prop_node * prop;
const bool is_void;
const bool is_integral;
const bool is_floating_point;
const bool is_array;
const bool is_enum;
const bool is_union;
const bool is_class;
const bool is_pointer;
const bool is_function_pointer;
const bool is_member_object_pointer;
const bool is_member_function_pointer;
const size_type extent;
bool(* const compare)(const void *, const void *);
meta_type_node *(* const remove_pointer)() ENTT_NOEXCEPT;
meta_type_node *(* const remove_extent)() ENTT_NOEXCEPT;
meta_base_node *base{nullptr};
meta_conv_node *conv{nullptr};
meta_ctor_node *ctor{nullptr};
meta_dtor_node *dtor{nullptr};
meta_data_node *data{nullptr};
meta_func_node *func{nullptr};
};
template<typename Type, typename Op, typename Node>
void visit(Op &op, Node *node) {
while(node) {
op(Type{node});
node = node->next;
}
}
template<auto Member, typename Type, typename Op>
void visit(Op &op, const internal::meta_type_node *node) {
if(node) {
internal::visit<Type>(op, node->*Member);
auto *next = node->base;
while(next) {
visit<Member, Type>(op, next->type());
next = next->next;
}
}
}
template<typename Op, typename Node>
auto find_if(const Op &op, Node *node) {
while(node && !op(node)) {
node = node->next;
}
return node;
}
template<auto Member, typename Op>
auto find_if(const Op &op, const meta_type_node *node)
-> decltype(find_if(op, node->*Member)) {
decltype(find_if(op, node->*Member)) ret = nullptr;
if(node) {
ret = find_if(op, node->*Member);
auto *next = node->base;
while(next && !ret) {
ret = find_if<Member>(op, next->type());
next = next->next;
}
}
return ret;
}
template<typename Type>
struct ENTT_API meta_node {
static_assert(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>, "Invalid type");
[[nodiscard]] static bool compare(const void *lhs, const void *rhs) {
if constexpr(!std::is_function_v<Type> && is_equality_comparable_v<Type>) {
return *static_cast<const Type *>(lhs) == *static_cast<const Type *>(rhs);
} else {
return lhs == rhs;
}
}
[[nodiscard]] static meta_type_node * resolve() ENTT_NOEXCEPT {
static meta_type_node node{
type_info<Type>::id(),
{},
nullptr,
nullptr,
std::is_void_v<Type>,
std::is_integral_v<Type>,
std::is_floating_point_v<Type>,
std::is_array_v<Type>,
std::is_enum_v<Type>,
std::is_union_v<Type>,
std::is_class_v<Type>,
std::is_pointer_v<Type>,
std::is_pointer_v<Type> && std::is_function_v<std::remove_pointer_t<Type>>,
std::is_member_object_pointer_v<Type>,
std::is_member_function_pointer_v<Type>,
std::extent_v<Type>,
&compare, // workaround for an issue with VS2017
&meta_node<std::remove_const_t<std::remove_pointer_t<Type>>>::resolve,
&meta_node<std::remove_const_t<std::remove_extent_t<Type>>>::resolve
};
return &node;
}
};
template<typename... Type>
struct meta_info: meta_node<std::remove_cv_t<std::remove_reference_t<Type>>...> {};
}
/**
* Internal details not to be documented.
* @endcond TURN_OFF_DOXYGEN
*/
}
#endif

View File

@@ -8,277 +8,16 @@
#include <utility>
#include "../config/config.h"
#include "../core/fwd.hpp"
#include "../core/type_info.hpp"
#include "../core/type_traits.hpp"
#include "ctx.hpp"
#include "internal.hpp"
namespace entt {
class meta_any;
class meta_type;
/**
* @cond TURN_OFF_DOXYGEN
* Internal details not to be documented.
*/
namespace internal {
struct meta_type_node;
struct meta_prop_node {
meta_prop_node * next;
meta_any(* const key)();
meta_any(* const value)();
};
struct meta_base_node {
meta_type_node * const parent;
meta_base_node * next;
meta_type_node *(* const type)() ENTT_NOEXCEPT;
void *(* const cast)(void *) ENTT_NOEXCEPT;
};
struct meta_conv_node {
meta_type_node * const parent;
meta_conv_node * next;
meta_type_node *(* const type)() ENTT_NOEXCEPT;
meta_any(* const conv)(const void *);
};
struct meta_ctor_node {
using size_type = std::size_t;
meta_type_node * const parent;
meta_ctor_node * next;
meta_prop_node * prop;
const size_type size;
meta_type_node *(* const arg)(size_type) ENTT_NOEXCEPT;
meta_any(* const invoke)(meta_any * const);
};
struct meta_dtor_node {
meta_type_node * const parent;
void(* const invoke)(void *);
};
struct meta_data_node {
id_type id;
meta_type_node * const parent;
meta_data_node * next;
meta_prop_node * prop;
const bool is_static;
meta_type_node *(* const type)() ENTT_NOEXCEPT;
bool(* const set)(meta_any, meta_any, meta_any);
meta_any(* const get)(meta_any, meta_any);
};
struct meta_func_node {
using size_type = std::size_t;
id_type id;
meta_type_node * const parent;
meta_func_node * next;
meta_prop_node * prop;
const size_type size;
const bool is_const;
const bool is_static;
meta_type_node *(* const ret)() ENTT_NOEXCEPT;
meta_type_node *(* const arg)(size_type) ENTT_NOEXCEPT;
meta_any(* const invoke)(meta_any, meta_any *);
};
struct meta_type_node {
using size_type = std::size_t;
const id_type type_id;
id_type id;
meta_type_node * next;
meta_prop_node * prop;
const bool is_void;
const bool is_integral;
const bool is_floating_point;
const bool is_array;
const bool is_enum;
const bool is_union;
const bool is_class;
const bool is_pointer;
const bool is_function_pointer;
const bool is_member_object_pointer;
const bool is_member_function_pointer;
const size_type extent;
bool(* const compare)(const void *, const void *);
meta_type_node *(* const remove_pointer)() ENTT_NOEXCEPT;
meta_type_node *(* const remove_extent)() ENTT_NOEXCEPT;
meta_base_node *base{nullptr};
meta_conv_node *conv{nullptr};
meta_ctor_node *ctor{nullptr};
meta_dtor_node *dtor{nullptr};
meta_data_node *data{nullptr};
meta_func_node *func{nullptr};
};
template<typename Type, typename Op, typename Node>
void visit(Op &op, Node *node) {
while(node) {
op(Type{node});
node = node->next;
}
}
template<auto Member, typename Type, typename Op>
void visit(Op &op, const internal::meta_type_node *node) {
if(node) {
internal::visit<Type>(op, node->*Member);
auto *next = node->base;
while(next) {
visit<Member, Type>(op, next->type());
next = next->next;
}
}
}
template<typename Op, typename Node>
auto find_if(const Op &op, Node *node) {
while(node && !op(node)) {
node = node->next;
}
return node;
}
template<auto Member, typename Op>
auto find_if(const Op &op, const meta_type_node *node)
-> decltype(find_if(op, node->*Member)) {
decltype(find_if(op, node->*Member)) ret = nullptr;
if(node) {
ret = find_if(op, node->*Member);
auto *next = node->base;
while(next && !ret) {
ret = find_if<Member>(op, next->type());
next = next->next;
}
}
return ret;
}
template<typename Type>
[[nodiscard]] bool compare(const void *lhs, const void *rhs) {
if constexpr(!std::is_function_v<Type> && is_equality_comparable_v<Type>) {
return *static_cast<const Type *>(lhs) == *static_cast<const Type *>(rhs);
} else {
return lhs == rhs;
}
}
struct ENTT_API meta_context {
// we could use the lines below but VS2017 returns with an ICE if combined with ENTT_API despite the code being valid C++
// inline static meta_type_node *local = nullptr;
// inline static meta_type_node **global = &local;
[[nodiscard]] static meta_type_node * & local() ENTT_NOEXCEPT {
static meta_type_node *chain = nullptr;
return chain;
}
[[nodiscard]] static meta_type_node ** & global() ENTT_NOEXCEPT {
static meta_type_node **chain = &local();
return chain;
}
static void detach(const meta_type_node *node) ENTT_NOEXCEPT {
auto **it = global();
while(*it && *it != node) {
it = &(*it)->next;
}
if(*it) {
*it = (*it)->next;
}
}
};
template<typename Type>
struct ENTT_API meta_node {
static_assert(std::is_same_v<Type, std::remove_cv_t<std::remove_reference_t<Type>>>, "Invalid type");
[[nodiscard]] static meta_type_node * resolve() ENTT_NOEXCEPT {
static meta_type_node node{
type_info<Type>::id(),
{},
nullptr,
nullptr,
std::is_void_v<Type>,
std::is_integral_v<Type>,
std::is_floating_point_v<Type>,
std::is_array_v<Type>,
std::is_enum_v<Type>,
std::is_union_v<Type>,
std::is_class_v<Type>,
std::is_pointer_v<Type>,
std::is_pointer_v<Type> && std::is_function_v<std::remove_pointer_t<Type>>,
std::is_member_object_pointer_v<Type>,
std::is_member_function_pointer_v<Type>,
std::extent_v<Type>,
&compare<Type>, // workaround for an issue with VS2017
&meta_node<std::remove_const_t<std::remove_pointer_t<Type>>>::resolve,
&meta_node<std::remove_const_t<std::remove_extent_t<Type>>>::resolve
};
return &node;
}
};
template<typename... Type>
struct meta_info: meta_node<std::remove_cv_t<std::remove_reference_t<Type>>...> {};
}
/**
* Internal details not to be documented.
* @endcond TURN_OFF_DOXYGEN
*/
/*! @brief Opaque container for a meta context. */
struct meta_ctx {
/**
* @brief Binds the meta system to a given context.
* @param other A valid context to which to bind.
*/
static void bind(meta_ctx other) ENTT_NOEXCEPT {
internal::meta_context::global() = other.ctx;
}
private:
internal::meta_type_node **ctx{&internal::meta_context::local()};
};
/**
* @brief Opaque container for values of any type.
*