| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486 |
- #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 MetaContainer: ::testing::Test {
- static void SetUpTestCase() {
- entt::meta<double>().conv<int>();
- entt::meta<int>().conv<char>();
- }
- };
- 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};
- entt::meta_any any{std::ref(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_NE(first, last);
- ASSERT_EQ((*(first++)).cast<int>(), 2);
- ASSERT_EQ((*(++first)).cast<int>(), 4);
- ASSERT_NE(first++, last);
- ASSERT_EQ(first, last);
- ASSERT_TRUE(first == last);
- ASSERT_FALSE(first != last);
- }
- TEST_F(MetaContainer, AssociativeContainerIterator) {
- std::map<int, char> map{{2, 'c'}, {3, 'd'}, {4, 'e'}};
- entt::meta_any any{std::ref(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{};
- entt::meta_any any{std::ref(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.second);
- ASSERT_FALSE(view.insert(ret.first, 'c').second);
- ASSERT_TRUE(view.insert(++ret.first, 1.).second);
- ASSERT_EQ(view.size(), 5u);
- ASSERT_EQ((*view.begin()).cast<int>(), 0);
- ASSERT_EQ((*++view.begin()).cast<int>(), 1);
- it = view.begin();
- ret = view.erase(it);
- ASSERT_TRUE(ret.second);
- ASSERT_EQ(view.size(), 4u);
- ASSERT_EQ((*ret.first).cast<int>(), 1);
- ASSERT_TRUE(view.clear());
- ASSERT_EQ(view.size(), 0u);
- }
- TEST_F(MetaContainer, StdArray) {
- std::array<int, 3> arr{};
- entt::meta_any any{std::ref(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.second);
- ASSERT_FALSE(view.insert(it, 'c').second);
- ASSERT_FALSE(view.insert(++it, 1).second);
- 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.second);
- 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'}};
- entt::meta_any any{std::ref(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('a', 'a'));
- ASSERT_FALSE(view.insert(1, 1.));
- 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('c'));
- ASSERT_EQ(view.size(), 5u);
- ASSERT_FALSE(view.find('c'));
- 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)).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};
- entt::meta_any any{std::ref(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('0'));
- 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('c'));
- ASSERT_EQ(view.size(), 5u);
- ASSERT_FALSE(view.find('c'));
- ASSERT_TRUE(view.erase(0));
- ASSERT_EQ(view.size(), 4u);
- ASSERT_EQ(view.find(0), view.end());
- ASSERT_EQ((*view.find(1)).first.try_cast<int>(), nullptr);
- ASSERT_NE((*view.find(1)).first.try_cast<const int>(), nullptr);
- ASSERT_EQ((*view.find(1)).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{};
- entt::meta_any any{std::cref(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_DEATH(view[0].cast<int &>() = 2, ".*");
- ASSERT_EQ(view[0].cast<const int &>(), 42);
- auto it = view.begin();
- auto ret = view.insert(it, 0);
- ASSERT_FALSE(ret.second);
- 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.second);
- ASSERT_EQ(view.size(), 1u);
- ASSERT_FALSE(view.clear());
- ASSERT_EQ(view.size(), 1u);
- }
- TEST_F(MetaContainer, ConstKeyValueAssociativeContainer) {
- std::map<int, char> map{};
- entt::meta_any any{std::cref(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_DEATH((*view.find(2)).second.cast<char &>() = 'a', ".*");
- 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(MetaContainer, ConstKeyOnlyAssociativeContainer) {
- std::set<int> set{};
- entt::meta_any any{std::cref(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_DEATH(view[0].cast<int &>() = 2, ".*");
- ASSERT_EQ(view[0].cast<const int &>(), 42);
- };
- std::vector<int> vec{42};
- test(vec);
- test(std::ref(vec));
- test(std::cref(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_DEATH((*view.find(2)).second.cast<char &>() = 'a', ".*");
- ASSERT_EQ((*view.find(2)).second.cast<const char &>(), 'c');
- };
- std::map<int, char> map{{2, 'c'}};
- test(map);
- test(std::ref(map));
- test(std::cref(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(std::ref(set));
- test(std::cref(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{};
- entt::meta_any any{std::ref(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.second);
- ASSERT_FALSE(view.insert(ret.first, 'c').second);
- ASSERT_TRUE(view.insert(++ret.first, false).second);
- 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.second);
- ASSERT_EQ(view.size(), 4u);
- ASSERT_EQ((*ret.first).cast<proxy_type>(), false);
- ASSERT_TRUE(view.clear());
- ASSERT_EQ(cview.size(), 0u);
- }
|