Browse Source

fixed errors with vs2017 + const begin/end on iterators for sparse set

Michele Caini 7 years ago
parent
commit
3f04247a53
3 changed files with 86 additions and 5 deletions
  1. 67 0
      src/entt/entity/sparse_set.hpp
  2. 9 5
      src/entt/entity/view.hpp
  3. 10 0
      test/entt/entity/sparse_set.cpp

+ 67 - 0
src/entt/entity/sparse_set.hpp

@@ -218,6 +218,22 @@ public:
         return const_iterator_type{direct.data(), direct.size()};
     }
 
+    /**
+     * @brief Returns an iterator to the beginning.
+     *
+     * The returned iterator points to the first entity of the internal packed
+     * array. If the sparse set is empty, the returned iterator will be equal to
+     * `end()`.
+     *
+     * @note
+     * Input iterators stay true to the order imposed by a call to `respect`.
+     *
+     * @return An iterator to the first entity of the internal packed array.
+     */
+    inline const_iterator_type begin() const ENTT_NOEXCEPT {
+        return cbegin();
+    }
+
     /**
      * @brief Returns an iterator to the beginning.
      *
@@ -251,6 +267,23 @@ public:
         return const_iterator_type{direct.data(), 0};
     }
 
+    /**
+     * @brief Returns an iterator to the end.
+     *
+     * The returned iterator points to the element following the last entity in
+     * the internal packed array. Attempting to dereference the returned
+     * iterator results in undefined behavior.
+     *
+     * @note
+     * Input iterators stay true to the order imposed by a call to `respect`.
+     *
+     * @return An iterator to the element following the last entity of the
+     * internal packed array.
+     */
+    inline const_iterator_type end() const ENTT_NOEXCEPT {
+        return cend();
+    }
+
     /**
      * @brief Returns an iterator to the end.
      *
@@ -613,6 +646,22 @@ public:
         return const_iterator_type{instances.data(), instances.size()};
     }
 
+    /**
+     * @brief Returns an iterator to the beginning.
+     *
+     * The returned iterator points to the first instance of the given type. If
+     * the sparse set is empty, the returned iterator will be equal to `end()`.
+     *
+     * @note
+     * Input iterators stay true to the order imposed by a call to either `sort`
+     * or `respect`.
+     *
+     * @return An iterator to the first instance of the given type.
+     */
+    inline const_iterator_type begin() const ENTT_NOEXCEPT {
+        return cbegin();
+    }
+
     /**
      * @brief Returns an iterator to the beginning.
      *
@@ -647,6 +696,24 @@ public:
         return const_iterator_type{instances.data(), 0};
     }
 
+    /**
+     * @brief Returns an iterator to the end.
+     *
+     * The returned iterator points to the element following the last instance
+     * of the given type. Attempting to dereference the returned iterator
+     * results in undefined behavior.
+     *
+     * @note
+     * Input iterators stay true to the order imposed by a call to either `sort`
+     * or `respect`.
+     *
+     * @return An iterator to the element following the last instance of the
+     * given type.
+     */
+    inline const_iterator_type end() const ENTT_NOEXCEPT {
+        return cend();
+    }
+
     /**
      * @brief Returns an iterator to the end.
      *

+ 9 - 5
src/entt/entity/view.hpp

@@ -759,16 +759,20 @@ public:
     template<typename Func>
     void each(Func func) const {
         auto iterate = [&func, this](const auto &cpool) {
-            std::for_each(cpool.view_type::cbegin(), cpool.view_type::cend(), [&func, raw = cpool.cbegin(), unchecked = this->unchecked(&cpool), extent = this->extent(), this](const auto entity) mutable {
+            const auto other = unchecked(&cpool);
+            const auto ext = extent();
+            auto raw = cpool.cbegin();
+
+            for(const auto entity: static_cast<const view_type &>(cpool)) {
                 const auto sz = size_type(entity & traits_type::entity_mask);
 
-                if(sz < extent && std::all_of(unchecked.cbegin(), unchecked.cend(), [entity](const view_type *view) { return view->fast(entity); })) {
-                    // avoided indirections due to the sparse set for the pivot type
-                    func(entity, this->get<typename std::decay_t<decltype(cpool)>::object_type, Component>(raw, entity)...);
+                if(sz < ext && std::all_of(other.cbegin(), other.cend(), [entity](const view_type *view) { return view->fast(entity); })) {
+                    // avoided indirections due to the sparse set for the pivot type (see get for more details)
+                    func(entity, get<typename std::decay_t<decltype(cpool)>::object_type, Component>(raw, entity)...);
                 }
 
                 ++raw;
-            });
+            }
         };
 
         const auto *view = candidate();

+ 10 - 0
test/entt/entity/sparse_set.cpp

@@ -4,10 +4,12 @@
 
 TEST(SparseSetNoType, Functionalities) {
     entt::SparseSet<unsigned int> set;
+    const auto &cset = set;
 
     ASSERT_NO_THROW(set.reserve(42));
     ASSERT_TRUE(set.empty());
     ASSERT_EQ(set.size(), 0u);
+    ASSERT_EQ(cset.begin(), cset.end());
     ASSERT_EQ(set.begin(), set.end());
     ASSERT_FALSE(set.has(0));
     ASSERT_FALSE(set.has(42));
@@ -18,6 +20,7 @@ TEST(SparseSetNoType, Functionalities) {
 
     ASSERT_FALSE(set.empty());
     ASSERT_EQ(set.size(), 1u);
+    ASSERT_NE(cset.begin(), cset.end());
     ASSERT_NE(set.begin(), set.end());
     ASSERT_FALSE(set.has(0));
     ASSERT_TRUE(set.has(42));
@@ -28,6 +31,7 @@ TEST(SparseSetNoType, Functionalities) {
 
     ASSERT_TRUE(set.empty());
     ASSERT_EQ(set.size(), 0u);
+    ASSERT_EQ(cset.begin(), cset.end());
     ASSERT_EQ(set.begin(), set.end());
     ASSERT_FALSE(set.has(0));
     ASSERT_FALSE(set.has(42));
@@ -40,6 +44,7 @@ TEST(SparseSetNoType, Functionalities) {
 
     ASSERT_TRUE(set.empty());
     ASSERT_EQ(set.size(), 0u);
+    ASSERT_EQ(cset.begin(), cset.end());
     ASSERT_EQ(set.begin(), set.end());
     ASSERT_FALSE(set.has(0));
     ASSERT_FALSE(set.has(42));
@@ -254,10 +259,12 @@ TEST(SparseSetNoType, RespectUnordered) {
 
 TEST(SparseSetWithType, Functionalities) {
     entt::SparseSet<unsigned int, int> set;
+    const auto &cset = set;
 
     ASSERT_NO_THROW(set.reserve(42));
     ASSERT_TRUE(set.empty());
     ASSERT_EQ(set.size(), 0u);
+    ASSERT_EQ(cset.begin(), cset.end());
     ASSERT_EQ(set.begin(), set.end());
     ASSERT_FALSE(set.has(0));
     ASSERT_FALSE(set.has(42));
@@ -267,6 +274,7 @@ TEST(SparseSetWithType, Functionalities) {
     ASSERT_EQ(set.get(42), 3);
     ASSERT_FALSE(set.empty());
     ASSERT_EQ(set.size(), 1u);
+    ASSERT_NE(cset.begin(), cset.end());
     ASSERT_NE(set.begin(), set.end());
     ASSERT_FALSE(set.has(0));
     ASSERT_TRUE(set.has(42));
@@ -277,6 +285,7 @@ TEST(SparseSetWithType, Functionalities) {
 
     ASSERT_TRUE(set.empty());
     ASSERT_EQ(set.size(), 0u);
+    ASSERT_EQ(cset.begin(), cset.end());
     ASSERT_EQ(set.begin(), set.end());
     ASSERT_FALSE(set.has(0));
     ASSERT_FALSE(set.has(42));
@@ -289,6 +298,7 @@ TEST(SparseSetWithType, Functionalities) {
 
     ASSERT_TRUE(set.empty());
     ASSERT_EQ(set.size(), 0u);
+    ASSERT_EQ(cset.begin(), cset.end());
     ASSERT_EQ(set.begin(), set.end());
     ASSERT_FALSE(set.has(0));
     ASSERT_FALSE(set.has(42));