Bläddra i källkod

meta: minimal (and still inefficient) support for lists as sequence containers

Michele Caini 3 år sedan
förälder
incheckning
14ce88730f
4 ändrade filer med 65 tillägg och 5 borttagningar
  1. 1 0
      TODO
  2. 15 4
      src/entt/meta/container.hpp
  3. 1 1
      src/entt/meta/meta.hpp
  4. 48 0
      test/entt/meta/meta_container.cpp

+ 1 - 0
TODO

@@ -12,6 +12,7 @@ DOC:
 * update entity doc when the storage based model is in place
 
 WIP:
+* meta: add deque support as sequence container
 * sparse set/storage support for move-only types, internal rework required
 * get rid of observers, storage based views made them pointless - document alternatives
 * add storage getter for filters to views and groups

+ 15 - 4
src/entt/meta/container.hpp

@@ -2,6 +2,8 @@
 #define ENTT_META_CONTAINER_HPP
 
 #include <array>
+#include <iterator>
+#include <list>
 #include <map>
 #include <set>
 #include <type_traits>
@@ -70,12 +72,12 @@ struct basic_meta_sequence_container_traits {
                     // this abomination is necessary because only on macos value_type and const_reference are different types for std::vector<bool>
                     if(value.allow_cast<typename Type::const_reference>() || value.allow_cast<typename Type::value_type>()) {
                         const auto *element = value.try_cast<std::remove_reference_t<typename Type::const_reference>>();
-                        const auto curr = cont->insert(cont->begin() + offset, element ? *element : value.cast<typename Type::value_type>());
-                        return iterator{*cont, curr - cont->begin()};
+                        const auto curr = cont->insert(std::next(cont->begin(), offset), element ? *element : value.cast<typename Type::value_type>());
+                        return iterator{*cont, static_cast<std::ptrdiff_t>(offset)};
                     }
                 } else {
-                    const auto curr = cont->erase(cont->begin() + offset);
-                    return iterator{*cont, curr - cont->begin()};
+                    const auto curr = cont->erase(std::next(cont->begin(), offset));
+                    return iterator{*cont, static_cast<std::ptrdiff_t>(offset)};
                 }
             }
         }
@@ -167,6 +169,15 @@ template<typename Type, auto N>
 struct meta_sequence_container_traits<std::array<Type, N>>
     : internal::basic_meta_sequence_container_traits<std::array<Type, N>> {};
 
+/**
+ * @brief Meta sequence container traits for `std::list`s of any type.
+ * @tparam Type The type of elements.
+ * @tparam Args Other arguments.
+ */
+template<typename Type, typename... Args>
+struct meta_sequence_container_traits<std::list<Type, Args...>>
+    : internal::basic_meta_sequence_container_traits<std::list<Type, Args...>> {};
+
 /**
  * @brief Meta associative container traits for `std::map`s of any type.
  * @tparam Key The key type of elements.

+ 1 - 1
src/entt/meta/meta.hpp

@@ -1471,7 +1471,7 @@ class meta_sequence_container::meta_iterator final {
 
     template<typename It>
     static meta_any deref_fn(const any &value, const std::ptrdiff_t pos) {
-        return meta_any{std::in_place_type<typename std::iterator_traits<It>::reference>, any_cast<const It &>(value)[pos]};
+        return meta_any{std::in_place_type<typename std::iterator_traits<It>::reference>, *std::next(any_cast<const It &>(value), pos)};
     }
 
 public:

+ 48 - 0
test/entt/meta/meta_container.cpp

@@ -1,4 +1,5 @@
 #include <array>
+#include <list>
 #include <map>
 #include <set>
 #include <utility>
@@ -204,6 +205,53 @@ TEST_F(MetaContainer, StdArray) {
     ASSERT_EQ(view.size(), 3u);
 }
 
+TEST_F(MetaContainer, StdList) {
+    std::list<int> list{};
+    auto any = entt::forward_as_meta(list);
+    auto view = any.as_sequence_container();
+
+    ASSERT_TRUE(view);
+    ASSERT_EQ(view.value_type(), entt::resolve<int>());
+
+    ASSERT_EQ(view.size(), 0u);
+    ASSERT_EQ(view.begin(), view.end());
+    ASSERT_TRUE(view.resize(3u));
+    ASSERT_EQ(view.size(), 3u);
+    ASSERT_NE(view.begin(), view.end());
+
+    view[0].cast<int &>() = 2;
+    view[1].cast<int &>() = 3;
+    view[2].cast<int &>() = 4;
+
+    ASSERT_EQ(view[1u].cast<int>(), 3);
+
+    auto it = view.begin();
+    auto ret = view.insert(it, 0);
+
+    ASSERT_TRUE(ret);
+    ASSERT_FALSE(view.insert(ret, invalid_type{}));
+    ASSERT_TRUE(view.insert(++ret, 1.));
+
+    ASSERT_EQ(view.size(), 5u);
+    ASSERT_EQ(view.begin()->cast<int>(), 0);
+    ASSERT_EQ((++view.begin())->cast<int>(), 1);
+
+    ret = view.insert(view.end(), 42);
+
+    ASSERT_TRUE(ret);
+    ASSERT_EQ(*ret, 42);
+
+    it = view.begin();
+    ret = view.erase(it);
+
+    ASSERT_TRUE(ret);
+    ASSERT_EQ(view.size(), 5u);
+    ASSERT_EQ(ret->cast<int>(), 1);
+
+    ASSERT_TRUE(view.clear());
+    ASSERT_EQ(view.size(), 0u);
+}
+
 TEST_F(MetaContainer, StdMap) {
     std::map<int, char> map{{2, 'c'}, {3, 'd'}, {4, 'e'}};
     auto any = entt::forward_as_meta(map);