meta_utility.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. #include <array>
  2. #include <iterator>
  3. #include <utility>
  4. #include <gtest/gtest.h>
  5. #include <entt/core/type_traits.hpp>
  6. #include <entt/meta/meta.hpp>
  7. #include <entt/meta/policy.hpp>
  8. #include <entt/meta/resolve.hpp>
  9. #include <entt/meta/utility.hpp>
  10. #include "../../common/config.h"
  11. #include "../../common/value_type.h"
  12. struct MetaUtility: ::testing::Test {
  13. struct clazz {
  14. void setter(int iv) {
  15. member = iv;
  16. }
  17. [[nodiscard]] int getter() const {
  18. return member;
  19. }
  20. static void static_setter(clazz &instance, int iv) {
  21. instance.member = iv;
  22. }
  23. [[nodiscard]] static int static_getter(const clazz &instance) {
  24. return instance.member;
  25. }
  26. static void reset_value() {
  27. value = 0;
  28. }
  29. [[nodiscard]] static int get_value() {
  30. return value;
  31. }
  32. [[nodiscard]] static clazz factory(int iv) {
  33. clazz instance{};
  34. instance.member = iv;
  35. return instance;
  36. }
  37. int member{};
  38. const int cmember{}; // NOLINT
  39. inline static int value{}; // NOLINT
  40. inline static const int cvalue{}; // NOLINT
  41. inline static int arr[3u]{}; // NOLINT
  42. };
  43. void SetUp() override {
  44. clazz::value = 0;
  45. }
  46. };
  47. using MetaUtilityDeathTest = MetaUtility;
  48. TEST_F(MetaUtility, MetaDispatch) {
  49. int value = 2;
  50. auto as_cref = entt::meta_dispatch<entt::as_cref_t>(value);
  51. auto as_ref = entt::meta_dispatch<entt::as_ref_t>(value);
  52. auto as_void = entt::meta_dispatch<entt::as_void_t>(value);
  53. auto as_is_copy = entt::meta_dispatch<entt::as_is_t>(static_cast<int &&>(value));
  54. auto as_is_cref = entt::meta_dispatch<entt::as_is_t>(std::as_const(value));
  55. auto as_is_ref = entt::meta_dispatch<entt::as_is_t>(value);
  56. auto as_value = entt::meta_dispatch(value);
  57. ASSERT_EQ(as_cref.type(), entt::resolve<int>());
  58. ASSERT_EQ(as_ref.type(), entt::resolve<int>());
  59. ASSERT_EQ(as_void.type(), entt::resolve<void>());
  60. ASSERT_EQ(as_is_copy.type(), entt::resolve<int>());
  61. ASSERT_EQ(as_is_cref.type(), entt::resolve<int>());
  62. ASSERT_EQ(as_is_ref.type(), entt::resolve<int>());
  63. ASSERT_EQ(as_value.type(), entt::resolve<int>());
  64. ASSERT_EQ(as_cref.base().policy(), entt::any_policy::cref);
  65. ASSERT_EQ(as_ref.base().policy(), entt::any_policy::ref);
  66. ASSERT_EQ(as_void.base().policy(), entt::any_policy::empty);
  67. ASSERT_EQ(as_is_copy.base().policy(), entt::any_policy::embedded);
  68. ASSERT_EQ(as_is_cref.base().policy(), entt::any_policy::cref);
  69. ASSERT_EQ(as_is_ref.base().policy(), entt::any_policy::ref);
  70. ASSERT_EQ(as_value.base().policy(), entt::any_policy::embedded);
  71. ASSERT_EQ(as_cref.try_cast<int>(), nullptr);
  72. ASSERT_NE(as_cref.try_cast<const int>(), nullptr);
  73. ASSERT_NE(as_ref.try_cast<int>(), nullptr);
  74. ASSERT_NE(as_is_copy.try_cast<int>(), nullptr);
  75. ASSERT_EQ(as_is_cref.try_cast<int>(), nullptr);
  76. ASSERT_NE(as_is_ref.try_cast<int>(), nullptr);
  77. ASSERT_NE(as_value.try_cast<int>(), nullptr);
  78. ASSERT_EQ(as_cref.cast<int>(), 2);
  79. ASSERT_EQ(as_ref.cast<int>(), 2);
  80. ASSERT_EQ(as_is_copy.cast<int>(), 2);
  81. ASSERT_EQ(as_is_cref.cast<int>(), 2);
  82. ASSERT_EQ(as_is_ref.cast<int>(), 2);
  83. ASSERT_EQ(as_value.cast<int>(), 2);
  84. }
  85. TEST_F(MetaUtility, MetaDispatchMetaAny) {
  86. entt::meta_any any{2};
  87. auto from_any = entt::meta_dispatch(any);
  88. auto from_const_any = entt::meta_dispatch(std::as_const(any));
  89. ASSERT_EQ(from_any.type(), entt::resolve<int>());
  90. ASSERT_EQ(from_const_any.type(), entt::resolve<int>());
  91. ASSERT_NE(from_any.try_cast<int>(), nullptr);
  92. ASSERT_NE(from_const_any.try_cast<int>(), nullptr);
  93. ASSERT_EQ(from_any.cast<int>(), 2);
  94. ASSERT_EQ(from_const_any.cast<int>(), 2);
  95. }
  96. TEST_F(MetaUtility, MetaDispatchMetaAnyAsRef) {
  97. entt::meta_any any{2};
  98. auto from_any = entt::meta_dispatch(any.as_ref());
  99. auto from_const_any = entt::meta_dispatch(std::as_const(any).as_ref());
  100. ASSERT_EQ(from_any.type(), entt::resolve<int>());
  101. ASSERT_EQ(from_const_any.type(), entt::resolve<int>());
  102. ASSERT_NE(from_any.try_cast<int>(), nullptr);
  103. ASSERT_EQ(from_const_any.try_cast<int>(), nullptr);
  104. ASSERT_NE(from_const_any.try_cast<const int>(), nullptr);
  105. ASSERT_EQ(from_any.cast<int>(), 2);
  106. ASSERT_EQ(from_const_any.cast<int>(), 2);
  107. }
  108. TEST_F(MetaUtility, MetaArg) {
  109. ASSERT_EQ((entt::meta_arg<entt::type_list<int, char>>(0u)), entt::resolve<int>());
  110. ASSERT_EQ((entt::meta_arg<entt::type_list<int, char>>(1u)), entt::resolve<char>());
  111. }
  112. ENTT_DEBUG_TEST_F(MetaUtilityDeathTest, MetaArg) {
  113. ASSERT_DEATH([[maybe_unused]] auto type = entt::meta_arg<entt::type_list<>>(0u), "");
  114. ASSERT_DEATH([[maybe_unused]] auto type = entt::meta_arg<entt::type_list<int>>(3u), "");
  115. }
  116. TEST_F(MetaUtility, MetaSetter) {
  117. const int invalid{};
  118. clazz instance{};
  119. ASSERT_FALSE((entt::meta_setter<clazz, &clazz::static_setter>(instance, instance)));
  120. ASSERT_FALSE((entt::meta_setter<clazz, &clazz::static_setter>(std::as_const(instance), 4)));
  121. ASSERT_FALSE((entt::meta_setter<clazz, &clazz::static_setter>(invalid, 4)));
  122. ASSERT_TRUE((entt::meta_setter<clazz, &clazz::static_setter>(instance, 4)));
  123. ASSERT_EQ(instance.member, 4);
  124. ASSERT_FALSE((entt::meta_setter<clazz, &clazz::setter>(instance, instance)));
  125. ASSERT_FALSE((entt::meta_setter<clazz, &clazz::setter>(std::as_const(instance), 3)));
  126. ASSERT_FALSE((entt::meta_setter<clazz, &clazz::setter>(invalid, 3)));
  127. ASSERT_TRUE((entt::meta_setter<clazz, &clazz::setter>(instance, 3)));
  128. ASSERT_EQ(instance.member, 3);
  129. ASSERT_FALSE((entt::meta_setter<clazz, &clazz::member>(instance, instance)));
  130. ASSERT_FALSE((entt::meta_setter<clazz, &clazz::member>(invalid, 8)));
  131. ASSERT_TRUE((entt::meta_setter<clazz, &clazz::member>(instance, 8)));
  132. ASSERT_EQ(instance.member, 8);
  133. ASSERT_FALSE((entt::meta_setter<clazz, &clazz::cmember>(instance, 8)));
  134. ASSERT_FALSE((entt::meta_setter<clazz, &clazz::cmember>(invalid, 8)));
  135. ASSERT_EQ(instance.cmember, 0);
  136. ASSERT_FALSE((entt::meta_setter<clazz, &clazz::value>(instance, instance)));
  137. ASSERT_TRUE((entt::meta_setter<clazz, &clazz::value>(invalid, 1)));
  138. ASSERT_TRUE((entt::meta_setter<clazz, &clazz::value>(instance, 2)));
  139. ASSERT_EQ(clazz::value, 2);
  140. ASSERT_FALSE((entt::meta_setter<clazz, &clazz::cvalue>(instance, 1)));
  141. ASSERT_FALSE((entt::meta_setter<clazz, &clazz::cvalue>(invalid, 1)));
  142. ASSERT_EQ(clazz::cvalue, 0);
  143. }
  144. TEST_F(MetaUtility, MetaGetter) {
  145. const int invalid{};
  146. clazz instance{};
  147. ASSERT_FALSE((entt::meta_getter<clazz, &clazz::static_getter>(invalid)));
  148. ASSERT_EQ((entt::meta_getter<clazz, &clazz::static_getter>(instance)).cast<int>(), 0);
  149. ASSERT_FALSE((entt::meta_getter<clazz, &clazz::getter>(invalid)));
  150. ASSERT_EQ((entt::meta_getter<clazz, &clazz::getter>(instance)).cast<int>(), 0);
  151. ASSERT_FALSE((entt::meta_getter<clazz, &clazz::member>(invalid)));
  152. ASSERT_EQ((entt::meta_getter<clazz, &clazz::member>(instance)).cast<int>(), 0);
  153. ASSERT_EQ((entt::meta_getter<clazz, &clazz::member>(std::as_const(instance))).cast<int>(), 0);
  154. ASSERT_FALSE((entt::meta_getter<clazz, &clazz::cmember>(invalid)));
  155. ASSERT_EQ((entt::meta_getter<clazz, &clazz::cmember>(instance)).cast<int>(), 0);
  156. ASSERT_EQ((entt::meta_getter<clazz, &clazz::cmember>(std::as_const(instance))).cast<int>(), 0);
  157. ASSERT_FALSE((entt::meta_getter<clazz, &clazz::arr>(invalid)));
  158. ASSERT_FALSE((entt::meta_getter<clazz, &clazz::arr>(instance)));
  159. ASSERT_EQ((entt::meta_getter<clazz, &clazz::value>(invalid)).cast<int>(), 0);
  160. ASSERT_EQ((entt::meta_getter<clazz, &clazz::value>(instance)).cast<int>(), 0);
  161. ASSERT_EQ((entt::meta_getter<clazz, &clazz::cvalue>(invalid)).cast<int>(), 0);
  162. ASSERT_EQ((entt::meta_getter<clazz, &clazz::cvalue>(instance)).cast<int>(), 0);
  163. ASSERT_EQ((entt::meta_getter<clazz, 1>(invalid)).cast<int>(), 1);
  164. ASSERT_EQ((entt::meta_getter<clazz, 1>(instance)).cast<int>(), 1);
  165. }
  166. TEST_F(MetaUtility, MetaInvokeWithCandidate) {
  167. std::array args{entt::meta_any{clazz{}}, entt::meta_any{4}};
  168. clazz::value = 3;
  169. ASSERT_FALSE((entt::meta_invoke<clazz>({}, &clazz::setter, std::next(args.data()))));
  170. ASSERT_FALSE((entt::meta_invoke<clazz>({}, &clazz::getter, nullptr)));
  171. ASSERT_TRUE((entt::meta_invoke<clazz>(args[0u], &clazz::setter, std::next(args.data()))));
  172. ASSERT_FALSE((entt::meta_invoke<clazz>(args[0u], &clazz::setter, args.data())));
  173. ASSERT_EQ((entt::meta_invoke<clazz>(args[0u], &clazz::getter, nullptr)).cast<int>(), 4);
  174. ASSERT_FALSE((entt::meta_invoke<clazz>(args[1u], &clazz::getter, nullptr)));
  175. ASSERT_EQ((entt::meta_invoke<clazz>({}, &clazz::get_value, nullptr)).cast<int>(), 3);
  176. ASSERT_TRUE((entt::meta_invoke<clazz>({}, &clazz::reset_value, nullptr)));
  177. ASSERT_EQ(args[0u].cast<clazz &>().value, 0);
  178. const auto setter = [](int &value) { value = 3; };
  179. const auto getter = [](int value) { return value * 2; };
  180. ASSERT_TRUE(entt::meta_invoke<test::empty>({}, setter, std::next(args.data())));
  181. ASSERT_EQ(entt::meta_invoke<test::empty>({}, getter, std::next(args.data())).cast<int>(), 6);
  182. }
  183. TEST_F(MetaUtility, MetaInvoke) {
  184. std::array args{entt::meta_any{clazz{}}, entt::meta_any{4}};
  185. clazz::value = 3;
  186. ASSERT_FALSE((entt::meta_invoke<clazz, &clazz::setter>({}, std::next(args.data()))));
  187. ASSERT_FALSE((entt::meta_invoke<clazz, &clazz::getter>({}, nullptr)));
  188. ASSERT_TRUE((entt::meta_invoke<clazz, &clazz::setter>(args[0u], std::next(args.data()))));
  189. ASSERT_FALSE((entt::meta_invoke<clazz, &clazz::setter>(args[0u], args.data())));
  190. ASSERT_EQ((entt::meta_invoke<clazz, &clazz::getter>(args[0u], nullptr)).cast<int>(), 4);
  191. ASSERT_FALSE((entt::meta_invoke<clazz, &clazz::getter>(args[1u], nullptr)));
  192. ASSERT_EQ((entt::meta_invoke<clazz, &clazz::get_value>({}, nullptr)).cast<int>(), 3);
  193. ASSERT_TRUE((entt::meta_invoke<clazz, &clazz::reset_value>({}, nullptr)));
  194. ASSERT_EQ(args[0u].cast<clazz &>().value, 0);
  195. }
  196. TEST_F(MetaUtility, MetaConstructArgsOnly) {
  197. std::array args{entt::meta_any{clazz{}}, entt::meta_any{4}};
  198. const auto any = entt::meta_construct<clazz, int>(std::next(args.data()));
  199. ASSERT_TRUE(any);
  200. ASSERT_FALSE((entt::meta_construct<clazz, int>(args.data())));
  201. ASSERT_EQ(any.cast<const clazz &>().member, 4);
  202. }
  203. TEST_F(MetaUtility, MetaConstructWithCandidate) {
  204. std::array args{entt::meta_any{clazz{}}, entt::meta_any{4}};
  205. const auto any = entt::meta_construct<clazz>(&clazz::factory, std::next(args.data()));
  206. ASSERT_TRUE(any);
  207. ASSERT_FALSE((entt::meta_construct<clazz>(&clazz::factory, args.data())));
  208. ASSERT_EQ(any.cast<const clazz &>().member, 4);
  209. ASSERT_EQ(args[0u].cast<const clazz &>().member, 0);
  210. ASSERT_TRUE((entt::meta_construct<clazz>(&clazz::static_setter, args.data())));
  211. ASSERT_EQ(args[0u].cast<const clazz &>().member, 4);
  212. const auto setter = [](int &value) { value = 3; };
  213. const auto builder = [](int value) { return value * 2; };
  214. ASSERT_TRUE(entt::meta_construct<test::empty>(setter, std::next(args.data())));
  215. ASSERT_EQ(entt::meta_construct<test::empty>(builder, std::next(args.data())).cast<int>(), 6);
  216. }
  217. TEST_F(MetaUtility, MetaConstruct) {
  218. std::array args{entt::meta_any{clazz{}}, entt::meta_any{4}};
  219. const auto any = entt::meta_construct<clazz, &clazz::factory>(std::next(args.data()));
  220. ASSERT_TRUE(any);
  221. ASSERT_FALSE((entt::meta_construct<clazz, &clazz::factory>(args.data())));
  222. ASSERT_EQ(any.cast<const clazz &>().member, 4);
  223. ASSERT_EQ(args[0u].cast<const clazz &>().member, 0);
  224. ASSERT_TRUE((entt::meta_construct<clazz, &clazz::static_setter>(args.data())));
  225. ASSERT_EQ(args[0u].cast<const clazz &>().member, 4);
  226. }