| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- #ifndef ENTT_RESOURCE_RESOURCE_HPP
- #define ENTT_RESOURCE_RESOURCE_HPP
- #include <memory>
- #include <type_traits>
- #include <utility>
- #include "fwd.hpp"
- namespace entt {
- /**
- * @brief Basic resource handle.
- *
- * A handle wraps a resource and extends its lifetime. It also shares the same
- * resource with all other handles constructed from the same element.<br/>
- * As a rule of thumb, resources should never be copied nor moved. Handles are
- * the way to go to push references around.
- *
- * @tparam Type Type of resource managed by a handle.
- */
- template<typename Type>
- class resource {
- template<typename>
- friend class resource;
- template<typename Other>
- static constexpr bool is_acceptable_v = !std::is_same_v<Type, Other> && std::is_constructible_v<Type &, Other &>;
- public:
- /*! @brief Resource type. */
- using element_type = Type;
- /*! @brief Handle type. */
- using handle_type = std::shared_ptr<element_type>;
- /*! @brief Default constructor. */
- resource() noexcept
- : value{} {}
- /**
- * @brief Creates a handle from a weak pointer, namely a resource.
- * @param res A weak pointer to a resource.
- */
- explicit resource(handle_type res) noexcept
- : value{std::move(res)} {}
- /*! @brief Default copy constructor. */
- resource(const resource &) noexcept = default;
- /*! @brief Default move constructor. */
- resource(resource &&) noexcept = default;
- /**
- * @brief Aliasing constructor.
- * @tparam Other Type of resource managed by the received handle.
- * @param other The handle with which to share ownership information.
- * @param res Unrelated and unmanaged resources.
- */
- template<typename Other>
- resource(const resource<Other> &other, element_type &res) noexcept
- : value{other.value, std::addressof(res)} {}
- /**
- * @brief Copy constructs a handle which shares ownership of the resource.
- * @tparam Other Type of resource managed by the received handle.
- * @param other The handle to copy from.
- */
- template<typename Other, typename = std::enable_if_t<is_acceptable_v<Other>>>
- resource(const resource<Other> &other) noexcept
- : value{other.value} {}
- /**
- * @brief Move constructs a handle which takes ownership of the resource.
- * @tparam Other Type of resource managed by the received handle.
- * @param other The handle to move from.
- */
- template<typename Other, typename = std::enable_if_t<is_acceptable_v<Other>>>
- resource(resource<Other> &&other) noexcept
- : value{std::move(other.value)} {}
- /**
- * @brief Default copy assignment operator.
- * @return This resource handle.
- */
- resource &operator=(const resource &) noexcept = default;
- /**
- * @brief Default move assignment operator.
- * @return This resource handle.
- */
- resource &operator=(resource &&) noexcept = default;
- /**
- * @brief Copy assignment operator from foreign handle.
- * @tparam Other Type of resource managed by the received handle.
- * @param other The handle to copy from.
- * @return This resource handle.
- */
- template<typename Other>
- std::enable_if_t<is_acceptable_v<Other>, resource &>
- operator=(const resource<Other> &other) noexcept {
- value = other.value;
- return *this;
- }
- /**
- * @brief Move assignment operator from foreign handle.
- * @tparam Other Type of resource managed by the received handle.
- * @param other The handle to move from.
- * @return This resource handle.
- */
- template<typename Other>
- std::enable_if_t<is_acceptable_v<Other>, resource &>
- operator=(resource<Other> &&other) noexcept {
- value = std::move(other.value);
- return *this;
- }
- /**
- * @brief Returns a reference to the managed resource.
- *
- * @warning
- * The behavior is undefined if the handle doesn't contain a resource.
- *
- * @return A reference to the managed resource.
- */
- [[nodiscard]] element_type &operator*() const noexcept {
- return *value;
- }
- /*! @copydoc operator* */
- [[nodiscard]] operator element_type &() const noexcept {
- return *value;
- }
- /**
- * @brief Returns a pointer to the managed resource.
- * @return A pointer to the managed resource.
- */
- [[nodiscard]] element_type *operator->() const noexcept {
- return value.get();
- }
- /**
- * @brief Returns true if a handle contains a resource, false otherwise.
- * @return True if the handle contains a resource, false otherwise.
- */
- [[nodiscard]] explicit operator bool() const noexcept {
- return static_cast<bool>(value);
- }
- /**
- * @brief Returns the underlying resource handle.
- * @return The underlying resource handle.
- */
- [[nodiscard]] const handle_type &handle() const noexcept {
- return value;
- }
- private:
- handle_type value;
- };
- /**
- * @brief Compares two handles.
- * @tparam Lhs Type of resource managed by the first handle.
- * @tparam Rhs Type of resource managed by the second handle.
- * @param lhs A valid handle.
- * @param rhs A valid handle.
- * @return True if both handles refer to the same resource, false otherwise.
- */
- template<typename Lhs, typename Rhs>
- [[nodiscard]] bool operator==(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept {
- return (std::addressof(*lhs) == std::addressof(*rhs));
- }
- /**
- * @brief Compares two handles.
- * @tparam Lhs Type of resource managed by the first handle.
- * @tparam Rhs Type of resource managed by the second handle.
- * @param lhs A valid handle.
- * @param rhs A valid handle.
- * @return False if both handles refer to the same resource, true otherwise.
- */
- template<typename Lhs, typename Rhs>
- [[nodiscard]] bool operator!=(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept {
- return !(lhs == rhs);
- }
- /**
- * @brief Compares two handles.
- * @tparam Lhs Type of resource managed by the first handle.
- * @tparam Rhs Type of resource managed by the second handle.
- * @param lhs A valid handle.
- * @param rhs A valid handle.
- * @return True if the first handle is less than the second, false otherwise.
- */
- template<typename Lhs, typename Rhs>
- [[nodiscard]] bool operator<(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept {
- return (std::addressof(*lhs) < std::addressof(*rhs));
- }
- /**
- * @brief Compares two handles.
- * @tparam Lhs Type of resource managed by the first handle.
- * @tparam Rhs Type of resource managed by the second handle.
- * @param lhs A valid handle.
- * @param rhs A valid handle.
- * @return True if the first handle is greater than the second, false otherwise.
- */
- template<typename Lhs, typename Rhs>
- [[nodiscard]] bool operator>(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept {
- return rhs < lhs;
- }
- /**
- * @brief Compares two handles.
- * @tparam Lhs Type of resource managed by the first handle.
- * @tparam Rhs Type of resource managed by the second handle.
- * @param lhs A valid handle.
- * @param rhs A valid handle.
- * @return True if the first handle is less than or equal to the second, false
- * otherwise.
- */
- template<typename Lhs, typename Rhs>
- [[nodiscard]] bool operator<=(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept {
- return !(lhs > rhs);
- }
- /**
- * @brief Compares two handles.
- * @tparam Lhs Type of resource managed by the first handle.
- * @tparam Rhs Type of resource managed by the second handle.
- * @param lhs A valid handle.
- * @param rhs A valid handle.
- * @return True if the first handle is greater than or equal to the second,
- * false otherwise.
- */
- template<typename Lhs, typename Rhs>
- [[nodiscard]] bool operator>=(const resource<Lhs> &lhs, const resource<Rhs> &rhs) noexcept {
- return !(lhs < rhs);
- }
- } // namespace entt
- #endif
|