2
0

resource.hpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. #ifndef ENTT_RESOURCE_RESOURCE_HPP
  2. #define ENTT_RESOURCE_RESOURCE_HPP
  3. #include <memory>
  4. #include <type_traits>
  5. #include <utility>
  6. #include "fwd.hpp"
  7. namespace entt {
  8. /**
  9. * @brief Basic resource handle.
  10. *
  11. * A handle wraps a resource and extends its lifetime. It also shares the same
  12. * resource with all other handles constructed from the same element.<br/>
  13. * As a rule of thumb, resources should never be copied nor moved. Handles are
  14. * the way to go to push references around.
  15. *
  16. * @tparam Type Type of resource managed by a handle.
  17. */
  18. template<typename Type>
  19. class resource {
  20. template<typename>
  21. friend class resource;
  22. template<typename Other>
  23. static constexpr bool is_acceptable_v = !std::is_same_v<Type, Other> && std::is_constructible_v<Type &, Other &>;
  24. public:
  25. /*! @brief Resource type. */
  26. using element_type = Type;
  27. /*! @brief Handle type. */
  28. using handle_type = std::shared_ptr<element_type>;
  29. /*! @brief Default constructor. */
  30. resource() noexcept
  31. : value{} {}
  32. /**
  33. * @brief Creates a handle from a weak pointer, namely a resource.
  34. * @param res A weak pointer to a resource.
  35. */
  36. explicit resource(handle_type res) noexcept
  37. : value{std::move(res)} {}
  38. /*! @brief Default copy constructor. */
  39. resource(const resource &) noexcept = default;
  40. /*! @brief Default move constructor. */
  41. resource(resource &&) noexcept = default;
  42. /**
  43. * @brief Aliasing constructor.
  44. * @tparam Other Type of resource managed by the received handle.
  45. * @param other The handle with which to share ownership information.
  46. * @param res Unrelated and unmanaged resources.
  47. */
  48. template<typename Other>
  49. resource(const resource<Other> &other, element_type &res) noexcept
  50. : value{other.value, std::addressof(res)} {}
  51. /**
  52. * @brief Copy constructs a handle which shares ownership of the resource.
  53. * @tparam Other Type of resource managed by the received handle.
  54. * @param other The handle to copy from.
  55. */
  56. template<typename Other, typename = std::enable_if_t<is_acceptable_v<Other>>>
  57. resource(const resource<Other> &other) noexcept
  58. : value{other.value} {}
  59. /**
  60. * @brief Move constructs a handle which takes ownership of the resource.
  61. * @tparam Other Type of resource managed by the received handle.
  62. * @param other The handle to move from.
  63. */
  64. template<typename Other, typename = std::enable_if_t<is_acceptable_v<Other>>>
  65. resource(resource<Other> &&other) noexcept
  66. : value{std::move(other.value)} {}
  67. /**
  68. * @brief Default copy assignment operator.
  69. * @return This resource handle.
  70. */
  71. resource &operator=(const resource &) noexcept = default;
  72. /**
  73. * @brief Default move assignment operator.
  74. * @return This resource handle.
  75. */
  76. resource &operator=(resource &&) noexcept = default;
  77. /**
  78. * @brief Copy assignment operator from foreign handle.
  79. * @tparam Other Type of resource managed by the received handle.
  80. * @param other The handle to copy from.
  81. * @return This resource handle.
  82. */
  83. template<typename Other>
  84. std::enable_if_t<is_acceptable_v<Other>, resource &>
  85. operator=(const resource<Other> &other) noexcept {
  86. value = other.value;
  87. return *this;
  88. }
  89. /**
  90. * @brief Move assignment operator from foreign handle.
  91. * @tparam Other Type of resource managed by the received handle.
  92. * @param other The handle to move from.
  93. * @return This resource handle.
  94. */
  95. template<typename Other>
  96. std::enable_if_t<is_acceptable_v<Other>, resource &>
  97. operator=(resource<Other> &&other) noexcept {
  98. value = std::move(other.value);
  99. return *this;
  100. }
  101. /**
  102. * @brief Returns a reference to the managed resource.
  103. *
  104. * @warning
  105. * The behavior is undefined if the handle doesn't contain a resource.
  106. *
  107. * @return A reference to the managed resource.
  108. */
  109. [[nodiscard]] element_type &operator*() const noexcept {
  110. return *value;
  111. }
  112. /*! @copydoc operator* */
  113. [[nodiscard]] operator element_type &() const noexcept {
  114. return *value;
  115. }
  116. /**
  117. * @brief Returns a pointer to the managed resource.
  118. * @return A pointer to the managed resource.
  119. */
  120. [[nodiscard]] element_type *operator->() const noexcept {
  121. return value.get();
  122. }
  123. /**
  124. * @brief Returns true if a handle contains a resource, false otherwise.
  125. * @return True if the handle contains a resource, false otherwise.
  126. */
  127. [[nodiscard]] explicit operator bool() const noexcept {
  128. return static_cast<bool>(value);
  129. }
  130. /**
  131. * @brief Returns the underlying resource handle.
  132. * @return The underlying resource handle.
  133. */
  134. [[nodiscard]] const handle_type &handle() const noexcept {
  135. return value;
  136. }
  137. private:
  138. handle_type value;
  139. };
  140. /**
  141. * @brief Compares two handles.
  142. * @tparam Lhs Type of resource managed by the first handle.
  143. * @tparam Rhs Type of resource managed by the second handle.
  144. * @param lhs A valid handle.
  145. * @param rhs A valid handle.
  146. * @return True if both handles refer to the same resource, false otherwise.
  147. */
  148. template<typename Lhs, typename Rhs>
  149. [[nodiscard]] bool operator==(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept {
  150. return (std::addressof(*lhs) == std::addressof(*rhs));
  151. }
  152. /**
  153. * @brief Compares two handles.
  154. * @tparam Lhs Type of resource managed by the first handle.
  155. * @tparam Rhs Type of resource managed by the second handle.
  156. * @param lhs A valid handle.
  157. * @param rhs A valid handle.
  158. * @return False if both handles refer to the same resource, true otherwise.
  159. */
  160. template<typename Lhs, typename Rhs>
  161. [[nodiscard]] bool operator!=(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept {
  162. return !(lhs == rhs);
  163. }
  164. /**
  165. * @brief Compares two handles.
  166. * @tparam Lhs Type of resource managed by the first handle.
  167. * @tparam Rhs Type of resource managed by the second handle.
  168. * @param lhs A valid handle.
  169. * @param rhs A valid handle.
  170. * @return True if the first handle is less than the second, false otherwise.
  171. */
  172. template<typename Lhs, typename Rhs>
  173. [[nodiscard]] bool operator<(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept {
  174. return (std::addressof(*lhs) < std::addressof(*rhs));
  175. }
  176. /**
  177. * @brief Compares two handles.
  178. * @tparam Lhs Type of resource managed by the first handle.
  179. * @tparam Rhs Type of resource managed by the second handle.
  180. * @param lhs A valid handle.
  181. * @param rhs A valid handle.
  182. * @return True if the first handle is greater than the second, false otherwise.
  183. */
  184. template<typename Lhs, typename Rhs>
  185. [[nodiscard]] bool operator>(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept {
  186. return rhs < lhs;
  187. }
  188. /**
  189. * @brief Compares two handles.
  190. * @tparam Lhs Type of resource managed by the first handle.
  191. * @tparam Rhs Type of resource managed by the second handle.
  192. * @param lhs A valid handle.
  193. * @param rhs A valid handle.
  194. * @return True if the first handle is less than or equal to the second, false
  195. * otherwise.
  196. */
  197. template<typename Lhs, typename Rhs>
  198. [[nodiscard]] bool operator<=(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept {
  199. return !(lhs > rhs);
  200. }
  201. /**
  202. * @brief Compares two handles.
  203. * @tparam Lhs Type of resource managed by the first handle.
  204. * @tparam Rhs Type of resource managed by the second handle.
  205. * @param lhs A valid handle.
  206. * @param rhs A valid handle.
  207. * @return True if the first handle is greater than or equal to the second,
  208. * false otherwise.
  209. */
  210. template<typename Lhs, typename Rhs>
  211. [[nodiscard]] bool operator>=(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept {
  212. return !(lhs < rhs);
  213. }
  214. } // namespace entt
  215. #endif