Squashed 'external/entt/entt/' content from commit fef92113
git-subtree-dir: external/entt/entt git-subtree-split: fef921132cae7588213d0f9bcd2fb9c8ffd8b7fc
This commit is contained in:
1371
test/entt/meta/meta_any.cpp
Normal file
1371
test/entt/meta/meta_any.cpp
Normal file
File diff suppressed because it is too large
Load Diff
193
test/entt/meta/meta_base.cpp
Normal file
193
test/entt/meta/meta_base.cpp
Normal file
@ -0,0 +1,193 @@
|
||||
#include <utility>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/hashed_string.hpp>
|
||||
#include <entt/locator/locator.hpp>
|
||||
#include <entt/meta/factory.hpp>
|
||||
#include <entt/meta/meta.hpp>
|
||||
#include <entt/meta/node.hpp>
|
||||
#include <entt/meta/resolve.hpp>
|
||||
|
||||
struct base_1_t {
|
||||
base_1_t() = default;
|
||||
int value_1{};
|
||||
};
|
||||
|
||||
struct base_2_t {
|
||||
base_2_t() = default;
|
||||
|
||||
operator int() const {
|
||||
return value_2;
|
||||
}
|
||||
|
||||
int value_2{};
|
||||
};
|
||||
|
||||
struct base_3_t: base_2_t {
|
||||
base_3_t() = default;
|
||||
int value_3{};
|
||||
};
|
||||
|
||||
struct derived_t: base_1_t, base_3_t {
|
||||
derived_t() = default;
|
||||
int value{};
|
||||
};
|
||||
|
||||
struct MetaBase: ::testing::Test {
|
||||
void SetUp() override {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::meta<base_1_t>()
|
||||
.data<&base_1_t::value_1>("value_1"_hs);
|
||||
|
||||
entt::meta<base_2_t>()
|
||||
.conv<int>()
|
||||
.data<&base_2_t::value_2>("value_2"_hs);
|
||||
|
||||
entt::meta<base_3_t>()
|
||||
.base<base_2_t>()
|
||||
.data<&base_3_t::value_3>("value_3"_hs);
|
||||
|
||||
entt::meta<derived_t>()
|
||||
.type("derived"_hs)
|
||||
.base<base_1_t>()
|
||||
.base<base_3_t>()
|
||||
.data<&derived_t::value>("value"_hs);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
entt::meta_reset();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(MetaBase, Functionalities) {
|
||||
auto any = entt::resolve<derived_t>().construct();
|
||||
any.cast<derived_t &>().value_1 = 42;
|
||||
auto as_derived = any.as_ref();
|
||||
|
||||
ASSERT_TRUE(any.allow_cast<base_1_t &>());
|
||||
|
||||
ASSERT_FALSE(any.allow_cast<char>());
|
||||
ASSERT_FALSE(as_derived.allow_cast<char>());
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.cast<base_1_t &>().value_1, as_derived.cast<derived_t &>().value_1);
|
||||
|
||||
any.cast<base_1_t &>().value_1 = 3;
|
||||
|
||||
ASSERT_EQ(any.cast<const base_1_t &>().value_1, as_derived.cast<const derived_t &>().value_1);
|
||||
}
|
||||
|
||||
TEST_F(MetaBase, SetGetWithMutatingThis) {
|
||||
using namespace entt::literals;
|
||||
|
||||
derived_t instance;
|
||||
auto any = entt::forward_as_meta(instance);
|
||||
auto as_cref = std::as_const(any).as_ref();
|
||||
|
||||
ASSERT_NE(static_cast<const void *>(static_cast<const base_1_t *>(&instance)), static_cast<const void *>(static_cast<const base_2_t *>(&instance)));
|
||||
ASSERT_NE(static_cast<const void *>(static_cast<const base_1_t *>(&instance)), static_cast<const void *>(static_cast<const base_3_t *>(&instance)));
|
||||
ASSERT_EQ(static_cast<const void *>(static_cast<const base_2_t *>(&instance)), static_cast<const void *>(static_cast<const base_3_t *>(&instance)));
|
||||
ASSERT_EQ(static_cast<const void *>(&instance), static_cast<const void *>(static_cast<const base_1_t *>(&instance)));
|
||||
|
||||
ASSERT_TRUE(any.set("value"_hs, 42));
|
||||
ASSERT_TRUE(any.set("value_1"_hs, 1));
|
||||
ASSERT_TRUE(any.set("value_2"_hs, 2));
|
||||
ASSERT_TRUE(any.set("value_3"_hs, 3));
|
||||
|
||||
ASSERT_FALSE(as_cref.set("value"_hs, 0));
|
||||
ASSERT_FALSE(as_cref.set("value_1"_hs, 0));
|
||||
ASSERT_FALSE(as_cref.set("value_2"_hs, 0));
|
||||
ASSERT_FALSE(as_cref.set("value_3"_hs, 0));
|
||||
|
||||
ASSERT_EQ(any.get("value"_hs).cast<int>(), 42);
|
||||
ASSERT_EQ(any.get("value_1"_hs).cast<const int>(), 1);
|
||||
ASSERT_EQ(any.get("value_2"_hs).cast<int>(), 2);
|
||||
ASSERT_EQ(any.get("value_3"_hs).cast<const int>(), 3);
|
||||
|
||||
ASSERT_EQ(as_cref.get("value"_hs).cast<const int>(), 42);
|
||||
ASSERT_EQ(as_cref.get("value_1"_hs).cast<int>(), 1);
|
||||
ASSERT_EQ(as_cref.get("value_2"_hs).cast<const int>(), 2);
|
||||
ASSERT_EQ(as_cref.get("value_3"_hs).cast<int>(), 3);
|
||||
|
||||
ASSERT_EQ(instance.value, 42);
|
||||
ASSERT_EQ(instance.value_1, 1);
|
||||
ASSERT_EQ(instance.value_2, 2);
|
||||
ASSERT_EQ(instance.value_3, 3);
|
||||
}
|
||||
|
||||
TEST_F(MetaBase, ConvWithMutatingThis) {
|
||||
entt::meta_any any{derived_t{}};
|
||||
auto &&ref = any.cast<derived_t &>();
|
||||
auto as_cref = std::as_const(any).as_ref();
|
||||
ref.value_2 = 42;
|
||||
|
||||
auto conv = std::as_const(any).allow_cast<int>();
|
||||
auto from_cref = std::as_const(as_cref).allow_cast<int>();
|
||||
|
||||
ASSERT_TRUE(conv);
|
||||
ASSERT_TRUE(from_cref);
|
||||
ASSERT_EQ(conv.cast<int>(), 42);
|
||||
ASSERT_EQ(from_cref.cast<int>(), 42);
|
||||
|
||||
ASSERT_TRUE(as_cref.allow_cast<int>());
|
||||
ASSERT_TRUE(any.allow_cast<int>());
|
||||
|
||||
ASSERT_EQ(as_cref.cast<int>(), 42);
|
||||
ASSERT_EQ(any.cast<int>(), 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaBase, OpaqueConvWithMutatingThis) {
|
||||
entt::meta_any any{derived_t{}};
|
||||
auto as_cref = std::as_const(any).as_ref();
|
||||
any.cast<derived_t &>().value_2 = 42;
|
||||
|
||||
auto conv = std::as_const(any).allow_cast(entt::resolve<int>());
|
||||
auto from_cref = std::as_const(as_cref).allow_cast(entt::resolve<int>());
|
||||
|
||||
ASSERT_TRUE(conv);
|
||||
ASSERT_TRUE(from_cref);
|
||||
ASSERT_EQ(conv.cast<int>(), 42);
|
||||
ASSERT_EQ(from_cref.cast<int>(), 42);
|
||||
|
||||
ASSERT_TRUE(as_cref.allow_cast(entt::resolve<int>()));
|
||||
ASSERT_TRUE(any.allow_cast(entt::resolve<int>()));
|
||||
|
||||
ASSERT_EQ(as_cref.cast<int>(), 42);
|
||||
ASSERT_EQ(any.cast<int>(), 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaBase, AssignWithMutatingThis) {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::meta_any dst{base_2_t{}};
|
||||
entt::meta_any src{derived_t{}};
|
||||
|
||||
dst.cast<base_2_t &>().value_2 = 0;
|
||||
src.cast<derived_t &>().value_2 = 42;
|
||||
|
||||
ASSERT_TRUE(dst.assign(src));
|
||||
ASSERT_EQ(dst.get("value_2"_hs).cast<int>(), 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaBase, TransferWithMutatingThis) {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::meta_any dst{base_2_t{}};
|
||||
entt::meta_any src{derived_t{}};
|
||||
|
||||
dst.cast<base_2_t &>().value_2 = 0;
|
||||
src.cast<derived_t &>().value_2 = 42;
|
||||
|
||||
ASSERT_TRUE(dst.assign(std::move(src)));
|
||||
ASSERT_EQ(dst.get("value_2"_hs).cast<int>(), 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaBase, ReRegistration) {
|
||||
SetUp();
|
||||
|
||||
auto &&node = entt::internal::resolve<derived_t>(entt::internal::meta_context::from(entt::locator<entt::meta_ctx>::value_or()));
|
||||
|
||||
ASSERT_TRUE(node.details);
|
||||
ASSERT_FALSE(node.details->base.empty());
|
||||
ASSERT_EQ(node.details->base.size(), 2u);
|
||||
}
|
757
test/entt/meta/meta_container.cpp
Normal file
757
test/entt/meta/meta_container.cpp
Normal file
@ -0,0 +1,757 @@
|
||||
#include <array>
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/hashed_string.hpp>
|
||||
#include <entt/meta/container.hpp>
|
||||
#include <entt/meta/factory.hpp>
|
||||
#include <entt/meta/meta.hpp>
|
||||
#include <entt/meta/resolve.hpp>
|
||||
#include "../common/config.h"
|
||||
|
||||
struct invalid_type {};
|
||||
|
||||
struct MetaContainer: ::testing::Test {
|
||||
void SetUp() override {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::meta<double>()
|
||||
.type("double"_hs);
|
||||
|
||||
entt::meta<int>()
|
||||
.type("int"_hs);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
entt::meta_reset();
|
||||
}
|
||||
};
|
||||
|
||||
using MetaContainerDeathTest = MetaContainer;
|
||||
|
||||
TEST_F(MetaContainer, InvalidContainer) {
|
||||
ASSERT_FALSE(entt::meta_any{42}.as_sequence_container());
|
||||
ASSERT_FALSE(entt::meta_any{42}.as_associative_container());
|
||||
|
||||
ASSERT_FALSE((entt::meta_any{std::map<int, char>{}}.as_sequence_container()));
|
||||
ASSERT_FALSE(entt::meta_any{std::vector<int>{}}.as_associative_container());
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, EmptySequenceContainer) {
|
||||
entt::meta_sequence_container container{};
|
||||
|
||||
ASSERT_FALSE(container);
|
||||
|
||||
entt::meta_any any{std::vector<int>{}};
|
||||
container = any.as_sequence_container();
|
||||
|
||||
ASSERT_TRUE(container);
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, EmptyAssociativeContainer) {
|
||||
entt::meta_associative_container container{};
|
||||
|
||||
ASSERT_FALSE(container);
|
||||
|
||||
entt::meta_any any{std::map<int, char>{}};
|
||||
container = any.as_associative_container();
|
||||
|
||||
ASSERT_TRUE(container);
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, SequenceContainerIterator) {
|
||||
std::vector<int> vec{2, 3, 4};
|
||||
auto any = entt::forward_as_meta(vec);
|
||||
entt::meta_sequence_container::iterator first{};
|
||||
auto view = any.as_sequence_container();
|
||||
|
||||
ASSERT_FALSE(first);
|
||||
|
||||
first = view.begin();
|
||||
const auto last = view.end();
|
||||
|
||||
ASSERT_TRUE(first);
|
||||
ASSERT_TRUE(last);
|
||||
|
||||
ASSERT_FALSE(first == last);
|
||||
ASSERT_TRUE(first != last);
|
||||
|
||||
ASSERT_EQ((first++)->cast<int>(), 2);
|
||||
ASSERT_EQ((++first)->cast<int>(), 4);
|
||||
|
||||
ASSERT_NE(first++, last);
|
||||
ASSERT_TRUE(first == last);
|
||||
ASSERT_FALSE(first != last);
|
||||
ASSERT_EQ(first--, last);
|
||||
|
||||
ASSERT_EQ((first--)->cast<int>(), 4);
|
||||
ASSERT_EQ((--first)->cast<int>(), 2);
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, AssociativeContainerIterator) {
|
||||
std::map<int, char> map{{2, 'c'}, {3, 'd'}, {4, 'e'}};
|
||||
auto any = entt::forward_as_meta(map);
|
||||
entt::meta_associative_container::iterator first{};
|
||||
auto view = any.as_associative_container();
|
||||
|
||||
ASSERT_FALSE(first);
|
||||
|
||||
first = view.begin();
|
||||
const auto last = view.end();
|
||||
|
||||
ASSERT_TRUE(first);
|
||||
ASSERT_TRUE(last);
|
||||
|
||||
ASSERT_FALSE(first == last);
|
||||
ASSERT_TRUE(first != last);
|
||||
|
||||
ASSERT_NE(first, last);
|
||||
ASSERT_EQ((first++)->first.cast<int>(), 2);
|
||||
ASSERT_EQ((++first)->second.cast<char>(), 'e');
|
||||
ASSERT_NE(first++, last);
|
||||
ASSERT_EQ(first, last);
|
||||
|
||||
ASSERT_TRUE(first == last);
|
||||
ASSERT_FALSE(first != last);
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, StdVector) {
|
||||
std::vector<int> vec{};
|
||||
auto any = entt::forward_as_meta(vec);
|
||||
auto view = any.as_sequence_container();
|
||||
auto cview = std::as_const(any).as_sequence_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_EQ(view.value_type(), entt::resolve<int>());
|
||||
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
ASSERT_EQ(view.begin(), view.end());
|
||||
ASSERT_TRUE(view.resize(3u));
|
||||
ASSERT_EQ(view.size(), 3u);
|
||||
ASSERT_NE(view.begin(), view.end());
|
||||
|
||||
view[0].cast<int &>() = 2;
|
||||
view[1].cast<int &>() = 3;
|
||||
view[2].cast<int &>() = 4;
|
||||
|
||||
ASSERT_EQ(view[1u].cast<int>(), 3);
|
||||
|
||||
auto it = view.begin();
|
||||
auto ret = view.insert(it, 0);
|
||||
|
||||
ASSERT_TRUE(ret);
|
||||
ASSERT_FALSE(view.insert(ret, invalid_type{}));
|
||||
ASSERT_TRUE(view.insert(++ret, 1.));
|
||||
|
||||
ASSERT_EQ(view.size(), 5u);
|
||||
ASSERT_EQ(view.begin()->cast<int>(), 0);
|
||||
ASSERT_EQ((++view.begin())->cast<int>(), 1);
|
||||
|
||||
ret = view.insert(cview.end(), 42);
|
||||
|
||||
ASSERT_TRUE(ret);
|
||||
ASSERT_EQ(*ret, 42);
|
||||
|
||||
it = view.begin();
|
||||
ret = view.erase(it);
|
||||
|
||||
ASSERT_TRUE(ret);
|
||||
ASSERT_EQ(view.size(), 5u);
|
||||
ASSERT_EQ(ret->cast<int>(), 1);
|
||||
|
||||
ret = view.erase(cview.begin());
|
||||
|
||||
ASSERT_TRUE(ret);
|
||||
ASSERT_EQ(view.size(), 4u);
|
||||
ASSERT_EQ(ret->cast<int>(), 2);
|
||||
|
||||
ASSERT_TRUE(view.clear());
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, StdArray) {
|
||||
std::array<int, 3> arr{};
|
||||
auto any = entt::forward_as_meta(arr);
|
||||
auto view = any.as_sequence_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_EQ(view.value_type(), entt::resolve<int>());
|
||||
|
||||
ASSERT_EQ(view.size(), 3u);
|
||||
ASSERT_NE(view.begin(), view.end());
|
||||
ASSERT_FALSE(view.resize(5u));
|
||||
ASSERT_EQ(view.size(), 3u);
|
||||
|
||||
view[0].cast<int &>() = 2;
|
||||
view[1].cast<int &>() = 3;
|
||||
view[2].cast<int &>() = 4;
|
||||
|
||||
ASSERT_EQ(view[1u].cast<int>(), 3);
|
||||
|
||||
auto it = view.begin();
|
||||
auto ret = view.insert(it, 0);
|
||||
|
||||
ASSERT_FALSE(ret);
|
||||
ASSERT_FALSE(view.insert(it, 'c'));
|
||||
ASSERT_FALSE(view.insert(++it, 1.));
|
||||
|
||||
ASSERT_EQ(view.size(), 3u);
|
||||
ASSERT_EQ(view.begin()->cast<int>(), 2);
|
||||
ASSERT_EQ((++view.begin())->cast<int>(), 3);
|
||||
|
||||
it = view.begin();
|
||||
ret = view.erase(it);
|
||||
|
||||
ASSERT_FALSE(ret);
|
||||
ASSERT_EQ(view.size(), 3u);
|
||||
ASSERT_EQ(it->cast<int>(), 2);
|
||||
|
||||
ASSERT_FALSE(view.clear());
|
||||
ASSERT_EQ(view.size(), 3u);
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, StdList) {
|
||||
std::list<int> list{};
|
||||
auto any = entt::forward_as_meta(list);
|
||||
auto view = any.as_sequence_container();
|
||||
auto cview = std::as_const(any).as_sequence_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_EQ(view.value_type(), entt::resolve<int>());
|
||||
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
ASSERT_EQ(view.begin(), view.end());
|
||||
ASSERT_TRUE(view.resize(3u));
|
||||
ASSERT_EQ(view.size(), 3u);
|
||||
ASSERT_NE(view.begin(), view.end());
|
||||
|
||||
view[0].cast<int &>() = 2;
|
||||
view[1].cast<int &>() = 3;
|
||||
view[2].cast<int &>() = 4;
|
||||
|
||||
ASSERT_EQ(view[1u].cast<int>(), 3);
|
||||
|
||||
auto it = view.begin();
|
||||
auto ret = view.insert(it, 0);
|
||||
|
||||
ASSERT_TRUE(ret);
|
||||
ASSERT_FALSE(view.insert(ret, invalid_type{}));
|
||||
ASSERT_TRUE(view.insert(++ret, 1.));
|
||||
|
||||
ASSERT_EQ(view.size(), 5u);
|
||||
ASSERT_EQ(view.begin()->cast<int>(), 0);
|
||||
ASSERT_EQ((++view.begin())->cast<int>(), 1);
|
||||
|
||||
ret = view.insert(cview.end(), 42);
|
||||
|
||||
ASSERT_TRUE(ret);
|
||||
ASSERT_EQ(*ret, 42);
|
||||
|
||||
it = view.begin();
|
||||
ret = view.erase(it);
|
||||
|
||||
ASSERT_TRUE(ret);
|
||||
ASSERT_EQ(view.size(), 5u);
|
||||
ASSERT_EQ(ret->cast<int>(), 1);
|
||||
|
||||
ret = view.erase(cview.begin());
|
||||
|
||||
ASSERT_TRUE(ret);
|
||||
ASSERT_EQ(view.size(), 4u);
|
||||
ASSERT_EQ(ret->cast<int>(), 2);
|
||||
|
||||
ASSERT_TRUE(view.clear());
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, StdDeque) {
|
||||
std::deque<int> deque{};
|
||||
auto any = entt::forward_as_meta(deque);
|
||||
auto view = any.as_sequence_container();
|
||||
auto cview = std::as_const(any).as_sequence_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_EQ(view.value_type(), entt::resolve<int>());
|
||||
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
ASSERT_EQ(view.begin(), view.end());
|
||||
ASSERT_TRUE(view.resize(3u));
|
||||
ASSERT_EQ(view.size(), 3u);
|
||||
ASSERT_NE(view.begin(), view.end());
|
||||
|
||||
view[0].cast<int &>() = 2;
|
||||
view[1].cast<int &>() = 3;
|
||||
view[2].cast<int &>() = 4;
|
||||
|
||||
ASSERT_EQ(view[1u].cast<int>(), 3);
|
||||
|
||||
auto it = view.begin();
|
||||
auto ret = view.insert(it, 0);
|
||||
|
||||
ASSERT_TRUE(ret);
|
||||
ASSERT_FALSE(view.insert(ret, invalid_type{}));
|
||||
ASSERT_TRUE(view.insert(++ret, 1.));
|
||||
|
||||
ASSERT_EQ(view.size(), 5u);
|
||||
ASSERT_EQ(view.begin()->cast<int>(), 0);
|
||||
ASSERT_EQ((++view.begin())->cast<int>(), 1);
|
||||
|
||||
ret = view.insert(cview.end(), 42);
|
||||
|
||||
ASSERT_TRUE(ret);
|
||||
ASSERT_EQ(*ret, 42);
|
||||
|
||||
it = view.begin();
|
||||
ret = view.erase(it);
|
||||
|
||||
ASSERT_TRUE(ret);
|
||||
ASSERT_EQ(view.size(), 5u);
|
||||
ASSERT_EQ(ret->cast<int>(), 1);
|
||||
|
||||
ret = view.erase(cview.begin());
|
||||
|
||||
ASSERT_TRUE(ret);
|
||||
ASSERT_EQ(view.size(), 4u);
|
||||
ASSERT_EQ(ret->cast<int>(), 2);
|
||||
|
||||
ASSERT_TRUE(view.clear());
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, StdMap) {
|
||||
std::map<int, char> map{{2, 'c'}, {3, 'd'}, {4, 'e'}};
|
||||
auto any = entt::forward_as_meta(map);
|
||||
auto view = any.as_associative_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_FALSE(view.key_only());
|
||||
ASSERT_EQ(view.key_type(), entt::resolve<int>());
|
||||
ASSERT_EQ(view.mapped_type(), entt::resolve<char>());
|
||||
ASSERT_EQ(view.value_type(), (entt::resolve<std::pair<const int, char>>()));
|
||||
|
||||
ASSERT_EQ(view.size(), 3u);
|
||||
ASSERT_NE(view.begin(), view.end());
|
||||
|
||||
ASSERT_EQ(view.find(3)->second.cast<char>(), 'd');
|
||||
|
||||
ASSERT_FALSE(view.insert(invalid_type{}, 'a'));
|
||||
ASSERT_FALSE(view.insert(1, invalid_type{}));
|
||||
|
||||
ASSERT_TRUE(view.insert(0, 'a'));
|
||||
ASSERT_TRUE(view.insert(1., static_cast<int>('b')));
|
||||
|
||||
ASSERT_EQ(view.size(), 5u);
|
||||
ASSERT_EQ(view.find(0)->second.cast<char>(), 'a');
|
||||
ASSERT_EQ(view.find(1.)->second.cast<char>(), 'b');
|
||||
|
||||
ASSERT_EQ(view.erase(invalid_type{}), 0u);
|
||||
ASSERT_FALSE(view.find(invalid_type{}));
|
||||
ASSERT_EQ(view.size(), 5u);
|
||||
|
||||
ASSERT_EQ(view.erase(0), 1u);
|
||||
ASSERT_EQ(view.size(), 4u);
|
||||
ASSERT_EQ(view.find(0), view.end());
|
||||
|
||||
view.find(1.)->second.cast<char &>() = 'f';
|
||||
|
||||
ASSERT_EQ(view.find(1.f)->second.cast<char>(), 'f');
|
||||
|
||||
ASSERT_EQ(view.erase(1.), 1u);
|
||||
ASSERT_TRUE(view.clear());
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, StdSet) {
|
||||
std::set<int> set{2, 3, 4};
|
||||
auto any = entt::forward_as_meta(set);
|
||||
auto view = any.as_associative_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_TRUE(view.key_only());
|
||||
ASSERT_EQ(view.key_type(), entt::resolve<int>());
|
||||
ASSERT_EQ(view.mapped_type(), entt::meta_type{});
|
||||
ASSERT_EQ(view.value_type(), entt::resolve<int>());
|
||||
|
||||
ASSERT_EQ(view.size(), 3u);
|
||||
ASSERT_NE(view.begin(), view.end());
|
||||
|
||||
ASSERT_EQ(view.find(3)->first.cast<int>(), 3);
|
||||
|
||||
ASSERT_FALSE(view.insert(invalid_type{}));
|
||||
|
||||
ASSERT_TRUE(view.insert(.0));
|
||||
ASSERT_TRUE(view.insert(1));
|
||||
|
||||
ASSERT_EQ(view.size(), 5u);
|
||||
ASSERT_EQ(view.find(0)->first.cast<int>(), 0);
|
||||
ASSERT_EQ(view.find(1.)->first.cast<int>(), 1);
|
||||
|
||||
ASSERT_EQ(view.erase(invalid_type{}), 0u);
|
||||
ASSERT_FALSE(view.find(invalid_type{}));
|
||||
ASSERT_EQ(view.size(), 5u);
|
||||
|
||||
ASSERT_EQ(view.erase(0), 1u);
|
||||
ASSERT_EQ(view.size(), 4u);
|
||||
ASSERT_EQ(view.find(0), view.end());
|
||||
|
||||
ASSERT_EQ(view.find(1.f)->first.try_cast<int>(), nullptr);
|
||||
ASSERT_NE(view.find(1.)->first.try_cast<const int>(), nullptr);
|
||||
ASSERT_EQ(view.find(true)->first.cast<const int &>(), 1);
|
||||
|
||||
ASSERT_EQ(view.erase(1.), 1u);
|
||||
ASSERT_TRUE(view.clear());
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, DenseMap) {
|
||||
entt::dense_map<int, char> map{};
|
||||
auto any = entt::forward_as_meta(map);
|
||||
auto view = any.as_associative_container();
|
||||
|
||||
map.emplace(2, 'c');
|
||||
map.emplace(3, 'd');
|
||||
map.emplace(4, '3');
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_FALSE(view.key_only());
|
||||
ASSERT_EQ(view.key_type(), entt::resolve<int>());
|
||||
ASSERT_EQ(view.mapped_type(), entt::resolve<char>());
|
||||
ASSERT_EQ(view.value_type(), (entt::resolve<std::pair<const int, char>>()));
|
||||
|
||||
ASSERT_EQ(view.size(), 3u);
|
||||
ASSERT_NE(view.begin(), view.end());
|
||||
|
||||
ASSERT_EQ(view.find(3)->second.cast<char>(), 'd');
|
||||
|
||||
ASSERT_FALSE(view.insert(invalid_type{}, 'a'));
|
||||
ASSERT_FALSE(view.insert(1, invalid_type{}));
|
||||
|
||||
ASSERT_TRUE(view.insert(0, 'a'));
|
||||
ASSERT_TRUE(view.insert(1., static_cast<int>('b')));
|
||||
|
||||
ASSERT_EQ(view.size(), 5u);
|
||||
ASSERT_EQ(view.find(0)->second.cast<char>(), 'a');
|
||||
ASSERT_EQ(view.find(1.)->second.cast<char>(), 'b');
|
||||
|
||||
ASSERT_EQ(view.erase(invalid_type{}), 0u);
|
||||
ASSERT_FALSE(view.find(invalid_type{}));
|
||||
ASSERT_EQ(view.size(), 5u);
|
||||
|
||||
ASSERT_EQ(view.erase(0), 1u);
|
||||
ASSERT_EQ(view.size(), 4u);
|
||||
ASSERT_EQ(view.find(0), view.end());
|
||||
|
||||
view.find(1.)->second.cast<char &>() = 'f';
|
||||
|
||||
ASSERT_EQ(view.find(1.f)->second.cast<char>(), 'f');
|
||||
|
||||
ASSERT_EQ(view.erase(1.), 1u);
|
||||
ASSERT_TRUE(view.clear());
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, DenseSet) {
|
||||
entt::dense_set<int> set{};
|
||||
auto any = entt::forward_as_meta(set);
|
||||
auto view = any.as_associative_container();
|
||||
|
||||
set.emplace(2);
|
||||
set.emplace(3);
|
||||
set.emplace(4);
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_TRUE(view.key_only());
|
||||
ASSERT_EQ(view.key_type(), entt::resolve<int>());
|
||||
ASSERT_EQ(view.mapped_type(), entt::meta_type{});
|
||||
ASSERT_EQ(view.value_type(), entt::resolve<int>());
|
||||
|
||||
ASSERT_EQ(view.size(), 3u);
|
||||
ASSERT_NE(view.begin(), view.end());
|
||||
|
||||
ASSERT_EQ(view.find(3)->first.cast<int>(), 3);
|
||||
|
||||
ASSERT_FALSE(view.insert(invalid_type{}));
|
||||
|
||||
ASSERT_TRUE(view.insert(.0));
|
||||
ASSERT_TRUE(view.insert(1));
|
||||
|
||||
ASSERT_EQ(view.size(), 5u);
|
||||
ASSERT_EQ(view.find(0)->first.cast<int>(), 0);
|
||||
ASSERT_EQ(view.find(1.)->first.cast<int>(), 1);
|
||||
|
||||
ASSERT_EQ(view.erase(invalid_type{}), 0u);
|
||||
ASSERT_FALSE(view.find(invalid_type{}));
|
||||
ASSERT_EQ(view.size(), 5u);
|
||||
|
||||
ASSERT_EQ(view.erase(0), 1u);
|
||||
ASSERT_EQ(view.size(), 4u);
|
||||
ASSERT_EQ(view.find(0), view.end());
|
||||
|
||||
ASSERT_EQ(view.find(1.f)->first.try_cast<int>(), nullptr);
|
||||
ASSERT_NE(view.find(1.)->first.try_cast<const int>(), nullptr);
|
||||
ASSERT_EQ(view.find(true)->first.cast<const int &>(), 1);
|
||||
|
||||
ASSERT_EQ(view.erase(1.), 1u);
|
||||
ASSERT_TRUE(view.clear());
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, ConstSequenceContainer) {
|
||||
std::vector<int> vec{};
|
||||
auto any = entt::forward_as_meta(std::as_const(vec));
|
||||
auto view = any.as_sequence_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_EQ(view.value_type(), entt::resolve<int>());
|
||||
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
ASSERT_EQ(view.begin(), view.end());
|
||||
ASSERT_FALSE(view.resize(3u));
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
ASSERT_EQ(view.begin(), view.end());
|
||||
|
||||
vec.push_back(42);
|
||||
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
ASSERT_NE(view.begin(), view.end());
|
||||
ASSERT_EQ(view[0].cast<const int &>(), 42);
|
||||
|
||||
auto it = view.begin();
|
||||
auto ret = view.insert(it, 0);
|
||||
|
||||
ASSERT_FALSE(ret);
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
ASSERT_EQ(it->cast<int>(), 42);
|
||||
ASSERT_EQ(++it, view.end());
|
||||
|
||||
it = view.begin();
|
||||
ret = view.erase(it);
|
||||
|
||||
ASSERT_FALSE(ret);
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
|
||||
ASSERT_FALSE(view.clear());
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
}
|
||||
|
||||
ENTT_DEBUG_TEST_F(MetaContainerDeathTest, ConstSequenceContainer) {
|
||||
std::vector<int> vec{};
|
||||
auto any = entt::forward_as_meta(std::as_const(vec));
|
||||
auto view = any.as_sequence_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_DEATH(view[0].cast<int &>() = 2, "");
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, ConstKeyValueAssociativeContainer) {
|
||||
std::map<int, char> map{};
|
||||
auto any = entt::forward_as_meta(std::as_const(map));
|
||||
auto view = any.as_associative_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_FALSE(view.key_only());
|
||||
ASSERT_EQ(view.key_type(), entt::resolve<int>());
|
||||
ASSERT_EQ(view.mapped_type(), entt::resolve<char>());
|
||||
ASSERT_EQ(view.value_type(), (entt::resolve<std::pair<const int, char>>()));
|
||||
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
ASSERT_EQ(view.begin(), view.end());
|
||||
|
||||
map[2] = 'c';
|
||||
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
ASSERT_NE(view.begin(), view.end());
|
||||
ASSERT_EQ(view.find(2)->second.cast<const char &>(), 'c');
|
||||
|
||||
ASSERT_FALSE(view.insert(0, 'a'));
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
ASSERT_EQ(view.find(0), view.end());
|
||||
ASSERT_EQ(view.find(2)->second.cast<char>(), 'c');
|
||||
|
||||
ASSERT_EQ(view.erase(2), 0u);
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
ASSERT_NE(view.find(2), view.end());
|
||||
|
||||
ASSERT_FALSE(view.clear());
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
}
|
||||
|
||||
ENTT_DEBUG_TEST_F(MetaContainerDeathTest, ConstKeyValueAssociativeContainer) {
|
||||
std::map<int, char> map{};
|
||||
auto any = entt::forward_as_meta(std::as_const(map));
|
||||
auto view = any.as_associative_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_DEATH(view.find(2)->second.cast<char &>() = 'a', "");
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, ConstKeyOnlyAssociativeContainer) {
|
||||
std::set<int> set{};
|
||||
auto any = entt::forward_as_meta(std::as_const(set));
|
||||
auto view = any.as_associative_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_TRUE(view.key_only());
|
||||
ASSERT_EQ(view.key_type(), entt::resolve<int>());
|
||||
ASSERT_EQ(view.mapped_type(), entt::meta_type{});
|
||||
ASSERT_EQ(view.value_type(), (entt::resolve<int>()));
|
||||
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
ASSERT_EQ(view.begin(), view.end());
|
||||
|
||||
set.insert(2);
|
||||
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
ASSERT_NE(view.begin(), view.end());
|
||||
|
||||
ASSERT_EQ(view.find(2)->first.try_cast<int>(), nullptr);
|
||||
ASSERT_NE(view.find(2)->first.try_cast<const int>(), nullptr);
|
||||
ASSERT_EQ(view.find(2)->first.cast<int>(), 2);
|
||||
ASSERT_EQ(view.find(2)->first.cast<const int &>(), 2);
|
||||
|
||||
ASSERT_FALSE(view.insert(0));
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
ASSERT_EQ(view.find(0), view.end());
|
||||
ASSERT_EQ(view.find(2)->first.cast<int>(), 2);
|
||||
|
||||
ASSERT_EQ(view.erase(2), 0u);
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
ASSERT_NE(view.find(2), view.end());
|
||||
|
||||
ASSERT_FALSE(view.clear());
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, SequenceContainerConstMetaAny) {
|
||||
auto test = [](const entt::meta_any any) {
|
||||
auto view = any.as_sequence_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_EQ(view.value_type(), entt::resolve<int>());
|
||||
ASSERT_EQ(view[0].cast<const int &>(), 42);
|
||||
};
|
||||
|
||||
std::vector<int> vec{42};
|
||||
|
||||
test(vec);
|
||||
test(entt::forward_as_meta(vec));
|
||||
test(entt::forward_as_meta(std::as_const(vec)));
|
||||
}
|
||||
|
||||
ENTT_DEBUG_TEST_F(MetaContainerDeathTest, SequenceContainerConstMetaAny) {
|
||||
auto test = [](const entt::meta_any any) {
|
||||
auto view = any.as_sequence_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_DEATH(view[0].cast<int &>() = 2, "");
|
||||
};
|
||||
|
||||
std::vector<int> vec{42};
|
||||
|
||||
test(vec);
|
||||
test(entt::forward_as_meta(vec));
|
||||
test(entt::forward_as_meta(std::as_const(vec)));
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, KeyValueAssociativeContainerConstMetaAny) {
|
||||
auto test = [](const entt::meta_any any) {
|
||||
auto view = any.as_associative_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_EQ(view.value_type(), (entt::resolve<std::pair<const int, char>>()));
|
||||
ASSERT_EQ(view.find(2)->second.cast<const char &>(), 'c');
|
||||
};
|
||||
|
||||
std::map<int, char> map{{2, 'c'}};
|
||||
|
||||
test(map);
|
||||
test(entt::forward_as_meta(map));
|
||||
test(entt::forward_as_meta(std::as_const(map)));
|
||||
}
|
||||
|
||||
ENTT_DEBUG_TEST_F(MetaContainerDeathTest, KeyValueAssociativeContainerConstMetaAny) {
|
||||
auto test = [](const entt::meta_any any) {
|
||||
auto view = any.as_associative_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_DEATH(view.find(2)->second.cast<char &>() = 'a', "");
|
||||
};
|
||||
|
||||
std::map<int, char> map{{2, 'c'}};
|
||||
|
||||
test(map);
|
||||
test(entt::forward_as_meta(map));
|
||||
test(entt::forward_as_meta(std::as_const(map)));
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, KeyOnlyAssociativeContainerConstMetaAny) {
|
||||
auto test = [](const entt::meta_any any) {
|
||||
auto view = any.as_associative_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_EQ(view.value_type(), (entt::resolve<int>()));
|
||||
|
||||
ASSERT_EQ(view.find(2)->first.try_cast<int>(), nullptr);
|
||||
ASSERT_NE(view.find(2)->first.try_cast<const int>(), nullptr);
|
||||
ASSERT_EQ(view.find(2)->first.cast<int>(), 2);
|
||||
ASSERT_EQ(view.find(2)->first.cast<const int &>(), 2);
|
||||
};
|
||||
|
||||
std::set<int> set{2};
|
||||
|
||||
test(set);
|
||||
test(entt::forward_as_meta(set));
|
||||
test(entt::forward_as_meta(std::as_const(set)));
|
||||
}
|
||||
|
||||
TEST_F(MetaContainer, StdVectorBool) {
|
||||
using proxy_type = typename std::vector<bool>::reference;
|
||||
using const_proxy_type = typename std::vector<bool>::const_reference;
|
||||
|
||||
std::vector<bool> vec{};
|
||||
auto any = entt::forward_as_meta(vec);
|
||||
auto cany = std::as_const(any).as_ref();
|
||||
|
||||
auto view = any.as_sequence_container();
|
||||
auto cview = cany.as_sequence_container();
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_EQ(view.value_type(), entt::resolve<bool>());
|
||||
|
||||
ASSERT_EQ(view.size(), 0u);
|
||||
ASSERT_EQ(view.begin(), view.end());
|
||||
ASSERT_TRUE(view.resize(3u));
|
||||
ASSERT_EQ(view.size(), 3u);
|
||||
ASSERT_NE(view.begin(), view.end());
|
||||
|
||||
view[0].cast<proxy_type>() = true;
|
||||
view[1].cast<proxy_type>() = true;
|
||||
view[2].cast<proxy_type>() = false;
|
||||
|
||||
ASSERT_EQ(cview[1u].cast<const_proxy_type>(), true);
|
||||
|
||||
auto it = view.begin();
|
||||
auto ret = view.insert(it, true);
|
||||
|
||||
ASSERT_TRUE(ret);
|
||||
ASSERT_FALSE(view.insert(ret, invalid_type{}));
|
||||
ASSERT_TRUE(view.insert(++ret, false));
|
||||
|
||||
ASSERT_EQ(view.size(), 5u);
|
||||
ASSERT_EQ(view.begin()->cast<proxy_type>(), true);
|
||||
ASSERT_EQ((++cview.begin())->cast<const_proxy_type>(), false);
|
||||
|
||||
it = view.begin();
|
||||
ret = view.erase(it);
|
||||
|
||||
ASSERT_TRUE(ret);
|
||||
ASSERT_EQ(view.size(), 4u);
|
||||
ASSERT_EQ(ret->cast<proxy_type>(), false);
|
||||
|
||||
ASSERT_TRUE(view.clear());
|
||||
ASSERT_EQ(cview.size(), 0u);
|
||||
}
|
505
test/entt/meta/meta_context.cpp
Normal file
505
test/entt/meta/meta_context.cpp
Normal file
@ -0,0 +1,505 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/hashed_string.hpp>
|
||||
#include <entt/meta/container.hpp>
|
||||
#include <entt/meta/context.hpp>
|
||||
#include <entt/meta/factory.hpp>
|
||||
#include <entt/meta/pointer.hpp>
|
||||
#include <entt/meta/template.hpp>
|
||||
|
||||
struct base {
|
||||
base() = default;
|
||||
|
||||
base(char v)
|
||||
: value{v} {}
|
||||
|
||||
char get() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
char value;
|
||||
};
|
||||
|
||||
struct clazz: base {
|
||||
clazz() = default;
|
||||
|
||||
clazz(int v)
|
||||
: base{},
|
||||
value{v} {}
|
||||
|
||||
clazz(char c, int v)
|
||||
: base{c},
|
||||
value{v} {}
|
||||
|
||||
int func(int v) {
|
||||
return (value = v);
|
||||
}
|
||||
|
||||
int cfunc(int v) const {
|
||||
return v;
|
||||
}
|
||||
|
||||
static void move_to_bucket(const clazz &instance) {
|
||||
bucket = instance.value;
|
||||
}
|
||||
|
||||
int value{};
|
||||
static inline int bucket{};
|
||||
};
|
||||
|
||||
struct local_only {};
|
||||
|
||||
struct argument {
|
||||
argument(int val)
|
||||
: value{val} {}
|
||||
|
||||
int get() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
int get_mul() const {
|
||||
return value * 2;
|
||||
}
|
||||
|
||||
private:
|
||||
int value{};
|
||||
};
|
||||
|
||||
template<typename...>
|
||||
struct template_clazz {};
|
||||
|
||||
class MetaContext: public ::testing::Test {
|
||||
void init_global_context() {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::meta<int>()
|
||||
.data<global_marker>("marker"_hs);
|
||||
|
||||
entt::meta<argument>()
|
||||
.conv<&argument::get>();
|
||||
|
||||
entt::meta<clazz>()
|
||||
.type("foo"_hs)
|
||||
.prop("prop"_hs, prop_value)
|
||||
.ctor<int>()
|
||||
.data<&clazz::value>("value"_hs)
|
||||
.data<&clazz::value>("rw"_hs)
|
||||
.func<&clazz::func>("func"_hs);
|
||||
|
||||
entt::meta<template_clazz<int>>()
|
||||
.type("template"_hs);
|
||||
}
|
||||
|
||||
void init_local_context() {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::meta<int>(context)
|
||||
.data<local_marker>("marker"_hs);
|
||||
|
||||
entt::meta<local_only>(context)
|
||||
.type("quux"_hs);
|
||||
|
||||
entt::meta<argument>(context)
|
||||
.conv<&argument::get_mul>();
|
||||
|
||||
entt::meta<base>(context)
|
||||
.data<&base::value>("char"_hs)
|
||||
.func<&base::get>("get"_hs);
|
||||
|
||||
entt::meta<clazz>(context)
|
||||
.type("bar"_hs)
|
||||
.prop("prop"_hs, prop_value)
|
||||
.base<base>()
|
||||
.ctor<char, int>()
|
||||
.dtor<&clazz::move_to_bucket>()
|
||||
.data<nullptr, &clazz::value>("value"_hs)
|
||||
.data<&clazz::value>("rw"_hs)
|
||||
.func<&clazz::cfunc>("func"_hs);
|
||||
|
||||
entt::meta<template_clazz<int, char>>(context)
|
||||
.type("template"_hs);
|
||||
}
|
||||
|
||||
public:
|
||||
void SetUp() override {
|
||||
init_global_context();
|
||||
init_local_context();
|
||||
|
||||
clazz::bucket = bucket_value;
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
entt::meta_reset(context);
|
||||
entt::meta_reset();
|
||||
}
|
||||
|
||||
protected:
|
||||
static constexpr int global_marker = 1;
|
||||
static constexpr int local_marker = 42;
|
||||
static constexpr int bucket_value = 99;
|
||||
static constexpr int prop_value = 3;
|
||||
entt::meta_ctx context{};
|
||||
};
|
||||
|
||||
TEST_F(MetaContext, Resolve) {
|
||||
using namespace entt::literals;
|
||||
|
||||
ASSERT_TRUE(entt::resolve<clazz>());
|
||||
ASSERT_TRUE(entt::resolve<clazz>(context));
|
||||
|
||||
ASSERT_TRUE(entt::resolve<local_only>());
|
||||
ASSERT_TRUE(entt::resolve<local_only>(context));
|
||||
|
||||
ASSERT_TRUE(entt::resolve(entt::type_id<clazz>()));
|
||||
ASSERT_TRUE(entt::resolve(context, entt::type_id<clazz>()));
|
||||
|
||||
ASSERT_FALSE(entt::resolve(entt::type_id<local_only>()));
|
||||
ASSERT_TRUE(entt::resolve(context, entt::type_id<local_only>()));
|
||||
|
||||
ASSERT_TRUE(entt::resolve("foo"_hs));
|
||||
ASSERT_FALSE(entt::resolve(context, "foo"_hs));
|
||||
|
||||
ASSERT_FALSE(entt::resolve("bar"_hs));
|
||||
ASSERT_TRUE(entt::resolve(context, "bar"_hs));
|
||||
|
||||
ASSERT_FALSE(entt::resolve("quux"_hs));
|
||||
ASSERT_TRUE(entt::resolve(context, "quux"_hs));
|
||||
|
||||
ASSERT_EQ((std::distance(entt::resolve().cbegin(), entt::resolve().cend())), 4);
|
||||
ASSERT_EQ((std::distance(entt::resolve(context).cbegin(), entt::resolve(context).cend())), 6);
|
||||
}
|
||||
|
||||
TEST_F(MetaContext, MetaType) {
|
||||
using namespace entt::literals;
|
||||
|
||||
const auto global = entt::resolve<clazz>();
|
||||
const auto local = entt::resolve<clazz>(context);
|
||||
|
||||
ASSERT_TRUE(global);
|
||||
ASSERT_TRUE(local);
|
||||
|
||||
ASSERT_NE(global, local);
|
||||
|
||||
ASSERT_EQ(global, entt::resolve("foo"_hs));
|
||||
ASSERT_EQ(local, entt::resolve(context, "bar"_hs));
|
||||
|
||||
ASSERT_EQ(global.id(), "foo"_hs);
|
||||
ASSERT_EQ(local.id(), "bar"_hs);
|
||||
|
||||
clazz instance{'c', 99};
|
||||
const argument value{2};
|
||||
|
||||
ASSERT_NE(instance.value, value.get());
|
||||
ASSERT_EQ(global.invoke("func"_hs, instance, value).cast<int>(), value.get());
|
||||
ASSERT_EQ(instance.value, value.get());
|
||||
|
||||
ASSERT_NE(instance.value, value.get_mul());
|
||||
ASSERT_EQ(local.invoke("func"_hs, instance, value).cast<int>(), value.get_mul());
|
||||
ASSERT_NE(instance.value, value.get_mul());
|
||||
|
||||
ASSERT_FALSE(global.invoke("get"_hs, instance));
|
||||
ASSERT_EQ(local.invoke("get"_hs, instance).cast<char>(), 'c');
|
||||
}
|
||||
|
||||
TEST_F(MetaContext, MetaBase) {
|
||||
const auto global = entt::resolve<clazz>();
|
||||
const auto local = entt::resolve<clazz>(context);
|
||||
|
||||
ASSERT_EQ((std::distance(global.base().cbegin(), global.base().cend())), 0);
|
||||
ASSERT_EQ((std::distance(local.base().cbegin(), local.base().cend())), 1);
|
||||
|
||||
ASSERT_EQ(local.base().cbegin()->second.info(), entt::type_id<base>());
|
||||
|
||||
ASSERT_FALSE(entt::resolve(entt::type_id<base>()));
|
||||
ASSERT_TRUE(entt::resolve(context, entt::type_id<base>()));
|
||||
}
|
||||
|
||||
TEST_F(MetaContext, MetaData) {
|
||||
using namespace entt::literals;
|
||||
|
||||
const auto global = entt::resolve<clazz>();
|
||||
const auto local = entt::resolve<clazz>(context);
|
||||
|
||||
ASSERT_TRUE(global.data("value"_hs));
|
||||
ASSERT_TRUE(local.data("value"_hs));
|
||||
|
||||
ASSERT_FALSE(global.data("value"_hs).is_const());
|
||||
ASSERT_TRUE(local.data("value"_hs).is_const());
|
||||
|
||||
ASSERT_EQ(global.data("value"_hs).type().data("marker"_hs).get({}).cast<int>(), global_marker);
|
||||
ASSERT_EQ(local.data("value"_hs).type().data("marker"_hs).get({}).cast<int>(), local_marker);
|
||||
|
||||
ASSERT_EQ(global.data("rw"_hs).arg(0u).data("marker"_hs).get({}).cast<int>(), global_marker);
|
||||
ASSERT_EQ(local.data("rw"_hs).arg(0u).data("marker"_hs).get({}).cast<int>(), local_marker);
|
||||
|
||||
clazz instance{'c', 99};
|
||||
const argument value{2};
|
||||
|
||||
ASSERT_NE(instance.value, value.get());
|
||||
ASSERT_TRUE(global.data("rw"_hs).set(instance, value));
|
||||
ASSERT_EQ(instance.value, value.get());
|
||||
|
||||
ASSERT_NE(instance.value, value.get_mul());
|
||||
ASSERT_TRUE(local.data("rw"_hs).set(instance, value));
|
||||
ASSERT_EQ(instance.value, value.get_mul());
|
||||
|
||||
ASSERT_FALSE(global.data("char"_hs));
|
||||
ASSERT_EQ(local.data("char"_hs).get(instance).cast<char>(), 'c');
|
||||
ASSERT_TRUE(local.data("char"_hs).set(instance, 'x'));
|
||||
ASSERT_EQ(instance.base::value, 'x');
|
||||
}
|
||||
|
||||
TEST_F(MetaContext, MetaFunc) {
|
||||
using namespace entt::literals;
|
||||
|
||||
const auto global = entt::resolve<clazz>();
|
||||
const auto local = entt::resolve<clazz>(context);
|
||||
|
||||
ASSERT_TRUE(global.func("func"_hs));
|
||||
ASSERT_TRUE(local.func("func"_hs));
|
||||
|
||||
ASSERT_FALSE(global.func("func"_hs).is_const());
|
||||
ASSERT_TRUE(local.func("func"_hs).is_const());
|
||||
|
||||
ASSERT_EQ(global.func("func"_hs).arg(0u).data("marker"_hs).get({}).cast<int>(), global_marker);
|
||||
ASSERT_EQ(local.func("func"_hs).arg(0u).data("marker"_hs).get({}).cast<int>(), local_marker);
|
||||
|
||||
ASSERT_EQ(global.func("func"_hs).ret().data("marker"_hs).get({}).cast<int>(), global_marker);
|
||||
ASSERT_EQ(local.func("func"_hs).ret().data("marker"_hs).get({}).cast<int>(), local_marker);
|
||||
|
||||
clazz instance{'c', 99};
|
||||
const argument value{2};
|
||||
|
||||
ASSERT_NE(instance.value, value.get());
|
||||
ASSERT_EQ(global.func("func"_hs).invoke(instance, value).cast<int>(), value.get());
|
||||
ASSERT_EQ(instance.value, value.get());
|
||||
|
||||
ASSERT_NE(instance.value, value.get_mul());
|
||||
ASSERT_EQ(local.func("func"_hs).invoke(instance, value).cast<int>(), value.get_mul());
|
||||
ASSERT_NE(instance.value, value.get_mul());
|
||||
|
||||
ASSERT_FALSE(global.func("get"_hs));
|
||||
ASSERT_EQ(local.func("get"_hs).invoke(instance).cast<char>(), 'c');
|
||||
}
|
||||
|
||||
TEST_F(MetaContext, MetaCtor) {
|
||||
const auto global = entt::resolve<clazz>();
|
||||
const auto local = entt::resolve<clazz>(context);
|
||||
|
||||
auto any = global.construct();
|
||||
auto other = local.construct();
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_TRUE(other);
|
||||
|
||||
ASSERT_EQ(any.cast<const clazz &>().value, 0);
|
||||
ASSERT_EQ(other.cast<const clazz &>().value, 0);
|
||||
|
||||
argument argument{2};
|
||||
|
||||
any = global.construct(argument);
|
||||
other = local.construct(argument);
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_FALSE(other);
|
||||
ASSERT_EQ(any.cast<const clazz &>().value, 2);
|
||||
|
||||
any = global.construct('c', argument);
|
||||
other = local.construct('c', argument);
|
||||
|
||||
ASSERT_FALSE(any);
|
||||
ASSERT_TRUE(other);
|
||||
ASSERT_EQ(other.cast<const clazz &>().value, 4);
|
||||
}
|
||||
|
||||
TEST_F(MetaContext, MetaConv) {
|
||||
argument value{2};
|
||||
|
||||
auto global = entt::forward_as_meta(value);
|
||||
auto local = entt::forward_as_meta(context, value);
|
||||
|
||||
ASSERT_TRUE(global.allow_cast<int>());
|
||||
ASSERT_TRUE(local.allow_cast<int>());
|
||||
|
||||
ASSERT_EQ(global.cast<int>(), value.get());
|
||||
ASSERT_EQ(local.cast<int>(), value.get_mul());
|
||||
}
|
||||
|
||||
TEST_F(MetaContext, MetaDtor) {
|
||||
auto global = entt::resolve<clazz>().construct();
|
||||
auto local = entt::resolve<clazz>(context).construct();
|
||||
|
||||
ASSERT_EQ(clazz::bucket, bucket_value);
|
||||
|
||||
global.reset();
|
||||
|
||||
ASSERT_EQ(clazz::bucket, bucket_value);
|
||||
|
||||
local.reset();
|
||||
|
||||
ASSERT_NE(clazz::bucket, bucket_value);
|
||||
}
|
||||
|
||||
TEST_F(MetaContext, MetaProp) {
|
||||
using namespace entt::literals;
|
||||
|
||||
const auto global = entt::resolve<clazz>();
|
||||
const auto local = entt::resolve<clazz>(context);
|
||||
|
||||
ASSERT_TRUE(global.prop("prop"_hs));
|
||||
ASSERT_TRUE(local.prop("prop"_hs));
|
||||
|
||||
ASSERT_EQ(global.prop("prop"_hs).value().type(), entt::resolve<int>());
|
||||
ASSERT_EQ(local.prop("prop"_hs).value().type(), entt::resolve<int>(context));
|
||||
|
||||
ASSERT_EQ(global.prop("prop"_hs).value().cast<int>(), prop_value);
|
||||
ASSERT_EQ(local.prop("prop"_hs).value().cast<int>(), prop_value);
|
||||
|
||||
ASSERT_EQ(global.prop("prop"_hs).value().type().data("marker"_hs).get({}).cast<int>(), global_marker);
|
||||
ASSERT_EQ(local.prop("prop"_hs).value().type().data("marker"_hs).get({}).cast<int>(), local_marker);
|
||||
}
|
||||
|
||||
TEST_F(MetaContext, MetaTemplate) {
|
||||
using namespace entt::literals;
|
||||
|
||||
const auto global = entt::resolve("template"_hs);
|
||||
const auto local = entt::resolve(context, "template"_hs);
|
||||
|
||||
ASSERT_TRUE(global.is_template_specialization());
|
||||
ASSERT_TRUE(local.is_template_specialization());
|
||||
|
||||
ASSERT_EQ(global.template_arity(), 1u);
|
||||
ASSERT_EQ(local.template_arity(), 2u);
|
||||
|
||||
ASSERT_EQ(global.template_arg(0u), entt::resolve<int>());
|
||||
ASSERT_EQ(local.template_arg(0u), entt::resolve<int>(context));
|
||||
ASSERT_EQ(local.template_arg(1u), entt::resolve<char>(context));
|
||||
|
||||
ASSERT_EQ(global.template_arg(0u).data("marker"_hs).get({}).cast<int>(), global_marker);
|
||||
ASSERT_EQ(local.template_arg(0u).data("marker"_hs).get({}).cast<int>(), local_marker);
|
||||
}
|
||||
|
||||
TEST_F(MetaContext, MetaPointer) {
|
||||
using namespace entt::literals;
|
||||
|
||||
int value = 42;
|
||||
|
||||
const entt::meta_any global{&value};
|
||||
const entt::meta_any local{context, &value};
|
||||
|
||||
ASSERT_TRUE(global.type().is_pointer());
|
||||
ASSERT_TRUE(local.type().is_pointer());
|
||||
|
||||
ASSERT_TRUE(global.type().is_pointer_like());
|
||||
ASSERT_TRUE(local.type().is_pointer_like());
|
||||
|
||||
ASSERT_EQ((*global).type().data("marker"_hs).get({}).cast<int>(), global_marker);
|
||||
ASSERT_EQ((*local).type().data("marker"_hs).get({}).cast<int>(), local_marker);
|
||||
}
|
||||
|
||||
TEST_F(MetaContext, MetaAssociativeContainer) {
|
||||
using namespace entt::literals;
|
||||
|
||||
std::unordered_map<int, int> map{{{0, 0}}};
|
||||
|
||||
auto global = entt::forward_as_meta(map).as_associative_container();
|
||||
auto local = entt::forward_as_meta(context, map).as_associative_container();
|
||||
|
||||
ASSERT_TRUE(global);
|
||||
ASSERT_TRUE(local);
|
||||
|
||||
ASSERT_EQ(global.size(), 1u);
|
||||
ASSERT_EQ(local.size(), 1u);
|
||||
|
||||
ASSERT_EQ(global.key_type().data("marker"_hs).get({}).cast<int>(), global_marker);
|
||||
ASSERT_EQ(local.key_type().data("marker"_hs).get({}).cast<int>(), local_marker);
|
||||
|
||||
ASSERT_EQ(global.mapped_type().data("marker"_hs).get({}).cast<int>(), global_marker);
|
||||
ASSERT_EQ(local.mapped_type().data("marker"_hs).get({}).cast<int>(), local_marker);
|
||||
|
||||
ASSERT_EQ((*global.begin()).first.type().data("marker"_hs).get({}).cast<int>(), global_marker);
|
||||
ASSERT_EQ((*local.begin()).first.type().data("marker"_hs).get({}).cast<int>(), local_marker);
|
||||
|
||||
ASSERT_EQ((*global.begin()).second.type().data("marker"_hs).get({}).cast<int>(), global_marker);
|
||||
ASSERT_EQ((*local.begin()).second.type().data("marker"_hs).get({}).cast<int>(), local_marker);
|
||||
}
|
||||
|
||||
TEST_F(MetaContext, MetaSequenceContainer) {
|
||||
using namespace entt::literals;
|
||||
|
||||
std::vector<int> vec{0};
|
||||
|
||||
auto global = entt::forward_as_meta(vec).as_sequence_container();
|
||||
auto local = entt::forward_as_meta(context, vec).as_sequence_container();
|
||||
|
||||
ASSERT_TRUE(global);
|
||||
ASSERT_TRUE(local);
|
||||
|
||||
ASSERT_EQ(global.size(), 1u);
|
||||
ASSERT_EQ(local.size(), 1u);
|
||||
|
||||
ASSERT_EQ(global.value_type().data("marker"_hs).get({}).cast<int>(), global_marker);
|
||||
ASSERT_EQ(local.value_type().data("marker"_hs).get({}).cast<int>(), local_marker);
|
||||
|
||||
ASSERT_EQ((*global.begin()).type().data("marker"_hs).get({}).cast<int>(), global_marker);
|
||||
ASSERT_EQ((*local.begin()).type().data("marker"_hs).get({}).cast<int>(), local_marker);
|
||||
}
|
||||
|
||||
TEST_F(MetaContext, MetaAny) {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::meta_any global{42};
|
||||
entt::meta_any ctx_value{context, 42};
|
||||
entt::meta_any in_place{context, std::in_place_type<int>, 42};
|
||||
entt::meta_any two_step_local{entt::meta_ctx_arg, context};
|
||||
|
||||
ASSERT_TRUE(global);
|
||||
ASSERT_TRUE(ctx_value);
|
||||
ASSERT_TRUE(in_place);
|
||||
ASSERT_FALSE(two_step_local);
|
||||
|
||||
two_step_local = 42;
|
||||
|
||||
ASSERT_TRUE(two_step_local);
|
||||
|
||||
ASSERT_EQ(global.type().data("marker"_hs).get({}).cast<int>(), global_marker);
|
||||
ASSERT_EQ(ctx_value.type().data("marker"_hs).get({}).cast<int>(), local_marker);
|
||||
ASSERT_EQ(in_place.type().data("marker"_hs).get({}).cast<int>(), local_marker);
|
||||
ASSERT_EQ(two_step_local.type().data("marker"_hs).get({}).cast<int>(), local_marker);
|
||||
}
|
||||
|
||||
TEST_F(MetaContext, MetaHandle) {
|
||||
using namespace entt::literals;
|
||||
|
||||
int value = 42;
|
||||
|
||||
entt::meta_handle global{value};
|
||||
entt::meta_handle ctx_value{context, value};
|
||||
entt::meta_handle two_step_local{entt::meta_ctx_arg, context};
|
||||
|
||||
ASSERT_TRUE(global);
|
||||
ASSERT_TRUE(ctx_value);
|
||||
ASSERT_FALSE(two_step_local);
|
||||
|
||||
two_step_local->emplace<int &>(value);
|
||||
|
||||
ASSERT_TRUE(two_step_local);
|
||||
|
||||
ASSERT_EQ(global->type().data("marker"_hs).get({}).cast<int>(), global_marker);
|
||||
ASSERT_EQ(ctx_value->type().data("marker"_hs).get({}).cast<int>(), local_marker);
|
||||
ASSERT_EQ(two_step_local->type().data("marker"_hs).get({}).cast<int>(), local_marker);
|
||||
}
|
||||
|
||||
TEST_F(MetaContext, ForwardAsMeta) {
|
||||
using namespace entt::literals;
|
||||
|
||||
const auto global = entt::forward_as_meta(42);
|
||||
const auto local = entt::forward_as_meta(context, 42);
|
||||
|
||||
ASSERT_TRUE(global);
|
||||
ASSERT_TRUE(local);
|
||||
|
||||
ASSERT_EQ(global.type().data("marker"_hs).get({}).cast<int>(), global_marker);
|
||||
ASSERT_EQ(local.type().data("marker"_hs).get({}).cast<int>(), local_marker);
|
||||
}
|
71
test/entt/meta/meta_conv.cpp
Normal file
71
test/entt/meta/meta_conv.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
#include <utility>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/hashed_string.hpp>
|
||||
#include <entt/locator/locator.hpp>
|
||||
#include <entt/meta/factory.hpp>
|
||||
#include <entt/meta/meta.hpp>
|
||||
#include <entt/meta/node.hpp>
|
||||
#include <entt/meta/resolve.hpp>
|
||||
|
||||
struct clazz_t {
|
||||
clazz_t() = default;
|
||||
|
||||
operator int() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
bool to_bool() const {
|
||||
return (value != 0);
|
||||
}
|
||||
|
||||
int value{};
|
||||
};
|
||||
|
||||
double conv_to_double(const clazz_t &instance) {
|
||||
return instance.value * 2.;
|
||||
}
|
||||
|
||||
struct MetaConv: ::testing::Test {
|
||||
void SetUp() override {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::meta<clazz_t>()
|
||||
.type("clazz"_hs)
|
||||
.conv<int>()
|
||||
.conv<&clazz_t::to_bool>()
|
||||
.conv<conv_to_double>();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
entt::meta_reset();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(MetaConv, Functionalities) {
|
||||
auto any = entt::resolve<clazz_t>().construct();
|
||||
any.cast<clazz_t &>().value = 42;
|
||||
|
||||
const auto as_int = std::as_const(any).allow_cast<int>();
|
||||
const auto as_bool = std::as_const(any).allow_cast<bool>();
|
||||
const auto as_double = std::as_const(any).allow_cast<double>();
|
||||
|
||||
ASSERT_FALSE(any.allow_cast<char>());
|
||||
|
||||
ASSERT_TRUE(as_int);
|
||||
ASSERT_TRUE(as_bool);
|
||||
ASSERT_TRUE(as_double);
|
||||
|
||||
ASSERT_EQ(as_int.cast<int>(), any.cast<clazz_t &>().operator int());
|
||||
ASSERT_EQ(as_bool.cast<bool>(), any.cast<clazz_t &>().to_bool());
|
||||
ASSERT_EQ(as_double.cast<double>(), conv_to_double(any.cast<clazz_t &>()));
|
||||
}
|
||||
|
||||
TEST_F(MetaConv, ReRegistration) {
|
||||
SetUp();
|
||||
|
||||
auto &&node = entt::internal::resolve<clazz_t>(entt::internal::meta_context::from(entt::locator<entt::meta_ctx>::value_or()));
|
||||
|
||||
ASSERT_TRUE(node.details);
|
||||
ASSERT_FALSE(node.details->conv.empty());
|
||||
ASSERT_EQ(node.details->conv.size(), 3u);
|
||||
}
|
215
test/entt/meta/meta_ctor.cpp
Normal file
215
test/entt/meta/meta_ctor.cpp
Normal file
@ -0,0 +1,215 @@
|
||||
#include <utility>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/hashed_string.hpp>
|
||||
#include <entt/core/utility.hpp>
|
||||
#include <entt/entity/registry.hpp>
|
||||
#include <entt/locator/locator.hpp>
|
||||
#include <entt/meta/factory.hpp>
|
||||
#include <entt/meta/meta.hpp>
|
||||
#include <entt/meta/resolve.hpp>
|
||||
|
||||
struct base_t {
|
||||
base_t()
|
||||
: value{'c'} {}
|
||||
|
||||
char value;
|
||||
};
|
||||
|
||||
struct derived_t: base_t {
|
||||
derived_t()
|
||||
: base_t{} {}
|
||||
};
|
||||
|
||||
struct clazz_t {
|
||||
clazz_t(const base_t &other, int &iv)
|
||||
: clazz_t{iv, other.value} {}
|
||||
|
||||
clazz_t(const int &iv, char cv)
|
||||
: i{iv}, c{cv} {}
|
||||
|
||||
operator int() const {
|
||||
return i;
|
||||
}
|
||||
|
||||
static clazz_t factory(int value) {
|
||||
return {value, 'c'};
|
||||
}
|
||||
|
||||
static clazz_t factory(base_t other, int value, int mul) {
|
||||
return {value * mul, other.value};
|
||||
}
|
||||
|
||||
int i{};
|
||||
char c{};
|
||||
};
|
||||
|
||||
double double_factory() {
|
||||
return 42.;
|
||||
}
|
||||
|
||||
struct MetaCtor: ::testing::Test {
|
||||
void SetUp() override {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::meta<double>()
|
||||
.type("double"_hs)
|
||||
.ctor<double_factory>();
|
||||
|
||||
entt::meta<derived_t>()
|
||||
.type("derived"_hs)
|
||||
.base<base_t>();
|
||||
|
||||
entt::meta<clazz_t>()
|
||||
.type("clazz"_hs)
|
||||
.ctor<&entt::registry::emplace_or_replace<clazz_t, const int &, const char &>, entt::as_ref_t>()
|
||||
.ctor<const base_t &, int &>()
|
||||
.ctor<const int &, char>()
|
||||
.ctor<entt::overload<clazz_t(int)>(clazz_t::factory)>()
|
||||
.ctor<entt::overload<clazz_t(base_t, int, int)>(clazz_t::factory)>()
|
||||
.conv<int>();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
entt::meta_reset();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(MetaCtor, Functionalities) {
|
||||
auto any = entt::resolve<clazz_t>().construct(42, 'c');
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.cast<clazz_t>().i, 42);
|
||||
ASSERT_EQ(any.cast<clazz_t>().c, 'c');
|
||||
}
|
||||
|
||||
TEST_F(MetaCtor, Func) {
|
||||
auto any = entt::resolve<clazz_t>().construct(42);
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.cast<clazz_t>().i, 42);
|
||||
ASSERT_EQ(any.cast<clazz_t>().c, 'c');
|
||||
}
|
||||
|
||||
TEST_F(MetaCtor, MetaAnyArgs) {
|
||||
auto any = entt::resolve<clazz_t>().construct(entt::meta_any{42}, entt::meta_any{'c'});
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.cast<clazz_t>().i, 42);
|
||||
ASSERT_EQ(any.cast<clazz_t>().c, 'c');
|
||||
}
|
||||
|
||||
TEST_F(MetaCtor, InvalidArgs) {
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().construct(entt::meta_any{}, derived_t{}));
|
||||
}
|
||||
|
||||
TEST_F(MetaCtor, CastAndConvert) {
|
||||
auto any = entt::resolve<clazz_t>().construct(derived_t{}, clazz_t{42, 'd'});
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.cast<clazz_t>().i, 42);
|
||||
ASSERT_EQ(any.cast<clazz_t>().c, 'c');
|
||||
}
|
||||
|
||||
TEST_F(MetaCtor, ArithmeticConversion) {
|
||||
auto any = entt::resolve<clazz_t>().construct(true, 4.2);
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.cast<clazz_t>().i, 1);
|
||||
ASSERT_EQ(any.cast<clazz_t>().c, char{4});
|
||||
}
|
||||
|
||||
TEST_F(MetaCtor, ConstNonConstRefArgs) {
|
||||
int ivalue = 42;
|
||||
const char cvalue = 'c';
|
||||
auto any = entt::resolve<clazz_t>().construct(entt::forward_as_meta(ivalue), entt::forward_as_meta(cvalue));
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.cast<clazz_t>().i, 42);
|
||||
ASSERT_EQ(any.cast<clazz_t>().c, 'c');
|
||||
}
|
||||
|
||||
TEST_F(MetaCtor, WrongConstness) {
|
||||
int value = 42;
|
||||
auto any = entt::resolve<clazz_t>().construct(derived_t{}, entt::forward_as_meta(value));
|
||||
auto other = entt::resolve<clazz_t>().construct(derived_t{}, entt::forward_as_meta(std::as_const(value)));
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_FALSE(other);
|
||||
ASSERT_EQ(any.cast<clazz_t>().i, 42);
|
||||
ASSERT_EQ(any.cast<clazz_t>().c, 'c');
|
||||
}
|
||||
|
||||
TEST_F(MetaCtor, FuncMetaAnyArgs) {
|
||||
auto any = entt::resolve<clazz_t>().construct(entt::meta_any{42});
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.cast<clazz_t>().i, 42);
|
||||
ASSERT_EQ(any.cast<clazz_t>().c, 'c');
|
||||
}
|
||||
|
||||
TEST_F(MetaCtor, FuncCastAndConvert) {
|
||||
auto any = entt::resolve<clazz_t>().construct(derived_t{}, 3., clazz_t{3, 'd'});
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.cast<clazz_t>().i, 9);
|
||||
ASSERT_EQ(any.cast<clazz_t>().c, 'c');
|
||||
}
|
||||
|
||||
TEST_F(MetaCtor, FuncArithmeticConversion) {
|
||||
auto any = entt::resolve<clazz_t>().construct(4.2);
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.cast<clazz_t>().i, 4);
|
||||
ASSERT_EQ(any.cast<clazz_t>().c, 'c');
|
||||
}
|
||||
|
||||
TEST_F(MetaCtor, FuncConstNonConstRefArgs) {
|
||||
int ivalue = 42;
|
||||
auto any = entt::resolve<clazz_t>().construct(entt::forward_as_meta(ivalue));
|
||||
auto other = entt::resolve<clazz_t>().construct(entt::forward_as_meta(std::as_const(ivalue)));
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_TRUE(other);
|
||||
ASSERT_EQ(any.cast<clazz_t>().i, 42);
|
||||
ASSERT_EQ(other.cast<clazz_t>().i, 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaCtor, ExternalMemberFunction) {
|
||||
entt::registry registry;
|
||||
const auto entity = registry.create();
|
||||
|
||||
ASSERT_FALSE(registry.all_of<clazz_t>(entity));
|
||||
|
||||
const auto any = entt::resolve<clazz_t>().construct(entt::forward_as_meta(registry), entity, 3, 'c');
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_TRUE(registry.all_of<clazz_t>(entity));
|
||||
ASSERT_EQ(registry.get<clazz_t>(entity).i, 3);
|
||||
ASSERT_EQ(registry.get<clazz_t>(entity).c, 'c');
|
||||
}
|
||||
|
||||
TEST_F(MetaCtor, OverrideImplicitlyGeneratedDefaultConstructor) {
|
||||
auto type = entt::resolve<double>();
|
||||
auto any = type.construct();
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.type(), entt::resolve<double>());
|
||||
ASSERT_EQ(any.cast<double>(), 42.);
|
||||
}
|
||||
|
||||
TEST_F(MetaCtor, NonDefaultConstructibleType) {
|
||||
auto type = entt::resolve<clazz_t>();
|
||||
// no implicitly generated default constructor
|
||||
ASSERT_FALSE(type.construct());
|
||||
}
|
||||
|
||||
TEST_F(MetaCtor, ReRegistration) {
|
||||
SetUp();
|
||||
|
||||
auto &&node = entt::internal::resolve<double>(entt::internal::meta_context::from(entt::locator<entt::meta_ctx>::value_or()));
|
||||
|
||||
ASSERT_TRUE(node.details);
|
||||
ASSERT_FALSE(node.details->ctor.empty());
|
||||
// implicitly generated default constructor is not cleared
|
||||
ASSERT_NE(node.default_constructor, nullptr);
|
||||
}
|
678
test/entt/meta/meta_data.cpp
Normal file
678
test/entt/meta/meta_data.cpp
Normal file
@ -0,0 +1,678 @@
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/hashed_string.hpp>
|
||||
#include <entt/core/type_traits.hpp>
|
||||
#include <entt/locator/locator.hpp>
|
||||
#include <entt/meta/factory.hpp>
|
||||
#include <entt/meta/meta.hpp>
|
||||
#include <entt/meta/node.hpp>
|
||||
#include <entt/meta/resolve.hpp>
|
||||
#include "../common/config.h"
|
||||
|
||||
struct base_t {
|
||||
virtual ~base_t() = default;
|
||||
|
||||
static void destroy(base_t &) {
|
||||
++counter;
|
||||
}
|
||||
|
||||
inline static int counter = 0;
|
||||
int value{3};
|
||||
};
|
||||
|
||||
struct derived_t: base_t {
|
||||
derived_t() {}
|
||||
};
|
||||
|
||||
struct clazz_t {
|
||||
clazz_t()
|
||||
: i{0},
|
||||
j{1},
|
||||
base{} {}
|
||||
|
||||
operator int() const {
|
||||
return h;
|
||||
}
|
||||
|
||||
int i{0};
|
||||
const int j{1};
|
||||
base_t base{};
|
||||
inline static int h{2};
|
||||
inline static const int k{3};
|
||||
};
|
||||
|
||||
struct setter_getter_t {
|
||||
setter_getter_t()
|
||||
: value{0} {}
|
||||
|
||||
int setter(double val) {
|
||||
return value = static_cast<int>(val);
|
||||
}
|
||||
|
||||
int getter() {
|
||||
return value;
|
||||
}
|
||||
|
||||
int setter_with_ref(const int &val) {
|
||||
return value = val;
|
||||
}
|
||||
|
||||
const int &getter_with_ref() {
|
||||
return value;
|
||||
}
|
||||
|
||||
static int static_setter(setter_getter_t &type, int value) {
|
||||
return type.value = value;
|
||||
}
|
||||
|
||||
static int static_getter(const setter_getter_t &type) {
|
||||
return type.value;
|
||||
}
|
||||
|
||||
int value;
|
||||
};
|
||||
|
||||
struct multi_setter_t {
|
||||
multi_setter_t()
|
||||
: value{0} {}
|
||||
|
||||
void from_double(double val) {
|
||||
value = val;
|
||||
}
|
||||
|
||||
void from_string(const char *val) {
|
||||
value = std::atoi(val);
|
||||
}
|
||||
|
||||
int value;
|
||||
};
|
||||
|
||||
struct array_t {
|
||||
static inline int global[3];
|
||||
int local[5];
|
||||
};
|
||||
|
||||
enum class property_t : entt::id_type {
|
||||
random,
|
||||
value
|
||||
};
|
||||
|
||||
struct MetaData: ::testing::Test {
|
||||
void SetUp() override {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::meta<double>()
|
||||
.type("double"_hs);
|
||||
|
||||
entt::meta<base_t>()
|
||||
.type("base"_hs)
|
||||
.dtor<base_t::destroy>()
|
||||
.data<&base_t::value>("value"_hs);
|
||||
|
||||
entt::meta<derived_t>()
|
||||
.type("derived"_hs)
|
||||
.base<base_t>()
|
||||
.dtor<derived_t::destroy>()
|
||||
.data<&base_t::value>("value_from_base"_hs);
|
||||
|
||||
entt::meta<clazz_t>()
|
||||
.type("clazz"_hs)
|
||||
.data<&clazz_t::i, entt::as_ref_t>("i"_hs)
|
||||
.prop(3u, 0)
|
||||
.data<&clazz_t::i, entt::as_cref_t>("ci"_hs)
|
||||
.data<&clazz_t::j>("j"_hs)
|
||||
.prop("true"_hs, 1)
|
||||
.data<&clazz_t::h>("h"_hs)
|
||||
.prop(static_cast<entt::id_type>(property_t::random), 2)
|
||||
.data<&clazz_t::k>("k"_hs)
|
||||
.prop(static_cast<entt::id_type>(property_t::value), 3)
|
||||
.data<&clazz_t::base>("base"_hs)
|
||||
.data<&clazz_t::i, entt::as_void_t>("void"_hs)
|
||||
.conv<int>();
|
||||
|
||||
entt::meta<setter_getter_t>()
|
||||
.type("setter_getter"_hs)
|
||||
.data<&setter_getter_t::static_setter, &setter_getter_t::static_getter>("x"_hs)
|
||||
.data<&setter_getter_t::setter, &setter_getter_t::getter>("y"_hs)
|
||||
.data<&setter_getter_t::static_setter, &setter_getter_t::getter>("z"_hs)
|
||||
.data<&setter_getter_t::setter_with_ref, &setter_getter_t::getter_with_ref>("w"_hs)
|
||||
.data<nullptr, &setter_getter_t::getter>("z_ro"_hs)
|
||||
.data<nullptr, &setter_getter_t::value>("value"_hs);
|
||||
|
||||
entt::meta<multi_setter_t>()
|
||||
.type("multi_setter"_hs)
|
||||
.data<entt::value_list<&multi_setter_t::from_double, &multi_setter_t::from_string>, &multi_setter_t::value>("value"_hs);
|
||||
|
||||
entt::meta<array_t>()
|
||||
.type("array"_hs)
|
||||
.data<&array_t::global>("global"_hs)
|
||||
.data<&array_t::local>("local"_hs);
|
||||
|
||||
base_t::counter = 0;
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
entt::meta_reset();
|
||||
}
|
||||
};
|
||||
|
||||
using MetaDataDeathTest = MetaData;
|
||||
|
||||
TEST_F(MetaData, Functionalities) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto data = entt::resolve<clazz_t>().data("i"_hs);
|
||||
clazz_t instance{};
|
||||
|
||||
ASSERT_TRUE(data);
|
||||
ASSERT_EQ(data.arity(), 1u);
|
||||
ASSERT_EQ(data.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(data.arg(0u), entt::resolve<int>());
|
||||
ASSERT_FALSE(data.is_const());
|
||||
ASSERT_FALSE(data.is_static());
|
||||
ASSERT_EQ(data.get(instance).cast<int>(), 0);
|
||||
ASSERT_TRUE(data.set(instance, 42));
|
||||
ASSERT_EQ(data.get(instance).cast<int>(), 42);
|
||||
|
||||
for(auto curr: data.prop()) {
|
||||
ASSERT_EQ(curr.first, 3u);
|
||||
ASSERT_EQ(curr.second.value(), 0);
|
||||
}
|
||||
|
||||
ASSERT_FALSE(data.prop(2));
|
||||
ASSERT_FALSE(data.prop('c'));
|
||||
|
||||
auto prop = data.prop(3u);
|
||||
|
||||
ASSERT_TRUE(prop);
|
||||
ASSERT_EQ(prop.value(), 0);
|
||||
}
|
||||
|
||||
TEST_F(MetaData, Const) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto data = entt::resolve<clazz_t>().data("j"_hs);
|
||||
clazz_t instance{};
|
||||
|
||||
ASSERT_TRUE(data);
|
||||
ASSERT_EQ(data.arity(), 1u);
|
||||
ASSERT_EQ(data.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(data.arg(0u), entt::resolve<int>());
|
||||
ASSERT_TRUE(data.is_const());
|
||||
ASSERT_FALSE(data.is_static());
|
||||
ASSERT_EQ(data.get(instance).cast<int>(), 1);
|
||||
ASSERT_FALSE(data.set(instance, 42));
|
||||
ASSERT_EQ(data.get(instance).cast<int>(), 1);
|
||||
|
||||
for(auto curr: data.prop()) {
|
||||
ASSERT_EQ(curr.first, "true"_hs);
|
||||
ASSERT_EQ(curr.second.value(), 1);
|
||||
}
|
||||
|
||||
ASSERT_FALSE(data.prop(false));
|
||||
ASSERT_FALSE(data.prop('c'));
|
||||
|
||||
auto prop = data.prop("true"_hs);
|
||||
|
||||
ASSERT_TRUE(prop);
|
||||
ASSERT_EQ(prop.value(), 1);
|
||||
}
|
||||
|
||||
TEST_F(MetaData, Static) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto data = entt::resolve<clazz_t>().data("h"_hs);
|
||||
|
||||
ASSERT_TRUE(data);
|
||||
ASSERT_EQ(data.arity(), 1u);
|
||||
ASSERT_EQ(data.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(data.arg(0u), entt::resolve<int>());
|
||||
ASSERT_FALSE(data.is_const());
|
||||
ASSERT_TRUE(data.is_static());
|
||||
ASSERT_EQ(data.get({}).cast<int>(), 2);
|
||||
ASSERT_TRUE(data.set({}, 42));
|
||||
ASSERT_EQ(data.get({}).cast<int>(), 42);
|
||||
|
||||
for(auto curr: data.prop()) {
|
||||
ASSERT_EQ(curr.first, static_cast<entt::id_type>(property_t::random));
|
||||
ASSERT_EQ(curr.second.value(), 2);
|
||||
}
|
||||
|
||||
ASSERT_FALSE(data.prop(static_cast<entt::id_type>(property_t::value)));
|
||||
ASSERT_FALSE(data.prop('c'));
|
||||
|
||||
auto prop = data.prop(static_cast<entt::id_type>(property_t::random));
|
||||
|
||||
ASSERT_TRUE(prop);
|
||||
ASSERT_EQ(prop.value(), 2);
|
||||
}
|
||||
|
||||
TEST_F(MetaData, ConstStatic) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto data = entt::resolve<clazz_t>().data("k"_hs);
|
||||
|
||||
ASSERT_TRUE(data);
|
||||
ASSERT_EQ(data.arity(), 1u);
|
||||
ASSERT_EQ(data.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(data.arg(0u), entt::resolve<int>());
|
||||
ASSERT_TRUE(data.is_const());
|
||||
ASSERT_TRUE(data.is_static());
|
||||
ASSERT_EQ(data.get({}).cast<int>(), 3);
|
||||
ASSERT_FALSE(data.set({}, 42));
|
||||
ASSERT_EQ(data.get({}).cast<int>(), 3);
|
||||
|
||||
for(auto curr: data.prop()) {
|
||||
ASSERT_EQ(curr.first, static_cast<entt::id_type>(property_t::value));
|
||||
ASSERT_EQ(curr.second.value(), 3);
|
||||
}
|
||||
|
||||
ASSERT_FALSE(data.prop(static_cast<entt::id_type>(property_t::random)));
|
||||
ASSERT_FALSE(data.prop('c'));
|
||||
|
||||
auto prop = data.prop(static_cast<entt::id_type>(property_t::value));
|
||||
|
||||
ASSERT_TRUE(prop);
|
||||
ASSERT_EQ(prop.value(), 3);
|
||||
}
|
||||
|
||||
TEST_F(MetaData, GetMetaAnyArg) {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::meta_any any{clazz_t{}};
|
||||
any.cast<clazz_t &>().i = 99;
|
||||
const auto value = entt::resolve<clazz_t>().data("i"_hs).get(any);
|
||||
|
||||
ASSERT_TRUE(value);
|
||||
ASSERT_TRUE(static_cast<bool>(value.cast<int>()));
|
||||
ASSERT_EQ(value.cast<int>(), 99);
|
||||
}
|
||||
|
||||
TEST_F(MetaData, GetInvalidArg) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto instance = 0;
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().data("i"_hs).get(instance));
|
||||
}
|
||||
|
||||
TEST_F(MetaData, SetMetaAnyArg) {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::meta_any any{clazz_t{}};
|
||||
entt::meta_any value{42};
|
||||
|
||||
ASSERT_EQ(any.cast<clazz_t>().i, 0);
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().data("i"_hs).set(any, value));
|
||||
ASSERT_EQ(any.cast<clazz_t>().i, 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaData, SetInvalidArg) {
|
||||
using namespace entt::literals;
|
||||
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().data("i"_hs).set({}, 'c'));
|
||||
}
|
||||
|
||||
TEST_F(MetaData, SetCast) {
|
||||
using namespace entt::literals;
|
||||
|
||||
clazz_t instance{};
|
||||
|
||||
ASSERT_EQ(base_t::counter, 0);
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().data("base"_hs).set(instance, derived_t{}));
|
||||
ASSERT_EQ(base_t::counter, 1);
|
||||
}
|
||||
|
||||
TEST_F(MetaData, SetConvert) {
|
||||
using namespace entt::literals;
|
||||
|
||||
clazz_t instance{};
|
||||
instance.h = 42;
|
||||
|
||||
ASSERT_EQ(instance.i, 0);
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().data("i"_hs).set(instance, instance));
|
||||
ASSERT_EQ(instance.i, 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaData, SetByRef) {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::meta_any any{clazz_t{}};
|
||||
int value{42};
|
||||
|
||||
ASSERT_EQ(any.cast<clazz_t>().i, 0);
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().data("i"_hs).set(any, entt::forward_as_meta(value)));
|
||||
ASSERT_EQ(any.cast<clazz_t>().i, 42);
|
||||
|
||||
value = 3;
|
||||
auto wrapper = entt::forward_as_meta(value);
|
||||
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().data("i"_hs).set(any, wrapper.as_ref()));
|
||||
ASSERT_EQ(any.cast<clazz_t>().i, 3);
|
||||
}
|
||||
|
||||
TEST_F(MetaData, SetByConstRef) {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::meta_any any{clazz_t{}};
|
||||
int value{42};
|
||||
|
||||
ASSERT_EQ(any.cast<clazz_t>().i, 0);
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().data("i"_hs).set(any, entt::forward_as_meta(std::as_const(value))));
|
||||
ASSERT_EQ(any.cast<clazz_t>().i, 42);
|
||||
|
||||
value = 3;
|
||||
auto wrapper = entt::forward_as_meta(std::as_const(value));
|
||||
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().data("i"_hs).set(any, wrapper.as_ref()));
|
||||
ASSERT_EQ(any.cast<clazz_t>().i, 3);
|
||||
}
|
||||
|
||||
TEST_F(MetaData, SetterGetterAsFreeFunctions) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto data = entt::resolve<setter_getter_t>().data("x"_hs);
|
||||
setter_getter_t instance{};
|
||||
|
||||
ASSERT_TRUE(data);
|
||||
ASSERT_EQ(data.arity(), 1u);
|
||||
ASSERT_EQ(data.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(data.arg(0u), entt::resolve<int>());
|
||||
ASSERT_FALSE(data.is_const());
|
||||
ASSERT_FALSE(data.is_static());
|
||||
ASSERT_EQ(data.get(instance).cast<int>(), 0);
|
||||
ASSERT_TRUE(data.set(instance, 42));
|
||||
ASSERT_EQ(data.get(instance).cast<int>(), 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaData, SetterGetterAsMemberFunctions) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto data = entt::resolve<setter_getter_t>().data("y"_hs);
|
||||
setter_getter_t instance{};
|
||||
|
||||
ASSERT_TRUE(data);
|
||||
ASSERT_EQ(data.arity(), 1u);
|
||||
ASSERT_EQ(data.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(data.arg(0u), entt::resolve<double>());
|
||||
ASSERT_FALSE(data.is_const());
|
||||
ASSERT_FALSE(data.is_static());
|
||||
ASSERT_EQ(data.get(instance).cast<int>(), 0);
|
||||
ASSERT_TRUE(data.set(instance, 42.));
|
||||
ASSERT_EQ(data.get(instance).cast<int>(), 42);
|
||||
ASSERT_TRUE(data.set(instance, 3));
|
||||
ASSERT_EQ(data.get(instance).cast<int>(), 3);
|
||||
}
|
||||
|
||||
TEST_F(MetaData, SetterGetterWithRefAsMemberFunctions) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto data = entt::resolve<setter_getter_t>().data("w"_hs);
|
||||
setter_getter_t instance{};
|
||||
|
||||
ASSERT_TRUE(data);
|
||||
ASSERT_EQ(data.arity(), 1u);
|
||||
ASSERT_EQ(data.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(data.arg(0u), entt::resolve<int>());
|
||||
ASSERT_FALSE(data.is_const());
|
||||
ASSERT_FALSE(data.is_static());
|
||||
ASSERT_EQ(data.get(instance).cast<int>(), 0);
|
||||
ASSERT_TRUE(data.set(instance, 42));
|
||||
ASSERT_EQ(data.get(instance).cast<int>(), 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaData, SetterGetterMixed) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto data = entt::resolve<setter_getter_t>().data("z"_hs);
|
||||
setter_getter_t instance{};
|
||||
|
||||
ASSERT_TRUE(data);
|
||||
ASSERT_EQ(data.arity(), 1u);
|
||||
ASSERT_EQ(data.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(data.arg(0u), entt::resolve<int>());
|
||||
ASSERT_FALSE(data.is_const());
|
||||
ASSERT_FALSE(data.is_static());
|
||||
ASSERT_EQ(data.get(instance).cast<int>(), 0);
|
||||
ASSERT_TRUE(data.set(instance, 42));
|
||||
ASSERT_EQ(data.get(instance).cast<int>(), 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaData, SetterGetterReadOnly) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto data = entt::resolve<setter_getter_t>().data("z_ro"_hs);
|
||||
setter_getter_t instance{};
|
||||
|
||||
ASSERT_TRUE(data);
|
||||
ASSERT_EQ(data.arity(), 0u);
|
||||
ASSERT_EQ(data.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(data.arg(0u), entt::meta_type{});
|
||||
ASSERT_TRUE(data.is_const());
|
||||
ASSERT_FALSE(data.is_static());
|
||||
ASSERT_EQ(data.get(instance).cast<int>(), 0);
|
||||
ASSERT_FALSE(data.set(instance, 42));
|
||||
ASSERT_EQ(data.get(instance).cast<int>(), 0);
|
||||
}
|
||||
|
||||
TEST_F(MetaData, SetterGetterReadOnlyDataMember) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto data = entt::resolve<setter_getter_t>().data("value"_hs);
|
||||
setter_getter_t instance{};
|
||||
|
||||
ASSERT_TRUE(data);
|
||||
ASSERT_EQ(data.arity(), 0u);
|
||||
ASSERT_EQ(data.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(data.arg(0u), entt::meta_type{});
|
||||
ASSERT_TRUE(data.is_const());
|
||||
ASSERT_FALSE(data.is_static());
|
||||
ASSERT_EQ(data.get(instance).cast<int>(), 0);
|
||||
ASSERT_FALSE(data.set(instance, 42));
|
||||
ASSERT_EQ(data.get(instance).cast<int>(), 0);
|
||||
}
|
||||
|
||||
TEST_F(MetaData, MultiSetter) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto data = entt::resolve<multi_setter_t>().data("value"_hs);
|
||||
multi_setter_t instance{};
|
||||
|
||||
ASSERT_TRUE(data);
|
||||
ASSERT_EQ(data.arity(), 2u);
|
||||
ASSERT_EQ(data.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(data.arg(0u), entt::resolve<double>());
|
||||
ASSERT_EQ(data.arg(1u), entt::resolve<const char *>());
|
||||
ASSERT_EQ(data.arg(2u), entt::meta_type{});
|
||||
ASSERT_FALSE(data.is_const());
|
||||
ASSERT_FALSE(data.is_static());
|
||||
ASSERT_EQ(data.get(instance).cast<int>(), 0);
|
||||
ASSERT_TRUE(data.set(instance, 42));
|
||||
ASSERT_EQ(data.get(instance).cast<int>(), 42);
|
||||
ASSERT_TRUE(data.set(instance, 3.));
|
||||
ASSERT_EQ(data.get(instance).cast<int>(), 3);
|
||||
ASSERT_FALSE(data.set(instance, std::string{"99"}));
|
||||
ASSERT_TRUE(data.set(instance, std::string{"99"}.c_str()));
|
||||
ASSERT_EQ(data.get(instance).cast<int>(), 99);
|
||||
}
|
||||
|
||||
TEST_F(MetaData, ConstInstance) {
|
||||
using namespace entt::literals;
|
||||
|
||||
clazz_t instance{};
|
||||
|
||||
ASSERT_NE(entt::resolve<clazz_t>().data("i"_hs).get(instance).try_cast<int>(), nullptr);
|
||||
ASSERT_NE(entt::resolve<clazz_t>().data("i"_hs).get(instance).try_cast<const int>(), nullptr);
|
||||
ASSERT_EQ(entt::resolve<clazz_t>().data("i"_hs).get(std::as_const(instance)).try_cast<int>(), nullptr);
|
||||
// as_ref_t adapts to the constness of the passed object and returns const references in case
|
||||
ASSERT_NE(entt::resolve<clazz_t>().data("i"_hs).get(std::as_const(instance)).try_cast<const int>(), nullptr);
|
||||
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().data("i"_hs).get(instance));
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().data("i"_hs).set(instance, 3));
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().data("i"_hs).get(std::as_const(instance)));
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().data("i"_hs).set(std::as_const(instance), 3));
|
||||
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().data("ci"_hs).get(instance));
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().data("ci"_hs).set(instance, 3));
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().data("ci"_hs).get(std::as_const(instance)));
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().data("ci"_hs).set(std::as_const(instance), 3));
|
||||
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().data("j"_hs).get(instance));
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().data("j"_hs).set(instance, 3));
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().data("j"_hs).get(std::as_const(instance)));
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().data("j"_hs).set(std::as_const(instance), 3));
|
||||
}
|
||||
|
||||
TEST_F(MetaData, ArrayStatic) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto data = entt::resolve<array_t>().data("global"_hs);
|
||||
|
||||
ASSERT_TRUE(data);
|
||||
ASSERT_EQ(data.arity(), 1u);
|
||||
ASSERT_EQ(data.type(), entt::resolve<int[3]>());
|
||||
ASSERT_EQ(data.arg(0u), entt::resolve<int[3]>());
|
||||
ASSERT_FALSE(data.is_const());
|
||||
ASSERT_TRUE(data.is_static());
|
||||
ASSERT_TRUE(data.type().is_array());
|
||||
ASSERT_FALSE(data.get({}));
|
||||
}
|
||||
|
||||
TEST_F(MetaData, Array) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto data = entt::resolve<array_t>().data("local"_hs);
|
||||
array_t instance{};
|
||||
|
||||
ASSERT_TRUE(data);
|
||||
ASSERT_EQ(data.arity(), 1u);
|
||||
ASSERT_EQ(data.type(), entt::resolve<int[5]>());
|
||||
ASSERT_EQ(data.arg(0u), entt::resolve<int[5]>());
|
||||
ASSERT_FALSE(data.is_const());
|
||||
ASSERT_FALSE(data.is_static());
|
||||
ASSERT_TRUE(data.type().is_array());
|
||||
ASSERT_FALSE(data.get(instance));
|
||||
}
|
||||
|
||||
TEST_F(MetaData, AsVoid) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto data = entt::resolve<clazz_t>().data("void"_hs);
|
||||
clazz_t instance{};
|
||||
|
||||
ASSERT_TRUE(data);
|
||||
ASSERT_EQ(data.arity(), 1u);
|
||||
ASSERT_EQ(data.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(data.arg(0u), entt::resolve<int>());
|
||||
ASSERT_TRUE(data.set(instance, 42));
|
||||
ASSERT_EQ(instance.i, 42);
|
||||
ASSERT_EQ(data.get(instance), entt::meta_any{std::in_place_type<void>});
|
||||
}
|
||||
|
||||
TEST_F(MetaData, AsRef) {
|
||||
using namespace entt::literals;
|
||||
|
||||
clazz_t instance{};
|
||||
auto data = entt::resolve<clazz_t>().data("i"_hs);
|
||||
|
||||
ASSERT_TRUE(data);
|
||||
ASSERT_EQ(data.arity(), 1u);
|
||||
ASSERT_EQ(data.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(data.arg(0u), entt::resolve<int>());
|
||||
ASSERT_NE(data.prop().cbegin(), data.prop().cend());
|
||||
ASSERT_EQ(instance.i, 0);
|
||||
|
||||
data.get(instance).cast<int &>() = 3;
|
||||
|
||||
ASSERT_EQ(instance.i, 3);
|
||||
}
|
||||
|
||||
TEST_F(MetaData, AsConstRef) {
|
||||
using namespace entt::literals;
|
||||
|
||||
clazz_t instance{};
|
||||
auto data = entt::resolve<clazz_t>().data("ci"_hs);
|
||||
|
||||
ASSERT_EQ(instance.i, 0);
|
||||
ASSERT_EQ(data.arity(), 1u);
|
||||
ASSERT_EQ(data.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(data.arg(0u), entt::resolve<int>());
|
||||
ASSERT_EQ(data.get(instance).cast<const int &>(), 0);
|
||||
ASSERT_EQ(data.get(instance).cast<int>(), 0);
|
||||
ASSERT_EQ(data.prop().cbegin(), data.prop().cend());
|
||||
ASSERT_EQ(instance.i, 0);
|
||||
}
|
||||
|
||||
ENTT_DEBUG_TEST_F(MetaDataDeathTest, AsConstRef) {
|
||||
using namespace entt::literals;
|
||||
|
||||
clazz_t instance{};
|
||||
auto data = entt::resolve<clazz_t>().data("ci"_hs);
|
||||
|
||||
ASSERT_DEATH(data.get(instance).cast<int &>() = 3, "");
|
||||
}
|
||||
|
||||
TEST_F(MetaData, SetGetBaseData) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto type = entt::resolve<derived_t>();
|
||||
derived_t instance{};
|
||||
|
||||
ASSERT_TRUE(type.data("value"_hs));
|
||||
|
||||
ASSERT_EQ(instance.value, 3);
|
||||
ASSERT_TRUE(type.data("value"_hs).set(instance, 42));
|
||||
ASSERT_EQ(type.data("value"_hs).get(instance).cast<int>(), 42);
|
||||
ASSERT_EQ(instance.value, 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaData, SetGetFromBase) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto type = entt::resolve<derived_t>();
|
||||
derived_t instance{};
|
||||
|
||||
ASSERT_TRUE(type.data("value_from_base"_hs));
|
||||
|
||||
ASSERT_EQ(instance.value, 3);
|
||||
ASSERT_TRUE(type.data("value_from_base"_hs).set(instance, 42));
|
||||
ASSERT_EQ(type.data("value_from_base"_hs).get(instance).cast<int>(), 42);
|
||||
ASSERT_EQ(instance.value, 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaData, ReRegistration) {
|
||||
using namespace entt::literals;
|
||||
|
||||
SetUp();
|
||||
|
||||
auto &&node = entt::internal::resolve<base_t>(entt::internal::meta_context::from(entt::locator<entt::meta_ctx>::value_or()));
|
||||
auto type = entt::resolve<base_t>();
|
||||
|
||||
ASSERT_TRUE(node.details);
|
||||
ASSERT_FALSE(node.details->data.empty());
|
||||
ASSERT_EQ(node.details->data.size(), 1u);
|
||||
ASSERT_TRUE(type.data("value"_hs));
|
||||
|
||||
entt::meta<base_t>().data<&base_t::value>("field"_hs);
|
||||
|
||||
ASSERT_TRUE(node.details);
|
||||
ASSERT_EQ(node.details->data.size(), 2u);
|
||||
ASSERT_TRUE(type.data("value"_hs));
|
||||
ASSERT_TRUE(type.data("field"_hs));
|
||||
}
|
||||
|
||||
TEST_F(MetaData, CollisionAndReuse) {
|
||||
using namespace entt::literals;
|
||||
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().data("j"_hs));
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().data("cj"_hs));
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().data("j"_hs).is_const());
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(entt::meta<clazz_t>().data<&clazz_t::i>("j"_hs));
|
||||
ASSERT_NO_FATAL_FAILURE(entt::meta<clazz_t>().data<&clazz_t::j>("cj"_hs));
|
||||
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().data("j"_hs));
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().data("cj"_hs));
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().data("j"_hs).is_const());
|
||||
}
|
113
test/entt/meta/meta_dtor.cpp
Normal file
113
test/entt/meta/meta_dtor.cpp
Normal file
@ -0,0 +1,113 @@
|
||||
#include <utility>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/hashed_string.hpp>
|
||||
#include <entt/locator/locator.hpp>
|
||||
#include <entt/meta/factory.hpp>
|
||||
#include <entt/meta/meta.hpp>
|
||||
#include <entt/meta/node.hpp>
|
||||
#include <entt/meta/resolve.hpp>
|
||||
|
||||
struct clazz_t {
|
||||
clazz_t() {
|
||||
++counter;
|
||||
}
|
||||
|
||||
static void destroy_decr(clazz_t &) {
|
||||
--counter;
|
||||
}
|
||||
|
||||
void destroy_incr() const {
|
||||
++counter;
|
||||
}
|
||||
|
||||
inline static int counter = 0;
|
||||
};
|
||||
|
||||
struct MetaDtor: ::testing::Test {
|
||||
void SetUp() override {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::meta<clazz_t>()
|
||||
.type("clazz"_hs)
|
||||
.dtor<clazz_t::destroy_decr>();
|
||||
|
||||
clazz_t::counter = 0;
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
entt::meta_reset();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(MetaDtor, Functionalities) {
|
||||
ASSERT_EQ(clazz_t::counter, 0);
|
||||
|
||||
auto any = entt::resolve<clazz_t>().construct();
|
||||
auto cref = std::as_const(any).as_ref();
|
||||
auto ref = any.as_ref();
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_TRUE(cref);
|
||||
ASSERT_TRUE(ref);
|
||||
|
||||
ASSERT_EQ(clazz_t::counter, 1);
|
||||
|
||||
cref.reset();
|
||||
ref.reset();
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_FALSE(cref);
|
||||
ASSERT_FALSE(ref);
|
||||
|
||||
ASSERT_EQ(clazz_t::counter, 1);
|
||||
|
||||
any.reset();
|
||||
|
||||
ASSERT_FALSE(any);
|
||||
ASSERT_FALSE(cref);
|
||||
ASSERT_FALSE(ref);
|
||||
|
||||
ASSERT_EQ(clazz_t::counter, 0);
|
||||
}
|
||||
|
||||
TEST_F(MetaDtor, AsRefConstruction) {
|
||||
ASSERT_EQ(clazz_t::counter, 0);
|
||||
|
||||
clazz_t instance{};
|
||||
auto any = entt::forward_as_meta(instance);
|
||||
auto cany = entt::forward_as_meta(std::as_const(instance));
|
||||
auto cref = cany.as_ref();
|
||||
auto ref = any.as_ref();
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_TRUE(cany);
|
||||
ASSERT_TRUE(cref);
|
||||
ASSERT_TRUE(ref);
|
||||
|
||||
ASSERT_EQ(clazz_t::counter, 1);
|
||||
|
||||
any.reset();
|
||||
cany.reset();
|
||||
cref.reset();
|
||||
ref.reset();
|
||||
|
||||
ASSERT_FALSE(any);
|
||||
ASSERT_FALSE(cany);
|
||||
ASSERT_FALSE(cref);
|
||||
ASSERT_FALSE(ref);
|
||||
|
||||
ASSERT_EQ(clazz_t::counter, 1);
|
||||
}
|
||||
|
||||
TEST_F(MetaDtor, ReRegistration) {
|
||||
SetUp();
|
||||
|
||||
auto &&node = entt::internal::resolve<clazz_t>(entt::internal::meta_context::from(entt::locator<entt::meta_ctx>::value_or()));
|
||||
|
||||
ASSERT_NE(node.dtor.dtor, nullptr);
|
||||
|
||||
entt::meta<clazz_t>().dtor<&clazz_t::destroy_incr>();
|
||||
entt::resolve<clazz_t>().construct().reset();
|
||||
|
||||
ASSERT_EQ(clazz_t::counter, 2);
|
||||
}
|
608
test/entt/meta/meta_func.cpp
Normal file
608
test/entt/meta/meta_func.cpp
Normal file
@ -0,0 +1,608 @@
|
||||
#include <cstddef>
|
||||
#include <utility>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/hashed_string.hpp>
|
||||
#include <entt/core/utility.hpp>
|
||||
#include <entt/entity/registry.hpp>
|
||||
#include <entt/meta/factory.hpp>
|
||||
#include <entt/meta/meta.hpp>
|
||||
#include <entt/meta/resolve.hpp>
|
||||
#include "../common/config.h"
|
||||
|
||||
struct base_t {
|
||||
base_t() {}
|
||||
virtual ~base_t() = default;
|
||||
|
||||
static void destroy(base_t &) {
|
||||
++counter;
|
||||
}
|
||||
|
||||
void setter(int v) {
|
||||
value = v;
|
||||
}
|
||||
|
||||
int getter() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
static void static_setter(base_t &ref, int v) {
|
||||
ref.value = v;
|
||||
}
|
||||
|
||||
inline static int counter = 0;
|
||||
int value{3};
|
||||
};
|
||||
|
||||
void fake_member(base_t &instance, int value) {
|
||||
instance.value = value;
|
||||
}
|
||||
|
||||
int fake_const_member(const base_t &instance) {
|
||||
return instance.value;
|
||||
}
|
||||
|
||||
struct derived_t: base_t {
|
||||
derived_t()
|
||||
: base_t{} {}
|
||||
};
|
||||
|
||||
struct func_t {
|
||||
int f(const base_t &, int a, int b) {
|
||||
return f(a, b);
|
||||
}
|
||||
|
||||
int f(int a, int b) {
|
||||
value = a;
|
||||
return b * b;
|
||||
}
|
||||
|
||||
int f(int v) const {
|
||||
return v * v;
|
||||
}
|
||||
|
||||
void g(int v) {
|
||||
value = v * v;
|
||||
}
|
||||
|
||||
static int h(int &v) {
|
||||
return (v *= value);
|
||||
}
|
||||
|
||||
static void k(int v) {
|
||||
value = v;
|
||||
}
|
||||
|
||||
int v(int v) const {
|
||||
return (value = v);
|
||||
}
|
||||
|
||||
int &a() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
operator int() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
inline static int value = 0;
|
||||
};
|
||||
|
||||
struct MetaFunc: ::testing::Test {
|
||||
void SetUp() override {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::meta<double>()
|
||||
.type("double"_hs);
|
||||
|
||||
entt::meta<base_t>()
|
||||
.type("base"_hs)
|
||||
.dtor<base_t::destroy>()
|
||||
.func<&base_t::setter>("setter"_hs)
|
||||
.func<fake_member>("fake_member"_hs)
|
||||
.func<fake_const_member>("fake_const_member"_hs);
|
||||
|
||||
entt::meta<derived_t>()
|
||||
.type("derived"_hs)
|
||||
.base<base_t>()
|
||||
.func<&base_t::setter>("setter_from_base"_hs)
|
||||
.func<&base_t::getter>("getter_from_base"_hs)
|
||||
.func<&base_t::static_setter>("static_setter_from_base"_hs)
|
||||
.dtor<derived_t::destroy>();
|
||||
|
||||
entt::meta<func_t>()
|
||||
.type("func"_hs)
|
||||
.func<&entt::registry::emplace_or_replace<func_t>>("emplace"_hs)
|
||||
.func<entt::overload<int(const base_t &, int, int)>(&func_t::f)>("f3"_hs)
|
||||
.func<entt::overload<int(int, int)>(&func_t::f)>("f2"_hs)
|
||||
.prop("true"_hs, false)
|
||||
.func<entt::overload<int(int) const>(&func_t::f)>("f1"_hs)
|
||||
.prop("true"_hs, false)
|
||||
.func<&func_t::g>("g"_hs)
|
||||
.prop("true"_hs, false)
|
||||
.func<func_t::h>("h"_hs)
|
||||
.prop("true"_hs, false)
|
||||
.func<func_t::k>("k"_hs)
|
||||
.prop("true"_hs, false)
|
||||
.func<&func_t::v, entt::as_void_t>("v"_hs)
|
||||
.func<&func_t::a, entt::as_ref_t>("a"_hs)
|
||||
.func<&func_t::a, entt::as_cref_t>("ca"_hs)
|
||||
.conv<int>();
|
||||
|
||||
base_t::counter = 0;
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
entt::meta_reset();
|
||||
}
|
||||
|
||||
std::size_t reset_and_check() {
|
||||
std::size_t count = 0;
|
||||
|
||||
for(auto func: entt::resolve<func_t>().func()) {
|
||||
for(auto curr = func.second; curr; curr = curr.next()) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
|
||||
SetUp();
|
||||
|
||||
for(auto func: entt::resolve<func_t>().func()) {
|
||||
for(auto curr = func.second; curr; curr = curr.next()) {
|
||||
--count;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
};
|
||||
};
|
||||
|
||||
using MetaFuncDeathTest = MetaFunc;
|
||||
|
||||
TEST_F(MetaFunc, Functionalities) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto func = entt::resolve<func_t>().func("f2"_hs);
|
||||
func_t instance{};
|
||||
|
||||
ASSERT_TRUE(func);
|
||||
ASSERT_EQ(func.arity(), 2u);
|
||||
ASSERT_FALSE(func.is_const());
|
||||
ASSERT_FALSE(func.is_static());
|
||||
ASSERT_EQ(func.ret(), entt::resolve<int>());
|
||||
ASSERT_EQ(func.arg(0u), entt::resolve<int>());
|
||||
ASSERT_EQ(func.arg(1u), entt::resolve<int>());
|
||||
ASSERT_FALSE(func.arg(2u));
|
||||
|
||||
auto any = func.invoke(instance, 3, 2);
|
||||
auto empty = func.invoke(instance);
|
||||
|
||||
ASSERT_FALSE(empty);
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(any.cast<int>(), 4);
|
||||
ASSERT_EQ(func_t::value, 3);
|
||||
|
||||
for(auto curr: func.prop()) {
|
||||
ASSERT_EQ(curr.first, "true"_hs);
|
||||
ASSERT_FALSE(curr.second.value().template cast<bool>());
|
||||
}
|
||||
|
||||
ASSERT_FALSE(func.prop(false));
|
||||
ASSERT_FALSE(func.prop('c'));
|
||||
|
||||
auto prop = func.prop("true"_hs);
|
||||
|
||||
ASSERT_TRUE(prop);
|
||||
ASSERT_FALSE(prop.value().cast<bool>());
|
||||
}
|
||||
|
||||
TEST_F(MetaFunc, Const) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto func = entt::resolve<func_t>().func("f1"_hs);
|
||||
func_t instance{};
|
||||
|
||||
ASSERT_TRUE(func);
|
||||
ASSERT_EQ(func.arity(), 1u);
|
||||
ASSERT_TRUE(func.is_const());
|
||||
ASSERT_FALSE(func.is_static());
|
||||
ASSERT_EQ(func.ret(), entt::resolve<int>());
|
||||
ASSERT_EQ(func.arg(0u), entt::resolve<int>());
|
||||
ASSERT_FALSE(func.arg(1u));
|
||||
|
||||
auto any = func.invoke(instance, 4);
|
||||
auto empty = func.invoke(instance, derived_t{});
|
||||
|
||||
ASSERT_FALSE(empty);
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(any.cast<int>(), 16);
|
||||
|
||||
for(auto curr: func.prop()) {
|
||||
ASSERT_EQ(curr.first, "true"_hs);
|
||||
ASSERT_FALSE(curr.second.value().template cast<bool>());
|
||||
}
|
||||
|
||||
ASSERT_FALSE(func.prop(false));
|
||||
ASSERT_FALSE(func.prop('c'));
|
||||
|
||||
auto prop = func.prop("true"_hs);
|
||||
|
||||
ASSERT_TRUE(prop);
|
||||
ASSERT_FALSE(prop.value().cast<bool>());
|
||||
}
|
||||
|
||||
TEST_F(MetaFunc, RetVoid) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto func = entt::resolve<func_t>().func("g"_hs);
|
||||
func_t instance{};
|
||||
|
||||
ASSERT_TRUE(func);
|
||||
ASSERT_EQ(func.arity(), 1u);
|
||||
ASSERT_FALSE(func.is_const());
|
||||
ASSERT_FALSE(func.is_static());
|
||||
ASSERT_EQ(func.ret(), entt::resolve<void>());
|
||||
ASSERT_EQ(func.arg(0u), entt::resolve<int>());
|
||||
ASSERT_FALSE(func.arg(1u));
|
||||
|
||||
auto any = func.invoke(instance, 5);
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.type(), entt::resolve<void>());
|
||||
ASSERT_EQ(func_t::value, 25);
|
||||
|
||||
for(auto curr: func.prop()) {
|
||||
ASSERT_EQ(curr.first, "true"_hs);
|
||||
ASSERT_FALSE(curr.second.value().template cast<bool>());
|
||||
}
|
||||
|
||||
ASSERT_FALSE(func.prop(false));
|
||||
ASSERT_FALSE(func.prop('c'));
|
||||
|
||||
auto prop = func.prop("true"_hs);
|
||||
|
||||
ASSERT_TRUE(prop);
|
||||
ASSERT_FALSE(prop.value().cast<bool>());
|
||||
}
|
||||
|
||||
TEST_F(MetaFunc, Static) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto func = entt::resolve<func_t>().func("h"_hs);
|
||||
func_t::value = 2;
|
||||
|
||||
ASSERT_TRUE(func);
|
||||
ASSERT_EQ(func.arity(), 1u);
|
||||
ASSERT_FALSE(func.is_const());
|
||||
ASSERT_TRUE(func.is_static());
|
||||
ASSERT_EQ(func.ret(), entt::resolve<int>());
|
||||
ASSERT_EQ(func.arg(0u), entt::resolve<int>());
|
||||
ASSERT_FALSE(func.arg(1u));
|
||||
|
||||
auto any = func.invoke({}, 3);
|
||||
auto empty = func.invoke({}, derived_t{});
|
||||
|
||||
ASSERT_FALSE(empty);
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(any.cast<int>(), 6);
|
||||
|
||||
for(auto curr: func.prop()) {
|
||||
ASSERT_EQ(curr.first, "true"_hs);
|
||||
ASSERT_FALSE(curr.second.value().template cast<bool>());
|
||||
}
|
||||
|
||||
ASSERT_FALSE(func.prop(false));
|
||||
ASSERT_FALSE(func.prop('c'));
|
||||
|
||||
auto prop = func.prop("true"_hs);
|
||||
|
||||
ASSERT_TRUE(prop);
|
||||
ASSERT_FALSE(prop.value().cast<bool>());
|
||||
}
|
||||
|
||||
TEST_F(MetaFunc, StaticRetVoid) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto func = entt::resolve<func_t>().func("k"_hs);
|
||||
|
||||
ASSERT_TRUE(func);
|
||||
ASSERT_EQ(func.arity(), 1u);
|
||||
ASSERT_FALSE(func.is_const());
|
||||
ASSERT_TRUE(func.is_static());
|
||||
ASSERT_EQ(func.ret(), entt::resolve<void>());
|
||||
ASSERT_EQ(func.arg(0u), entt::resolve<int>());
|
||||
ASSERT_FALSE(func.arg(1u));
|
||||
|
||||
auto any = func.invoke({}, 42);
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.type(), entt::resolve<void>());
|
||||
ASSERT_EQ(func_t::value, 42);
|
||||
|
||||
for(auto curr: func.prop()) {
|
||||
ASSERT_EQ(curr.first, "true"_hs);
|
||||
ASSERT_FALSE(curr.second.value().template cast<bool>());
|
||||
}
|
||||
|
||||
ASSERT_FALSE(func.prop(false));
|
||||
ASSERT_FALSE(func.prop('c'));
|
||||
|
||||
auto prop = func.prop("true"_hs);
|
||||
|
||||
ASSERT_TRUE(prop);
|
||||
ASSERT_FALSE(prop.value().cast<bool>());
|
||||
}
|
||||
|
||||
TEST_F(MetaFunc, StaticAsMember) {
|
||||
using namespace entt::literals;
|
||||
|
||||
base_t instance{};
|
||||
auto func = entt::resolve<base_t>().func("fake_member"_hs);
|
||||
auto any = func.invoke(instance, 42);
|
||||
|
||||
ASSERT_TRUE(func);
|
||||
ASSERT_EQ(func.arity(), 1u);
|
||||
ASSERT_FALSE(func.is_const());
|
||||
ASSERT_FALSE(func.is_static());
|
||||
ASSERT_EQ(func.ret(), entt::resolve<void>());
|
||||
ASSERT_EQ(func.arg(0u), entt::resolve<int>());
|
||||
ASSERT_FALSE(func.arg(1u));
|
||||
|
||||
ASSERT_EQ(func.prop().cbegin(), func.prop().cend());
|
||||
|
||||
ASSERT_FALSE(func.invoke({}, 42));
|
||||
ASSERT_FALSE(func.invoke(std::as_const(instance), 42));
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.type(), entt::resolve<void>());
|
||||
ASSERT_EQ(instance.value, 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaFunc, StaticAsConstMember) {
|
||||
using namespace entt::literals;
|
||||
|
||||
base_t instance{};
|
||||
auto func = entt::resolve<base_t>().func("fake_const_member"_hs);
|
||||
auto any = func.invoke(std::as_const(instance));
|
||||
|
||||
ASSERT_TRUE(func);
|
||||
ASSERT_EQ(func.arity(), 0u);
|
||||
ASSERT_TRUE(func.is_const());
|
||||
ASSERT_FALSE(func.is_static());
|
||||
ASSERT_EQ(func.ret(), entt::resolve<int>());
|
||||
ASSERT_FALSE(func.arg(0u));
|
||||
|
||||
ASSERT_EQ(func.prop().cbegin(), func.prop().cend());
|
||||
|
||||
ASSERT_FALSE(func.invoke({}));
|
||||
ASSERT_TRUE(func.invoke(instance));
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(any.cast<int>(), 3);
|
||||
}
|
||||
|
||||
TEST_F(MetaFunc, MetaAnyArgs) {
|
||||
using namespace entt::literals;
|
||||
|
||||
func_t instance;
|
||||
auto any = entt::resolve<func_t>().func("f1"_hs).invoke(instance, 3);
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(any.cast<int>(), 9);
|
||||
}
|
||||
|
||||
TEST_F(MetaFunc, InvalidArgs) {
|
||||
using namespace entt::literals;
|
||||
|
||||
int value = 3;
|
||||
ASSERT_FALSE(entt::resolve<func_t>().func("f1"_hs).invoke(value, 'c'));
|
||||
}
|
||||
|
||||
TEST_F(MetaFunc, CastAndConvert) {
|
||||
using namespace entt::literals;
|
||||
|
||||
func_t instance;
|
||||
instance.value = 3;
|
||||
auto any = entt::resolve<func_t>().func("f3"_hs).invoke(instance, derived_t{}, 0, instance);
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(any.cast<int>(), 9);
|
||||
ASSERT_EQ(instance.value, 0);
|
||||
}
|
||||
|
||||
TEST_F(MetaFunc, ArithmeticConversion) {
|
||||
using namespace entt::literals;
|
||||
|
||||
func_t instance;
|
||||
auto any = entt::resolve<func_t>().func("f2"_hs).invoke(instance, true, 4.2);
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(any.cast<int>(), 16);
|
||||
ASSERT_EQ(instance.value, 1);
|
||||
}
|
||||
|
||||
TEST_F(MetaFunc, ArgsByRef) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto func = entt::resolve<func_t>().func("h"_hs);
|
||||
func_t::value = 2;
|
||||
entt::meta_any any{3};
|
||||
int value = 4;
|
||||
|
||||
ASSERT_EQ(func.invoke({}, entt::forward_as_meta(value)).cast<int>(), 8);
|
||||
ASSERT_EQ(func.invoke({}, any.as_ref()).cast<int>(), 6);
|
||||
ASSERT_EQ(any.cast<int>(), 6);
|
||||
ASSERT_EQ(value, 8);
|
||||
}
|
||||
|
||||
TEST_F(MetaFunc, ArgsByConstRef) {
|
||||
using namespace entt::literals;
|
||||
|
||||
func_t instance{};
|
||||
auto func = entt::resolve<func_t>().func("g"_hs);
|
||||
entt::meta_any any{2};
|
||||
int value = 3;
|
||||
|
||||
ASSERT_TRUE(func.invoke(instance, entt::forward_as_meta(std::as_const(value))));
|
||||
ASSERT_EQ(func_t::value, 9);
|
||||
|
||||
ASSERT_TRUE(func.invoke(instance, std::as_const(any).as_ref()));
|
||||
ASSERT_EQ(func_t::value, 4);
|
||||
}
|
||||
|
||||
TEST_F(MetaFunc, ConstInstance) {
|
||||
using namespace entt::literals;
|
||||
|
||||
func_t instance{};
|
||||
auto any = entt::resolve<func_t>().func("f1"_hs).invoke(std::as_const(instance), 2);
|
||||
|
||||
ASSERT_FALSE(entt::resolve<func_t>().func("g"_hs).invoke(std::as_const(instance), 42));
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.cast<int>(), 4);
|
||||
}
|
||||
|
||||
TEST_F(MetaFunc, AsVoid) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto func = entt::resolve<func_t>().func("v"_hs);
|
||||
func_t instance{};
|
||||
|
||||
ASSERT_EQ(func.invoke(instance, 42), entt::meta_any{std::in_place_type<void>});
|
||||
ASSERT_EQ(func.ret(), entt::resolve<void>());
|
||||
ASSERT_EQ(instance.value, 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaFunc, AsRef) {
|
||||
using namespace entt::literals;
|
||||
|
||||
func_t instance{};
|
||||
auto func = entt::resolve<func_t>().func("a"_hs);
|
||||
func.invoke(instance).cast<int &>() = 3;
|
||||
|
||||
ASSERT_EQ(func.ret(), entt::resolve<int>());
|
||||
ASSERT_EQ(instance.value, 3);
|
||||
}
|
||||
|
||||
TEST_F(MetaFunc, AsConstRef) {
|
||||
using namespace entt::literals;
|
||||
|
||||
func_t instance{};
|
||||
auto func = entt::resolve<func_t>().func("ca"_hs);
|
||||
|
||||
ASSERT_EQ(func.ret(), entt::resolve<int>());
|
||||
ASSERT_EQ(func.invoke(instance).cast<const int &>(), 3);
|
||||
ASSERT_EQ(func.invoke(instance).cast<int>(), 3);
|
||||
}
|
||||
|
||||
ENTT_DEBUG_TEST_F(MetaFuncDeathTest, AsConstRef) {
|
||||
using namespace entt::literals;
|
||||
|
||||
func_t instance{};
|
||||
auto func = entt::resolve<func_t>().func("ca"_hs);
|
||||
|
||||
ASSERT_DEATH((func.invoke(instance).cast<int &>() = 3), "");
|
||||
}
|
||||
|
||||
TEST_F(MetaFunc, InvokeBaseFunction) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto type = entt::resolve<derived_t>();
|
||||
derived_t instance{};
|
||||
|
||||
ASSERT_TRUE(type.func("setter"_hs));
|
||||
ASSERT_EQ(instance.value, 3);
|
||||
|
||||
type.func("setter"_hs).invoke(instance, 42);
|
||||
|
||||
ASSERT_EQ(instance.value, 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaFunc, InvokeFromBase) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto type = entt::resolve<derived_t>();
|
||||
derived_t instance{};
|
||||
|
||||
auto setter_from_base = type.func("setter_from_base"_hs);
|
||||
|
||||
ASSERT_TRUE(setter_from_base);
|
||||
ASSERT_EQ(instance.value, 3);
|
||||
|
||||
setter_from_base.invoke(instance, 42);
|
||||
|
||||
ASSERT_EQ(instance.value, 42);
|
||||
|
||||
auto getter_from_base = type.func("getter_from_base"_hs);
|
||||
|
||||
ASSERT_TRUE(getter_from_base);
|
||||
ASSERT_EQ(getter_from_base.invoke(instance).cast<int>(), 42);
|
||||
|
||||
auto static_setter_from_base = type.func("static_setter_from_base"_hs);
|
||||
|
||||
ASSERT_TRUE(static_setter_from_base);
|
||||
ASSERT_EQ(instance.value, 42);
|
||||
|
||||
static_setter_from_base.invoke(instance, 3);
|
||||
|
||||
ASSERT_EQ(instance.value, 3);
|
||||
}
|
||||
|
||||
TEST_F(MetaFunc, ExternalMemberFunction) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto func = entt::resolve<func_t>().func("emplace"_hs);
|
||||
|
||||
ASSERT_TRUE(func);
|
||||
ASSERT_EQ(func.arity(), 2u);
|
||||
ASSERT_FALSE(func.is_const());
|
||||
ASSERT_TRUE(func.is_static());
|
||||
ASSERT_EQ(func.ret(), entt::resolve<void>());
|
||||
ASSERT_EQ(func.arg(0u), entt::resolve<entt::registry>());
|
||||
ASSERT_EQ(func.arg(1u), entt::resolve<entt::entity>());
|
||||
ASSERT_FALSE(func.arg(2u));
|
||||
|
||||
entt::registry registry;
|
||||
const auto entity = registry.create();
|
||||
|
||||
ASSERT_FALSE(registry.all_of<func_t>(entity));
|
||||
|
||||
func.invoke({}, entt::forward_as_meta(registry), entity);
|
||||
|
||||
ASSERT_TRUE(registry.all_of<func_t>(entity));
|
||||
}
|
||||
|
||||
TEST_F(MetaFunc, ReRegistration) {
|
||||
using namespace entt::literals;
|
||||
|
||||
ASSERT_EQ(reset_and_check(), 0u);
|
||||
|
||||
func_t instance{};
|
||||
auto type = entt::resolve<func_t>();
|
||||
|
||||
ASSERT_TRUE(type.func("f2"_hs));
|
||||
ASSERT_FALSE(type.invoke("f2"_hs, instance, 0));
|
||||
ASSERT_TRUE(type.invoke("f2"_hs, instance, 0, 0));
|
||||
|
||||
ASSERT_TRUE(type.func("f1"_hs));
|
||||
ASSERT_TRUE(type.invoke("f1"_hs, instance, 0));
|
||||
ASSERT_FALSE(type.invoke("f1"_hs, instance, 0, 0));
|
||||
|
||||
entt::meta<func_t>()
|
||||
.func<entt::overload<int(int, int)>(&func_t::f)>("f"_hs)
|
||||
.func<entt::overload<int(int) const>(&func_t::f)>("f"_hs);
|
||||
|
||||
ASSERT_TRUE(type.func("f1"_hs));
|
||||
ASSERT_TRUE(type.func("f2"_hs));
|
||||
ASSERT_TRUE(type.func("f"_hs));
|
||||
|
||||
ASSERT_TRUE(type.invoke("f"_hs, instance, 0));
|
||||
ASSERT_TRUE(type.invoke("f"_hs, instance, 0, 0));
|
||||
|
||||
ASSERT_EQ(reset_and_check(), 0u);
|
||||
}
|
66
test/entt/meta/meta_handle.cpp
Normal file
66
test/entt/meta/meta_handle.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
#include <utility>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/hashed_string.hpp>
|
||||
#include <entt/meta/factory.hpp>
|
||||
#include <entt/meta/meta.hpp>
|
||||
|
||||
struct clazz_t {
|
||||
clazz_t()
|
||||
: value{} {}
|
||||
|
||||
void incr() {
|
||||
++value;
|
||||
}
|
||||
|
||||
void decr() {
|
||||
--value;
|
||||
}
|
||||
|
||||
int value;
|
||||
};
|
||||
|
||||
struct MetaHandle: ::testing::Test {
|
||||
void SetUp() override {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::meta<clazz_t>()
|
||||
.type("clazz"_hs)
|
||||
.func<&clazz_t::incr>("incr"_hs)
|
||||
.func<&clazz_t::decr>("decr"_hs);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
entt::meta_reset();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(MetaHandle, Functionalities) {
|
||||
using namespace entt::literals;
|
||||
|
||||
clazz_t instance{};
|
||||
entt::meta_handle handle{};
|
||||
entt::meta_handle chandle{};
|
||||
|
||||
ASSERT_FALSE(handle);
|
||||
ASSERT_FALSE(chandle);
|
||||
|
||||
handle = entt::meta_handle{instance};
|
||||
chandle = entt::meta_handle{std::as_const(instance)};
|
||||
|
||||
ASSERT_TRUE(handle);
|
||||
ASSERT_TRUE(chandle);
|
||||
|
||||
ASSERT_TRUE(handle->invoke("incr"_hs));
|
||||
ASSERT_FALSE(chandle->invoke("incr"_hs));
|
||||
ASSERT_FALSE(std::as_const(handle)->invoke("incr"_hs));
|
||||
ASSERT_EQ(instance.value, 1);
|
||||
|
||||
auto any = entt::forward_as_meta(instance);
|
||||
handle = entt::meta_handle{any};
|
||||
chandle = entt::meta_handle{std::as_const(any)};
|
||||
|
||||
ASSERT_TRUE(handle->invoke("decr"_hs));
|
||||
ASSERT_FALSE(chandle->invoke("decr"_hs));
|
||||
ASSERT_FALSE(std::as_const(handle)->invoke("decr"_hs));
|
||||
ASSERT_EQ(instance.value, 0);
|
||||
}
|
414
test/entt/meta/meta_pointer.cpp
Normal file
414
test/entt/meta/meta_pointer.cpp
Normal file
@ -0,0 +1,414 @@
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/meta/meta.hpp>
|
||||
#include <entt/meta/pointer.hpp>
|
||||
#include <entt/meta/resolve.hpp>
|
||||
#include "../common/config.h"
|
||||
|
||||
template<typename Type>
|
||||
struct wrapped_shared_ptr {
|
||||
wrapped_shared_ptr(Type init)
|
||||
: ptr{new Type{init}} {}
|
||||
|
||||
Type &deref() const {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr<Type> ptr;
|
||||
};
|
||||
|
||||
struct self_ptr {
|
||||
using element_type = self_ptr;
|
||||
|
||||
self_ptr(int v)
|
||||
: value{v} {}
|
||||
|
||||
const self_ptr &operator*() const {
|
||||
return *this;
|
||||
}
|
||||
|
||||
int value;
|
||||
};
|
||||
|
||||
struct proxy_ptr {
|
||||
using element_type = proxy_ptr;
|
||||
|
||||
proxy_ptr(int &v)
|
||||
: value{&v} {}
|
||||
|
||||
proxy_ptr operator*() const {
|
||||
return *this;
|
||||
}
|
||||
|
||||
int *value;
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
struct adl_wrapped_shared_ptr: wrapped_shared_ptr<Type> {};
|
||||
|
||||
template<typename Type>
|
||||
struct spec_wrapped_shared_ptr: wrapped_shared_ptr<Type> {};
|
||||
|
||||
template<typename Type>
|
||||
struct entt::is_meta_pointer_like<adl_wrapped_shared_ptr<Type>>: std::true_type {};
|
||||
|
||||
template<typename Type>
|
||||
struct entt::is_meta_pointer_like<spec_wrapped_shared_ptr<Type>>: std::true_type {};
|
||||
|
||||
template<>
|
||||
struct entt::is_meta_pointer_like<self_ptr>: std::true_type {};
|
||||
|
||||
template<>
|
||||
struct entt::is_meta_pointer_like<proxy_ptr>: std::true_type {};
|
||||
|
||||
template<typename Type>
|
||||
struct entt::adl_meta_pointer_like<spec_wrapped_shared_ptr<Type>> {
|
||||
static decltype(auto) dereference(const spec_wrapped_shared_ptr<Type> &ptr) {
|
||||
return ptr.deref();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
Type &dereference_meta_pointer_like(const adl_wrapped_shared_ptr<Type> &ptr) {
|
||||
return ptr.deref();
|
||||
}
|
||||
|
||||
int test_function() {
|
||||
return 42;
|
||||
}
|
||||
|
||||
struct not_copyable_t {
|
||||
not_copyable_t() = default;
|
||||
not_copyable_t(const not_copyable_t &) = delete;
|
||||
not_copyable_t(not_copyable_t &&) = default;
|
||||
not_copyable_t &operator=(const not_copyable_t &) = delete;
|
||||
not_copyable_t &operator=(not_copyable_t &&) = default;
|
||||
};
|
||||
|
||||
TEST(MetaPointerLike, DereferenceOperatorInvalidType) {
|
||||
int value = 0;
|
||||
entt::meta_any any{value};
|
||||
|
||||
ASSERT_FALSE(any.type().is_pointer());
|
||||
ASSERT_FALSE(any.type().is_pointer_like());
|
||||
ASSERT_EQ(any.type(), entt::resolve<int>());
|
||||
|
||||
auto deref = *any;
|
||||
|
||||
ASSERT_FALSE(deref);
|
||||
}
|
||||
|
||||
TEST(MetaPointerLike, DereferenceOperatorConstType) {
|
||||
const int value = 42;
|
||||
entt::meta_any any{&value};
|
||||
|
||||
ASSERT_TRUE(any.type().is_pointer());
|
||||
ASSERT_TRUE(any.type().is_pointer_like());
|
||||
ASSERT_EQ(any.type(), entt::resolve<const int *>());
|
||||
|
||||
auto deref = *any;
|
||||
|
||||
ASSERT_TRUE(deref);
|
||||
ASSERT_FALSE(deref.type().is_pointer());
|
||||
ASSERT_FALSE(deref.type().is_pointer_like());
|
||||
ASSERT_EQ(deref.type(), entt::resolve<int>());
|
||||
|
||||
ASSERT_EQ(deref.try_cast<int>(), nullptr);
|
||||
ASSERT_EQ(deref.try_cast<const int>(), &value);
|
||||
ASSERT_EQ(deref.cast<const int &>(), 42);
|
||||
}
|
||||
|
||||
ENTT_DEBUG_TEST(MetaPointerLikeDeathTest, DereferenceOperatorConstType) {
|
||||
const int value = 42;
|
||||
entt::meta_any any{&value};
|
||||
auto deref = *any;
|
||||
|
||||
ASSERT_TRUE(deref);
|
||||
ASSERT_DEATH(deref.cast<int &>() = 0, "");
|
||||
}
|
||||
|
||||
TEST(MetaPointerLike, DereferenceOperatorConstAnyNonConstType) {
|
||||
int value = 42;
|
||||
const entt::meta_any any{&value};
|
||||
auto deref = *any;
|
||||
|
||||
ASSERT_TRUE(deref);
|
||||
ASSERT_FALSE(deref.type().is_pointer());
|
||||
ASSERT_FALSE(deref.type().is_pointer_like());
|
||||
ASSERT_EQ(deref.type(), entt::resolve<int>());
|
||||
|
||||
ASSERT_NE(deref.try_cast<int>(), nullptr);
|
||||
ASSERT_NE(deref.try_cast<const int>(), nullptr);
|
||||
ASSERT_EQ(deref.cast<int &>(), 42);
|
||||
ASSERT_EQ(deref.cast<const int &>(), 42);
|
||||
}
|
||||
|
||||
TEST(MetaPointerLike, DereferenceOperatorConstAnyConstType) {
|
||||
const int value = 42;
|
||||
const entt::meta_any any{&value};
|
||||
auto deref = *any;
|
||||
|
||||
ASSERT_TRUE(deref);
|
||||
ASSERT_FALSE(deref.type().is_pointer());
|
||||
ASSERT_FALSE(deref.type().is_pointer_like());
|
||||
ASSERT_EQ(deref.type(), entt::resolve<int>());
|
||||
|
||||
ASSERT_EQ(deref.try_cast<int>(), nullptr);
|
||||
ASSERT_NE(deref.try_cast<const int>(), nullptr);
|
||||
ASSERT_EQ(deref.cast<const int &>(), 42);
|
||||
}
|
||||
|
||||
ENTT_DEBUG_TEST(MetaPointerLikeDeathTest, DereferenceOperatorConstAnyConstType) {
|
||||
const int value = 42;
|
||||
const entt::meta_any any{&value};
|
||||
auto deref = *any;
|
||||
|
||||
ASSERT_TRUE(deref);
|
||||
ASSERT_DEATH(deref.cast<int &>() = 0, "");
|
||||
}
|
||||
|
||||
TEST(MetaPointerLike, DereferenceOperatorRawPointer) {
|
||||
int value = 0;
|
||||
entt::meta_any any{&value};
|
||||
|
||||
ASSERT_TRUE(any.type().is_pointer());
|
||||
ASSERT_TRUE(any.type().is_pointer_like());
|
||||
ASSERT_EQ(any.type(), entt::resolve<int *>());
|
||||
|
||||
auto deref = *any;
|
||||
|
||||
ASSERT_TRUE(deref);
|
||||
ASSERT_FALSE(deref.type().is_pointer());
|
||||
ASSERT_FALSE(deref.type().is_pointer_like());
|
||||
ASSERT_EQ(deref.type(), entt::resolve<int>());
|
||||
|
||||
deref.cast<int &>() = 42;
|
||||
|
||||
ASSERT_EQ(*any.cast<int *>(), 42);
|
||||
ASSERT_EQ(value, 42);
|
||||
}
|
||||
|
||||
TEST(MetaPointerLike, DereferenceOperatorSmartPointer) {
|
||||
auto value = std::make_shared<int>(0);
|
||||
entt::meta_any any{value};
|
||||
|
||||
ASSERT_FALSE(any.type().is_pointer());
|
||||
ASSERT_TRUE(any.type().is_pointer_like());
|
||||
ASSERT_EQ(any.type(), entt::resolve<std::shared_ptr<int>>());
|
||||
|
||||
auto deref = *any;
|
||||
|
||||
ASSERT_TRUE(deref);
|
||||
ASSERT_FALSE(deref.type().is_pointer());
|
||||
ASSERT_FALSE(deref.type().is_pointer_like());
|
||||
ASSERT_EQ(deref.type(), entt::resolve<int>());
|
||||
|
||||
deref.cast<int &>() = 42;
|
||||
|
||||
ASSERT_EQ(*any.cast<std::shared_ptr<int>>(), 42);
|
||||
ASSERT_EQ(*value, 42);
|
||||
}
|
||||
|
||||
TEST(MetaPointerLike, PointerToConstMoveOnlyType) {
|
||||
const not_copyable_t instance;
|
||||
entt::meta_any any{&instance};
|
||||
auto deref = *any;
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_TRUE(deref);
|
||||
|
||||
ASSERT_EQ(deref.try_cast<not_copyable_t>(), nullptr);
|
||||
ASSERT_NE(deref.try_cast<const not_copyable_t>(), nullptr);
|
||||
ASSERT_EQ(&deref.cast<const not_copyable_t &>(), &instance);
|
||||
}
|
||||
|
||||
TEST(MetaPointerLike, AsRef) {
|
||||
int value = 0;
|
||||
int *ptr = &value;
|
||||
entt::meta_any any{entt::forward_as_meta(ptr)};
|
||||
|
||||
ASSERT_TRUE(any.type().is_pointer());
|
||||
ASSERT_TRUE(any.type().is_pointer_like());
|
||||
ASSERT_EQ(any.type(), entt::resolve<int *>());
|
||||
|
||||
auto deref = *any;
|
||||
|
||||
ASSERT_TRUE(deref);
|
||||
ASSERT_FALSE(deref.type().is_pointer());
|
||||
ASSERT_FALSE(deref.type().is_pointer_like());
|
||||
ASSERT_EQ(deref.type(), entt::resolve<int>());
|
||||
|
||||
deref.cast<int &>() = 42;
|
||||
|
||||
ASSERT_EQ(*any.cast<int *>(), 42);
|
||||
ASSERT_EQ(value, 42);
|
||||
}
|
||||
|
||||
TEST(MetaPointerLike, AsConstRef) {
|
||||
int value = 42;
|
||||
int *const ptr = &value;
|
||||
entt::meta_any any{entt::forward_as_meta(ptr)};
|
||||
|
||||
ASSERT_TRUE(any.type().is_pointer());
|
||||
ASSERT_TRUE(any.type().is_pointer_like());
|
||||
ASSERT_EQ(any.type(), entt::resolve<int *>());
|
||||
|
||||
auto deref = *any;
|
||||
|
||||
ASSERT_TRUE(deref);
|
||||
ASSERT_FALSE(deref.type().is_pointer());
|
||||
ASSERT_FALSE(deref.type().is_pointer_like());
|
||||
ASSERT_EQ(deref.type(), entt::resolve<int>());
|
||||
|
||||
deref.cast<int &>() = 42;
|
||||
|
||||
ASSERT_EQ(*any.cast<int *>(), 42);
|
||||
ASSERT_EQ(value, 42);
|
||||
}
|
||||
|
||||
TEST(MetaPointerLike, DereferenceOverload) {
|
||||
auto test = [](entt::meta_any any) {
|
||||
ASSERT_FALSE(any.type().is_pointer());
|
||||
ASSERT_TRUE(any.type().is_pointer_like());
|
||||
|
||||
auto deref = *any;
|
||||
|
||||
ASSERT_TRUE(deref);
|
||||
ASSERT_FALSE(deref.type().is_pointer());
|
||||
ASSERT_FALSE(deref.type().is_pointer_like());
|
||||
ASSERT_EQ(deref.type(), entt::resolve<int>());
|
||||
|
||||
ASSERT_EQ(deref.cast<int &>(), 42);
|
||||
ASSERT_EQ(deref.cast<const int &>(), 42);
|
||||
};
|
||||
|
||||
test(adl_wrapped_shared_ptr<int>{42});
|
||||
test(spec_wrapped_shared_ptr<int>{42});
|
||||
}
|
||||
|
||||
TEST(MetaPointerLike, DereferencePointerToConstOverload) {
|
||||
auto test = [](entt::meta_any any) {
|
||||
ASSERT_FALSE(any.type().is_pointer());
|
||||
ASSERT_TRUE(any.type().is_pointer_like());
|
||||
|
||||
auto deref = *any;
|
||||
|
||||
ASSERT_TRUE(deref);
|
||||
ASSERT_FALSE(deref.type().is_pointer());
|
||||
ASSERT_FALSE(deref.type().is_pointer_like());
|
||||
ASSERT_EQ(deref.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(deref.cast<const int &>(), 42);
|
||||
};
|
||||
|
||||
test(adl_wrapped_shared_ptr<const int>{42});
|
||||
test(spec_wrapped_shared_ptr<const int>{42});
|
||||
}
|
||||
|
||||
ENTT_DEBUG_TEST(MetaPointerLikeDeathTest, DereferencePointerToConstOverload) {
|
||||
auto test = [](entt::meta_any any) {
|
||||
auto deref = *any;
|
||||
|
||||
ASSERT_TRUE(deref);
|
||||
ASSERT_DEATH(deref.cast<int &>() = 42, "");
|
||||
};
|
||||
|
||||
test(adl_wrapped_shared_ptr<const int>{42});
|
||||
test(spec_wrapped_shared_ptr<const int>{42});
|
||||
}
|
||||
|
||||
TEST(MetaPointerLike, DereferencePointerToVoid) {
|
||||
auto test = [](entt::meta_any any) {
|
||||
ASSERT_TRUE(any.type().is_pointer());
|
||||
ASSERT_TRUE(any.type().is_pointer_like());
|
||||
|
||||
auto deref = *any;
|
||||
|
||||
ASSERT_FALSE(deref);
|
||||
};
|
||||
|
||||
test(static_cast<void *>(nullptr));
|
||||
test(static_cast<const void *>(nullptr));
|
||||
}
|
||||
|
||||
TEST(MetaPointerLike, DereferenceSmartPointerToVoid) {
|
||||
auto test = [](entt::meta_any any) {
|
||||
ASSERT_TRUE(any.type().is_class());
|
||||
ASSERT_FALSE(any.type().is_pointer());
|
||||
ASSERT_TRUE(any.type().is_pointer_like());
|
||||
|
||||
auto deref = *any;
|
||||
|
||||
ASSERT_FALSE(deref);
|
||||
};
|
||||
|
||||
test(std::shared_ptr<void>{});
|
||||
test(std::unique_ptr<void, void (*)(void *)>{nullptr, nullptr});
|
||||
}
|
||||
|
||||
TEST(MetaPointerLike, DereferencePointerToFunction) {
|
||||
auto test = [](entt::meta_any any) {
|
||||
ASSERT_TRUE(any.type().is_pointer());
|
||||
ASSERT_TRUE(any.type().is_pointer_like());
|
||||
ASSERT_NE(any.try_cast<int (*)()>(), nullptr);
|
||||
ASSERT_EQ(any.cast<int (*)()>()(), 42);
|
||||
};
|
||||
|
||||
entt::meta_any func{&test_function};
|
||||
|
||||
test(func);
|
||||
test(*func);
|
||||
test(**func);
|
||||
test(*std::as_const(func));
|
||||
}
|
||||
|
||||
TEST(MetaPointerLike, DereferenceSelfPointer) {
|
||||
self_ptr obj{42};
|
||||
entt::meta_any any{entt::forward_as_meta(obj)};
|
||||
entt::meta_any deref = *any;
|
||||
|
||||
ASSERT_TRUE(deref);
|
||||
ASSERT_TRUE(any.type().is_pointer_like());
|
||||
ASSERT_EQ(deref.cast<const self_ptr &>().value, obj.value);
|
||||
ASSERT_FALSE(deref.try_cast<self_ptr>());
|
||||
}
|
||||
|
||||
TEST(MetaPointerLike, DereferenceProxyPointer) {
|
||||
int value = 3;
|
||||
proxy_ptr obj{value};
|
||||
entt::meta_any any{obj};
|
||||
entt::meta_any deref = *any;
|
||||
|
||||
ASSERT_TRUE(deref);
|
||||
ASSERT_TRUE(any.type().is_pointer_like());
|
||||
ASSERT_EQ(*deref.cast<const proxy_ptr &>().value, value);
|
||||
ASSERT_TRUE(deref.try_cast<proxy_ptr>());
|
||||
|
||||
*deref.cast<proxy_ptr &>().value = 42;
|
||||
|
||||
ASSERT_EQ(value, 42);
|
||||
}
|
||||
|
||||
TEST(MetaPointerLike, DereferenceArray) {
|
||||
entt::meta_any array{std::in_place_type<int[3]>};
|
||||
entt::meta_any array_of_array{std::in_place_type<int[3][3]>};
|
||||
|
||||
ASSERT_EQ(array.type(), entt::resolve<int[3]>());
|
||||
ASSERT_EQ(array_of_array.type(), entt::resolve<int[3][3]>());
|
||||
|
||||
ASSERT_FALSE(*array);
|
||||
ASSERT_FALSE(*array_of_array);
|
||||
}
|
||||
|
||||
TEST(MetaPointerLike, DereferenceVerifiableNullPointerLike) {
|
||||
auto test = [](entt::meta_any any) {
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_FALSE(*any);
|
||||
};
|
||||
|
||||
test(entt::meta_any{static_cast<int *>(nullptr)});
|
||||
test(entt::meta_any{std::shared_ptr<int>{}});
|
||||
test(entt::meta_any{std::unique_ptr<int>{}});
|
||||
}
|
111
test/entt/meta/meta_prop.cpp
Normal file
111
test/entt/meta/meta_prop.cpp
Normal file
@ -0,0 +1,111 @@
|
||||
#include <cstring>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/hashed_string.hpp>
|
||||
#include <entt/locator/locator.hpp>
|
||||
#include <entt/meta/factory.hpp>
|
||||
#include <entt/meta/meta.hpp>
|
||||
#include <entt/meta/resolve.hpp>
|
||||
|
||||
struct base_1_t {};
|
||||
struct base_2_t {};
|
||||
struct base_3_t {};
|
||||
struct derived_t: base_1_t, base_2_t, base_3_t {};
|
||||
|
||||
struct MetaProp: ::testing::Test {
|
||||
void SetUp() override {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::meta<base_1_t>()
|
||||
.type("base_1"_hs)
|
||||
.prop("int"_hs, 42);
|
||||
|
||||
entt::meta<base_2_t>()
|
||||
.type("base_2"_hs)
|
||||
.prop("bool"_hs, false)
|
||||
.prop("char[]"_hs, "char[]");
|
||||
|
||||
entt::meta<base_3_t>()
|
||||
.type("base_3"_hs)
|
||||
.prop("key_only"_hs)
|
||||
.prop("key"_hs, 42);
|
||||
|
||||
entt::meta<derived_t>()
|
||||
.type("derived"_hs)
|
||||
.base<base_1_t>()
|
||||
.base<base_2_t>()
|
||||
.base<base_3_t>();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
entt::meta_reset();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(MetaProp, Functionalities) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto prop = entt::resolve<base_1_t>().prop("int"_hs);
|
||||
|
||||
ASSERT_TRUE(prop);
|
||||
ASSERT_EQ(prop.value(), 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaProp, FromBase) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto type = entt::resolve<derived_t>();
|
||||
auto prop_bool = type.prop("bool"_hs);
|
||||
auto prop_int = type.prop("int"_hs);
|
||||
auto key_only = type.prop("key_only"_hs);
|
||||
auto key_value = type.prop("key"_hs);
|
||||
|
||||
ASSERT_TRUE(prop_bool);
|
||||
ASSERT_TRUE(prop_int);
|
||||
ASSERT_TRUE(key_only);
|
||||
ASSERT_TRUE(key_value);
|
||||
|
||||
ASSERT_FALSE(prop_bool.value().cast<bool>());
|
||||
ASSERT_EQ(prop_int.value().cast<int>(), 42);
|
||||
ASSERT_FALSE(key_only.value());
|
||||
ASSERT_EQ(key_value.value().cast<int>(), 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaProp, DeducedArrayType) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto prop = entt::resolve<base_2_t>().prop("char[]"_hs);
|
||||
|
||||
ASSERT_TRUE(prop);
|
||||
ASSERT_EQ(prop.value().type(), entt::resolve<const char *>());
|
||||
ASSERT_EQ(strcmp(prop.value().cast<const char *>(), "char[]"), 0);
|
||||
}
|
||||
|
||||
TEST_F(MetaProp, ReRegistration) {
|
||||
using namespace entt::literals;
|
||||
|
||||
SetUp();
|
||||
|
||||
auto &&node = entt::internal::resolve<base_1_t>(entt::internal::meta_context::from(entt::locator<entt::meta_ctx>::value_or()));
|
||||
auto type = entt::resolve<base_1_t>();
|
||||
|
||||
ASSERT_TRUE(node.details);
|
||||
ASSERT_FALSE(node.details->prop.empty());
|
||||
ASSERT_EQ(node.details->prop.size(), 1u);
|
||||
|
||||
ASSERT_TRUE(type.prop("int"_hs));
|
||||
ASSERT_EQ(type.prop("int"_hs).value().cast<int>(), 42);
|
||||
|
||||
entt::meta<base_1_t>().prop("int"_hs, 0);
|
||||
entt::meta<base_1_t>().prop("double"_hs, 3.);
|
||||
|
||||
ASSERT_TRUE(node.details);
|
||||
ASSERT_FALSE(node.details->prop.empty());
|
||||
ASSERT_EQ(node.details->prop.size(), 2u);
|
||||
|
||||
ASSERT_TRUE(type.prop("int"_hs));
|
||||
ASSERT_TRUE(type.prop("double"_hs));
|
||||
ASSERT_EQ(type.prop("int"_hs).value().cast<int>(), 0);
|
||||
ASSERT_EQ(type.prop("double"_hs).value().cast<double>(), 3.);
|
||||
}
|
95
test/entt/meta/meta_range.cpp
Normal file
95
test/entt/meta/meta_range.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
#include <type_traits>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/hashed_string.hpp>
|
||||
#include <entt/locator/locator.hpp>
|
||||
#include <entt/meta/factory.hpp>
|
||||
#include <entt/meta/meta.hpp>
|
||||
#include <entt/meta/range.hpp>
|
||||
#include <entt/meta/resolve.hpp>
|
||||
|
||||
struct MetaRange: ::testing::Test {
|
||||
void SetUp() override {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::meta<int>().type("int"_hs).data<42>("answer"_hs);
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
entt::meta_reset();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(MetaRange, EmptyRange) {
|
||||
entt::meta_reset();
|
||||
auto range = entt::resolve();
|
||||
ASSERT_EQ(range.begin(), range.end());
|
||||
}
|
||||
|
||||
TEST_F(MetaRange, Iterator) {
|
||||
using namespace entt::literals;
|
||||
|
||||
using iterator = typename decltype(entt::resolve())::iterator;
|
||||
|
||||
static_assert(std::is_same_v<iterator::value_type, std::pair<entt::id_type, entt::meta_type>>);
|
||||
static_assert(std::is_same_v<iterator::pointer, entt::input_iterator_pointer<std::pair<entt::id_type, entt::meta_type>>>);
|
||||
static_assert(std::is_same_v<iterator::reference, std::pair<entt::id_type, entt::meta_type>>);
|
||||
|
||||
auto range = entt::resolve();
|
||||
|
||||
iterator end{range.begin()};
|
||||
iterator begin{};
|
||||
begin = range.end();
|
||||
std::swap(begin, end);
|
||||
|
||||
ASSERT_EQ(begin, range.begin());
|
||||
ASSERT_EQ(end, range.end());
|
||||
ASSERT_NE(begin, end);
|
||||
|
||||
ASSERT_EQ(begin++, range.begin());
|
||||
ASSERT_EQ(begin--, range.end());
|
||||
|
||||
ASSERT_EQ(begin + 1, range.end());
|
||||
ASSERT_EQ(end - 1, range.begin());
|
||||
|
||||
ASSERT_EQ(++begin, range.end());
|
||||
ASSERT_EQ(--begin, range.begin());
|
||||
|
||||
ASSERT_EQ(begin += 1, range.end());
|
||||
ASSERT_EQ(begin -= 1, range.begin());
|
||||
|
||||
ASSERT_EQ(begin + (end - begin), range.end());
|
||||
ASSERT_EQ(begin - (begin - end), range.end());
|
||||
|
||||
ASSERT_EQ(end - (end - begin), range.begin());
|
||||
ASSERT_EQ(end + (begin - end), range.begin());
|
||||
|
||||
ASSERT_EQ(begin[0u].first, range.begin()->first);
|
||||
ASSERT_EQ(begin[0u].second, (*range.begin()).second);
|
||||
|
||||
ASSERT_LT(begin, end);
|
||||
ASSERT_LE(begin, range.begin());
|
||||
|
||||
ASSERT_GT(end, begin);
|
||||
ASSERT_GE(end, range.end());
|
||||
|
||||
entt::meta<double>().type("double"_hs);
|
||||
range = entt::resolve();
|
||||
begin = range.begin();
|
||||
|
||||
ASSERT_EQ(begin[0u].first, entt::resolve<int>().info().hash());
|
||||
ASSERT_EQ(begin[1u].second, entt::resolve("double"_hs));
|
||||
}
|
||||
|
||||
TEST_F(MetaRange, DirectValue) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto type = entt::resolve<int>();
|
||||
auto range = type.data();
|
||||
|
||||
ASSERT_NE(range.cbegin(), range.cend());
|
||||
|
||||
for(auto &&[id, data]: range) {
|
||||
ASSERT_EQ(id, "answer"_hs);
|
||||
ASSERT_EQ(data.get({}).cast<int>(), 42);
|
||||
}
|
||||
}
|
49
test/entt/meta/meta_template.cpp
Normal file
49
test/entt/meta/meta_template.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/type_traits.hpp>
|
||||
#include <entt/meta/meta.hpp>
|
||||
#include <entt/meta/resolve.hpp>
|
||||
#include <entt/meta/template.hpp>
|
||||
|
||||
template<typename>
|
||||
struct function_type;
|
||||
|
||||
template<typename Ret, typename... Args>
|
||||
struct function_type<Ret(Args...)> {};
|
||||
|
||||
template<typename Ret, typename... Args>
|
||||
struct entt::meta_template_traits<function_type<Ret(Args...)>> {
|
||||
using class_type = meta_class_template_tag<function_type>;
|
||||
using args_type = type_list<Ret, Args...>;
|
||||
};
|
||||
|
||||
TEST(MetaTemplate, Invalid) {
|
||||
const auto type = entt::resolve<int>();
|
||||
|
||||
ASSERT_FALSE(type.is_template_specialization());
|
||||
ASSERT_EQ(type.template_arity(), 0u);
|
||||
ASSERT_EQ(type.template_type(), entt::meta_type{});
|
||||
ASSERT_EQ(type.template_arg(0u), entt::meta_type{});
|
||||
}
|
||||
|
||||
TEST(MetaTemplate, Valid) {
|
||||
const auto type = entt::resolve<entt::type_list<int, char>>();
|
||||
|
||||
ASSERT_TRUE(type.is_template_specialization());
|
||||
ASSERT_EQ(type.template_arity(), 2u);
|
||||
ASSERT_EQ(type.template_type(), entt::resolve<entt::meta_class_template_tag<entt::type_list>>());
|
||||
ASSERT_EQ(type.template_arg(0u), entt::resolve<int>());
|
||||
ASSERT_EQ(type.template_arg(1u), entt::resolve<char>());
|
||||
ASSERT_EQ(type.template_arg(2u), entt::meta_type{});
|
||||
}
|
||||
|
||||
TEST(MetaTemplate, CustomTraits) {
|
||||
const auto type = entt::resolve<function_type<void(int, const char &)>>();
|
||||
|
||||
ASSERT_TRUE(type.is_template_specialization());
|
||||
ASSERT_EQ(type.template_arity(), 3u);
|
||||
ASSERT_EQ(type.template_type(), entt::resolve<entt::meta_class_template_tag<function_type>>());
|
||||
ASSERT_EQ(type.template_arg(0u), entt::resolve<void>());
|
||||
ASSERT_EQ(type.template_arg(1u), entt::resolve<int>());
|
||||
ASSERT_EQ(type.template_arg(2u), entt::resolve<char>());
|
||||
ASSERT_EQ(type.template_arg(3u), entt::meta_type{});
|
||||
}
|
765
test/entt/meta/meta_type.cpp
Normal file
765
test/entt/meta/meta_type.cpp
Normal file
@ -0,0 +1,765 @@
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/hashed_string.hpp>
|
||||
#include <entt/core/type_info.hpp>
|
||||
#include <entt/core/utility.hpp>
|
||||
#include <entt/locator/locator.hpp>
|
||||
#include <entt/meta/container.hpp>
|
||||
#include <entt/meta/context.hpp>
|
||||
#include <entt/meta/factory.hpp>
|
||||
#include <entt/meta/meta.hpp>
|
||||
#include <entt/meta/pointer.hpp>
|
||||
#include <entt/meta/resolve.hpp>
|
||||
#include <entt/meta/template.hpp>
|
||||
#include "../common/config.h"
|
||||
|
||||
template<typename Type>
|
||||
void set(Type &prop, Type value) {
|
||||
prop = value;
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
Type get(Type &prop) {
|
||||
return prop;
|
||||
}
|
||||
|
||||
struct base_t {
|
||||
base_t()
|
||||
: value{'c'} {};
|
||||
|
||||
char value;
|
||||
};
|
||||
|
||||
struct derived_t: base_t {
|
||||
derived_t()
|
||||
: base_t{} {}
|
||||
};
|
||||
|
||||
struct abstract_t {
|
||||
virtual ~abstract_t() = default;
|
||||
|
||||
virtual void func(int) {}
|
||||
void base_only(int) {}
|
||||
};
|
||||
|
||||
struct concrete_t: base_t, abstract_t {
|
||||
void func(int v) override {
|
||||
abstract_t::func(v);
|
||||
value = v;
|
||||
}
|
||||
|
||||
int value{3};
|
||||
};
|
||||
|
||||
struct clazz_t {
|
||||
clazz_t() = default;
|
||||
|
||||
clazz_t(const base_t &, int v)
|
||||
: value{v} {}
|
||||
|
||||
void member() {}
|
||||
static void func() {}
|
||||
|
||||
operator int() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
int value{};
|
||||
};
|
||||
|
||||
struct overloaded_func_t {
|
||||
int e(int v) const {
|
||||
return v + v;
|
||||
}
|
||||
|
||||
int f(const base_t &, int a, int b) {
|
||||
return f(a, b);
|
||||
}
|
||||
|
||||
int f(int a, int b) {
|
||||
value = a;
|
||||
return g(b);
|
||||
}
|
||||
|
||||
int f(int v) {
|
||||
return 2 * std::as_const(*this).f(v);
|
||||
}
|
||||
|
||||
int f(int v) const {
|
||||
return g(v);
|
||||
}
|
||||
|
||||
float f(int a, float b) {
|
||||
value = a;
|
||||
return static_cast<float>(e(static_cast<int>(b)));
|
||||
}
|
||||
|
||||
int g(int v) const {
|
||||
return v * v;
|
||||
}
|
||||
|
||||
inline static int value = 0;
|
||||
};
|
||||
|
||||
enum class property_t : entt::id_type {
|
||||
random,
|
||||
value,
|
||||
key_only,
|
||||
list
|
||||
};
|
||||
|
||||
struct MetaType: ::testing::Test {
|
||||
void SetUp() override {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::meta<double>()
|
||||
.type("double"_hs)
|
||||
.data<set<double>, get<double>>("var"_hs);
|
||||
|
||||
entt::meta<unsigned int>()
|
||||
.type("unsigned int"_hs)
|
||||
.data<0u>("min"_hs)
|
||||
.data<100u>("max"_hs);
|
||||
|
||||
entt::meta<base_t>()
|
||||
.type("base"_hs)
|
||||
.data<&base_t::value>("value"_hs);
|
||||
|
||||
entt::meta<derived_t>()
|
||||
.type("derived"_hs)
|
||||
.base<base_t>();
|
||||
|
||||
entt::meta<abstract_t>()
|
||||
.type("abstract"_hs)
|
||||
.func<&abstract_t::func>("func"_hs)
|
||||
.func<&abstract_t::base_only>("base_only"_hs);
|
||||
|
||||
entt::meta<concrete_t>()
|
||||
.type("concrete"_hs)
|
||||
.base<base_t>()
|
||||
.base<abstract_t>();
|
||||
|
||||
entt::meta<overloaded_func_t>()
|
||||
.type("overloaded_func"_hs)
|
||||
.func<&overloaded_func_t::e>("e"_hs)
|
||||
.func<entt::overload<int(const base_t &, int, int)>(&overloaded_func_t::f)>("f"_hs)
|
||||
.func<entt::overload<int(int, int)>(&overloaded_func_t::f)>("f"_hs)
|
||||
.func<entt::overload<int(int)>(&overloaded_func_t::f)>("f"_hs)
|
||||
.func<entt::overload<int(int) const>(&overloaded_func_t::f)>("f"_hs)
|
||||
.func<entt::overload<float(int, float)>(&overloaded_func_t::f)>("f"_hs)
|
||||
.func<&overloaded_func_t::g>("g"_hs);
|
||||
|
||||
entt::meta<property_t>()
|
||||
.type("property"_hs)
|
||||
.data<property_t::random>("random"_hs)
|
||||
.prop(static_cast<entt::id_type>(property_t::random), 0)
|
||||
.prop(static_cast<entt::id_type>(property_t::value), 3)
|
||||
.data<property_t::value>("value"_hs)
|
||||
.prop(static_cast<entt::id_type>(property_t::random), true)
|
||||
.prop(static_cast<entt::id_type>(property_t::value), 0)
|
||||
.prop(static_cast<entt::id_type>(property_t::key_only))
|
||||
.prop(static_cast<entt::id_type>(property_t::list))
|
||||
.data<property_t::key_only>("key_only"_hs)
|
||||
.prop(static_cast<entt::id_type>(property_t::key_only))
|
||||
.data<property_t::list>("list"_hs)
|
||||
.prop(static_cast<entt::id_type>(property_t::random), false)
|
||||
.prop(static_cast<entt::id_type>(property_t::value), 0)
|
||||
.prop(static_cast<entt::id_type>(property_t::key_only))
|
||||
.data<set<property_t>, get<property_t>>("var"_hs);
|
||||
|
||||
entt::meta<clazz_t>()
|
||||
.type("clazz"_hs)
|
||||
.prop(static_cast<entt::id_type>(property_t::value), 42)
|
||||
.ctor<const base_t &, int>()
|
||||
.data<&clazz_t::value>("value"_hs)
|
||||
.func<&clazz_t::member>("member"_hs)
|
||||
.func<clazz_t::func>("func"_hs)
|
||||
.conv<int>();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
entt::meta_reset();
|
||||
}
|
||||
};
|
||||
|
||||
using MetaTypeDeathTest = MetaType;
|
||||
|
||||
TEST_F(MetaType, Resolve) {
|
||||
using namespace entt::literals;
|
||||
|
||||
ASSERT_EQ(entt::resolve<double>(), entt::resolve("double"_hs));
|
||||
ASSERT_EQ(entt::resolve<double>(), entt::resolve(entt::type_id<double>()));
|
||||
ASSERT_FALSE(entt::resolve(entt::type_id<void>()));
|
||||
|
||||
auto range = entt::resolve();
|
||||
// it could be "char"_hs rather than entt::hashed_string::value("char") if it weren't for a bug in VS2017
|
||||
const auto it = std::find_if(range.begin(), range.end(), [](auto curr) { return curr.second.id() == entt::hashed_string::value("clazz"); });
|
||||
|
||||
ASSERT_NE(it, range.end());
|
||||
ASSERT_EQ(it->second, entt::resolve<clazz_t>());
|
||||
|
||||
bool found = false;
|
||||
|
||||
for(auto curr: entt::resolve()) {
|
||||
found = found || curr.second == entt::resolve<double>();
|
||||
}
|
||||
|
||||
ASSERT_TRUE(found);
|
||||
}
|
||||
|
||||
TEST_F(MetaType, Functionalities) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto type = entt::resolve<clazz_t>();
|
||||
|
||||
ASSERT_TRUE(type);
|
||||
ASSERT_NE(type, entt::meta_type{});
|
||||
ASSERT_EQ(type.id(), "clazz"_hs);
|
||||
ASSERT_EQ(type.info(), entt::type_id<clazz_t>());
|
||||
|
||||
for(auto curr: type.prop()) {
|
||||
ASSERT_EQ(curr.first, static_cast<entt::id_type>(property_t::value));
|
||||
ASSERT_EQ(curr.second.value(), 42);
|
||||
}
|
||||
|
||||
ASSERT_FALSE(type.prop(static_cast<entt::id_type>(property_t::key_only)));
|
||||
ASSERT_FALSE(type.prop("property"_hs));
|
||||
|
||||
auto prop = type.prop(static_cast<entt::id_type>(property_t::value));
|
||||
|
||||
ASSERT_TRUE(prop);
|
||||
ASSERT_EQ(prop.value(), 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaType, SizeOf) {
|
||||
ASSERT_EQ(entt::resolve<void>().size_of(), 0u);
|
||||
ASSERT_EQ(entt::resolve<int>().size_of(), sizeof(int));
|
||||
ASSERT_EQ(entt::resolve<int[]>().size_of(), 0u);
|
||||
ASSERT_EQ(entt::resolve<int[3]>().size_of(), sizeof(int[3]));
|
||||
}
|
||||
|
||||
TEST_F(MetaType, Traits) {
|
||||
ASSERT_TRUE(entt::resolve<bool>().is_arithmetic());
|
||||
ASSERT_TRUE(entt::resolve<double>().is_arithmetic());
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().is_arithmetic());
|
||||
|
||||
ASSERT_TRUE(entt::resolve<int>().is_integral());
|
||||
ASSERT_FALSE(entt::resolve<double>().is_integral());
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().is_integral());
|
||||
|
||||
ASSERT_TRUE(entt::resolve<long>().is_signed());
|
||||
ASSERT_FALSE(entt::resolve<unsigned int>().is_signed());
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().is_signed());
|
||||
|
||||
ASSERT_TRUE(entt::resolve<int[5]>().is_array());
|
||||
ASSERT_TRUE(entt::resolve<int[5][3]>().is_array());
|
||||
ASSERT_FALSE(entt::resolve<int>().is_array());
|
||||
|
||||
ASSERT_TRUE(entt::resolve<property_t>().is_enum());
|
||||
ASSERT_FALSE(entt::resolve<char>().is_enum());
|
||||
|
||||
ASSERT_TRUE(entt::resolve<derived_t>().is_class());
|
||||
ASSERT_FALSE(entt::resolve<double>().is_class());
|
||||
|
||||
ASSERT_TRUE(entt::resolve<int *>().is_pointer());
|
||||
ASSERT_FALSE(entt::resolve<int>().is_pointer());
|
||||
|
||||
ASSERT_TRUE(entt::resolve<int *>().is_pointer_like());
|
||||
ASSERT_TRUE(entt::resolve<std::shared_ptr<int>>().is_pointer_like());
|
||||
ASSERT_FALSE(entt::resolve<int>().is_pointer_like());
|
||||
|
||||
ASSERT_FALSE((entt::resolve<int>().is_sequence_container()));
|
||||
ASSERT_TRUE(entt::resolve<std::vector<int>>().is_sequence_container());
|
||||
ASSERT_FALSE((entt::resolve<std::map<int, char>>().is_sequence_container()));
|
||||
|
||||
ASSERT_FALSE((entt::resolve<int>().is_associative_container()));
|
||||
ASSERT_TRUE((entt::resolve<std::map<int, char>>().is_associative_container()));
|
||||
ASSERT_FALSE(entt::resolve<std::vector<int>>().is_associative_container());
|
||||
}
|
||||
|
||||
TEST_F(MetaType, RemovePointer) {
|
||||
ASSERT_EQ(entt::resolve<void *>().remove_pointer(), entt::resolve<void>());
|
||||
ASSERT_EQ(entt::resolve<char **>().remove_pointer(), entt::resolve<char *>());
|
||||
ASSERT_EQ(entt::resolve<int (*)(char, double)>().remove_pointer(), entt::resolve<int(char, double)>());
|
||||
ASSERT_EQ(entt::resolve<derived_t>().remove_pointer(), entt::resolve<derived_t>());
|
||||
}
|
||||
|
||||
TEST_F(MetaType, TemplateInfo) {
|
||||
ASSERT_FALSE(entt::resolve<int>().is_template_specialization());
|
||||
ASSERT_EQ(entt::resolve<int>().template_arity(), 0u);
|
||||
ASSERT_EQ(entt::resolve<int>().template_type(), entt::meta_type{});
|
||||
ASSERT_EQ(entt::resolve<int>().template_arg(0u), entt::meta_type{});
|
||||
|
||||
ASSERT_TRUE(entt::resolve<std::shared_ptr<int>>().is_template_specialization());
|
||||
ASSERT_EQ(entt::resolve<std::shared_ptr<int>>().template_arity(), 1u);
|
||||
ASSERT_EQ(entt::resolve<std::shared_ptr<int>>().template_type(), entt::resolve<entt::meta_class_template_tag<std::shared_ptr>>());
|
||||
ASSERT_EQ(entt::resolve<std::shared_ptr<int>>().template_arg(0u), entt::resolve<int>());
|
||||
ASSERT_EQ(entt::resolve<std::shared_ptr<int>>().template_arg(1u), entt::meta_type{});
|
||||
}
|
||||
|
||||
TEST_F(MetaType, Base) {
|
||||
using namespace entt::literals;
|
||||
auto type = entt::resolve<derived_t>();
|
||||
|
||||
ASSERT_NE(type.base().cbegin(), type.base().cend());
|
||||
|
||||
for(auto curr: type.base()) {
|
||||
ASSERT_EQ(curr.first, entt::type_id<base_t>().hash());
|
||||
ASSERT_EQ(curr.second, entt::resolve<base_t>());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(MetaType, Ctor) {
|
||||
derived_t derived;
|
||||
base_t &base = derived;
|
||||
auto type = entt::resolve<clazz_t>();
|
||||
|
||||
ASSERT_TRUE((type.construct(entt::forward_as_meta(derived), 42)));
|
||||
ASSERT_TRUE((type.construct(entt::forward_as_meta(base), 42)));
|
||||
|
||||
// use the implicitly generated default constructor
|
||||
auto any = type.construct();
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.type(), entt::resolve<clazz_t>());
|
||||
}
|
||||
|
||||
TEST_F(MetaType, Data) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto type = entt::resolve<clazz_t>();
|
||||
int counter{};
|
||||
|
||||
for([[maybe_unused]] auto curr: type.data()) {
|
||||
++counter;
|
||||
}
|
||||
|
||||
ASSERT_EQ(counter, 1);
|
||||
ASSERT_TRUE(type.data("value"_hs));
|
||||
|
||||
type = entt::resolve<void>();
|
||||
|
||||
ASSERT_TRUE(type);
|
||||
ASSERT_EQ(type.data().cbegin(), type.data().cend());
|
||||
}
|
||||
|
||||
TEST_F(MetaType, Func) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto type = entt::resolve<clazz_t>();
|
||||
clazz_t instance{};
|
||||
int counter{};
|
||||
|
||||
for([[maybe_unused]] auto curr: type.func()) {
|
||||
++counter;
|
||||
}
|
||||
|
||||
ASSERT_EQ(counter, 2);
|
||||
ASSERT_TRUE(type.func("member"_hs));
|
||||
ASSERT_TRUE(type.func("func"_hs));
|
||||
ASSERT_TRUE(type.func("member"_hs).invoke(instance));
|
||||
ASSERT_TRUE(type.func("func"_hs).invoke({}));
|
||||
|
||||
type = entt::resolve<void>();
|
||||
|
||||
ASSERT_TRUE(type);
|
||||
ASSERT_EQ(type.func().cbegin(), type.func().cend());
|
||||
}
|
||||
|
||||
TEST_F(MetaType, Invoke) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto type = entt::resolve<clazz_t>();
|
||||
clazz_t instance{};
|
||||
|
||||
ASSERT_TRUE(type.invoke("member"_hs, instance));
|
||||
ASSERT_FALSE(type.invoke("rebmem"_hs, {}));
|
||||
}
|
||||
|
||||
TEST_F(MetaType, InvokeFromBase) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto type = entt::resolve<concrete_t>();
|
||||
concrete_t instance{};
|
||||
|
||||
ASSERT_TRUE(type.invoke("base_only"_hs, instance, 42));
|
||||
ASSERT_FALSE(type.invoke("ylno_esab"_hs, {}, 'c'));
|
||||
}
|
||||
|
||||
TEST_F(MetaType, OverloadedFunc) {
|
||||
using namespace entt::literals;
|
||||
|
||||
const auto type = entt::resolve<overloaded_func_t>();
|
||||
overloaded_func_t instance{};
|
||||
entt::meta_any res{};
|
||||
|
||||
ASSERT_TRUE(type.func("f"_hs));
|
||||
ASSERT_TRUE(type.func("e"_hs));
|
||||
ASSERT_TRUE(type.func("g"_hs));
|
||||
|
||||
res = type.invoke("f"_hs, instance, base_t{}, 1, 2);
|
||||
|
||||
ASSERT_TRUE(res);
|
||||
ASSERT_EQ(overloaded_func_t::value, 1);
|
||||
ASSERT_NE(res.try_cast<int>(), nullptr);
|
||||
ASSERT_EQ(res.cast<int>(), 4);
|
||||
|
||||
res = type.invoke("f"_hs, instance, 3, 4);
|
||||
|
||||
ASSERT_TRUE(res);
|
||||
ASSERT_EQ(overloaded_func_t::value, 3);
|
||||
ASSERT_NE(res.try_cast<int>(), nullptr);
|
||||
ASSERT_EQ(res.cast<int>(), 16);
|
||||
|
||||
res = type.invoke("f"_hs, instance, 5);
|
||||
|
||||
ASSERT_TRUE(res);
|
||||
ASSERT_EQ(overloaded_func_t::value, 3);
|
||||
ASSERT_NE(res.try_cast<int>(), nullptr);
|
||||
ASSERT_EQ(res.cast<int>(), 50);
|
||||
|
||||
res = type.invoke("f"_hs, std::as_const(instance), 5);
|
||||
|
||||
ASSERT_TRUE(res);
|
||||
ASSERT_EQ(overloaded_func_t::value, 3);
|
||||
ASSERT_NE(res.try_cast<int>(), nullptr);
|
||||
ASSERT_EQ(res.cast<int>(), 25);
|
||||
|
||||
res = type.invoke("f"_hs, instance, 6, 7.f);
|
||||
|
||||
ASSERT_TRUE(res);
|
||||
ASSERT_EQ(overloaded_func_t::value, 6);
|
||||
ASSERT_NE(res.try_cast<float>(), nullptr);
|
||||
ASSERT_EQ(res.cast<float>(), 14.f);
|
||||
|
||||
res = type.invoke("f"_hs, instance, 8, 9.f);
|
||||
|
||||
ASSERT_TRUE(res);
|
||||
ASSERT_EQ(overloaded_func_t::value, 8);
|
||||
ASSERT_NE(res.try_cast<float>(), nullptr);
|
||||
ASSERT_EQ(res.cast<float>(), 18.f);
|
||||
|
||||
// it fails as an ambiguous call
|
||||
ASSERT_FALSE(type.invoke("f"_hs, instance, 8, 9.));
|
||||
}
|
||||
|
||||
TEST_F(MetaType, Construct) {
|
||||
auto any = entt::resolve<clazz_t>().construct(base_t{}, 42);
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.cast<clazz_t>().value, 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaType, ConstructNoArgs) {
|
||||
// this should work, no other tests required
|
||||
auto any = entt::resolve<clazz_t>().construct();
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
}
|
||||
|
||||
TEST_F(MetaType, ConstructMetaAnyArgs) {
|
||||
auto any = entt::resolve<clazz_t>().construct(entt::meta_any{base_t{}}, entt::meta_any{42});
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.cast<clazz_t>().value, 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaType, ConstructInvalidArgs) {
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().construct('c', base_t{}));
|
||||
}
|
||||
|
||||
TEST_F(MetaType, LessArgs) {
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().construct(base_t{}));
|
||||
}
|
||||
|
||||
TEST_F(MetaType, ConstructCastAndConvert) {
|
||||
auto any = entt::resolve<clazz_t>().construct(derived_t{}, clazz_t{derived_t{}, 42});
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.cast<clazz_t>().value, 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaType, ConstructArithmeticConversion) {
|
||||
auto any = entt::resolve<clazz_t>().construct(derived_t{}, clazz_t{derived_t{}, true});
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_EQ(any.cast<clazz_t>().value, 1);
|
||||
}
|
||||
|
||||
TEST_F(MetaType, FromVoid) {
|
||||
using namespace entt::literals;
|
||||
|
||||
ASSERT_FALSE(entt::resolve<double>().from_void(static_cast<double *>(nullptr)));
|
||||
ASSERT_FALSE(entt::resolve<double>().from_void(static_cast<const double *>(nullptr)));
|
||||
|
||||
auto type = entt::resolve<double>();
|
||||
double value = 4.2;
|
||||
|
||||
ASSERT_FALSE(entt::resolve<void>().from_void(static_cast<void *>(&value)));
|
||||
ASSERT_FALSE(entt::resolve<void>().from_void(static_cast<const void *>(&value)));
|
||||
|
||||
auto as_void = type.from_void(static_cast<void *>(&value));
|
||||
auto as_const_void = type.from_void(static_cast<const void *>(&value));
|
||||
|
||||
ASSERT_TRUE(as_void);
|
||||
ASSERT_TRUE(as_const_void);
|
||||
|
||||
ASSERT_EQ(as_void.type(), entt::resolve<double>());
|
||||
ASSERT_NE(as_void.try_cast<double>(), nullptr);
|
||||
|
||||
ASSERT_EQ(as_const_void.type(), entt::resolve<double>());
|
||||
ASSERT_EQ(as_const_void.try_cast<double>(), nullptr);
|
||||
ASSERT_NE(as_const_void.try_cast<const double>(), nullptr);
|
||||
|
||||
value = 1.2;
|
||||
|
||||
ASSERT_EQ(as_void.cast<double>(), as_const_void.cast<double>());
|
||||
ASSERT_EQ(as_void.cast<double>(), 1.2);
|
||||
}
|
||||
|
||||
TEST_F(MetaType, Reset) {
|
||||
using namespace entt::literals;
|
||||
|
||||
ASSERT_TRUE(entt::resolve("clazz"_hs));
|
||||
ASSERT_EQ(entt::resolve<clazz_t>().id(), "clazz"_hs);
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().prop(static_cast<entt::id_type>(property_t::value)));
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().data("value"_hs));
|
||||
ASSERT_TRUE((entt::resolve<clazz_t>().construct(derived_t{}, clazz_t{})));
|
||||
// implicitly generated default constructor
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().construct());
|
||||
|
||||
entt::meta_reset("clazz"_hs);
|
||||
|
||||
ASSERT_FALSE(entt::resolve("clazz"_hs));
|
||||
ASSERT_NE(entt::resolve<clazz_t>().id(), "clazz"_hs);
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().prop(static_cast<entt::id_type>(property_t::value)));
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().data("value"_hs));
|
||||
ASSERT_FALSE((entt::resolve<clazz_t>().construct(derived_t{}, clazz_t{})));
|
||||
// implicitly generated default constructor is not cleared
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().construct());
|
||||
|
||||
entt::meta<clazz_t>().type("clazz"_hs);
|
||||
|
||||
ASSERT_TRUE(entt::resolve("clazz"_hs));
|
||||
}
|
||||
|
||||
TEST_F(MetaType, ResetLast) {
|
||||
auto id = (entt::resolve().cend() - 1u)->second.id();
|
||||
|
||||
ASSERT_TRUE(entt::resolve(id));
|
||||
|
||||
entt::meta_reset(id);
|
||||
|
||||
ASSERT_FALSE(entt::resolve(id));
|
||||
}
|
||||
|
||||
TEST_F(MetaType, ResetAll) {
|
||||
using namespace entt::literals;
|
||||
|
||||
ASSERT_NE(entt::resolve().begin(), entt::resolve().end());
|
||||
|
||||
ASSERT_TRUE(entt::resolve("clazz"_hs));
|
||||
ASSERT_TRUE(entt::resolve("overloaded_func"_hs));
|
||||
ASSERT_TRUE(entt::resolve("double"_hs));
|
||||
|
||||
entt::meta_reset();
|
||||
|
||||
ASSERT_FALSE(entt::resolve("clazz"_hs));
|
||||
ASSERT_FALSE(entt::resolve("overloaded_func"_hs));
|
||||
ASSERT_FALSE(entt::resolve("double"_hs));
|
||||
|
||||
ASSERT_EQ(entt::resolve().begin(), entt::resolve().end());
|
||||
}
|
||||
|
||||
TEST_F(MetaType, AbstractClass) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto type = entt::resolve<abstract_t>();
|
||||
concrete_t instance;
|
||||
|
||||
ASSERT_EQ(type.info(), entt::type_id<abstract_t>());
|
||||
ASSERT_EQ(instance.base_t::value, 'c');
|
||||
ASSERT_EQ(instance.value, 3);
|
||||
|
||||
type.func("func"_hs).invoke(instance, 42);
|
||||
|
||||
ASSERT_EQ(instance.base_t::value, 'c');
|
||||
ASSERT_EQ(instance.value, 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaType, EnumAndNamedConstants) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto type = entt::resolve<property_t>();
|
||||
|
||||
ASSERT_TRUE(type.data("random"_hs));
|
||||
ASSERT_TRUE(type.data("value"_hs));
|
||||
|
||||
ASSERT_EQ(type.data("random"_hs).type(), type);
|
||||
ASSERT_EQ(type.data("value"_hs).type(), type);
|
||||
|
||||
ASSERT_FALSE(type.data("random"_hs).set({}, property_t::value));
|
||||
ASSERT_FALSE(type.data("value"_hs).set({}, property_t::random));
|
||||
|
||||
ASSERT_EQ(type.data("random"_hs).get({}).cast<property_t>(), property_t::random);
|
||||
ASSERT_EQ(type.data("value"_hs).get({}).cast<property_t>(), property_t::value);
|
||||
}
|
||||
|
||||
TEST_F(MetaType, ArithmeticTypeAndNamedConstants) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto type = entt::resolve<unsigned int>();
|
||||
|
||||
ASSERT_TRUE(type.data("min"_hs));
|
||||
ASSERT_TRUE(type.data("max"_hs));
|
||||
|
||||
ASSERT_EQ(type.data("min"_hs).type(), type);
|
||||
ASSERT_EQ(type.data("max"_hs).type(), type);
|
||||
|
||||
ASSERT_FALSE(type.data("min"_hs).set({}, 100u));
|
||||
ASSERT_FALSE(type.data("max"_hs).set({}, 0u));
|
||||
|
||||
ASSERT_EQ(type.data("min"_hs).get({}).cast<unsigned int>(), 0u);
|
||||
ASSERT_EQ(type.data("max"_hs).get({}).cast<unsigned int>(), 100u);
|
||||
}
|
||||
|
||||
TEST_F(MetaType, Variables) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto p_data = entt::resolve<property_t>().data("var"_hs);
|
||||
auto d_data = entt::resolve("double"_hs).data("var"_hs);
|
||||
|
||||
property_t prop{property_t::key_only};
|
||||
double d = 3.;
|
||||
|
||||
p_data.set(prop, property_t::random);
|
||||
d_data.set(d, 42.);
|
||||
|
||||
ASSERT_EQ(p_data.get(prop).cast<property_t>(), property_t::random);
|
||||
ASSERT_EQ(d_data.get(d).cast<double>(), 42.);
|
||||
ASSERT_EQ(prop, property_t::random);
|
||||
ASSERT_EQ(d, 42.);
|
||||
}
|
||||
|
||||
TEST_F(MetaType, PropertiesAndCornerCases) {
|
||||
using namespace entt::literals;
|
||||
|
||||
auto type = entt::resolve<property_t>();
|
||||
|
||||
ASSERT_EQ(type.prop().cbegin(), type.prop().cend());
|
||||
|
||||
ASSERT_EQ(type.data("random"_hs).prop(static_cast<entt::id_type>(property_t::random)).value().cast<int>(), 0);
|
||||
ASSERT_EQ(type.data("random"_hs).prop(static_cast<entt::id_type>(property_t::value)).value().cast<int>(), 3);
|
||||
|
||||
ASSERT_EQ(type.data("value"_hs).prop(static_cast<entt::id_type>(property_t::random)).value().cast<bool>(), true);
|
||||
ASSERT_EQ(type.data("value"_hs).prop(static_cast<entt::id_type>(property_t::value)).value().cast<int>(), 0);
|
||||
ASSERT_TRUE(type.data("value"_hs).prop(static_cast<entt::id_type>(property_t::key_only)));
|
||||
ASSERT_FALSE(type.data("value"_hs).prop(static_cast<entt::id_type>(property_t::key_only)).value());
|
||||
|
||||
ASSERT_TRUE(type.data("key_only"_hs).prop(static_cast<entt::id_type>(property_t::key_only)));
|
||||
ASSERT_FALSE(type.data("key_only"_hs).prop(static_cast<entt::id_type>(property_t::key_only)).value());
|
||||
|
||||
ASSERT_EQ(type.data("list"_hs).prop(static_cast<entt::id_type>(property_t::random)).value().cast<bool>(), false);
|
||||
ASSERT_EQ(type.data("list"_hs).prop(static_cast<entt::id_type>(property_t::value)).value().cast<int>(), 0);
|
||||
ASSERT_TRUE(type.data("list"_hs).prop(static_cast<entt::id_type>(property_t::key_only)));
|
||||
ASSERT_FALSE(type.data("list"_hs).prop(static_cast<entt::id_type>(property_t::key_only)).value());
|
||||
|
||||
type = entt::resolve<void>();
|
||||
|
||||
ASSERT_EQ(type.prop().cbegin(), type.prop().cend());
|
||||
}
|
||||
|
||||
TEST_F(MetaType, ResetAndReRegistrationAfterReset) {
|
||||
using namespace entt::literals;
|
||||
|
||||
ASSERT_FALSE(entt::internal::meta_context::from(entt::locator<entt::meta_ctx>::value_or()).value.empty());
|
||||
|
||||
entt::meta_reset<double>();
|
||||
entt::meta_reset<unsigned int>();
|
||||
entt::meta_reset<base_t>();
|
||||
entt::meta_reset<derived_t>();
|
||||
entt::meta_reset<abstract_t>();
|
||||
entt::meta_reset<concrete_t>();
|
||||
entt::meta_reset<overloaded_func_t>();
|
||||
entt::meta_reset<property_t>();
|
||||
entt::meta_reset<clazz_t>();
|
||||
|
||||
ASSERT_FALSE(entt::resolve("double"_hs));
|
||||
ASSERT_FALSE(entt::resolve("base"_hs));
|
||||
ASSERT_FALSE(entt::resolve("derived"_hs));
|
||||
ASSERT_FALSE(entt::resolve("clazz"_hs));
|
||||
|
||||
ASSERT_TRUE(entt::internal::meta_context::from(entt::locator<entt::meta_ctx>::value_or()).value.empty());
|
||||
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().prop(static_cast<entt::id_type>(property_t::value)));
|
||||
// implicitly generated default constructor is not cleared
|
||||
ASSERT_TRUE(entt::resolve<clazz_t>().construct());
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().data("value"_hs));
|
||||
ASSERT_FALSE(entt::resolve<clazz_t>().func("member"_hs));
|
||||
|
||||
entt::meta<double>().type("double"_hs);
|
||||
entt::meta_any any{42.};
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_TRUE(any.allow_cast<int>());
|
||||
ASSERT_TRUE(any.allow_cast<float>());
|
||||
|
||||
ASSERT_FALSE(entt::resolve("derived"_hs));
|
||||
ASSERT_TRUE(entt::resolve("double"_hs));
|
||||
|
||||
entt::meta<property_t>()
|
||||
.type("property"_hs)
|
||||
.data<property_t::random>("rand"_hs)
|
||||
.prop(static_cast<entt::id_type>(property_t::value), 42)
|
||||
.prop(static_cast<entt::id_type>(property_t::random), 3);
|
||||
|
||||
ASSERT_TRUE(entt::resolve<property_t>().data("rand"_hs).prop(static_cast<entt::id_type>(property_t::value)));
|
||||
ASSERT_TRUE(entt::resolve<property_t>().data("rand"_hs).prop(static_cast<entt::id_type>(property_t::random)));
|
||||
}
|
||||
|
||||
TEST_F(MetaType, ReRegistration) {
|
||||
using namespace entt::literals;
|
||||
|
||||
int count = 0;
|
||||
|
||||
for([[maybe_unused]] auto type: entt::resolve()) {
|
||||
++count;
|
||||
}
|
||||
|
||||
SetUp();
|
||||
|
||||
for([[maybe_unused]] auto type: entt::resolve()) {
|
||||
--count;
|
||||
}
|
||||
|
||||
ASSERT_EQ(count, 0);
|
||||
ASSERT_TRUE(entt::resolve("double"_hs));
|
||||
|
||||
entt::meta<double>().type("real"_hs);
|
||||
|
||||
ASSERT_FALSE(entt::resolve("double"_hs));
|
||||
ASSERT_TRUE(entt::resolve("real"_hs));
|
||||
ASSERT_TRUE(entt::resolve("real"_hs).data("var"_hs));
|
||||
}
|
||||
|
||||
TEST_F(MetaType, NameCollision) {
|
||||
using namespace entt::literals;
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(entt::meta<clazz_t>().type("clazz"_hs));
|
||||
ASSERT_TRUE(entt::resolve("clazz"_hs));
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(entt::meta<clazz_t>().type("quux"_hs));
|
||||
ASSERT_FALSE(entt::resolve("clazz"_hs));
|
||||
ASSERT_TRUE(entt::resolve("quux"_hs));
|
||||
}
|
||||
|
||||
ENTT_DEBUG_TEST_F(MetaTypeDeathTest, NameCollision) {
|
||||
using namespace entt::literals;
|
||||
|
||||
ASSERT_DEATH(entt::meta<clazz_t>().type("abstract"_hs), "");
|
||||
}
|
268
test/entt/meta/meta_utility.cpp
Normal file
268
test/entt/meta/meta_utility.cpp
Normal file
@ -0,0 +1,268 @@
|
||||
#include <utility>
|
||||
#include <gtest/gtest.h>
|
||||
#include <entt/core/type_traits.hpp>
|
||||
#include <entt/meta/meta.hpp>
|
||||
#include <entt/meta/resolve.hpp>
|
||||
#include <entt/meta/utility.hpp>
|
||||
#include "../common/config.h"
|
||||
|
||||
struct clazz {
|
||||
void setter(int v) {
|
||||
member = v;
|
||||
}
|
||||
|
||||
int getter() const {
|
||||
return member;
|
||||
}
|
||||
|
||||
static void static_setter(clazz &instance, int v) {
|
||||
instance.member = v;
|
||||
}
|
||||
|
||||
static int static_getter(const clazz &instance) {
|
||||
return instance.member;
|
||||
}
|
||||
|
||||
static void reset_value() {
|
||||
value = 0;
|
||||
}
|
||||
|
||||
static int get_value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
static clazz factory(int v) {
|
||||
clazz instance{};
|
||||
instance.member = v;
|
||||
return instance;
|
||||
}
|
||||
|
||||
int member{};
|
||||
const int cmember{};
|
||||
inline static int value{};
|
||||
inline static const int cvalue{};
|
||||
inline static int arr[3u]{};
|
||||
};
|
||||
|
||||
struct dummy {};
|
||||
|
||||
struct MetaUtility: ::testing::Test {
|
||||
void SetUp() override {
|
||||
clazz::value = 0;
|
||||
}
|
||||
};
|
||||
|
||||
using MetaUtilityDeathTest = MetaUtility;
|
||||
|
||||
TEST_F(MetaUtility, MetaDispatch) {
|
||||
int value = 42;
|
||||
|
||||
auto as_void = entt::meta_dispatch<entt::as_void_t>(value);
|
||||
auto as_ref = entt::meta_dispatch<entt::as_ref_t>(value);
|
||||
auto as_cref = entt::meta_dispatch<entt::as_cref_t>(value);
|
||||
auto as_is = entt::meta_dispatch(value);
|
||||
|
||||
ASSERT_EQ(as_void.type(), entt::resolve<void>());
|
||||
ASSERT_EQ(as_ref.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(as_cref.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(as_is.type(), entt::resolve<int>());
|
||||
|
||||
ASSERT_NE(as_is.try_cast<int>(), nullptr);
|
||||
ASSERT_NE(as_ref.try_cast<int>(), nullptr);
|
||||
ASSERT_EQ(as_cref.try_cast<int>(), nullptr);
|
||||
ASSERT_NE(as_cref.try_cast<const int>(), nullptr);
|
||||
|
||||
ASSERT_EQ(as_is.cast<int>(), 42);
|
||||
ASSERT_EQ(as_ref.cast<int>(), 42);
|
||||
ASSERT_EQ(as_cref.cast<int>(), 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaUtility, MetaDispatchMetaAny) {
|
||||
entt::meta_any any{42};
|
||||
|
||||
auto from_any = entt::meta_dispatch(any);
|
||||
auto from_const_any = entt::meta_dispatch(std::as_const(any));
|
||||
|
||||
ASSERT_EQ(from_any.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(from_const_any.type(), entt::resolve<int>());
|
||||
|
||||
ASSERT_NE(from_any.try_cast<int>(), nullptr);
|
||||
ASSERT_NE(from_const_any.try_cast<int>(), nullptr);
|
||||
|
||||
ASSERT_EQ(from_any.cast<int>(), 42);
|
||||
ASSERT_EQ(from_const_any.cast<int>(), 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaUtility, MetaDispatchMetaAnyAsRef) {
|
||||
entt::meta_any any{42};
|
||||
|
||||
auto from_any = entt::meta_dispatch(any.as_ref());
|
||||
auto from_const_any = entt::meta_dispatch(std::as_const(any).as_ref());
|
||||
|
||||
ASSERT_EQ(from_any.type(), entt::resolve<int>());
|
||||
ASSERT_EQ(from_const_any.type(), entt::resolve<int>());
|
||||
|
||||
ASSERT_NE(from_any.try_cast<int>(), nullptr);
|
||||
ASSERT_EQ(from_const_any.try_cast<int>(), nullptr);
|
||||
ASSERT_NE(from_const_any.try_cast<const int>(), nullptr);
|
||||
|
||||
ASSERT_EQ(from_any.cast<int>(), 42);
|
||||
ASSERT_EQ(from_const_any.cast<int>(), 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaUtility, MetaArg) {
|
||||
ASSERT_EQ((entt::meta_arg<entt::type_list<int, char>>(0u)), entt::resolve<int>());
|
||||
ASSERT_EQ((entt::meta_arg<entt::type_list<int, char>>(1u)), entt::resolve<char>());
|
||||
}
|
||||
|
||||
ENTT_DEBUG_TEST_F(MetaUtilityDeathTest, MetaArg) {
|
||||
ASSERT_DEATH([[maybe_unused]] auto type = entt::meta_arg<entt::type_list<>>(0u), "");
|
||||
ASSERT_DEATH([[maybe_unused]] auto type = entt::meta_arg<entt::type_list<int>>(3u), "");
|
||||
}
|
||||
|
||||
TEST_F(MetaUtility, MetaSetter) {
|
||||
const int invalid{};
|
||||
clazz instance{};
|
||||
|
||||
ASSERT_FALSE((entt::meta_setter<clazz, &clazz::static_setter>(instance, instance)));
|
||||
ASSERT_FALSE((entt::meta_setter<clazz, &clazz::static_setter>(std::as_const(instance), 42)));
|
||||
ASSERT_FALSE((entt::meta_setter<clazz, &clazz::static_setter>(invalid, 42)));
|
||||
ASSERT_TRUE((entt::meta_setter<clazz, &clazz::static_setter>(instance, 42)));
|
||||
ASSERT_EQ(instance.member, 42);
|
||||
|
||||
ASSERT_FALSE((entt::meta_setter<clazz, &clazz::setter>(instance, instance)));
|
||||
ASSERT_FALSE((entt::meta_setter<clazz, &clazz::setter>(std::as_const(instance), 3)));
|
||||
ASSERT_FALSE((entt::meta_setter<clazz, &clazz::setter>(invalid, 3)));
|
||||
ASSERT_TRUE((entt::meta_setter<clazz, &clazz::setter>(instance, 3)));
|
||||
ASSERT_EQ(instance.member, 3);
|
||||
|
||||
ASSERT_FALSE((entt::meta_setter<clazz, &clazz::member>(instance, instance)));
|
||||
ASSERT_FALSE((entt::meta_setter<clazz, &clazz::member>(invalid, 99)));
|
||||
ASSERT_TRUE((entt::meta_setter<clazz, &clazz::member>(instance, 99)));
|
||||
ASSERT_EQ(instance.member, 99);
|
||||
|
||||
ASSERT_FALSE((entt::meta_setter<clazz, &clazz::cmember>(instance, 99)));
|
||||
ASSERT_FALSE((entt::meta_setter<clazz, &clazz::cmember>(invalid, 99)));
|
||||
ASSERT_EQ(instance.cmember, 0);
|
||||
|
||||
ASSERT_FALSE((entt::meta_setter<clazz, &clazz::value>(instance, instance)));
|
||||
ASSERT_TRUE((entt::meta_setter<clazz, &clazz::value>(invalid, 1)));
|
||||
ASSERT_TRUE((entt::meta_setter<clazz, &clazz::value>(instance, 2)));
|
||||
ASSERT_EQ(clazz::value, 2);
|
||||
|
||||
ASSERT_FALSE((entt::meta_setter<clazz, &clazz::cvalue>(instance, 1)));
|
||||
ASSERT_FALSE((entt::meta_setter<clazz, &clazz::cvalue>(invalid, 1)));
|
||||
ASSERT_EQ(clazz::cvalue, 0);
|
||||
}
|
||||
|
||||
TEST_F(MetaUtility, MetaGetter) {
|
||||
const int invalid{};
|
||||
clazz instance{};
|
||||
|
||||
ASSERT_FALSE((entt::meta_getter<clazz, &clazz::static_getter>(invalid)));
|
||||
ASSERT_EQ((entt::meta_getter<clazz, &clazz::static_getter>(instance)).cast<int>(), 0);
|
||||
|
||||
ASSERT_FALSE((entt::meta_getter<clazz, &clazz::getter>(invalid)));
|
||||
ASSERT_EQ((entt::meta_getter<clazz, &clazz::getter>(instance)).cast<int>(), 0);
|
||||
|
||||
ASSERT_FALSE((entt::meta_getter<clazz, &clazz::member>(invalid)));
|
||||
ASSERT_EQ((entt::meta_getter<clazz, &clazz::member>(instance)).cast<int>(), 0);
|
||||
ASSERT_EQ((entt::meta_getter<clazz, &clazz::member>(std::as_const(instance))).cast<int>(), 0);
|
||||
|
||||
ASSERT_FALSE((entt::meta_getter<clazz, &clazz::cmember>(invalid)));
|
||||
ASSERT_EQ((entt::meta_getter<clazz, &clazz::cmember>(instance)).cast<int>(), 0);
|
||||
ASSERT_EQ((entt::meta_getter<clazz, &clazz::cmember>(std::as_const(instance))).cast<int>(), 0);
|
||||
|
||||
ASSERT_FALSE((entt::meta_getter<clazz, &clazz::arr>(invalid)));
|
||||
ASSERT_FALSE((entt::meta_getter<clazz, &clazz::arr>(instance)));
|
||||
|
||||
ASSERT_EQ((entt::meta_getter<clazz, &clazz::value>(invalid)).cast<int>(), 0);
|
||||
ASSERT_EQ((entt::meta_getter<clazz, &clazz::value>(instance)).cast<int>(), 0);
|
||||
|
||||
ASSERT_EQ((entt::meta_getter<clazz, &clazz::cvalue>(invalid)).cast<int>(), 0);
|
||||
ASSERT_EQ((entt::meta_getter<clazz, &clazz::cvalue>(instance)).cast<int>(), 0);
|
||||
|
||||
ASSERT_EQ((entt::meta_getter<clazz, 42>(invalid)).cast<int>(), 42);
|
||||
ASSERT_EQ((entt::meta_getter<clazz, 42>(instance)).cast<int>(), 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaUtility, MetaInvokeWithCandidate) {
|
||||
entt::meta_any args[2u]{clazz{}, 42};
|
||||
args[0u].cast<clazz &>().value = 99;
|
||||
|
||||
ASSERT_FALSE((entt::meta_invoke<clazz>({}, &clazz::setter, nullptr)));
|
||||
ASSERT_FALSE((entt::meta_invoke<clazz>({}, &clazz::getter, nullptr)));
|
||||
|
||||
ASSERT_TRUE((entt::meta_invoke<clazz>(args[0u], &clazz::setter, args + 1u)));
|
||||
ASSERT_FALSE((entt::meta_invoke<clazz>(args[0u], &clazz::setter, args)));
|
||||
ASSERT_EQ((entt::meta_invoke<clazz>(args[0u], &clazz::getter, nullptr)).cast<int>(), 42);
|
||||
ASSERT_FALSE((entt::meta_invoke<clazz>(args[1u], &clazz::getter, nullptr)));
|
||||
|
||||
ASSERT_EQ((entt::meta_invoke<clazz>({}, &clazz::get_value, nullptr)).cast<int>(), 99);
|
||||
ASSERT_TRUE((entt::meta_invoke<clazz>({}, &clazz::reset_value, nullptr)));
|
||||
ASSERT_EQ(args[0u].cast<clazz &>().value, 0);
|
||||
|
||||
const auto setter = [](int &value) { value = 3; };
|
||||
const auto getter = [](int value) { return value * 2; };
|
||||
|
||||
ASSERT_TRUE(entt::meta_invoke<dummy>({}, setter, args + 1u));
|
||||
ASSERT_EQ(entt::meta_invoke<dummy>({}, getter, args + 1u).cast<int>(), 6);
|
||||
}
|
||||
|
||||
TEST_F(MetaUtility, MetaInvoke) {
|
||||
entt::meta_any args[2u]{clazz{}, 42};
|
||||
args[0u].cast<clazz &>().value = 99;
|
||||
|
||||
ASSERT_FALSE((entt::meta_invoke<clazz, &clazz::setter>({}, nullptr)));
|
||||
ASSERT_FALSE((entt::meta_invoke<clazz, &clazz::getter>({}, nullptr)));
|
||||
|
||||
ASSERT_TRUE((entt::meta_invoke<clazz, &clazz::setter>(args[0u], args + 1u)));
|
||||
ASSERT_FALSE((entt::meta_invoke<clazz, &clazz::setter>(args[0u], args)));
|
||||
ASSERT_EQ((entt::meta_invoke<clazz, &clazz::getter>(args[0u], nullptr)).cast<int>(), 42);
|
||||
ASSERT_FALSE((entt::meta_invoke<clazz, &clazz::getter>(args[1u], nullptr)));
|
||||
|
||||
ASSERT_EQ((entt::meta_invoke<clazz, &clazz::get_value>({}, nullptr)).cast<int>(), 99);
|
||||
ASSERT_TRUE((entt::meta_invoke<clazz, &clazz::reset_value>({}, nullptr)));
|
||||
ASSERT_EQ(args[0u].cast<clazz &>().value, 0);
|
||||
}
|
||||
|
||||
TEST_F(MetaUtility, MetaConstructArgsOnly) {
|
||||
entt::meta_any args[2u]{clazz{}, 42};
|
||||
const auto any = entt::meta_construct<clazz, int>(args + 1u);
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_FALSE((entt::meta_construct<clazz, int>(args)));
|
||||
ASSERT_EQ(any.cast<const clazz &>().member, 42);
|
||||
}
|
||||
|
||||
TEST_F(MetaUtility, MetaConstructWithCandidate) {
|
||||
entt::meta_any args[2u]{clazz{}, 42};
|
||||
const auto any = entt::meta_construct<clazz>(&clazz::factory, args + 1u);
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_FALSE((entt::meta_construct<clazz>(&clazz::factory, args)));
|
||||
ASSERT_EQ(any.cast<const clazz &>().member, 42);
|
||||
|
||||
ASSERT_EQ(args[0u].cast<const clazz &>().member, 0);
|
||||
ASSERT_TRUE((entt::meta_construct<clazz>(&clazz::static_setter, args)));
|
||||
ASSERT_EQ(args[0u].cast<const clazz &>().member, 42);
|
||||
|
||||
const auto setter = [](int &value) { value = 3; };
|
||||
const auto builder = [](int value) { return value * 2; };
|
||||
|
||||
ASSERT_TRUE(entt::meta_construct<dummy>(setter, args + 1u));
|
||||
ASSERT_EQ(entt::meta_construct<dummy>(builder, args + 1u).cast<int>(), 6);
|
||||
}
|
||||
|
||||
TEST_F(MetaUtility, MetaConstruct) {
|
||||
entt::meta_any args[2u]{clazz{}, 42};
|
||||
const auto any = entt::meta_construct<clazz, &clazz::factory>(args + 1u);
|
||||
|
||||
ASSERT_TRUE(any);
|
||||
ASSERT_FALSE((entt::meta_construct<clazz, &clazz::factory>(args)));
|
||||
ASSERT_EQ(any.cast<const clazz &>().member, 42);
|
||||
|
||||
ASSERT_EQ(args[0u].cast<const clazz &>().member, 0);
|
||||
ASSERT_TRUE((entt::meta_construct<clazz, &clazz::static_setter>(args)));
|
||||
ASSERT_EQ(args[0u].cast<const clazz &>().member, 42);
|
||||
}
|
Reference in New Issue
Block a user