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

This commit is contained in:
skypjack
2026-01-29 12:36:02 +01:00
parent ad330e4c94
commit 9d0028e036
16 changed files with 124 additions and 25 deletions

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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)...);

View File

@@ -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>())...};

View File

@@ -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()) {

View File

@@ -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();

View File

@@ -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);

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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>},

View File

@@ -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
src/entt/stl/concepts.hpp Normal file
View File

@@ -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