diff --git a/Property_map/include/CGAL/Property_container.h b/Property_map/include/CGAL/Property_container.h index 4aa3fe15577..8b517a7694a 100644 --- a/Property_map/include/CGAL/Property_container.h +++ b/Property_map/include/CGAL/Property_container.h @@ -248,6 +248,7 @@ class Property_container { std::multimap>> m_properties; std::vector m_active_indices{}; + bool m_has_deleted_elements = false; public: @@ -258,6 +259,7 @@ public: Property_container(const Property_container& other) { m_active_indices = other.m_active_indices; + m_has_deleted_elements = other.m_has_deleted_elements; for (auto [name, array] : other.m_properties) { // todo: this could probably be made faster using emplace_hint @@ -273,6 +275,7 @@ public: // This is not exactly an assignment as existing unique properties are kept. Property_container& operator=(const Property_container& other) { m_active_indices = other.m_active_indices; + m_has_deleted_elements = other.m_has_deleted_elements; for (auto [name, array] : other.m_properties) { // search if property already exists @@ -295,6 +298,7 @@ public: // This is not exactly an assignment as existing unique properties are kept. Property_container& operator=(Property_container&& other) { m_active_indices = std::move(other.m_active_indices); + m_has_deleted_elements = other.m_has_deleted_elements; for (auto [name, array] : other.m_properties) { // search if property already exists @@ -312,7 +316,7 @@ public: } // The moved-from property map should retain all of its properties, but contain 0 elements - other.reserve(0); + other.resize(0); return *this; } @@ -441,16 +445,15 @@ public: }*/ public: - - void reserve(std::size_t n) { - m_active_indices.resize(n); - for (auto [name, array]: m_properties) - array->reserve(n); - } - void resize(std::size_t n) { - reserve(n); + + m_active_indices.resize(n); + for (auto [name, array] : m_properties) + array->reserve(n); + std::fill(m_active_indices.begin(), m_active_indices.end(), true); + + m_has_deleted_elements = false; } [[nodiscard]] std::size_t size() const { return std::count(m_active_indices.begin(), m_active_indices.end(), true); } @@ -460,8 +463,11 @@ public: Index emplace_back() { // Expand the storage and return the last element - reserve(capacity() + 1); - m_active_indices.back() = true; + m_active_indices.push_back(true); + + for (auto [name, array] : m_properties) + array->reserve(capacity()); + auto first_new_index = Index(capacity() - 1); reset(first_new_index); return first_new_index; @@ -469,6 +475,9 @@ public: Index emplace() { + if (!m_has_deleted_elements) + return emplace_back(); + // If there are empty slots, return the index of one of them and mark it as full auto first_unused = std::find_if(m_active_indices.begin(), m_active_indices.end(), [](bool used) { return !used; }); if (first_unused != m_active_indices.end()) { @@ -478,20 +487,27 @@ public: return index; } + m_has_deleted_elements = false; + return emplace_back(); } Index emplace_group_back(std::size_t n) { // Expand the storage and return the start of the new region - reserve(capacity() + n); - for (auto it = m_active_indices.end() - n; it < m_active_indices.end(); ++it) - *it = true; + m_active_indices.resize(capacity() + n, true); + + for (auto [name, array] : m_properties) + array->reserve(capacity()); + return Index(capacity() - n); } Index emplace_group(std::size_t n) { + if (!m_has_deleted_elements) + return emplace_group_back(n); + auto search_start = m_active_indices.begin(); while (search_start != m_active_indices.end()) { @@ -544,6 +560,7 @@ public: void erase(Index i) { m_active_indices[i] = false; + m_has_deleted_elements = true; for (auto [name, array]: m_properties) array->reset(i); } diff --git a/Property_map/test/Property_map/test_Property_container.cpp b/Property_map/test/Property_map/test_Property_container.cpp index eb0099ed8c1..364ae65fdd6 100644 --- a/Property_map/test/Property_map/test_Property_container.cpp +++ b/Property_map/test/Property_map/test_Property_container.cpp @@ -41,11 +41,6 @@ void test_element_access() { auto& integers = properties.add_property("integers", 5); - // Reserve space for 100 elements - properties.reserve(100); - assert(properties.capacity() == 100); - assert(properties.size() == 0); - // Newly emplaced elements should go at the front assert(properties.emplace() == 0); assert(properties.emplace() == 1); @@ -61,7 +56,6 @@ void test_element_access() { auto& floats = properties.add_property("floats", 6.0f); // The new property array should already be of the right size - assert(floats.capacity() == 100); assert(properties.size() == 3); // Pre-existing elements should contain the default value @@ -87,9 +81,8 @@ void test_element_access() { // Erase an element, and the size should be reduced properties.erase(1); assert(properties.size() == 2); - assert(properties.capacity() == 100); assert(properties.active_list().size() == 2); - assert(properties.inactive_list().size() == 98); + assert(properties.inactive_list().size() == 1); // A newly emplaced element should take the empty slot assert(properties.emplace() == 1);