resource_handle: conversion functions (close #706)
This commit is contained in:
@@ -91,8 +91,6 @@ struct resource_cache {
|
||||
*/
|
||||
template<typename Loader, typename... Args>
|
||||
resource_handle<Resource> load(const id_type id, Args &&... args) {
|
||||
static_assert(std::is_base_of_v<resource_loader<Loader, Resource>, Loader>, "Invalid loader type");
|
||||
|
||||
if(auto it = resources.find(id); it == resources.cend()) {
|
||||
if(auto handle = temp<Loader>(std::forward<Args>(args)...); handle) {
|
||||
return (resources[id] = std::move(handle));
|
||||
|
||||
@@ -10,7 +10,7 @@ struct resource_cache;
|
||||
|
||||
|
||||
template<typename>
|
||||
struct resource_handle;
|
||||
class resource_handle;
|
||||
|
||||
|
||||
template<typename, typename>
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include "../config/config.h"
|
||||
#include "fwd.hpp"
|
||||
@@ -24,7 +25,12 @@ namespace entt {
|
||||
* @tparam Resource Type of resource managed by a handle.
|
||||
*/
|
||||
template<typename Resource>
|
||||
struct resource_handle {
|
||||
class resource_handle {
|
||||
/*! @brief Resource handles are friends with each other. */
|
||||
template<typename>
|
||||
friend class resource_handle;
|
||||
|
||||
public:
|
||||
/*! @brief Default constructor. */
|
||||
resource_handle() ENTT_NOEXCEPT = default;
|
||||
|
||||
@@ -36,6 +42,74 @@ struct resource_handle {
|
||||
: resource{std::move(res)}
|
||||
{}
|
||||
|
||||
/**
|
||||
* @brief Copy constructor.
|
||||
* @param other The instance to copy from.
|
||||
*/
|
||||
resource_handle(const resource_handle<Resource> &other) ENTT_NOEXCEPT = default;
|
||||
|
||||
/**
|
||||
* @brief Move constructor.
|
||||
* @param other The instance to move from.
|
||||
*/
|
||||
resource_handle(resource_handle<Resource> &&other) ENTT_NOEXCEPT = default;
|
||||
|
||||
/**
|
||||
* @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<!std::is_same_v<Other, Resource> && std::is_base_of_v<Resource, Other>>>
|
||||
resource_handle(const resource_handle<Other> &other) ENTT_NOEXCEPT
|
||||
: resource{other.resource}
|
||||
{}
|
||||
|
||||
/**
|
||||
* @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<!std::is_same_v<Other, Resource> && std::is_base_of_v<Resource, Other>>>
|
||||
resource_handle(resource_handle<Other> &&other) ENTT_NOEXCEPT
|
||||
: resource{std::move(other.resource)}
|
||||
{}
|
||||
|
||||
/**
|
||||
* @brief Copy assignment operator.
|
||||
* @param other The instance to copy from.
|
||||
*/
|
||||
resource_handle & operator=(const resource_handle<Resource> &other) ENTT_NOEXCEPT = default;
|
||||
|
||||
/**
|
||||
* @brief Move assignment operator.
|
||||
* @param other The instance to move from.
|
||||
*/
|
||||
resource_handle & operator=(resource_handle<Resource> &&other) ENTT_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.
|
||||
*/
|
||||
template<typename Other>
|
||||
std::enable_if_t<!std::is_same_v<Other, Resource> && std::is_base_of_v<Resource, Other>, resource_handle &>
|
||||
operator=(const resource_handle<Other> &other) ENTT_NOEXCEPT {
|
||||
resource = other.resource;
|
||||
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.
|
||||
*/
|
||||
template<typename Other>
|
||||
std::enable_if_t<!std::is_same_v<Other, Resource> && std::is_base_of_v<Resource, Other>, resource_handle &>
|
||||
operator=(resource_handle<Other> &&other) ENTT_NOEXCEPT {
|
||||
resource = std::move(other.resource);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets a reference to the managed resource.
|
||||
*
|
||||
|
||||
@@ -44,7 +44,8 @@ namespace entt {
|
||||
template<typename Loader, typename Resource>
|
||||
class resource_loader {
|
||||
/*! @brief Resource loaders are friends of their caches. */
|
||||
friend struct resource_cache<Resource>;
|
||||
template<typename Other>
|
||||
friend struct resource_cache;
|
||||
|
||||
/**
|
||||
* @brief Loads the resource and returns it.
|
||||
|
||||
@@ -4,15 +4,20 @@
|
||||
#include <entt/resource/cache.hpp>
|
||||
|
||||
struct resource { int value; };
|
||||
struct derived_resource: resource {};
|
||||
|
||||
struct loader: entt::resource_loader<loader, resource> {
|
||||
std::shared_ptr<resource> load(int value) const {
|
||||
return std::shared_ptr<resource>(new resource{ value });
|
||||
template<typename Resource>
|
||||
struct loader: entt::resource_loader<loader<Resource>, Resource> {
|
||||
std::shared_ptr<Resource> load(int value) const {
|
||||
auto res = std::shared_ptr<Resource>(new Resource);
|
||||
res->value = value;
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
struct broken_loader: entt::resource_loader<broken_loader, resource> {
|
||||
std::shared_ptr<resource> load(int) const {
|
||||
template<typename Resource>
|
||||
struct broken_loader: entt::resource_loader<broken_loader<Resource>, Resource> {
|
||||
std::shared_ptr<Resource> load(int) const {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
@@ -28,16 +33,16 @@ TEST(Resource, Functionalities) {
|
||||
ASSERT_FALSE(cache.contains(hs1));
|
||||
ASSERT_FALSE(cache.contains(hs2));
|
||||
|
||||
ASSERT_FALSE(cache.load<broken_loader>(hs1, 42));
|
||||
ASSERT_FALSE(cache.reload<broken_loader>(hs1, 42));
|
||||
ASSERT_FALSE(cache.load<broken_loader<resource>>(hs1, 42));
|
||||
ASSERT_FALSE(cache.reload<broken_loader<resource>>(hs1, 42));
|
||||
|
||||
ASSERT_EQ(cache.size(), 0u);
|
||||
ASSERT_TRUE(cache.empty());
|
||||
ASSERT_FALSE(cache.contains(hs1));
|
||||
ASSERT_FALSE(cache.contains(hs2));
|
||||
|
||||
ASSERT_TRUE(cache.load<loader>(hs1, 42));
|
||||
ASSERT_TRUE(cache.reload<loader>(hs1, 42));
|
||||
ASSERT_TRUE(cache.load<loader<resource>>(hs1, 42));
|
||||
ASSERT_TRUE(cache.reload<loader<resource>>(hs1, 42));
|
||||
|
||||
ASSERT_NE(cache.size(), 0u);
|
||||
ASSERT_FALSE(cache.empty());
|
||||
@@ -45,8 +50,8 @@ TEST(Resource, Functionalities) {
|
||||
ASSERT_FALSE(cache.contains(hs2));
|
||||
ASSERT_EQ((*cache.handle(hs1)).value, 42);
|
||||
|
||||
ASSERT_TRUE(cache.load<loader>(hs1, 42));
|
||||
ASSERT_TRUE(cache.load<loader>(hs2, 42));
|
||||
ASSERT_TRUE(cache.load<loader<resource>>(hs1, 42));
|
||||
ASSERT_TRUE(cache.load<loader<resource>>(hs2, 42));
|
||||
|
||||
ASSERT_NE(cache.size(), 0u);
|
||||
ASSERT_FALSE(cache.empty());
|
||||
@@ -61,7 +66,7 @@ TEST(Resource, Functionalities) {
|
||||
ASSERT_TRUE(cache.contains(hs2));
|
||||
ASSERT_EQ(cache.handle(hs2)->value, 42);
|
||||
|
||||
ASSERT_TRUE(cache.load<loader>(hs1, 42));
|
||||
ASSERT_TRUE(cache.load<loader<resource>>(hs1, 42));
|
||||
ASSERT_NO_FATAL_FAILURE(cache.clear());
|
||||
|
||||
ASSERT_EQ(cache.size(), 0u);
|
||||
@@ -69,7 +74,7 @@ TEST(Resource, Functionalities) {
|
||||
ASSERT_FALSE(cache.contains(hs1));
|
||||
ASSERT_FALSE(cache.contains(hs2));
|
||||
|
||||
ASSERT_TRUE(cache.load<loader>(hs1, 42));
|
||||
ASSERT_TRUE(cache.load<loader<resource>>(hs1, 42));
|
||||
|
||||
ASSERT_NE(cache.size(), 0u);
|
||||
ASSERT_FALSE(cache.empty());
|
||||
@@ -83,7 +88,7 @@ TEST(Resource, Functionalities) {
|
||||
ASSERT_EQ(cache.size(), 0u);
|
||||
ASSERT_TRUE(cache.empty());
|
||||
|
||||
ASSERT_TRUE(cache.temp<loader>(42));
|
||||
ASSERT_TRUE(cache.temp<loader<resource>>(42));
|
||||
ASSERT_TRUE(cache.empty());
|
||||
|
||||
ASSERT_FALSE(entt::resource_handle<resource>{});
|
||||
@@ -97,7 +102,7 @@ TEST(Resource, MutableHandle) {
|
||||
entt::resource_cache<resource> cache;
|
||||
|
||||
constexpr auto hs = entt::hashed_string{"res"};
|
||||
auto handle = cache.load<loader>(hs, 0);
|
||||
auto handle = cache.load<loader<resource>>(hs, 0);
|
||||
|
||||
ASSERT_TRUE(handle);
|
||||
|
||||
@@ -109,11 +114,50 @@ TEST(Resource, MutableHandle) {
|
||||
ASSERT_EQ(cache.handle(hs)->value, 4);
|
||||
}
|
||||
|
||||
TEST(Resource, HandleCast) {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::resource_cache<resource> cache;
|
||||
auto handle = cache.load<loader<derived_resource>>("resource"_hs, 0);
|
||||
|
||||
auto resource = std::make_shared<derived_resource>();
|
||||
entt::resource_handle<derived_resource> other{resource};
|
||||
|
||||
ASSERT_TRUE(handle);
|
||||
ASSERT_TRUE(other);
|
||||
ASSERT_NE(&*handle, &*other);
|
||||
ASSERT_EQ(resource.use_count(), 2u);
|
||||
|
||||
auto temp = std::move(handle);
|
||||
handle = other;
|
||||
|
||||
ASSERT_TRUE(handle);
|
||||
ASSERT_TRUE(other);
|
||||
ASSERT_TRUE(temp);
|
||||
ASSERT_EQ(&*handle, &*other);
|
||||
ASSERT_EQ(resource.use_count(), 3u);
|
||||
|
||||
temp = std::move(other);
|
||||
|
||||
ASSERT_TRUE(handle);
|
||||
ASSERT_FALSE(other);
|
||||
ASSERT_TRUE(temp);
|
||||
ASSERT_EQ(&*handle, &*temp);
|
||||
ASSERT_EQ(resource.use_count(), 3u);
|
||||
|
||||
temp = handle = {};
|
||||
|
||||
ASSERT_FALSE(handle);
|
||||
ASSERT_FALSE(other);
|
||||
ASSERT_FALSE(temp);
|
||||
ASSERT_EQ(resource.use_count(), 1u);
|
||||
}
|
||||
|
||||
TEST(Resource, Each) {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::resource_cache<resource> cache;
|
||||
cache.load<loader>("resource"_hs, 0);
|
||||
cache.load<loader<resource>>("resource"_hs, 0);
|
||||
|
||||
cache.each([](entt::resource_handle<resource> res) {
|
||||
++res->value;
|
||||
|
||||
Reference in New Issue
Block a user