ソースを参照

ENTT_DISABLE_ETO to disable empty type optimization (close #330)

Michele Caini 6 年 前
コミット
ad5651ffb2

+ 3 - 1
docs/md/entity.md

@@ -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
 

+ 9 - 0
src/entt/config/config.h

@@ -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

+ 3 - 3
src/entt/entity/group.hpp

@@ -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{});
     }
 

+ 3 - 3
src/entt/entity/registry.hpp

@@ -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{};

+ 1 - 3
src/entt/entity/storage.hpp

@@ -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>;
 

+ 2 - 2
src/entt/entity/view.hpp

@@ -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();

+ 3 - 3
test/snapshot/snapshot.cpp

@@ -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) {