Просмотр исходного кода

memory: added pocca/pocma/pocs utility functions

Michele Caini 4 лет назад
Родитель
Сommit
52ea5e4074
2 измененных файлов с 68 добавлено и 0 удалено
  1. 46 0
      src/entt/core/memory.hpp
  2. 22 0
      test/entt/core/memory.cpp

+ 46 - 0
src/entt/core/memory.hpp

@@ -27,6 +27,52 @@ constexpr auto to_address(Type &&ptr) ENTT_NOEXCEPT {
 }
 
 
+/**
+ * @brief Utility function to design allocation-aware containers.
+ * @tparam Allocator Type of allocator.
+ * @param lhs A valid allocator.
+ * @param rhs Another valid allocator.
+ */
+template<typename Allocator>
+constexpr void propagate_on_container_copy_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) ENTT_NOEXCEPT {
+    if constexpr(std::allocator_traits<Allocator>::propagate_on_container_copy_assignment::value) {
+        lhs = rhs;
+    }
+}
+
+
+/**
+ * @brief Utility function to design allocation-aware containers.
+ * @tparam Allocator Type of allocator.
+ * @param lhs A valid allocator.
+ * @param rhs Another valid allocator.
+ */
+template<typename Allocator>
+constexpr void propagate_on_container_move_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) ENTT_NOEXCEPT {
+    if constexpr(std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) {
+        lhs = std::move(rhs);
+    }
+}
+
+
+/**
+ * @brief Utility function to design allocation-aware containers.
+ * @tparam Allocator Type of allocator.
+ * @param lhs A valid allocator.
+ * @param rhs Another valid allocator.
+ */
+template<typename Allocator>
+constexpr void propagate_on_container_swap(Allocator &lhs, Allocator &rhs) ENTT_NOEXCEPT {
+    static constexpr auto pocs = std::allocator_traits<Allocator>::propagate_on_container_swap::value;
+    ENTT_ASSERT(pocs || lhs == rhs, "Cannot swap the containers");
+
+    if constexpr(pocs) {
+        using std::swap;
+        swap(lhs, rhs);
+    }
+}
+
+
 }
 
 

+ 22 - 0
test/entt/core/memory.cpp

@@ -2,6 +2,20 @@
 #include <gtest/gtest.h>
 #include <entt/core/memory.hpp>
 
+struct test_allocator: std::allocator<int> {
+    using base = std::allocator<int>;
+    using propagate_on_container_copy_assignment = std::true_type;
+    using propagate_on_container_swap = std::true_type;
+
+    using std::allocator<int>::allocator;
+
+    test_allocator & operator=(const test_allocator &other) {
+        // necessary to avoid call suppression
+        base::operator=(other);
+        return *this;
+    }
+};
+
 TEST(Memory, ToAddress) {
     std::shared_ptr<int> shared = std::make_shared<int>();
     auto *plain = std::addressof(*shared);
@@ -9,3 +23,11 @@ TEST(Memory, ToAddress) {
     ASSERT_EQ(entt::to_address(shared), plain);
     ASSERT_EQ(entt::to_address(plain), plain);
 }
+
+TEST(Memory, PoccaPocmaAndPocs) {
+    test_allocator lhs, rhs;
+    // honestly, I don't even know how one is supposed to test such a thing :)
+    entt::propagate_on_container_copy_assignment(lhs, rhs);
+    entt::propagate_on_container_move_assignment(lhs, rhs);
+    entt::propagate_on_container_swap(lhs, rhs);
+}