ENTT_DISABLE_ETO to disable empty type optimization (close #330)

This commit is contained in:
Michele Caini
2019-10-20 17:12:27 +02:00
parent 717b091b49
commit ad5651ffb2
7 changed files with 24 additions and 15 deletions

View File

@@ -1683,7 +1683,9 @@ it cannot be caught by a non-const reference. Capture it by copy or by const
reference instead.
More in general, none of the features offered by the library is affected, but
for the ones that require to return actual instances.
for the ones that require to return actual instances.<br/>
This optimization can be disabled by defining the `ENTT_DISABLE_ETO` macro. In
this case, the empty types will be treated like all other types, no matter what.
# Multithreading

View File

@@ -25,6 +25,15 @@
#endif // ENTT_NO_ATOMIC
#ifndef ENTT_DISABLE_ETO
#include <type_traits>
#define ENTT_ENABLE_ETO(Type) std::is_empty_v<Type>
#else // ENTT_DISABLE_ETO
// sfinae-friendly definition
#define ENTT_ENABLE_ETO(Type) (false && std::is_empty_v<Type>)
#endif // ENTT_DISABLE_ETO
#ifndef ENTT_ID_TYPE
#include <cstdint>
#define ENTT_ID_TYPE std::uint32_t

View File

@@ -344,7 +344,7 @@ public:
*/
template<typename Func>
void less(Func func) const {
using get_type_list = type_list_cat_t<std::conditional_t<std::is_empty_v<Get>, type_list<>, type_list<Get>>...>;
using get_type_list = type_list_cat_t<std::conditional_t<ENTT_ENABLE_ETO(Get), type_list<>, type_list<Get>>...>;
traverse(std::move(func), get_type_list{});
}
@@ -763,8 +763,8 @@ public:
*/
template<typename Func>
void less(Func func) const {
using owned_type_list = type_list_cat_t<std::conditional_t<std::is_empty_v<Owned>, type_list<>, type_list<Owned>>...>;
using get_type_list = type_list_cat_t<std::conditional_t<std::is_empty_v<Get>, type_list<>, type_list<Get>>...>;
using owned_type_list = type_list_cat_t<std::conditional_t<ENTT_ENABLE_ETO(Owned), type_list<>, type_list<Owned>>...>;
using get_type_list = type_list_cat_t<std::conditional_t<ENTT_ENABLE_ETO(Get), type_list<>, type_list<Get>>...>;
traverse(std::move(func), owned_type_list{}, get_type_list{});
}

View File

@@ -70,7 +70,7 @@ class basic_registry {
template<typename... Args>
decltype(auto) assign(basic_registry &registry, const Entity entt, Args &&... args) {
if constexpr(std::is_empty_v<Component>) {
if constexpr(ENTT_ENABLE_ETO(Component)) {
storage<Entity, Component>::construct(entt);
construction.publish(entt, registry, Component{});
return Component{std::forward<Args>(args)...};
@@ -101,7 +101,7 @@ class basic_registry {
template<typename... Args>
decltype(auto) replace(basic_registry &registry, const Entity entt, Args &&... args) {
if constexpr(std::is_empty_v<Component>) {
if constexpr(ENTT_ENABLE_ETO(Component)) {
ENTT_ASSERT((storage<Entity, Component>::has(entt)));
update.publish(entt, registry, Component{});
return Component{std::forward<Args>(args)...};
@@ -113,7 +113,7 @@ class basic_registry {
}
private:
using reference_type = std::conditional_t<std::is_empty_v<Component>, const Component &, Component &>;
using reference_type = std::conditional_t<ENTT_ENABLE_ETO(Component), const Component &, Component &>;
sigh<void(const Entity, basic_registry &, reference_type)> construction{};
sigh<void(const Entity, basic_registry &, reference_type)> update{};
sigh<void(const Entity, basic_registry &)> destruction{};

View File

@@ -453,8 +453,6 @@ public:
};
if constexpr(std::is_invocable_v<Compare, const object_type &, const object_type &>) {
static_assert(!std::is_empty_v<object_type>);
underlying_type::arrange(from, to, std::move(apply), [this, compare = std::move(compare)](const auto lhs, const auto rhs) {
return compare(std::as_const(instances[underlying_type::index(lhs)]), std::as_const(instances[underlying_type::index(rhs)]));
}, std::move(algo), std::forward<Args>(args)...);
@@ -476,7 +474,7 @@ private:
/*! @copydoc basic_storage */
template<typename Entity, typename Type>
class basic_storage<Entity, Type, std::enable_if_t<std::is_empty_v<Type>>>: public sparse_set<Entity> {
class basic_storage<Entity, Type, std::enable_if_t<ENTT_ENABLE_ETO(Type)>>: public sparse_set<Entity> {
using traits_type = entt_traits<std::underlying_type_t<Entity>>;
using underlying_type = sparse_set<Entity>;

View File

@@ -503,7 +503,7 @@ public:
template<typename Comp, typename Func>
void less(Func func) const {
using other_type = type_list_cat_t<std::conditional_t<std::is_same_v<Comp, Component>, type_list<>, type_list<Component>>...>;
using non_empty_type = type_list_cat_t<std::conditional_t<std::is_empty_v<Component>, type_list<>, type_list<Component>>...>;
using non_empty_type = type_list_cat_t<std::conditional_t<ENTT_ENABLE_ETO(Component), type_list<>, type_list<Component>>...>;
traverse<Comp>(std::move(func), other_type{}, non_empty_type{});
}
@@ -767,7 +767,7 @@ public:
*/
template<typename Func>
void less(Func func) const {
if constexpr(std::is_empty_v<Component>) {
if constexpr(ENTT_ENABLE_ETO(Component)) {
if constexpr(std::is_invocable_v<Func>) {
for(auto pos = pool->size(); pos; --pos) {
func();

View File

@@ -21,17 +21,17 @@ struct relationship {
template<typename Archive>
void serialize(Archive &archive, position &position) {
archive(position.x, position.y);
archive(position.x, position.y);
}
template<typename Archive>
void serialize(Archive &archive, timer &timer) {
archive(timer.duration);
archive(timer.duration);
}
template<typename Archive>
void serialize(Archive &archive, relationship &relationship) {
archive(relationship.parent);
archive(relationship.parent);
}
TEST(Snapshot, Full) {