| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639 |
- #include <array>
- #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>
- 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();
- 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(view.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);
- 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, 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_FALSE(view.erase(invalid_type{}));
- ASSERT_FALSE(view.find(invalid_type{}));
- ASSERT_EQ(view.size(), 5u);
- ASSERT_TRUE(view.erase(0));
- 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_TRUE(view.erase(1.));
- 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_FALSE(view.erase(invalid_type{}));
- ASSERT_FALSE(view.find(invalid_type{}));
- ASSERT_EQ(view.size(), 5u);
- ASSERT_TRUE(view.erase(0));
- 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_TRUE(view.erase(1.));
- 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_FALSE(view.erase(invalid_type{}));
- ASSERT_FALSE(view.find(invalid_type{}));
- ASSERT_EQ(view.size(), 5u);
- ASSERT_TRUE(view.erase(0));
- 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_TRUE(view.erase(1.));
- 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_FALSE(view.erase(invalid_type{}));
- ASSERT_FALSE(view.find(invalid_type{}));
- ASSERT_EQ(view.size(), 5u);
- ASSERT_TRUE(view.erase(0));
- 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_TRUE(view.erase(1.));
- 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);
- }
- 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_FALSE(view.erase(2));
- ASSERT_EQ(view.size(), 1u);
- ASSERT_NE(view.find(2), view.end());
- ASSERT_FALSE(view.clear());
- ASSERT_EQ(view.size(), 1u);
- }
- 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_FALSE(view.erase(2));
- 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)));
- }
- 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)));
- }
- 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);
- }
|