]> git.ipfire.org Git - thirdparty/vectorscan.git/commitdiff
flat_set/map: workaround for gcc-4.8 C++11 defect
authorJustin Viiret <justin.viiret@intel.com>
Tue, 13 Jun 2017 00:36:11 +0000 (10:36 +1000)
committerMatthew Barr <matthew.barr@intel.com>
Tue, 13 Jun 2017 03:52:33 +0000 (13:52 +1000)
The STL shipped with gcc-4.8 does not provide
vector::erase(const_iterator) for C++11, instead only taking a mutable
iterator.  This causes problems with flat_set/map if we don't have
Boost small_vector available and we fall back to std::vector.

We work around this by providing a function to construct a mutable
iterator given a const_iterator for internal use.

src/util/small_vector.h
src/util/ue2_containers.h

index 0b60d8c0fa432e7c998c8d9b8f5052df4820df1b..6293759c6215182b6b9848f915e917cb91bce381 100644 (file)
@@ -55,6 +55,9 @@ using small_vector = boost::container::small_vector<T, N, Allocator>;
 template <class T, std::size_t N, typename Allocator = std::allocator<T>>
 using small_vector = std::vector<T, Allocator>;
 
+// Support workarounds for flat_set/flat_map and GCC 4.8.
+#define SMALL_VECTOR_IS_STL_VECTOR 1
+
 #endif // HAVE_BOOST_CONTAINER_SMALL_VECTOR
 
 } // namespace ue2
index 29919c7e1ac3b2998adf5edfa0081fb3d521479a..d345a4faa45310e032522706df17dbaa554c8c31 100644 (file)
@@ -162,9 +162,19 @@ class flat_set
       public totally_ordered<flat_set<T, Compare, Allocator>> {
     using base_type = flat_detail::flat_base<T, Compare, Allocator>;
     using storage_type = typename base_type::storage_type;
+    using storage_iterator = typename storage_type::iterator;
+    using storage_const_iterator = typename storage_type::const_iterator;
     using base_type::data;
     using base_type::comp;
 
+#if defined(SMALL_VECTOR_IS_STL_VECTOR)
+    // Construct a non-const iterator from a const iterator. Used in flat_map
+    // and flat_set erase() calls to work around g++-4.8 compatibility issues.
+    storage_iterator mutable_iterator(storage_const_iterator it) {
+        return data().begin() + std::distance(data().cbegin(), it);
+    }
+#endif
+
 public:
     // Member types.
     using key_type = T;
@@ -282,11 +292,27 @@ public:
     }
 
     void erase(const_iterator pos) {
-        data().erase(pos.get());
+#if defined(SMALL_VECTOR_IS_STL_VECTOR)
+        // Cope with libstdc++ 4.8's incomplete STL (it's missing C++11
+        // vector::erase(const_iterator)) by explicitly using a non-const
+        // iterator.
+        auto pos_it = mutable_iterator(pos.get());
+#else
+        auto pos_it = pos.get();
+#endif
+        data().erase(pos_it);
     }
 
     void erase(const_iterator first, const_iterator last) {
-        data().erase(first.get(), last.get());
+#if defined(SMALL_VECTOR_IS_STL_VECTOR)
+        // As above, work around libstdc++ 4.8's incomplete C++11 support.
+        auto first_it = mutable_iterator(first.get());
+        auto last_it = mutable_iterator(last.get());
+#else
+        auto first_it = first.get();
+        auto last_it = last.get();
+#endif
+        data().erase(first_it, last_it);
     }
 
     void erase(const key_type &key) {
@@ -374,9 +400,19 @@ private:
         flat_detail::flat_base<std::pair<Key, T>, Compare, Allocator>;
     using keyval_storage_type = std::pair<key_type, mapped_type>;
     using storage_type = typename base_type::storage_type;
+    using storage_iterator = typename storage_type::iterator;
+    using storage_const_iterator = typename storage_type::const_iterator;
     using base_type::data;
     using base_type::comp;
 
+#if defined(SMALL_VECTOR_IS_STL_VECTOR)
+    // Construct a non-const iterator from a const iterator. Used in flat_map
+    // and flat_set erase() calls to work around g++-4.8 compatibility issues.
+    storage_iterator mutable_iterator(storage_const_iterator it) {
+        return data().begin() + std::distance(data().cbegin(), it);
+    }
+#endif
+
 public:
     // More Member types.
     using size_type = typename storage_type::size_type;
@@ -444,9 +480,6 @@ public:
     const_reverse_iterator rend() const { return crend(); }
 
 private:
-    using storage_iterator = typename storage_type::iterator;
-    using storage_const_iterator = typename storage_type::const_iterator;
-
     storage_iterator data_lower_bound(const key_type &key) {
         return std::lower_bound(
             data().begin(), data().end(), key,
@@ -526,11 +559,27 @@ public:
     }
 
     void erase(const_iterator pos) {
-        data().erase(pos.get());
+#if defined(SMALL_VECTOR_IS_STL_VECTOR)
+        // Cope with libstdc++ 4.8's incomplete STL (it's missing C++11
+        // vector::erase(const_iterator)) by explicitly using a non-const
+        // iterator.
+        auto pos_it = mutable_iterator(pos.get());
+#else
+        auto pos_it = pos.get();
+#endif
+        data().erase(pos_it);
     }
 
     void erase(const_iterator first, const_iterator last) {
-        data().erase(first.get(), last.get());
+#if defined(SMALL_VECTOR_IS_STL_VECTOR)
+        // As above, work around libstdc++ 4.8's incomplete C++11 support.
+        auto first_it = mutable_iterator(first.get());
+        auto last_it = mutable_iterator(last.get());
+#else
+        auto first_it = first.get();
+        auto last_it = last.get();
+#endif
+        data().erase(first_it, last_it);
     }
 
     void erase(const key_type &key) {