Invoke.cpp 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzCore/std/any.h>
  9. #include <AzCore/std/containers/array.h>
  10. #include <AzCore/std/containers/vector.h>
  11. #include <AzCore/std/containers/unordered_map.h>
  12. #include <AzCore/std/function/invoke.h>
  13. #include <AzCore/std/smart_ptr/shared_ptr.h>
  14. #include <AzCore/std/smart_ptr/unique_ptr.h>
  15. #include <AzCore/std/string/string_view.h>
  16. #include "UserTypes.h"
  17. namespace UnitTest
  18. {
  19. //////////////////////////////////////////////////////////////////////////
  20. // Fixtures
  21. struct InvokeNonCopyable
  22. {
  23. InvokeNonCopyable() = default;
  24. private:
  25. InvokeNonCopyable(const InvokeNonCopyable&) = delete;
  26. InvokeNonCopyable& operator=(const InvokeNonCopyable&) = delete;
  27. };
  28. struct InvokeTestStruct
  29. {
  30. explicit InvokeTestStruct(int num)
  31. : m_data(num)
  32. {}
  33. int IntResultIntParameter(int) { return m_data; }
  34. int& operator()(InvokeNonCopyable&&) & { return m_data; }
  35. const int& operator()(InvokeNonCopyable&&) const & { return m_data; }
  36. volatile int& operator()(InvokeNonCopyable&&) volatile & { return m_data; }
  37. const volatile int& operator()(InvokeNonCopyable&&) const volatile & { return m_data; }
  38. int&& operator()(InvokeNonCopyable&&) && { return AZStd::move(m_data); }
  39. const int&& operator()(InvokeNonCopyable&&) const && { return AZStd::move(m_data); }
  40. volatile int&& operator()(InvokeNonCopyable&&) volatile && { return AZStd::move(m_data); }
  41. const volatile int&& operator()(InvokeNonCopyable&&) const volatile && { return AZStd::move(m_data); }
  42. int m_data;
  43. };
  44. struct InvokeTestDerivedStruct : InvokeTestStruct
  45. {
  46. explicit InvokeTestDerivedStruct(int num)
  47. : InvokeTestStruct(num)
  48. {}
  49. };
  50. struct InvokeTestImplicitConstructor
  51. {
  52. InvokeTestImplicitConstructor(AZ::s32) {}
  53. };
  54. struct InvokeTestExplicitConstructor
  55. {
  56. explicit InvokeTestExplicitConstructor(AZ::s32) {}
  57. };
  58. struct InvokeTestDeletedS32Callable
  59. {
  60. bool operator()(InvokeTestStruct) { return false; }
  61. private:
  62. bool operator()(AZ::s32) = delete;
  63. };
  64. // Fixture for non-typed tests
  65. class InvocableTest
  66. : public LeakDetectionFixture
  67. {
  68. };
  69. TEST_F(InvocableTest, InvalidInvocableArgsTest)
  70. {
  71. using Func = int(InvokeTestStruct::*)(int);
  72. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<Func, Test, int>::value));
  73. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<int>::value));
  74. }
  75. TEST_F(InvocableTest, MemberFunctionTest)
  76. {
  77. using Func = int(InvokeTestStruct::*)(int);
  78. using CLFunc = int(InvokeTestStruct::*)(int) const &;
  79. using RFunc = int(InvokeTestStruct::*)(int) &&;
  80. using CRFunc = int(InvokeTestStruct::*)(int) const &&;
  81. // Member functions require a "this" object in order to be invocable
  82. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<AZStd::decay_t<Func>>::value));
  83. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<AZStd::decay_t<CLFunc>>::value));
  84. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<AZStd::decay_t<RFunc>>::value));
  85. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<AZStd::decay_t<CRFunc>>::value));
  86. // Bullet 1
  87. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<Func, InvokeTestStruct, int>::value));
  88. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<Func, InvokeTestStruct&, int>::value));
  89. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<Func, InvokeTestStruct&&, int>::value));
  90. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<Func, InvokeTestDerivedStruct, int>::value));
  91. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<Func, const InvokeTestStruct&, int>::value));
  92. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<Func, const InvokeTestStruct&&, int>::value));
  93. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<Func, int, int>::value));
  94. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<Func, InvokeTestStruct, AZStd::string_view>::value));
  95. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<CLFunc, const InvokeTestStruct&, int>::value));
  96. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<CLFunc, const InvokeTestDerivedStruct&, int>::value));
  97. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<RFunc, InvokeTestStruct, int>::value));
  98. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<RFunc, InvokeTestStruct&&, int>::value));
  99. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<RFunc, const InvokeTestStruct&&, int>::value));
  100. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<RFunc, const InvokeTestStruct&, int>::value));
  101. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<RFunc, InvokeTestStruct&, int>::value));
  102. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<CRFunc, InvokeTestStruct, int>::value));
  103. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<CRFunc, InvokeTestStruct&&, int>::value));
  104. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<CRFunc, const InvokeTestStruct&&, int>::value));
  105. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<CRFunc, const InvokeTestStruct&, int>::value));
  106. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<CRFunc, InvokeTestStruct&, int>::value));
  107. // Bullet 2
  108. using RefTest = AZStd::reference_wrapper<InvokeTestStruct>;
  109. using RefDerivedTest = AZStd::reference_wrapper<InvokeTestDerivedStruct>;
  110. using RefConstTest = AZStd::reference_wrapper<const InvokeTestStruct>;
  111. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<Func, RefTest, int>::value));
  112. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<Func, RefDerivedTest, int>::value));
  113. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<Func, const RefTest, int>::value));
  114. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<Func, RefConstTest, int>::value));
  115. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<Func, RefTest&, int>::value));
  116. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<Func, RefDerivedTest&, int>::value));
  117. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<Func, const RefTest&, int>::value));
  118. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<Func, RefConstTest&, int>::value));
  119. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<CLFunc, RefTest, int>::value));
  120. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<CLFunc, const RefTest, int>::value));
  121. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<CLFunc, const RefTest&, int>::value));
  122. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<CLFunc, RefTest&, int>::value));
  123. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<CLFunc, RefTest&&, int>::value));
  124. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<CLFunc, const RefTest&&, int>::value));
  125. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<CLFunc, const RefDerivedTest, int>::value));
  126. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<CLFunc, RefConstTest, int>::value));
  127. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<CLFunc, RefConstTest&, int>::value));
  128. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<CLFunc, const RefConstTest, int>::value));
  129. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<CLFunc, RefConstTest&&, int>::value));
  130. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<CLFunc, const RefConstTest&&, int>::value));
  131. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<RFunc, RefTest, int>::value));
  132. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<RFunc, RefDerivedTest, int>::value));
  133. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<RFunc, RefConstTest, int>::value));
  134. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<CRFunc, RefTest, int>::value));
  135. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<CRFunc, RefDerivedTest, int>::value));
  136. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<CRFunc, RefConstTest, int>::value));
  137. // Bullet 3
  138. using TestPtrType = InvokeTestStruct*;
  139. using DerivedTestPtrType = InvokeTestDerivedStruct*;
  140. using ConstTestPtrType = const InvokeTestStruct*;
  141. using UniqueTestPtrType = AZStd::unique_ptr<InvokeTestStruct>;
  142. using SharedTestPtrType = AZStd::shared_ptr<InvokeTestStruct>;
  143. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<Func, TestPtrType&, int>::value));
  144. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<Func, const TestPtrType&, int>::value));
  145. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<Func, DerivedTestPtrType, int>::value));
  146. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<Func, UniqueTestPtrType, int>::value));
  147. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<Func, SharedTestPtrType, int>::value));
  148. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<Func, ConstTestPtrType&, int>::value));
  149. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<Func, ConstTestPtrType&&, int>::value));
  150. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<CLFunc, TestPtrType&, int>::value));
  151. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<CLFunc, const TestPtrType&, int>::value));
  152. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<CLFunc, DerivedTestPtrType, int>::value));
  153. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<CLFunc, UniqueTestPtrType, int>::value));
  154. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<CLFunc, SharedTestPtrType, int>::value));
  155. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<CLFunc, ConstTestPtrType&, int>::value));
  156. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<CLFunc, ConstTestPtrType&&, int>::value));
  157. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<RFunc, TestPtrType&, int>::value));
  158. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<RFunc, const TestPtrType&, int>::value));
  159. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<RFunc, DerivedTestPtrType, int>::value));
  160. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<RFunc, UniqueTestPtrType, int>::value));
  161. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<RFunc, SharedTestPtrType, int>::value));
  162. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<RFunc, ConstTestPtrType&, int>::value));
  163. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<RFunc, ConstTestPtrType&&, int>::value));
  164. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<CRFunc, TestPtrType&, int>::value));
  165. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<CRFunc, const TestPtrType&, int>::value));
  166. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<CRFunc, DerivedTestPtrType, int>::value));
  167. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<CRFunc, UniqueTestPtrType, int>::value));
  168. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<CRFunc, SharedTestPtrType, int>::value));
  169. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<CRFunc, ConstTestPtrType&, int>::value));
  170. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<CRFunc, ConstTestPtrType&&, int>::value));
  171. }
  172. TEST_F(InvocableTest, MemberObjectTest)
  173. {
  174. using MemberFn = int(InvokeTestStruct::*);
  175. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<MemberFn>::value));
  176. // Bullet 4
  177. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<MemberFn, InvokeTestStruct>::value));
  178. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<MemberFn, InvokeTestStruct&>::value));
  179. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<MemberFn, const InvokeTestStruct&>::value));
  180. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<MemberFn, InvokeTestStruct&&>::value));
  181. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<MemberFn, const InvokeTestStruct&&>::value));
  182. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<MemberFn, InvokeTestDerivedStruct&>::value));
  183. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<MemberFn, InvokeTestStruct, int>::value));
  184. // Bullet 5
  185. using RefTest = AZStd::reference_wrapper<InvokeTestStruct>;
  186. using RefDerivedTest = AZStd::reference_wrapper<InvokeTestDerivedStruct>;
  187. using RefConstTest = AZStd::reference_wrapper<const InvokeTestStruct>;
  188. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<MemberFn, RefTest>::value));
  189. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<MemberFn, RefTest&>::value));
  190. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<MemberFn, const RefTest&>::value));
  191. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<MemberFn, RefConstTest&&>::value));
  192. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<MemberFn, const RefConstTest&&>::value));
  193. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<MemberFn, RefDerivedTest&>::value));
  194. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<MemberFn, RefConstTest&>::value));
  195. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<MemberFn, RefTest, float>::value));
  196. // Bullet 6
  197. using TestPtrType = InvokeTestStruct*;
  198. using DerivedTestPtrType = InvokeTestDerivedStruct;
  199. using ConstTestPtrType = const InvokeTestStruct*;
  200. using UniqueTestPtrType = AZStd::unique_ptr<InvokeTestStruct>;
  201. using SharedTestPtrType = AZStd::shared_ptr<InvokeTestStruct>;
  202. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<MemberFn, TestPtrType>::value));
  203. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<MemberFn, TestPtrType&>::value));
  204. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<MemberFn, const TestPtrType&>::value));
  205. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<MemberFn, TestPtrType&&>::value));
  206. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<MemberFn, DerivedTestPtrType&>::value));
  207. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<MemberFn, ConstTestPtrType&>::value));
  208. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<MemberFn, SharedTestPtrType&>::value));
  209. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<MemberFn, UniqueTestPtrType&>::value));
  210. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<MemberFn, TestPtrType, float>::value));
  211. }
  212. TEST_F(InvocableTest, FunctionObjectTest)
  213. {
  214. using RawFuncPtr = AZStd::string_view(*)(InvokeTestStruct, int);
  215. using RawFuncRef = AZStd::string_view(&)(InvokeTestStruct&, int);
  216. using FuncObject = InvokeTestDeletedS32Callable;
  217. using StdFunctionObject = AZStd::function<int(InvokeTestStruct&&)>;
  218. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<RawFuncPtr>::value));
  219. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<RawFuncPtr, InvokeTestStruct&>::value));
  220. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<RawFuncPtr, InvokeTestStruct&, int>::value));
  221. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<RawFuncPtr, InvokeTestDerivedStruct&, int>::value));
  222. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<RawFuncRef>::value));
  223. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<RawFuncRef, InvokeTestStruct&, int>::value));
  224. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<RawFuncRef, const InvokeTestStruct&, int>::value));
  225. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<RawFuncRef, InvokeTestDerivedStruct&, int>::value));
  226. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<FuncObject, AZ::s32>::value));
  227. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<FuncObject, InvokeTestStruct>::value));
  228. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable<StdFunctionObject, InvokeTestStruct&>::value));
  229. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable<StdFunctionObject, InvokeTestStruct&&>::value));
  230. }
  231. TEST_F(InvocableTest, Invocable_R_Test)
  232. {
  233. using Func = int(*)();
  234. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable_r<int, Func>::value));
  235. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable_r<double, Func>::value));
  236. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable_r<const volatile void, Func>::value));
  237. AZ_TEST_STATIC_ASSERT((AZStd::is_invocable_r<InvokeTestImplicitConstructor, Func>::value));
  238. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable_r<InvokeTestExplicitConstructor, Func>::value));
  239. AZ_TEST_STATIC_ASSERT((!AZStd::is_invocable_r<InvokeTestStruct, Func>::value));
  240. }
  241. class InvokeTest
  242. : public LeakDetectionFixture
  243. {
  244. protected:
  245. static int RawIntFunc(int num)
  246. {
  247. return num;
  248. }
  249. static int DoubleRValueIntValue(int&& num)
  250. {
  251. return num * 2;
  252. }
  253. public:
  254. static const int s_rawFuncResult;
  255. };
  256. const int InvokeTest::s_rawFuncResult = 24;
  257. template<typename FuncSig, typename ExpectResultType, typename Functor>
  258. void InvokeMemberFunctionTester(Functor&& functor, int expectResult)
  259. {
  260. using MemberFunc = FuncSig;
  261. MemberFunc memberFunc = &InvokeTestStruct::operator();
  262. InvokeNonCopyable nonCopyableArg;
  263. using DeducedResultType = decltype(AZStd::invoke(memberFunc, AZStd::forward<Functor>(functor), AZStd::move(nonCopyableArg)));
  264. AZ_TEST_STATIC_ASSERT((AZStd::is_same<ExpectResultType, DeducedResultType>::value));
  265. AZ_TEST_STATIC_ASSERT((AZStd::is_same<ExpectResultType, AZStd::invoke_result_t<MemberFunc, Functor, InvokeNonCopyable&&>>::value));
  266. auto result = AZStd::invoke(memberFunc, AZStd::forward<Functor>(functor), AZStd::move(nonCopyableArg));
  267. EXPECT_EQ(expectResult, result);
  268. };
  269. template<typename ExpectResultType, typename Functor>
  270. void InvokeMemberObjectTester(Functor&& functor, int expectResult)
  271. {
  272. auto memberObjPtr = &InvokeTestStruct::m_data;
  273. using DeducedResultType = decltype(AZStd::invoke(memberObjPtr, AZStd::forward<Functor>(functor)));
  274. AZ_TEST_STATIC_ASSERT((AZStd::is_same<ExpectResultType, DeducedResultType>::value));
  275. AZ_TEST_STATIC_ASSERT((AZStd::is_same<ExpectResultType, AZStd::invoke_result_t<decltype(memberObjPtr), Functor>>::value));
  276. auto result = AZStd::invoke(memberObjPtr, AZStd::forward<Functor>(functor));
  277. EXPECT_EQ(expectResult, result);
  278. };
  279. template<typename ExpectResultType, typename Functor>
  280. void InvokeFunctionObjectTester(Functor&& functor, int expectResult)
  281. {
  282. InvokeNonCopyable nonCopyableArg;
  283. using DeducedResultType = decltype(AZStd::invoke(AZStd::forward<Functor>(functor), AZStd::move(nonCopyableArg)));
  284. AZ_TEST_STATIC_ASSERT((AZStd::is_same<ExpectResultType, DeducedResultType>::value));
  285. AZ_TEST_STATIC_ASSERT((AZStd::is_same<ExpectResultType, AZStd::invoke_result_t<Functor, InvokeNonCopyable&&>>::value));
  286. auto result = AZStd::invoke(AZStd::forward<Functor>(functor), AZStd::move(nonCopyableArg));
  287. EXPECT_EQ(expectResult, result);
  288. };
  289. int InvokeRawFunc(InvokeNonCopyable&&)
  290. {
  291. return InvokeTest::s_rawFuncResult;
  292. }
  293. TEST_F(InvokeTest, MemberFunctionTest)
  294. {
  295. {
  296. // Bullet 1
  297. {
  298. InvokeTestStruct test(1);
  299. InvokeMemberFunctionTester<int& (InvokeTestStruct::*)(InvokeNonCopyable&&) &, int&>(test, test.m_data);
  300. InvokeMemberFunctionTester<const int& (InvokeTestStruct::*)(InvokeNonCopyable&&) const &, const int&>(test, test.m_data);
  301. InvokeMemberFunctionTester<volatile int& (InvokeTestStruct::*)(InvokeNonCopyable&&) volatile &, volatile int&>(test, test.m_data);
  302. InvokeMemberFunctionTester<const volatile int& (InvokeTestStruct::*)(InvokeNonCopyable&&) const volatile &, const volatile int&>(test, test.m_data);
  303. InvokeMemberFunctionTester<int&& (InvokeTestStruct::*)(InvokeNonCopyable&&) && , int&&>(AZStd::move(test), test.m_data);
  304. InvokeMemberFunctionTester<const int&& (InvokeTestStruct::*)(InvokeNonCopyable&&) const &&, const int&&>(AZStd::move(test), test.m_data);
  305. InvokeMemberFunctionTester<volatile int&& (InvokeTestStruct::*)(InvokeNonCopyable&&) volatile &&, volatile int&&>(AZStd::move(test), test.m_data);
  306. InvokeMemberFunctionTester<const volatile int&& (InvokeTestStruct::*)(InvokeNonCopyable&&) const volatile &&, const volatile int&&>(AZStd::move(test), test.m_data);
  307. }
  308. {
  309. InvokeTestDerivedStruct derivedTest(2);
  310. InvokeMemberFunctionTester<int& (InvokeTestStruct::*)(InvokeNonCopyable&&) &, int&>(derivedTest, derivedTest.m_data);
  311. InvokeMemberFunctionTester<const int& (InvokeTestStruct::*)(InvokeNonCopyable&&) const &, const int&>(derivedTest, derivedTest.m_data);
  312. InvokeMemberFunctionTester<volatile int& (InvokeTestStruct::*)(InvokeNonCopyable&&) volatile &, volatile int&>(derivedTest, derivedTest.m_data);
  313. InvokeMemberFunctionTester<const volatile int& (InvokeTestStruct::*)(InvokeNonCopyable&&) const volatile &, const volatile int&>(derivedTest, derivedTest.m_data);
  314. using MemberDerivedRFunc = int&& (InvokeTestDerivedStruct::*)(InvokeNonCopyable&&) &&;
  315. using MemberDerivedCRFunc = const int&& (InvokeTestDerivedStruct::*)(InvokeNonCopyable&&) const &&;
  316. using MemberDerivedVRFunc = volatile int&& (InvokeTestDerivedStruct::*)(InvokeNonCopyable&&) volatile&&;
  317. using MemberDerivedCVRFunc = const volatile int&& (InvokeTestDerivedStruct::*)(InvokeNonCopyable&&) const volatile&&;
  318. InvokeMemberFunctionTester<MemberDerivedRFunc, int&&>(AZStd::move(derivedTest), derivedTest.m_data);
  319. InvokeMemberFunctionTester<MemberDerivedCRFunc, const int&&>(AZStd::move(derivedTest), derivedTest.m_data);
  320. InvokeMemberFunctionTester<MemberDerivedVRFunc, volatile int&&>(AZStd::move(derivedTest), derivedTest.m_data);
  321. InvokeMemberFunctionTester<MemberDerivedCVRFunc, const volatile int&&>(AZStd::move(derivedTest), derivedTest.m_data);
  322. }
  323. }
  324. {
  325. // Bullet 2
  326. {
  327. InvokeTestStruct testObj(3);
  328. AZStd::reference_wrapper<InvokeTestStruct> test(testObj);
  329. InvokeMemberFunctionTester<int& (InvokeTestStruct::*)(InvokeNonCopyable&&) &, int&>(test, test.get().m_data);
  330. InvokeMemberFunctionTester<const int& (InvokeTestStruct::*)(InvokeNonCopyable&&) const &, const int&>(test, test.get().m_data);
  331. InvokeMemberFunctionTester<volatile int& (InvokeTestStruct::*)(InvokeNonCopyable&&) volatile &, volatile int&>(test, test.get().m_data);
  332. InvokeMemberFunctionTester<const volatile int& (InvokeTestStruct::*)(InvokeNonCopyable&&) const volatile &, const volatile int&>(test, test.get().m_data);
  333. InvokeMemberFunctionTester<int& (InvokeTestStruct::*)(InvokeNonCopyable&&) & , int&>(AZStd::move(test), test.get().m_data);
  334. InvokeMemberFunctionTester<const int& (InvokeTestStruct::*)(InvokeNonCopyable&&) const &, const int&>(AZStd::move(test), test.get().m_data);
  335. InvokeMemberFunctionTester<volatile int& (InvokeTestStruct::*)(InvokeNonCopyable&&) volatile &, volatile int&>(AZStd::move(test), test.get().m_data);
  336. InvokeMemberFunctionTester<const volatile int& (InvokeTestStruct::*)(InvokeNonCopyable&&) const volatile &, const volatile int&>(AZStd::move(test), test.get().m_data);
  337. }
  338. {
  339. InvokeTestDerivedStruct derivedTestObj(4);
  340. AZStd::reference_wrapper<InvokeTestDerivedStruct> derivedTest(derivedTestObj);
  341. InvokeMemberFunctionTester<int& (InvokeTestStruct::*)(InvokeNonCopyable&&) &, int&>(derivedTest, derivedTest.get().m_data);
  342. InvokeMemberFunctionTester<const int& (InvokeTestStruct::*)(InvokeNonCopyable&&) const &, const int&>(derivedTest, derivedTest.get().m_data);
  343. InvokeMemberFunctionTester<volatile int& (InvokeTestStruct::*)(InvokeNonCopyable&&) volatile &, volatile int&>(derivedTest, derivedTest.get().m_data);
  344. InvokeMemberFunctionTester<const volatile int& (InvokeTestStruct::*)(InvokeNonCopyable&&) const volatile &, const volatile int&>(derivedTest, derivedTest.get().m_data);
  345. InvokeMemberFunctionTester<int& (InvokeTestStruct::*)(InvokeNonCopyable&&) & , int&>(AZStd::move(derivedTest), derivedTest.get().m_data);
  346. InvokeMemberFunctionTester<const int& (InvokeTestStruct::*)(InvokeNonCopyable&&) const &, const int&>(AZStd::move(derivedTest), derivedTest.get().m_data);
  347. InvokeMemberFunctionTester<volatile int& (InvokeTestStruct::*)(InvokeNonCopyable&&) volatile &, volatile int&>(AZStd::move(derivedTest), derivedTest.get().m_data);
  348. InvokeMemberFunctionTester<const volatile int& (InvokeTestStruct::*)(InvokeNonCopyable&&) const volatile &, const volatile int&>(AZStd::move(derivedTest), derivedTest.get().m_data);
  349. }
  350. }
  351. {
  352. // Bullet 3
  353. {
  354. InvokeTestStruct testObj(5);
  355. InvokeTestStruct* test(&testObj);
  356. InvokeMemberFunctionTester<int& (InvokeTestStruct::*)(InvokeNonCopyable&&) &, int&>(test, test->m_data);
  357. InvokeMemberFunctionTester<const int& (InvokeTestStruct::*)(InvokeNonCopyable&&) const &, const int&>(test, test->m_data);
  358. InvokeMemberFunctionTester<volatile int& (InvokeTestStruct::*)(InvokeNonCopyable&&) volatile &, volatile int&>(test, test->m_data);
  359. InvokeMemberFunctionTester<const volatile int& (InvokeTestStruct::*)(InvokeNonCopyable&&) const volatile &, const volatile int&>(test, test->m_data);
  360. InvokeMemberFunctionTester<int& (InvokeTestStruct::*)(InvokeNonCopyable&&) & , int&>(AZStd::move(test), test->m_data);
  361. InvokeMemberFunctionTester<const int& (InvokeTestStruct::*)(InvokeNonCopyable&&) const &, const int&>(AZStd::move(test), test->m_data);
  362. InvokeMemberFunctionTester<volatile int& (InvokeTestStruct::*)(InvokeNonCopyable&&) volatile &, volatile int&>(AZStd::move(test), test->m_data);
  363. InvokeMemberFunctionTester<const volatile int& (InvokeTestStruct::*)(InvokeNonCopyable&&) const volatile &, const volatile int&>(AZStd::move(test), test->m_data);
  364. AZStd::unique_ptr<InvokeTestStruct> testUniquePtr(&testObj);
  365. InvokeMemberFunctionTester<int& (InvokeTestStruct::*)(InvokeNonCopyable&&) &, int&>(test, test->m_data);
  366. InvokeMemberFunctionTester<const int& (InvokeTestStruct::*)(InvokeNonCopyable&&) const &, const int&>(test, test->m_data);
  367. InvokeMemberFunctionTester<volatile int& (InvokeTestStruct::*)(InvokeNonCopyable&&) volatile &, volatile int&>(test, test->m_data);
  368. InvokeMemberFunctionTester<const volatile int& (InvokeTestStruct::*)(InvokeNonCopyable&&) const volatile &, const volatile int&>(test, test->m_data);
  369. testUniquePtr.release();
  370. }
  371. {
  372. InvokeTestDerivedStruct derivedTestObj(6);
  373. InvokeTestDerivedStruct* derivedTest(&derivedTestObj);
  374. InvokeMemberFunctionTester<int& (InvokeTestStruct::*)(InvokeNonCopyable&&) &, int&>(derivedTest, derivedTest->m_data);
  375. InvokeMemberFunctionTester<const int& (InvokeTestStruct::*)(InvokeNonCopyable&&) const &, const int&>(derivedTest, derivedTest->m_data);
  376. InvokeMemberFunctionTester<volatile int& (InvokeTestStruct::*)(InvokeNonCopyable&&) volatile &, volatile int&>(derivedTest, derivedTest->m_data);
  377. InvokeMemberFunctionTester<const volatile int& (InvokeTestStruct::*)(InvokeNonCopyable&&) const volatile &, const volatile int&>(derivedTest, derivedTest->m_data);
  378. InvokeMemberFunctionTester<int& (InvokeTestStruct::*)(InvokeNonCopyable&&) & , int&>(AZStd::move(derivedTest), derivedTest->m_data);
  379. InvokeMemberFunctionTester<const int& (InvokeTestStruct::*)(InvokeNonCopyable&&) const &, const int&>(AZStd::move(derivedTest), derivedTest->m_data);
  380. InvokeMemberFunctionTester<volatile int& (InvokeTestStruct::*)(InvokeNonCopyable&&) volatile &, volatile int&>(AZStd::move(derivedTest), derivedTest->m_data);
  381. InvokeMemberFunctionTester<const volatile int& (InvokeTestStruct::*)(InvokeNonCopyable&&) const volatile &, const volatile int&>(AZStd::move(derivedTest), derivedTest->m_data);
  382. }
  383. }
  384. }
  385. TEST_F(InvokeTest, MemberObjectTest)
  386. {
  387. {
  388. // Bullet 4
  389. {
  390. using TestStruct = InvokeTestStruct;
  391. TestStruct test(7);
  392. InvokeMemberObjectTester<int&>(test, test.m_data);
  393. InvokeMemberObjectTester<const int&>(static_cast<const TestStruct&>(test), test.m_data);
  394. InvokeMemberObjectTester<volatile int&>(static_cast<volatile TestStruct&>(test), test.m_data);
  395. InvokeMemberObjectTester<const volatile int&>(static_cast<const volatile TestStruct&>(test), test.m_data);
  396. InvokeMemberObjectTester<int&&>(static_cast<TestStruct&&>(test), test.m_data);
  397. InvokeMemberObjectTester<const int&&>(static_cast<const TestStruct&&>(test), test.m_data);
  398. InvokeMemberObjectTester<volatile int&&>(static_cast<volatile TestStruct&&>(test), test.m_data);
  399. InvokeMemberObjectTester<const volatile int&&>(static_cast<const volatile TestStruct&&>(test), test.m_data);
  400. }
  401. {
  402. using TestStruct = InvokeTestDerivedStruct;
  403. TestStruct test(8);
  404. InvokeMemberObjectTester<int&>(test, test.m_data);
  405. InvokeMemberObjectTester<const int&>(static_cast<const TestStruct&>(test), test.m_data);
  406. InvokeMemberObjectTester<volatile int&>(static_cast<volatile TestStruct&>(test), test.m_data);
  407. InvokeMemberObjectTester<const volatile int&>(static_cast<const volatile TestStruct&>(test), test.m_data);
  408. InvokeMemberObjectTester<int&&>(static_cast<TestStruct&&>(test), test.m_data);
  409. InvokeMemberObjectTester<const int&&>(static_cast<const TestStruct&&>(test), test.m_data);
  410. InvokeMemberObjectTester<volatile int&&>(static_cast<volatile TestStruct&&>(test), test.m_data);
  411. InvokeMemberObjectTester<const volatile int&&>(static_cast<const volatile TestStruct&&>(test), test.m_data);
  412. }
  413. }
  414. {
  415. // Bullet 5
  416. {
  417. using TestStruct = InvokeTestStruct;
  418. TestStruct testObj(9);
  419. InvokeMemberObjectTester<int&>(AZStd::reference_wrapper<TestStruct>(testObj), testObj.m_data);
  420. InvokeMemberObjectTester<const int&>(AZStd::reference_wrapper<const TestStruct>(testObj), testObj.m_data);
  421. InvokeMemberObjectTester<volatile int&>(AZStd::reference_wrapper<volatile TestStruct>(testObj), testObj.m_data);
  422. InvokeMemberObjectTester<const volatile int&>(AZStd::reference_wrapper<const volatile TestStruct>(testObj), testObj.m_data);
  423. }
  424. {
  425. using TestStruct = InvokeTestDerivedStruct;
  426. TestStruct testObj(10);
  427. InvokeMemberObjectTester<int&>(AZStd::reference_wrapper<TestStruct>(testObj), testObj.m_data);
  428. InvokeMemberObjectTester<const int&>(AZStd::reference_wrapper<const TestStruct>(testObj), testObj.m_data);
  429. InvokeMemberObjectTester<volatile int&>(AZStd::reference_wrapper<volatile TestStruct>(testObj), testObj.m_data);
  430. InvokeMemberObjectTester<const volatile int&>(AZStd::reference_wrapper<const volatile TestStruct>(testObj), testObj.m_data);
  431. }
  432. }
  433. {
  434. // Bullet 6
  435. {
  436. using TestStruct = InvokeTestStruct;
  437. TestStruct testObj(11);
  438. TestStruct* test(&testObj);
  439. const TestStruct* cTest(&testObj);
  440. volatile TestStruct* vTest(&testObj);
  441. const volatile TestStruct* cvTest(&testObj);
  442. InvokeMemberObjectTester<int&>(test, test->m_data);
  443. InvokeMemberObjectTester<const int&>(cTest, test->m_data);
  444. InvokeMemberObjectTester<volatile int&>(vTest, test->m_data);
  445. InvokeMemberObjectTester<const volatile int&>(cvTest, test->m_data);
  446. }
  447. {
  448. using TestStruct = InvokeTestDerivedStruct;
  449. TestStruct testObj(12);
  450. TestStruct* test(&testObj);
  451. InvokeMemberObjectTester<int&>(test, test->m_data);
  452. InvokeMemberObjectTester<const int&>(static_cast<const TestStruct*>(test), test->m_data);
  453. InvokeMemberObjectTester<volatile int&>(static_cast<volatile TestStruct*>(test), test->m_data);
  454. InvokeMemberObjectTester<const volatile int&>(static_cast<const volatile TestStruct*>(test), test->m_data);
  455. }
  456. }
  457. }
  458. TEST_F(InvokeTest, FunctionObjectTest)
  459. {
  460. // Bullet 7
  461. using RawFuncPtr = int(*)(InvokeNonCopyable&&);
  462. using RawFuncRef = int(&)(InvokeNonCopyable&&);
  463. RawFuncPtr testRawFuncPtr = &InvokeRawFunc;
  464. RawFuncRef testRawFuncRef = InvokeRawFunc;
  465. InvokeFunctionObjectTester<int>(testRawFuncPtr, InvokeTest::s_rawFuncResult);
  466. InvokeFunctionObjectTester<int>(testRawFuncRef, InvokeTest::s_rawFuncResult);
  467. AZStd::function<int(int)> testStdFunc = &RawIntFunc;
  468. int numResult = AZStd::invoke(testStdFunc, InvokeTest::s_rawFuncResult);
  469. EXPECT_EQ(InvokeTest::s_rawFuncResult, numResult);
  470. AZStd::function<int(int&&)> testStdFuncWithRValueParam = &DoubleRValueIntValue;
  471. numResult = AZStd::invoke(testStdFuncWithRValueParam, 520);
  472. EXPECT_EQ(1040, numResult);
  473. InvokeTestStruct testFunctor(13);
  474. InvokeFunctionObjectTester<int&>(testFunctor, testFunctor.m_data);
  475. InvokeFunctionObjectTester<const int&>(static_cast<const InvokeTestStruct&>(testFunctor), testFunctor.m_data);
  476. InvokeFunctionObjectTester<volatile int&>(static_cast<volatile InvokeTestStruct&>(testFunctor), testFunctor.m_data);
  477. InvokeFunctionObjectTester<const volatile int&>(static_cast<const volatile InvokeTestStruct&>(testFunctor), testFunctor.m_data);
  478. InvokeFunctionObjectTester<int&&>(static_cast<InvokeTestStruct&&>(testFunctor), testFunctor.m_data);
  479. InvokeFunctionObjectTester<const int&&>(static_cast<const InvokeTestStruct&&>(testFunctor), testFunctor.m_data);
  480. InvokeFunctionObjectTester<volatile int&&>(static_cast<volatile InvokeTestStruct&&>(testFunctor), testFunctor.m_data);
  481. InvokeFunctionObjectTester<const volatile int&&>(static_cast<const volatile InvokeTestStruct&&>(testFunctor), testFunctor.m_data);
  482. }
  483. }