Ver código fonte

core: reintroduce entt::identity (it's not available everywhere yet, I need to find a solution to inject it when needed)

skypjack 3 meses atrás
pai
commit
ce2c8b3b91

+ 4 - 0
docs/md/core.md

@@ -915,6 +915,10 @@ It is not possible to escape the temptation to add utilities of some kind to a
 library. In fact, `EnTT` also provides a handful of tools to simplify the
 life of developers:
 
+* `entt::identity`: the identity function object that will be available with
+  C++20. It returns its argument unchanged and nothing more. It is useful as a
+  sort of _do nothing_ function in template programming.
+
 * `entt::overload`: a tool to disambiguate different overloads from their
   function type. It works with both free and member functions.<br/>
   Consider the following definition:

+ 1 - 1
src/entt/core/algorithm.hpp

@@ -94,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<typename It, typename Getter = std::identity>
+    template<typename It, typename Getter = identity>
     void operator()(It first, It last, Getter getter = Getter{}) const {
         if(first < last) {
             constexpr auto passes = N / Bit;

+ 17 - 0
src/entt/core/utility.hpp

@@ -6,6 +6,23 @@
 
 namespace entt {
 
+/*! @brief Identity function object (waiting for C++20). */
+struct identity {
+    /*! @brief Indicates that this is a transparent function object. */
+    using is_transparent = void;
+
+    /**
+     * @brief Returns its argument unchanged.
+     * @tparam Type Type of the argument.
+     * @param value The actual argument.
+     * @return The submitted value as-is.
+     */
+    template<typename Type>
+    [[nodiscard]] constexpr Type &&operator()(Type &&value) const noexcept {
+        return std::forward<Type>(value);
+    }
+};
+
 /**
  * @brief Constant utility to disambiguate overloaded members of a class.
  * @tparam Type Type of the desired overload.

+ 3 - 3
src/entt/entity/registry.hpp

@@ -223,7 +223,7 @@ public:
     }
 
 private:
-    dense_map<id_type, basic_any<0u>, std::identity, std::equal_to<>, allocator_type> ctx;
+    dense_map<id_type, basic_any<0u>, identity, std::equal_to<>, allocator_type> ctx;
 };
 
 } // namespace internal
@@ -240,8 +240,8 @@ class basic_registry {
     using alloc_traits = std::allocator_traits<Allocator>;
     static_assert(std::is_same_v<typename alloc_traits::value_type, Entity>, "Invalid value type");
     // std::shared_ptr because of its type erased allocator which is useful here
-    using pool_container_type = dense_map<id_type, std::shared_ptr<base_type>, std::identity, std::equal_to<>, typename alloc_traits::template rebind_alloc<std::pair<const id_type, std::shared_ptr<base_type>>>>;
-    using group_container_type = dense_map<id_type, std::shared_ptr<internal::group_descriptor>, std::identity, std::equal_to<>, typename alloc_traits::template rebind_alloc<std::pair<const id_type, std::shared_ptr<internal::group_descriptor>>>>;
+    using pool_container_type = dense_map<id_type, std::shared_ptr<base_type>, identity, std::equal_to<>, typename alloc_traits::template rebind_alloc<std::pair<const id_type, std::shared_ptr<base_type>>>>;
+    using group_container_type = dense_map<id_type, std::shared_ptr<internal::group_descriptor>, identity, std::equal_to<>, typename alloc_traits::template rebind_alloc<std::pair<const id_type, std::shared_ptr<internal::group_descriptor>>>>;
     using traits_type = entt_traits<Entity>;
 
     template<typename Type>

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

@@ -29,9 +29,9 @@ template<typename Allocator>
 class basic_flow {
     using alloc_traits = std::allocator_traits<Allocator>;
     static_assert(std::is_same_v<typename alloc_traits::value_type, id_type>, "Invalid value type");
-    using task_container_type = dense_set<id_type, std::identity, std::equal_to<>, typename alloc_traits::template rebind_alloc<id_type>>;
+    using task_container_type = dense_set<id_type, identity, std::equal_to<>, typename alloc_traits::template rebind_alloc<id_type>>;
     using ro_rw_container_type = std::vector<std::pair<std::size_t, bool>, typename alloc_traits::template rebind_alloc<std::pair<std::size_t, bool>>>;
-    using deps_container_type = dense_map<id_type, ro_rw_container_type, std::identity, std::equal_to<>, typename alloc_traits::template rebind_alloc<std::pair<const id_type, ro_rw_container_type>>>;
+    using deps_container_type = dense_map<id_type, ro_rw_container_type, identity, std::equal_to<>, typename alloc_traits::template rebind_alloc<std::pair<const id_type, ro_rw_container_type>>>;
     using adjacency_matrix_type = adjacency_matrix<directed_tag, typename alloc_traits::template rebind_alloc<std::size_t>>;
 
     void emplace(const id_type res, const bool is_rw) {

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

@@ -1,7 +1,6 @@
 #ifndef ENTT_META_CTX_HPP
 #define ENTT_META_CTX_HPP
 
-#include <functional>
 #include <memory>
 #include "../container/dense_map.hpp"
 #include "../core/fwd.hpp"
@@ -16,7 +15,7 @@ namespace internal {
 struct meta_type_node;
 
 struct meta_context {
-    dense_map<id_type, std::unique_ptr<meta_type_node>, std::identity> value;
+    dense_map<id_type, std::unique_ptr<meta_type_node>, identity> value;
 
     [[nodiscard]] inline static meta_context &from(meta_ctx &);
     [[nodiscard]] inline static const meta_context &from(const meta_ctx &);

+ 1 - 1
src/entt/resource/cache.hpp

@@ -154,7 +154,7 @@ class resource_cache {
     using alloc_traits = std::allocator_traits<Allocator>;
     static_assert(std::is_same_v<typename alloc_traits::value_type, Type>, "Invalid value type");
     using container_allocator = typename alloc_traits::template rebind_alloc<std::pair<const id_type, typename Loader::result_type>>;
-    using container_type = dense_map<id_type, typename Loader::result_type, std::identity, std::equal_to<>, container_allocator>;
+    using container_type = dense_map<id_type, typename Loader::result_type, identity, std::equal_to<>, container_allocator>;
 
 public:
     /*! @brief Allocator type. */

+ 1 - 1
src/entt/signal/dispatcher.hpp

@@ -115,7 +115,7 @@ class basic_dispatcher {
 
     using alloc_traits = std::allocator_traits<Allocator>;
     using container_allocator = typename alloc_traits::template rebind_alloc<std::pair<const key_type, mapped_type>>;
-    using container_type = dense_map<key_type, mapped_type, std::identity, std::equal_to<>, container_allocator>;
+    using container_type = dense_map<key_type, mapped_type, identity, std::equal_to<>, container_allocator>;
 
     template<typename Type>
     [[nodiscard]] handler_type<Type> &assure(const id_type id) {

+ 1 - 1
src/entt/signal/emitter.hpp

@@ -39,7 +39,7 @@ class emitter {
 
     using alloc_traits = std::allocator_traits<Allocator>;
     using container_allocator = typename alloc_traits::template rebind_alloc<std::pair<const key_type, mapped_type>>;
-    using container_type = dense_map<key_type, mapped_type, std::identity, std::equal_to<>, container_allocator>;
+    using container_type = dense_map<key_type, mapped_type, identity, std::equal_to<>, container_allocator>;
 
 public:
     /*! @brief Allocator type. */

+ 21 - 21
test/entt/container/dense_map.cpp

@@ -21,7 +21,7 @@
 #include "../../common/transparent_equal_to.h"
 
 TEST(DenseMap, Functionalities) {
-    entt::dense_map<int, int, std::identity, test::transparent_equal_to> map;
+    entt::dense_map<int, int, entt::identity, test::transparent_equal_to> map;
     const auto &cmap = map;
 
     ASSERT_NO_THROW([[maybe_unused]] auto alloc = map.get_allocator());
@@ -115,12 +115,12 @@ TEST(DenseMap, Constructors) {
 }
 
 TEST(DenseMap, Copy) {
-    entt::dense_map<std::size_t, std::size_t, std::identity> map;
+    entt::dense_map<std::size_t, std::size_t, entt::identity> map;
     const auto max_load_factor = map.max_load_factor() - .05f;
     map.max_load_factor(max_load_factor);
     map.emplace(3u, 1u);
 
-    entt::dense_map<std::size_t, std::size_t, std::identity> other{map};
+    entt::dense_map<std::size_t, std::size_t, entt::identity> other{map};
 
     ASSERT_TRUE(map.contains(3u));
     ASSERT_TRUE(other.contains(3u));
@@ -148,12 +148,12 @@ TEST(DenseMap, Copy) {
 }
 
 TEST(DenseMap, Move) {
-    entt::dense_map<std::size_t, std::size_t, std::identity> map;
+    entt::dense_map<std::size_t, std::size_t, entt::identity> map;
     const auto max_load_factor = map.max_load_factor() - .05f;
     map.max_load_factor(max_load_factor);
     map.emplace(3u, 1u);
 
-    entt::dense_map<std::size_t, std::size_t, std::identity> other{std::move(map)};
+    entt::dense_map<std::size_t, std::size_t, entt::identity> other{std::move(map)};
 
     test::is_initialized(map);
 
@@ -396,7 +396,7 @@ TEST(DenseMap, Insert) {
 
 TEST(DenseMap, InsertRehash) {
     constexpr std::size_t minimum_bucket_count = 8u;
-    entt::dense_map<std::size_t, std::size_t, std::identity> map;
+    entt::dense_map<std::size_t, std::size_t, entt::identity> map;
 
     ASSERT_EQ(map.size(), 0u);
     ASSERT_EQ(map.bucket_count(), minimum_bucket_count);
@@ -430,7 +430,7 @@ TEST(DenseMap, InsertRehash) {
 
 TEST(DenseMap, InsertSameBucket) {
     constexpr std::size_t minimum_bucket_count = 8u;
-    entt::dense_map<std::size_t, std::size_t, std::identity> map;
+    entt::dense_map<std::size_t, std::size_t, entt::identity> map;
 
     for(std::size_t next{}; next < minimum_bucket_count; ++next) {
         ASSERT_EQ(map.cbegin(next), map.cend(next));
@@ -599,7 +599,7 @@ TEST(DenseMap, Emplace) {
 
 TEST(DenseMap, EmplaceRehash) {
     constexpr std::size_t minimum_bucket_count = 8u;
-    entt::dense_map<std::size_t, std::size_t, std::identity> map;
+    entt::dense_map<std::size_t, std::size_t, entt::identity> map;
 
     ASSERT_EQ(map.size(), 0u);
     ASSERT_EQ(map.bucket_count(), minimum_bucket_count);
@@ -634,7 +634,7 @@ TEST(DenseMap, EmplaceRehash) {
 
 TEST(DenseMap, EmplaceSameBucket) {
     constexpr std::size_t minimum_bucket_count = 8u;
-    entt::dense_map<std::size_t, std::size_t, std::identity> map;
+    entt::dense_map<std::size_t, std::size_t, entt::identity> map;
 
     for(std::size_t next{}; next < minimum_bucket_count; ++next) {
         ASSERT_EQ(map.cbegin(next), map.cend(next));
@@ -682,7 +682,7 @@ TEST(DenseMap, TryEmplace) {
 
 TEST(DenseMap, TryEmplaceRehash) {
     constexpr std::size_t minimum_bucket_count = 8u;
-    entt::dense_map<std::size_t, std::size_t, std::identity> map;
+    entt::dense_map<std::size_t, std::size_t, entt::identity> map;
 
     ASSERT_EQ(map.size(), 0u);
     ASSERT_EQ(map.bucket_count(), minimum_bucket_count);
@@ -716,7 +716,7 @@ TEST(DenseMap, TryEmplaceRehash) {
 
 TEST(DenseMap, TryEmplaceSameBucket) {
     constexpr std::size_t minimum_bucket_count = 8u;
-    entt::dense_map<std::size_t, std::size_t, std::identity> map;
+    entt::dense_map<std::size_t, std::size_t, entt::identity> map;
 
     for(std::size_t next{}; next < minimum_bucket_count; ++next) {
         ASSERT_EQ(map.cbegin(next), map.cend(next));
@@ -750,7 +750,7 @@ TEST(DenseMap, TryEmplaceMovableType) {
 
 TEST(DenseMap, Erase) {
     constexpr std::size_t minimum_bucket_count = 8u;
-    entt::dense_map<std::size_t, std::size_t, std::identity> map;
+    entt::dense_map<std::size_t, std::size_t, entt::identity> map;
 
     for(std::size_t next{}, last = minimum_bucket_count + 1u; next < last; ++next) {
         map.emplace(next, next);
@@ -812,7 +812,7 @@ TEST(DenseMap, EraseWithMovableKeyValue) {
 
 TEST(DenseMap, EraseFromBucket) {
     constexpr std::size_t minimum_bucket_count = 8u;
-    entt::dense_map<std::size_t, std::size_t, std::identity> map;
+    entt::dense_map<std::size_t, std::size_t, entt::identity> map;
 
     ASSERT_EQ(map.bucket_count(), minimum_bucket_count);
     ASSERT_EQ(map.size(), 0u);
@@ -921,7 +921,7 @@ TEST(DenseMap, Swap) {
 }
 
 TEST(DenseMap, EqualRange) {
-    entt::dense_map<int, int, std::identity, test::transparent_equal_to> map;
+    entt::dense_map<int, int, entt::identity, test::transparent_equal_to> map;
     const auto &cmap = map;
 
     map.emplace(4, 1);
@@ -960,7 +960,7 @@ TEST(DenseMap, EqualRange) {
 }
 
 TEST(DenseMap, Indexing) {
-    entt::dense_map<int, int, std::identity, test::transparent_equal_to> map;
+    entt::dense_map<int, int, entt::identity, test::transparent_equal_to> map;
     const auto &cmap = map;
     const auto key = 1;
 
@@ -979,7 +979,7 @@ TEST(DenseMap, Indexing) {
 }
 
 ENTT_DEBUG_TEST(DenseMapDeathTest, Indexing) {
-    entt::dense_map<int, int, std::identity, test::transparent_equal_to> map;
+    entt::dense_map<int, int, entt::identity, test::transparent_equal_to> map;
     const auto &cmap = map;
 
     ASSERT_DEATH([[maybe_unused]] auto value = map.at(3), "");
@@ -990,14 +990,14 @@ ENTT_DEBUG_TEST(DenseMapDeathTest, Indexing) {
 }
 
 TEST(DenseMap, LocalIterator) {
-    using iterator = typename entt::dense_map<std::size_t, std::size_t, std::identity>::local_iterator;
+    using iterator = typename entt::dense_map<std::size_t, std::size_t, entt::identity>::local_iterator;
 
     testing::StaticAssertTypeEq<iterator::value_type, std::pair<const std::size_t &, std::size_t &>>();
     testing::StaticAssertTypeEq<iterator::pointer, entt::input_iterator_pointer<std::pair<const std::size_t &, std::size_t &>>>();
     testing::StaticAssertTypeEq<iterator::reference, std::pair<const std::size_t &, std::size_t &>>();
 
     constexpr std::size_t minimum_bucket_count = 8u;
-    entt::dense_map<std::size_t, std::size_t, std::identity> map;
+    entt::dense_map<std::size_t, std::size_t, entt::identity> map;
     map.emplace(3u, 2u);
     map.emplace(3u + minimum_bucket_count, 1u);
 
@@ -1018,14 +1018,14 @@ TEST(DenseMap, LocalIterator) {
 }
 
 TEST(DenseMap, ConstLocalIterator) {
-    using iterator = typename entt::dense_map<std::size_t, std::size_t, std::identity>::const_local_iterator;
+    using iterator = typename entt::dense_map<std::size_t, std::size_t, entt::identity>::const_local_iterator;
 
     testing::StaticAssertTypeEq<iterator::value_type, std::pair<const std::size_t &, const std::size_t &>>();
     testing::StaticAssertTypeEq<iterator::pointer, entt::input_iterator_pointer<std::pair<const std::size_t &, const std::size_t &>>>();
     testing::StaticAssertTypeEq<iterator::reference, std::pair<const std::size_t &, const std::size_t &>>();
 
     constexpr std::size_t minimum_bucket_count = 8u;
-    entt::dense_map<std::size_t, std::size_t, std::identity> map;
+    entt::dense_map<std::size_t, std::size_t, entt::identity> map;
     map.emplace(3u, 2u);
     map.emplace(3u + minimum_bucket_count, 1u);
 
@@ -1066,7 +1066,7 @@ TEST(DenseMap, LocalIteratorConversion) {
 
 TEST(DenseMap, Rehash) {
     constexpr std::size_t minimum_bucket_count = 8u;
-    entt::dense_map<std::size_t, std::size_t, std::identity> map;
+    entt::dense_map<std::size_t, std::size_t, entt::identity> map;
     map[32u] = 2u;
 
     ASSERT_EQ(map.bucket_count(), minimum_bucket_count);

+ 17 - 17
test/entt/container/dense_set.cpp

@@ -18,7 +18,7 @@
 #include "../../common/transparent_equal_to.h"
 
 TEST(DenseSet, Functionalities) {
-    entt::dense_set<int, std::identity, test::transparent_equal_to> set;
+    entt::dense_set<int, entt::identity, test::transparent_equal_to> set;
     const auto &cset = set;
 
     ASSERT_NO_THROW([[maybe_unused]] auto alloc = set.get_allocator());
@@ -112,12 +112,12 @@ TEST(DenseSet, Constructors) {
 }
 
 TEST(DenseSet, Copy) {
-    entt::dense_set<std::size_t, std::identity> set;
+    entt::dense_set<std::size_t, entt::identity> set;
     const auto max_load_factor = set.max_load_factor() - .05f;
     set.max_load_factor(max_load_factor);
     set.emplace(3u);
 
-    entt::dense_set<std::size_t, std::identity> other{set};
+    entt::dense_set<std::size_t, entt::identity> other{set};
 
     ASSERT_TRUE(set.contains(3u));
     ASSERT_TRUE(other.contains(3u));
@@ -141,12 +141,12 @@ TEST(DenseSet, Copy) {
 }
 
 TEST(DenseSet, Move) {
-    entt::dense_set<std::size_t, std::identity> set;
+    entt::dense_set<std::size_t, entt::identity> set;
     const auto max_load_factor = set.max_load_factor() - .05f;
     set.max_load_factor(max_load_factor);
     set.emplace(3u);
 
-    entt::dense_set<std::size_t, std::identity> other{std::move(set)};
+    entt::dense_set<std::size_t, entt::identity> other{std::move(set)};
 
     test::is_initialized(set);
 
@@ -462,7 +462,7 @@ TEST(DenseSet, Insert) {
 
 TEST(DenseSet, InsertRehash) {
     constexpr std::size_t minimum_bucket_count = 8u;
-    entt::dense_set<std::size_t, std::identity> set;
+    entt::dense_set<std::size_t, entt::identity> set;
 
     ASSERT_EQ(set.size(), 0u);
     ASSERT_EQ(set.bucket_count(), minimum_bucket_count);
@@ -493,7 +493,7 @@ TEST(DenseSet, InsertRehash) {
 
 TEST(DenseSet, InsertSameBucket) {
     constexpr std::size_t minimum_bucket_count = 8u;
-    entt::dense_set<std::size_t, std::identity> set;
+    entt::dense_set<std::size_t, entt::identity> set;
 
     for(std::size_t next{}; next < minimum_bucket_count; ++next) {
         ASSERT_EQ(set.cbegin(next), set.cend(next));
@@ -556,7 +556,7 @@ TEST(DenseSet, Emplace) {
 
 TEST(DenseSet, EmplaceRehash) {
     constexpr std::size_t minimum_bucket_count = 8u;
-    entt::dense_set<std::size_t, std::identity> set;
+    entt::dense_set<std::size_t, entt::identity> set;
 
     ASSERT_EQ(set.size(), 0u);
     ASSERT_EQ(set.bucket_count(), minimum_bucket_count);
@@ -588,7 +588,7 @@ TEST(DenseSet, EmplaceRehash) {
 
 TEST(DenseSet, EmplaceSameBucket) {
     constexpr std::size_t minimum_bucket_count = 8u;
-    entt::dense_set<std::size_t, std::identity> set;
+    entt::dense_set<std::size_t, entt::identity> set;
 
     for(std::size_t next{}; next < minimum_bucket_count; ++next) {
         ASSERT_EQ(set.cbegin(next), set.cend(next));
@@ -608,7 +608,7 @@ TEST(DenseSet, EmplaceSameBucket) {
 
 TEST(DenseSet, Erase) {
     constexpr std::size_t minimum_bucket_count = 8u;
-    entt::dense_set<std::size_t, std::identity> set;
+    entt::dense_set<std::size_t, entt::identity> set;
 
     for(std::size_t next{}, last = minimum_bucket_count + 1u; next < last; ++next) {
         set.emplace(next);
@@ -669,7 +669,7 @@ TEST(DenseSet, EraseWithMovableKeyValue) {
 
 TEST(DenseSet, EraseFromBucket) {
     constexpr std::size_t minimum_bucket_count = 8u;
-    entt::dense_set<std::size_t, std::identity> set;
+    entt::dense_set<std::size_t, entt::identity> set;
 
     ASSERT_EQ(set.bucket_count(), minimum_bucket_count);
     ASSERT_EQ(set.size(), 0u);
@@ -778,7 +778,7 @@ TEST(DenseSet, Swap) {
 }
 
 TEST(DenseSet, EqualRange) {
-    entt::dense_set<int, std::identity, test::transparent_equal_to> set;
+    entt::dense_set<int, entt::identity, test::transparent_equal_to> set;
     const auto &cset = set;
 
     set.emplace(1);
@@ -813,14 +813,14 @@ TEST(DenseSet, EqualRange) {
 }
 
 TEST(DenseSet, LocalIterator) {
-    using iterator = typename entt::dense_set<std::size_t, std::identity>::local_iterator;
+    using iterator = typename entt::dense_set<std::size_t, entt::identity>::local_iterator;
 
     testing::StaticAssertTypeEq<iterator::value_type, std::size_t>();
     testing::StaticAssertTypeEq<iterator::pointer, const std::size_t *>();
     testing::StaticAssertTypeEq<iterator::reference, const std::size_t &>();
 
     constexpr std::size_t minimum_bucket_count = 8u;
-    entt::dense_set<std::size_t, std::identity> set;
+    entt::dense_set<std::size_t, entt::identity> set;
     set.emplace(3u);
     set.emplace(3u + minimum_bucket_count);
 
@@ -841,14 +841,14 @@ TEST(DenseSet, LocalIterator) {
 }
 
 TEST(DenseSet, ConstLocalIterator) {
-    using iterator = typename entt::dense_set<std::size_t, std::identity>::const_local_iterator;
+    using iterator = typename entt::dense_set<std::size_t, entt::identity>::const_local_iterator;
 
     testing::StaticAssertTypeEq<iterator::value_type, std::size_t>();
     testing::StaticAssertTypeEq<iterator::pointer, const std::size_t *>();
     testing::StaticAssertTypeEq<iterator::reference, const std::size_t &>();
 
     constexpr std::size_t minimum_bucket_count = 8u;
-    entt::dense_set<std::size_t, std::identity> set;
+    entt::dense_set<std::size_t, entt::identity> set;
     set.emplace(3u);
     set.emplace(3u + minimum_bucket_count);
 
@@ -889,7 +889,7 @@ TEST(DenseSet, LocalIteratorConversion) {
 
 TEST(DenseSet, Rehash) {
     constexpr std::size_t minimum_bucket_count = 8u;
-    entt::dense_set<std::size_t, std::identity> set;
+    entt::dense_set<std::size_t, entt::identity> set;
     set.emplace(32u);
 
     ASSERT_EQ(set.bucket_count(), minimum_bucket_count);

+ 9 - 0
test/entt/core/utility.cpp

@@ -11,6 +11,15 @@ struct functions {
     void bar() {}
 };
 
+TEST(Identity, Functionalities) {
+    const entt::identity identity;
+    int value = 2;
+
+    ASSERT_TRUE(entt::is_transparent_v<entt::identity>);
+    ASSERT_EQ(identity(value), value);
+    ASSERT_EQ(&identity(value), &value);
+}
+
 TEST(Overload, Functionalities) {
     ASSERT_EQ(entt::overload<void(int)>(&functions::foo), static_cast<void (*)(int)>(&functions::foo));
     ASSERT_EQ(entt::overload<void()>(&functions::foo), static_cast<void (*)()>(&functions::foo));