Преглед на файлове

snapshot: components no longer need to be copyable (#498)

Replaced calls to std::as_const with std::move so that components can
be moved into place instead of copied when reading them in from a
snapshot.
Alex Ames преди 5 години
родител
ревизия
0273b7606e
променени са 3 файла, в които са добавени 60 реда и са изтрити 20 реда
  1. 1 0
      AUTHORS
  2. 21 15
      src/entt/entity/snapshot.hpp
  3. 38 5
      test/entt/entity/snapshot.cpp

+ 1 - 0
AUTHORS

@@ -4,6 +4,7 @@ skypjack
 
 # Contributors
 
+alexames
 BenediktConze
 bjadamson
 ceeac

+ 21 - 15
src/entt/entity/snapshot.hpp

@@ -166,25 +166,28 @@ class basic_snapshot_loader {
 
     using traits_type = entt_traits<std::underlying_type_t<Entity>>;
 
-    template<typename Type, typename Archive, typename... Args>
-    void assign(Archive &archive, Args... args) const {
+    template<typename Type, typename Archive>
+    void assign(Archive &archive) const {
         typename traits_type::entity_type length{};
         archive(length);
 
-        while(length--) {
-            entity_type entt{};
+        entity_type entt{};
 
-            if constexpr(std::is_empty_v<Type>) {
+        if constexpr(std::is_empty_v<Type>) {
+            while(length--) {
                 archive(entt);
                 const auto entity = reg->valid(entt) ? entt : reg->create(entt);
                 ENTT_ASSERT(entity == entt);
-                reg->template emplace<Type>(args..., entt);
-            } else {
-                Type instance{};
+                reg->template emplace<Type>(entity);
+            }
+        } else {
+            Type instance{};
+
+            while(length--) {
                 archive(entt, instance);
                 const auto entity = reg->valid(entt) ? entt : reg->create(entt);
                 ENTT_ASSERT(entity == entt);
-                reg->template emplace<Type>(args..., entt, std::as_const(instance));
+                reg->template emplace<Type>(entity, std::move(instance));
             }
         }
     }
@@ -383,19 +386,22 @@ class basic_continuous_loader {
         typename traits_type::entity_type length{};
         archive(length);
 
-        while(length--) {
-            entity_type entt{};
+        entity_type entt{};
 
-            if constexpr(std::is_empty_v<Other>) {
+        if constexpr(std::is_empty_v<Other>) {
+            while(length--) {
                 archive(entt);
                 restore(entt);
                 reg->template emplace_or_replace<Other>(map(entt));
-            } else {
-                Other instance{};
+            }
+        } else {
+            Other instance{};
+
+            while(length--) {
                 archive(entt, instance);
                 (update(instance, member), ...);
                 restore(entt);
-                reg->template emplace_or_replace<Other>(map(entt), std::as_const(instance));
+                reg->template emplace_or_replace<Other>(map(entt), std::move(instance));
             }
         }
     }

+ 38 - 5
test/entt/entity/snapshot.cpp

@@ -8,6 +8,19 @@
 #include <entt/entity/snapshot.hpp>
 #include <entt/entity/entity.hpp>
 
+struct noncopyable_component {
+    noncopyable_component(): value{} {}
+    explicit noncopyable_component(int v): value{v} {}
+
+    noncopyable_component(const noncopyable_component &) = delete;
+    noncopyable_component(noncopyable_component &&) = default;
+
+    noncopyable_component& operator=(const noncopyable_component &) = delete;
+    noncopyable_component& operator=(noncopyable_component &&) = default;
+
+    int value;
+};
+
 template<typename Storage>
 struct output_archive {
     output_archive(Storage &instance)
@@ -19,6 +32,10 @@ struct output_archive {
         (std::get<std::queue<Value>>(storage).push(value), ...);
     }
 
+    void operator()(const entt::entity &entity, const noncopyable_component &instance) {
+        (*this)(entity, instance.value);
+    }
+
 private:
     Storage &storage;
 };
@@ -40,6 +57,10 @@ struct input_archive {
         (assign(value), ...);
     }
 
+    void operator()(entt::entity &entity, noncopyable_component &instance) {
+        (*this)(entity, instance.value);
+    }
+
 private:
     Storage &storage;
 };
@@ -207,6 +228,7 @@ TEST(Snapshot, Iterator) {
     for(auto i = 0; i < 50; ++i) {
         const auto entity = registry.create();
         registry.emplace<another_component>(entity, i, i);
+        registry.emplace<noncopyable_component>(entity, i);
 
         if(i % 2) {
             registry.emplace<a_component>(entity);
@@ -216,7 +238,8 @@ TEST(Snapshot, Iterator) {
     using storage_type = std::tuple<
         std::queue<typename traits_type::entity_type>,
         std::queue<entt::entity>,
-        std::queue<another_component>
+        std::queue<another_component>,
+        std::queue<int>
     >;
 
     storage_type storage;
@@ -226,9 +249,9 @@ TEST(Snapshot, Iterator) {
     const auto view = registry.view<a_component>();
     const auto size = view.size();
 
-    entt::snapshot{registry}.component<another_component>(output, view.begin(), view.end());
+    entt::snapshot{registry}.component<another_component, noncopyable_component>(output, view.begin(), view.end());
     registry.clear();
-    entt::snapshot_loader{registry}.component<another_component>(input);
+    entt::snapshot_loader{registry}.component<another_component, noncopyable_component>(input);
 
     ASSERT_EQ(registry.view<another_component>().size(), size);
 
@@ -254,6 +277,7 @@ TEST(Snapshot, Continuous) {
         std::queue<another_component>,
         std::queue<what_a_component>,
         std::queue<map_component>,
+        std::queue<int>,
         std::queue<double>
     >;
 
@@ -273,6 +297,7 @@ TEST(Snapshot, Continuous) {
 
         src.emplace<a_component>(entity);
         src.emplace<another_component>(entity, i, i);
+        src.emplace<noncopyable_component>(entity, i);
 
         if(i % 2) {
             src.emplace<what_a_component>(entity, entity);
@@ -296,11 +321,12 @@ TEST(Snapshot, Continuous) {
     entity = dst.create();
     dst.emplace<a_component>(entity);
     dst.emplace<another_component>(entity, -1, -1);
+    dst.emplace<noncopyable_component>(entity, -1);
 
-    entt::snapshot{src}.entities(output).component<a_component, another_component, what_a_component, map_component>(output);
+    entt::snapshot{src}.entities(output).component<a_component, another_component, what_a_component, map_component, noncopyable_component>(output);
 
     loader.entities(input)
-        .component<a_component, another_component, what_a_component, map_component>(
+        .component<a_component, another_component, what_a_component, map_component, noncopyable_component>(
             input,
             &what_a_component::bar,
             &what_a_component::quux,
@@ -313,6 +339,7 @@ TEST(Snapshot, Continuous) {
     decltype(dst.size()) another_component_cnt{};
     decltype(dst.size()) what_a_component_cnt{};
     decltype(dst.size()) map_component_cnt{};
+    decltype(dst.size()) noncopyable_component_cnt{};
 
     dst.each([&dst, &a_component_cnt](auto entt) {
         ASSERT_TRUE(dst.has<a_component>(entt));
@@ -351,6 +378,11 @@ TEST(Snapshot, Continuous) {
         ++map_component_cnt;
     });
 
+    dst.view<noncopyable_component>().each([&dst, &noncopyable_component_cnt](auto, const auto &component) {
+        ++noncopyable_component_cnt;
+        ASSERT_EQ(component.value, (dst.size<noncopyable_component>() - noncopyable_component_cnt - 1));
+    });
+
     src.view<another_component>().each([](auto, auto &component) {
         component.value = 2 * component.key;
     });
@@ -375,6 +407,7 @@ TEST(Snapshot, Continuous) {
     ASSERT_EQ(dst.size<another_component>(), another_component_cnt);
     ASSERT_EQ(dst.size<what_a_component>(), what_a_component_cnt);
     ASSERT_EQ(dst.size<map_component>(), map_component_cnt);
+    ASSERT_EQ(dst.size<noncopyable_component>(), noncopyable_component_cnt);
 
     dst.view<another_component>().each([](auto, auto &component) {
         ASSERT_EQ(component.value, component.key < 0 ? -1 : (2 * component.key));