EnTT  3.9.0
memory.hpp
1 #ifndef ENTT_CORE_MEMORY_HPP
2 #define ENTT_CORE_MEMORY_HPP
3 
4 #include <cstddef>
5 #include <limits>
6 #include <memory>
7 #include <type_traits>
8 #include <utility>
9 #include "../config/config.h"
10 
11 namespace entt {
12 
19 template<typename Type>
20 [[nodiscard]] constexpr auto to_address(Type &&ptr) ENTT_NOEXCEPT {
21  if constexpr(std::is_pointer_v<std::remove_const_t<std::remove_reference_t<Type>>>) {
22  return ptr;
23  } else {
24  return to_address(std::forward<Type>(ptr).operator->());
25  }
26 }
27 
34 template<typename Allocator>
35 constexpr void propagate_on_container_copy_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) ENTT_NOEXCEPT {
36  if constexpr(std::allocator_traits<Allocator>::propagate_on_container_copy_assignment::value) {
37  lhs = rhs;
38  }
39 }
40 
47 template<typename Allocator>
48 constexpr void propagate_on_container_move_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) ENTT_NOEXCEPT {
49  if constexpr(std::allocator_traits<Allocator>::propagate_on_container_move_assignment::value) {
50  lhs = std::move(rhs);
51  }
52 }
53 
60 template<typename Allocator>
61 constexpr void propagate_on_container_swap([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs) ENTT_NOEXCEPT {
62  ENTT_ASSERT(std::allocator_traits<Allocator>::propagate_on_container_swap::value || lhs == rhs, "Cannot swap the containers");
63 
64  if constexpr(std::allocator_traits<Allocator>::propagate_on_container_swap::value) {
65  using std::swap;
66  swap(lhs, rhs);
67  }
68 }
69 
75 [[nodiscard]] inline constexpr bool is_power_of_two(const std::size_t value) ENTT_NOEXCEPT {
76  return value && ((value & (value - 1)) == 0);
77 }
78 
84 [[nodiscard]] inline constexpr std::size_t next_power_of_two(const std::size_t value) ENTT_NOEXCEPT {
85  ENTT_ASSERT(value < (std::size_t{1u} << (std::numeric_limits<std::size_t>::digits - 1)), "Numeric limits exceeded");
86  std::size_t curr = value - (value != 0u);
87 
88  for(int next = 1; next < std::numeric_limits<std::size_t>::digits; next = next * 2) {
89  curr |= curr >> next;
90  }
91 
92  return ++curr;
93 }
94 
101 [[nodiscard]] inline constexpr std::size_t fast_mod(const std::size_t value, const std::size_t mod) ENTT_NOEXCEPT {
102  ENTT_ASSERT(is_power_of_two(mod), "Value must be a power of two");
103  return value & (mod - 1u);
104 }
105 
106 } // namespace entt
107 
108 #endif
EnTT default namespace.
constexpr void propagate_on_container_move_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs)
Utility function to design allocation-aware containers.
Definition: memory.hpp:48
constexpr void propagate_on_container_swap([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs)
Utility function to design allocation-aware containers.
Definition: memory.hpp:61
constexpr std::size_t fast_mod(const std::size_t value, const std::size_t mod)
Fast module utility function (powers of two only).
Definition: memory.hpp:101
constexpr bool is_power_of_two(const std::size_t value)
Checks whether a value is a power of two or not.
Definition: memory.hpp:75
constexpr std::size_t next_power_of_two(const std::size_t value)
Computes the smallest power of two greater than or equal to a value.
Definition: memory.hpp:84
constexpr auto to_address(Type &&ptr)
Unwraps fancy pointers, does nothing otherwise (waiting for C++20).
Definition: memory.hpp:20
constexpr void propagate_on_container_copy_assignment([[maybe_unused]] Allocator &lhs, [[maybe_unused]] Allocator &rhs)
Utility function to design allocation-aware containers.
Definition: memory.hpp:35
void swap(compressed_pair< First, Second > &lhs, compressed_pair< First, Second > &rhs)
Swaps two compressed pair objects.