Sfoglia il codice sorgente

stl: fake iterator concepts to make up for the lack on some platforms

skypjack 1 mese fa
parent
commit
9d0028e036

+ 1 - 0
CMakeLists.txt

@@ -194,6 +194,7 @@ if(ENTT_INCLUDE_HEADERS)
         signal/emitter.hpp
         signal/fwd.hpp
         signal/sigh.hpp
+        stl/concepts.hpp
         stl/functional.hpp
         stl/memory.hpp
         tools/davey.hpp

+ 2 - 1
src/entt/container/dense_map.hpp

@@ -20,6 +20,7 @@
 #include "../core/iterator.hpp"
 #include "../core/memory.hpp"
 #include "../core/type_traits.hpp"
+#include "../stl/concepts.hpp"
 #include "fwd.hpp"
 
 namespace entt {
@@ -547,7 +548,7 @@ public:
      * @param first An iterator to the first element of the range of elements.
      * @param last An iterator past the last element of the range of elements.
      */
-    void insert(std::input_iterator auto first, std::input_iterator auto last) {
+    void insert(entt::stl::input_iterator auto first, entt::stl::input_iterator auto last) {
         for(; first != last; ++first) {
             insert(*first);
         }

+ 2 - 1
src/entt/container/dense_set.hpp

@@ -18,6 +18,7 @@
 #include "../core/bit.hpp"
 #include "../core/compressed_pair.hpp"
 #include "../core/type_traits.hpp"
+#include "../stl/concepts.hpp"
 #include "fwd.hpp"
 
 namespace entt {
@@ -524,7 +525,7 @@ public:
      * @param first An iterator to the first element of the range of elements.
      * @param last An iterator past the last element of the range of elements.
      */
-    void insert(std::input_iterator auto first, std::input_iterator auto last) {
+    void insert(entt::stl::input_iterator auto first, entt::stl::input_iterator auto last) {
         for(; first != last; ++first) {
             insert(*first);
         }

+ 4 - 3
src/entt/core/algorithm.hpp

@@ -7,6 +7,7 @@
 #include <iterator>
 #include <utility>
 #include <vector>
+#include "../stl/concepts.hpp"
 #include "../stl/functional.hpp"
 
 namespace entt {
@@ -33,7 +34,7 @@ struct std_sort {
      * @param args Arguments to forward to the sort function, if any.
      */
     template<typename Compare = std::less<>, typename... Args>
-    void operator()(std::random_access_iterator auto first, std::random_access_iterator auto last, Compare compare = Compare{}, Args &&...args) const {
+    void operator()(entt::stl::random_access_iterator auto first, entt::stl::random_access_iterator auto last, Compare compare = Compare{}, Args &&...args) const {
         std::sort(std::forward<Args>(args)..., std::move(first), std::move(last), std::move(compare));
     }
 };
@@ -51,7 +52,7 @@ struct insertion_sort {
      * @param compare A valid comparison function object.
      */
     template<typename Compare = std::less<>>
-    void operator()(std::random_access_iterator auto first, std::random_access_iterator auto last, Compare compare = Compare{}) const {
+    void operator()(entt::stl::random_access_iterator auto first, entt::stl::random_access_iterator auto last, Compare compare = Compare{}) const {
         if(first < last) {
             for(auto it = first + 1; it < last; ++it) {
                 auto value = std::move(*it);
@@ -93,7 +94,7 @@ struct radix_sort {
      * @param last An iterator past the last element of the range to sort.
      * @param getter A valid _getter_ function object.
      */
-    template<std::random_access_iterator It, typename Getter = stl::identity>
+    template<entt::stl::random_access_iterator It, typename Getter = stl::identity>
     void operator()(It first, It last, Getter getter = Getter{}) const {
         if(first < last) {
             constexpr auto passes = N / Bit;

+ 2 - 1
src/entt/core/iterator.hpp

@@ -6,6 +6,7 @@
 #include <memory>
 #include <type_traits>
 #include <utility>
+#include "../stl/concepts.hpp"
 
 namespace entt {
 
@@ -120,7 +121,7 @@ private:
  * @tparam It Type of iterator.
  * @tparam Sentinel Type of sentinel.
  */
-template<std::input_or_output_iterator It, std::sentinel_for<It> Sentinel = It>
+template<entt::stl::input_or_output_iterator It, entt::stl::sentinel_for<It> Sentinel = It>
 struct iterable_adaptor final {
     /*! @brief Value type. */
     using value_type = std::iterator_traits<It>::value_type;

+ 2 - 1
src/entt/entity/group.hpp

@@ -14,6 +14,7 @@
 #include "../core/iterator.hpp"
 #include "../core/type_info.hpp"
 #include "../core/type_traits.hpp"
+#include "../stl/concepts.hpp"
 #include "entity.hpp"
 #include "fwd.hpp"
 
@@ -642,7 +643,7 @@ public:
      * @param first An iterator to the first element of the range of entities.
      * @param last An iterator past the last element of the range of entities.
      */
-    void sort_as(std::input_iterator auto first, std::input_iterator auto last) const {
+    void sort_as(entt::stl::input_iterator auto first, entt::stl::input_iterator auto last) const {
         if(*this) {
             descriptor->handle().sort_as(first, last);
         }

+ 2 - 1
src/entt/entity/mixin.hpp

@@ -8,6 +8,7 @@
 #include "../core/any.hpp"
 #include "../core/type_info.hpp"
 #include "../signal/sigh.hpp"
+#include "../stl/concepts.hpp"
 #include "entity.hpp"
 #include "fwd.hpp"
 
@@ -362,7 +363,7 @@ public:
      * @param args Parameters to use to forward to the underlying storage.
      */
     template<typename... Args>
-    void insert(std::input_iterator auto first, std::input_iterator auto last, Args &&...args) {
+    void insert(entt::stl::input_iterator auto first, entt::stl::input_iterator auto last, Args &&...args) {
         auto from = underlying_type::size();
         underlying_type::insert(first, last, std::forward<Args>(args)...);
 

+ 6 - 5
src/entt/entity/registry.hpp

@@ -22,6 +22,7 @@
 #include "../core/memory.hpp"
 #include "../core/type_info.hpp"
 #include "../core/type_traits.hpp"
+#include "../stl/concepts.hpp"
 #include "../stl/functional.hpp"
 #include "entity.hpp"
 #include "fwd.hpp"
@@ -540,7 +541,7 @@ public:
      * @param first An iterator to the first element of the range of entities.
      * @param last An iterator past the last element of the range of entities.
      */
-    void destroy(std::input_iterator auto first, std::input_iterator auto last) {
+    void destroy(entt::stl::input_iterator auto first, entt::stl::input_iterator auto last) {
         const auto to = entities.sort_as(first, last);
         const auto from = entities.cend() - static_cast<common_type::difference_type>(entities.free_list());
 
@@ -582,7 +583,7 @@ public:
      * @param last An iterator past the last element of the range of entities.
      */
     template<typename Type>
-    void insert(std::input_iterator auto first, std::input_iterator auto last) {
+    void insert(entt::stl::input_iterator auto first, entt::stl::input_iterator auto last) {
         ENTT_ASSERT(std::all_of(first, last, [this](const auto entt) { return valid(entt); }), "Invalid entity");
         assure<Type>().insert(std::move(first), std::move(last));
     }
@@ -598,7 +599,7 @@ public:
      * @param value An instance of the element to assign.
      */
     template<typename Type>
-    void insert(std::input_iterator auto first, std::input_iterator auto last, const Type &value) {
+    void insert(entt::stl::input_iterator auto first, entt::stl::input_iterator auto last, const Type &value) {
         ENTT_ASSERT(std::all_of(first, last, [this](const auto entt) { return valid(entt); }), "Invalid entity");
         assure<Type>().insert(std::move(first), std::move(last), value);
     }
@@ -708,7 +709,7 @@ public:
      * @param last An iterator past the last element of the range of entities.
      * @return The number of elements actually removed.
      */
-    template<typename Type, typename... Other, std::input_iterator It>
+    template<typename Type, typename... Other, entt::stl::input_iterator It>
     size_type remove(It first, It last) {
         size_type count{};
 
@@ -761,7 +762,7 @@ public:
      * @param first An iterator to the first element of the range of entities.
      * @param last An iterator past the last element of the range of entities.
      */
-    template<typename Type, typename... Other, std::input_iterator It>
+    template<typename Type, typename... Other, entt::stl::input_iterator It>
     void erase(It first, It last) {
         if constexpr(std::is_same_v<It, typename common_type::iterator>) {
             std::array cpools{static_cast<common_type *>(&assure<Type>()), static_cast<common_type *>(&assure<Other>())...};

+ 2 - 1
src/entt/entity/snapshot.hpp

@@ -11,6 +11,7 @@
 #include "../config/config.h"
 #include "../container/dense_map.hpp"
 #include "../core/type_traits.hpp"
+#include "../stl/concepts.hpp"
 #include "entity.hpp"
 #include "fwd.hpp"
 #include "view.hpp"
@@ -137,7 +138,7 @@ public:
      * @return An object of this type to continue creating the snapshot.
      */
     template<typename Type, typename Archive>
-    const basic_snapshot &get(Archive &archive, std::input_iterator auto first, std::input_iterator auto last, const id_type id = type_hash<Type>::value()) const {
+    const basic_snapshot &get(Archive &archive, entt::stl::input_iterator auto first, entt::stl::input_iterator auto last, const id_type id = type_hash<Type>::value()) const {
         static_assert(!std::is_same_v<Type, entity_type>, "Entity types not supported");
 
         if(const auto *storage = reg->template storage<Type>(id); storage && !storage->empty()) {

+ 5 - 4
src/entt/entity/sparse_set.hpp

@@ -14,6 +14,7 @@
 #include "../core/any.hpp"
 #include "../core/bit.hpp"
 #include "../core/type_info.hpp"
+#include "../stl/concepts.hpp"
 #include "entity.hpp"
 #include "fwd.hpp"
 
@@ -791,7 +792,7 @@ public:
      * @return Iterator pointing to the first element inserted in case of
      * success, the `end()` iterator otherwise.
      */
-    iterator push(std::input_iterator auto first, std::input_iterator auto last) {
+    iterator push(entt::stl::input_iterator auto first, entt::stl::input_iterator auto last) {
         auto curr = end();
 
         for(; first != last; ++first) {
@@ -842,7 +843,7 @@ public:
      * @param first An iterator to the first element of the range of entities.
      * @param last An iterator past the last element of the range of entities.
      */
-    template<std::input_iterator It>
+    template<entt::stl::input_iterator It>
     void erase(It first, It last) {
         if constexpr(std::is_same_v<It, basic_iterator>) {
             pop(first, last);
@@ -869,7 +870,7 @@ public:
      * @param last An iterator past the last element of the range of entities.
      * @return The number of entities actually removed.
      */
-    template<std::input_iterator It>
+    template<entt::stl::input_iterator It>
     size_type remove(It first, It last) {
         size_type count{};
 
@@ -1028,7 +1029,7 @@ public:
      * @param last An iterator past the last element of the range of entities.
      * @return An iterator past the last of the elements actually shared.
      */
-    template<std::input_iterator It>
+    template<entt::stl::input_iterator It>
     iterator sort_as(It first, It last) {
         ENTT_ASSERT((mode != deletion_policy::in_place) || (head == max_size), "Sorting with tombstones not allowed");
         const size_type len = (mode == deletion_policy::swap_only) ? head : packed.size();

+ 3 - 2
src/entt/entity/storage.hpp

@@ -15,6 +15,7 @@
 #include "../core/iterator.hpp"
 #include "../core/memory.hpp"
 #include "../core/type_info.hpp"
+#include "../stl/concepts.hpp"
 #include "../stl/memory.hpp"
 #include "component.hpp"
 #include "entity.hpp"
@@ -693,7 +694,7 @@ public:
      * @param value An instance of the object to construct.
      * @return Iterator pointing to the first element inserted, if any.
      */
-    iterator insert(std::input_iterator auto first, std::input_iterator auto last, const value_type &value = {}) {
+    iterator insert(entt::stl::input_iterator auto first, entt::stl::input_iterator auto last, const value_type &value = {}) {
         for(; first != last; ++first) {
             emplace_element(*first, true, value);
         }
@@ -901,7 +902,7 @@ public:
      * @param first An iterator to the first element of the range of entities.
      * @param last An iterator past the last element of the range of entities.
      */
-    template<std::input_iterator It>
+    template<entt::stl::input_iterator It>
     void insert(It first, It last) {
         for(; first != last; ++first) {
             base_type::try_emplace(*first, true);

+ 1 - 0
src/entt/entt.hpp

@@ -65,6 +65,7 @@ namespace entt {}
 #include "signal/dispatcher.hpp"
 #include "signal/emitter.hpp"
 #include "signal/sigh.hpp"
+#include "stl/concepts.hpp"
 #include "stl/functional.hpp"
 #include "stl/memory.hpp"
 // IWYU pragma: end_exports

+ 3 - 2
src/entt/graph/flow.hpp

@@ -16,6 +16,7 @@
 #include "../core/compressed_pair.hpp"
 #include "../core/fwd.hpp"
 #include "../core/iterator.hpp"
+#include "../stl/concepts.hpp"
 #include "../stl/functional.hpp"
 #include "adjacency_matrix.hpp"
 #include "fwd.hpp"
@@ -288,7 +289,7 @@ public:
      * @param last An iterator past the last element of the range of elements.
      * @return This flow builder.
      */
-    basic_flow &ro(std::input_iterator auto first, std::input_iterator auto last) {
+    basic_flow &ro(entt::stl::input_iterator auto first, entt::stl::input_iterator auto last) {
         for(; first != last; ++first) {
             emplace(*first, false);
         }
@@ -312,7 +313,7 @@ public:
      * @param last An iterator past the last element of the range of elements.
      * @return This flow builder.
      */
-    basic_flow &rw(std::input_iterator auto first, std::input_iterator auto last) {
+    basic_flow &rw(entt::stl::input_iterator auto first, entt::stl::input_iterator auto last) {
         for(; first != last; ++first) {
             emplace(*first, true);
         }

+ 3 - 2
src/entt/meta/meta.hpp

@@ -17,6 +17,7 @@
 #include "../core/type_traits.hpp"
 #include "../core/utility.hpp"
 #include "../locator/locator.hpp"
+#include "../stl/concepts.hpp"
 #include "adl_pointer.hpp"
 #include "context.hpp"
 #include "fwd.hpp"
@@ -1617,7 +1618,7 @@ public:
 
     meta_iterator() = default;
 
-    template<std::bidirectional_iterator It>
+    template<entt::stl::bidirectional_iterator It>
     meta_iterator(const meta_ctx &area, It iter) noexcept
         : ctx{&area},
           vtable{&basic_vtable<It>},
@@ -1698,7 +1699,7 @@ public:
 
     meta_iterator() = default;
 
-    template<bool KeyOnly, std::forward_iterator It>
+    template<bool KeyOnly, entt::stl::forward_iterator It>
     meta_iterator(const meta_ctx &area, std::bool_constant<KeyOnly>, It iter) noexcept
         : ctx{&area},
           vtable{&basic_vtable<KeyOnly, It>},

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

@@ -8,6 +8,7 @@
 #include <utility>
 #include "../core/fwd.hpp"
 #include "../core/iterator.hpp"
+#include "../stl/concepts.hpp"
 #include "context.hpp"
 
 namespace entt {
@@ -111,7 +112,7 @@ private:
  * @tparam Type Type of meta objects returned.
  * @tparam It Type of forward iterator.
  */
-template<typename Type, std::forward_iterator It>
+template<typename Type, entt::stl::forward_iterator It>
 using meta_range = iterable_adaptor<internal::meta_range_iterator<Type, It>>;
 
 } // namespace entt

+ 84 - 0
src/entt/stl/concepts.hpp

@@ -0,0 +1,84 @@
+#ifndef ENTT_STL_CONCEPTS_HPP
+#define ENTT_STL_CONCEPTS_HPP
+
+#include "../config/config.h"
+
+/*! @cond ENTT_INTERNAL */
+namespace entt::stl {
+
+#ifndef ENTT_FORCE_STL
+#    if __has_include(<version>)
+#        include <version>
+#
+#        if defined(__cpp_lib_ranges)
+#            define ENTT_HAS_ITERATOR_CONCEPTS
+#            include <iterator>
+using std::bidirectional_iterator;
+using std::forward_iterator;
+using std::input_iterator;
+using std::input_or_output_iterator;
+using std::output_iterator;
+using std::random_access_iterator;
+using std::sentinel_for;
+#        endif
+#    endif
+#endif
+
+#ifndef ENTT_HAS_ITERATOR_CONCEPTS
+#    include <concepts>
+#    include <iterator>
+
+namespace internal {
+
+template<typename It>
+requires requires { typename std::iterator_traits<It>::iterator_category; }
+struct iterator_tag {
+    using type = typename std::iterator_traits<It>::iterator_category;
+};
+
+template<typename It>
+requires requires { typename It::iterator_concept; }
+struct iterator_tag<It> {
+    using type = typename It::iterator_concept;
+};
+
+template<typename It>
+using iterator_tag_t = typename iterator_tag<It>::type;
+
+} // namespace internal
+
+// Bare minimum definitions to support broken platforms like PS4.
+// EnTT does not provide full featured definitions for iterator concepts.
+
+template<typename It>
+concept input_or_output_iterator = requires(It it) {
+    *it;
+    { ++it } -> std::same_as<It &>;
+    it++;
+};
+
+template<typename It>
+concept input_iterator = std::derived_from<internal::iterator_tag_t<It>, std::input_iterator_tag>;
+
+template<typename It, typename Type>
+concept output_iterator = std::derived_from<internal::iterator_tag_t<It>, std::output_iterator_tag>;
+
+template<typename It>
+concept forward_iterator = std::derived_from<internal::iterator_tag_t<It>, std::forward_iterator_tag>;
+
+template<typename It>
+concept bidirectional_iterator = std::derived_from<internal::iterator_tag_t<It>, std::bidirectional_iterator_tag>;
+
+template<typename It>
+concept random_access_iterator = std::derived_from<internal::iterator_tag_t<It>, std::random_access_iterator_tag>;
+
+template<class Sentinel, typename It>
+concept sentinel_for = input_or_output_iterator<It> && requires(Sentinel sentinel, It it) {
+    { it == sentinel } -> std::same_as<bool>;
+};
+#endif
+
+} // namespace entt::stl
+/*! @endcond */
+
+#endif