Skip to content

Commit

Permalink
any: support taking ownership of passed in pointers
Browse files Browse the repository at this point in the history
  • Loading branch information
skypjack committed Nov 18, 2024
1 parent a7ba223 commit 5734063
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 4 deletions.
16 changes: 16 additions & 0 deletions src/entt/core/any.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,22 @@ class basic_any {
initialize<Type>(std::forward<Args>(args)...);
}

/**
* @brief Constructs a wrapper taking ownership of the passed object.
* @tparam Type Type of object to use to initialize the wrapper.
* @param value A pointer to an object to take ownership of.
*/
template<typename Type, typename = std::enable_if_t<!std::is_void_v<std::remove_const_t<Type>>>>
explicit basic_any(std::in_place_t, Type *value)
: instance{value},
info{&type_id<std::remove_const_t<Type>>()},
vtable{basic_vtable<std::remove_const_t<Type>>},
mode{any_policy::dynamic} {
if(instance == nullptr) {
reset();
}
}

/**
* @brief Constructs a wrapper from a given value.
* @tparam Type Type of object to use to initialize the wrapper.
Expand Down
70 changes: 66 additions & 4 deletions test/entt/core/any.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,17 @@ struct fat {

struct alignas(64u) over_aligned {};

TEST(Any, Empty) {
entt::any any{};

ASSERT_FALSE(any);
ASSERT_FALSE(any.owner());
ASSERT_EQ(any.policy(), entt::any_policy::empty);
ASSERT_EQ(any.type(), entt::type_id<void>());
ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
ASSERT_EQ(any.data(), nullptr);
}

TEST(Any, SBO) {
entt::any any{'c'};

Expand All @@ -69,15 +80,35 @@ TEST(Any, NoSBO) {
ASSERT_EQ(entt::any_cast<fat>(any), instance);
}

TEST(Any, Empty) {
entt::any any{};
TEST(Any, SBOInPlaceConstruction) {
std::unique_ptr<int> instance = std::make_unique<int>(2);
entt::any any{std::in_place, instance.release()};

ASSERT_TRUE(any);
ASSERT_TRUE(any.owner());
ASSERT_EQ(any.policy(), entt::any_policy::dynamic);
ASSERT_EQ(any.type(), entt::type_id<int>());
ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
ASSERT_EQ(entt::any_cast<int>(any), 2);

auto other = any.as_ref();

ASSERT_TRUE(other);
ASSERT_FALSE(other.owner());
ASSERT_EQ(other.policy(), entt::any_policy::ref);
ASSERT_EQ(other.type(), entt::type_id<int>());
ASSERT_EQ(entt::any_cast<int>(other), 2);
ASSERT_EQ(other.data(), any.data());
}

TEST(Any, SBOInPlaceNullptrConstruction) {
int *instance = nullptr;
entt::any any{std::in_place, instance};

ASSERT_FALSE(any);
ASSERT_FALSE(any.owner());
ASSERT_EQ(any.policy(), entt::any_policy::empty);
ASSERT_EQ(any.type(), entt::type_id<void>());
ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
ASSERT_EQ(any.data(), nullptr);
}

TEST(Any, SBOInPlaceTypeConstruction) {
Expand Down Expand Up @@ -361,6 +392,37 @@ TEST(Any, SBOAsConstRefTransferValue) {
ASSERT_EQ(value, 2);
}

TEST(Any, NoSBOInPlaceConstruction) {
std::unique_ptr<fat> instance = std::make_unique<fat>(.1, .2, .3, .4);
entt::any any{std::in_place, instance.release()};

ASSERT_TRUE(any);
ASSERT_TRUE(any.owner());
ASSERT_EQ(any.policy(), entt::any_policy::dynamic);
ASSERT_EQ(any.type(), entt::type_id<fat>());
ASSERT_EQ(entt::any_cast<double>(&any), nullptr);
ASSERT_EQ(entt::any_cast<fat>(any), (fat{.1, .2, .3, .4}));

auto other = any.as_ref();

ASSERT_TRUE(other);
ASSERT_FALSE(other.owner());
ASSERT_EQ(other.policy(), entt::any_policy::ref);
ASSERT_EQ(other.type(), entt::type_id<fat>());
ASSERT_EQ(entt::any_cast<fat>(other), (fat{.1, .2, .3, .4}));
ASSERT_EQ(other.data(), any.data());
}

TEST(Any, NoSBOInPlaceNullptrConstruction) {
fat *instance = nullptr;
entt::any any{std::in_place, instance};

ASSERT_FALSE(any);
ASSERT_FALSE(any.owner());
ASSERT_EQ(any.policy(), entt::any_policy::empty);
ASSERT_EQ(any.type(), entt::type_id<void>());
}

TEST(Any, NoSBOInPlaceTypeConstruction) {
const fat instance{.1, .2, .3, .4};
entt::any any{std::in_place_type<fat>, instance};
Expand Down

0 comments on commit 5734063

Please sign in to comment.