Tuple.cpp 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509
  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/string/string_view.h>
  13. #include <AzCore/std/smart_ptr/unique_ptr.h>
  14. #include <AzCore/std/tuple.h>
  15. #include "UserTypes.h"
  16. namespace UnitTest
  17. {
  18. template<class T1, class T2>
  19. std::pair<T1, T2> to_std_pair(const AZStd::pair<T1, T2>& azPair)
  20. {
  21. return std::make_pair(azPair.first, azPair.second);
  22. }
  23. template<class T1, class T2>
  24. std::pair<T1, T2> to_std_pair(AZStd::pair<T1, T2>&& azPair)
  25. {
  26. return std::make_pair(AZStd::move(azPair.first), AZStd::move(azPair.second));
  27. }
  28. //////////////////////////////////////////////////////////////////////////
  29. // Fixtures
  30. // Fixture for non-typed tests
  31. class TupleTest
  32. : public LeakDetectionFixture
  33. {
  34. protected:
  35. struct MoveOnlyType
  36. {
  37. AZ_CLASS_ALLOCATOR(MoveOnlyType, AZ::SystemAllocator);
  38. MoveOnlyType() = delete;
  39. MoveOnlyType(AZStd::tuple<AZ::s32&&, AZStd::string_view&&> tuplePair)
  40. : m_valueInt(AZStd::move(AZStd::get<0>(tuplePair)))
  41. , m_constString(AZStd::move(AZStd::get<1>(tuplePair)))
  42. {
  43. }
  44. AZ::s32 m_valueInt;
  45. AZStd::string_view m_constString;
  46. };
  47. };
  48. // Fixture for typed tests
  49. template<typename Tuple>
  50. class TupleTypedTest
  51. : public LeakDetectionFixture
  52. {
  53. };
  54. using TupleTestTypes = ::testing::Types<
  55. AZStd::tuple<>,
  56. AZStd::tuple<AZStd::unordered_map<AZStd::string, AZStd::string_view>>,
  57. AZStd::tuple<int, float, AZStd::string>,
  58. AZStd::tuple<int, float, int>,
  59. AZStd::tuple<bool, bool, bool, bool>
  60. >;
  61. TYPED_TEST_SUITE(TupleTypedTest, TupleTestTypes);
  62. //////////////////////////////////////////////////////////////////////////
  63. // Tests for constructors
  64. namespace Constructor
  65. {
  66. // Construct empty
  67. TEST_F(TupleTest, DefaultConstruct)
  68. {
  69. AZStd::tuple<AZStd::string, float, AZStd::vector<int>> testTuple;
  70. EXPECT_TRUE(AZStd::get<0>(testTuple).empty());
  71. EXPECT_FLOAT_EQ(0.0f, AZStd::get<1>(testTuple));
  72. EXPECT_TRUE(AZStd::get<2>(testTuple).empty());
  73. }
  74. TEST_F(TupleTest, InitializerConstruct)
  75. {
  76. AZStd::tuple<AZStd::string, float> testTuple{ AZStd::string("Test"), 4.0f };
  77. EXPECT_EQ("Test", AZStd::get<0>(testTuple));
  78. EXPECT_FLOAT_EQ(4.0f, AZStd::get<1>(testTuple));
  79. }
  80. TEST_F(TupleTest, ConvertingConstruct)
  81. {
  82. AZStd::tuple<AZStd::string, AZStd::array<AZStd::string_view, 2U>> testTuple("Test", { { "Arg1", "Arg2" } });
  83. EXPECT_EQ("Test", AZStd::get<0>(testTuple));
  84. EXPECT_EQ(2, AZStd::get<1>(testTuple).size());
  85. EXPECT_EQ("Arg1", AZStd::get<1>(testTuple)[0]);
  86. EXPECT_EQ("Arg2", AZStd::get<1>(testTuple)[1]);
  87. }
  88. TEST_F(TupleTest, PairCopyConstruct)
  89. {
  90. AZStd::vector<AZStd::string> testStringVector{ "Test1", "Test2" };
  91. auto testPair = std::make_pair(AZStd::string("Test"), AZStd::vector<AZStd::string>{ "Test1", "Test2" });
  92. AZStd::tuple<AZStd::string, AZStd::vector<AZStd::string>> testTuple(testPair);
  93. EXPECT_EQ(testPair.first, AZStd::get<0>(testTuple));
  94. EXPECT_EQ(testPair.second, AZStd::get<1>(testTuple));
  95. }
  96. TEST_F(TupleTest, PairMoveConstruct)
  97. {
  98. AZStd::vector<AZStd::string> testStringVector{ "Test1", "Test2" };
  99. auto testPair = std::make_pair(AZStd::string("Test"), testStringVector);
  100. AZStd::tuple<AZStd::string, AZStd::vector<AZStd::string>> testTuple(AZStd::move(testPair));
  101. EXPECT_EQ("Test", AZStd::get<0>(testTuple));
  102. EXPECT_EQ(testStringVector, AZStd::get<1>(testTuple));
  103. }
  104. TEST_F(TupleTest, TupleCopyConstruct)
  105. {
  106. AZStd::tuple<AZStd::string, double, AZStd::vector<int>> testTuple("Test", 16.0, AZStd::vector<int>{5});
  107. AZStd::tuple<AZStd::string, double, AZStd::vector<int>> copyTuple(testTuple);
  108. EXPECT_EQ(testTuple, copyTuple);
  109. }
  110. TEST_F(TupleTest, TupleMoveConstruct)
  111. {
  112. AZStd::tuple<AZStd::string, double, AZStd::vector<int>> testTuple("Test", 16.0, AZStd::vector<int>{5});
  113. AZStd::tuple<AZStd::string, double, AZStd::vector<int>> moveTuple(testTuple);
  114. EXPECT_EQ("Test", AZStd::get<0>(moveTuple));
  115. EXPECT_EQ(16.0, AZStd::get<1>(moveTuple));
  116. EXPECT_EQ(AZStd::vector<int>{5}, AZStd::get<2>(moveTuple));
  117. }
  118. }
  119. //////////////////////////////////////////////////////////////////////////
  120. // Tests for assignment operator
  121. namespace Assignment
  122. {
  123. // Test copy assign
  124. TEST_F(TupleTest, CopyAssignTest)
  125. {
  126. AZStd::tuple<AZStd::any> source(AZStd::make_any<AZStd::string>("Test"));
  127. AZStd::tuple<AZStd::any> dest;
  128. EXPECT_TRUE(AZStd::get<0>(source).is<AZStd::string>());
  129. EXPECT_EQ("Test", AZStd::any_cast<AZStd::string>(AZStd::get<0>(source)));
  130. EXPECT_TRUE(AZStd::get<0>(dest).empty());
  131. dest = source;
  132. EXPECT_TRUE(AZStd::get<0>(dest).is<AZStd::string>());
  133. EXPECT_EQ(AZStd::any_cast<AZStd::string>(AZStd::get<0>(source)), AZStd::any_cast<AZStd::string>(AZStd::get<0>(dest)));
  134. }
  135. // Test move assign
  136. TEST_F(TupleTest, MoveAssignTest)
  137. {
  138. AZStd::tuple<AZStd::any> source(AZStd::make_any<AZStd::string>("Test"));
  139. AZStd::tuple<AZStd::any> dest;
  140. EXPECT_TRUE(AZStd::get<0>(source).is<AZStd::string>());
  141. EXPECT_EQ("Test", AZStd::any_cast<AZStd::string>(AZStd::get<0>(source)));
  142. EXPECT_TRUE(AZStd::get<0>(dest).empty());
  143. dest = AZStd::move(source);
  144. EXPECT_TRUE(AZStd::get<0>(source).empty());
  145. EXPECT_FALSE(AZStd::get<0>(dest).empty());
  146. }
  147. }
  148. namespace FreeFunctions
  149. {
  150. TEST_F(TupleTest, MakeTupleTest)
  151. {
  152. auto testTuple = AZStd::make_tuple(AZStd::string("Test"), AZStd::make_unique<AZStd::string>("UniqueTest"));
  153. EXPECT_EQ("Test", AZStd::get<0>(testTuple));
  154. ASSERT_NE(nullptr, AZStd::get<1>(testTuple));
  155. EXPECT_EQ("UniqueTest", *AZStd::get<1>(testTuple));
  156. }
  157. TEST_F(TupleTest, TieTest)
  158. {
  159. int valueInt = 0;
  160. double valueDouble = 0.0;
  161. auto testTuple = AZStd::make_tuple(17, 42.52);
  162. AZStd::tie(valueInt, valueDouble) = testTuple;
  163. EXPECT_EQ(17, valueInt);
  164. EXPECT_DOUBLE_EQ(valueDouble, 42.52);
  165. auto ignoreTuple = AZStd::make_tuple(true, 1, 15.0f);
  166. bool valueBool = false;
  167. AZStd::tie(valueBool, AZStd::ignore, AZStd::ignore) = ignoreTuple;
  168. EXPECT_TRUE(valueBool);
  169. }
  170. TEST_F(TupleTest, ForwardAsTupleTest)
  171. {
  172. MoveOnlyType testResult(AZStd::forward_as_tuple(15, AZStd::string_view("LinkerLiteral")));
  173. EXPECT_EQ(15, testResult.m_valueInt);
  174. EXPECT_EQ("LinkerLiteral", testResult.m_constString);
  175. }
  176. TEST_F(TupleTest, TupleCatTest)
  177. {
  178. AZStd::tuple<int, float, double> intFloatDoubleTuple{ 1, 2.0f, 4.0 };
  179. AZStd::tuple<> emptyTuple;
  180. AZStd::tuple<AZStd::string, AZStd::string> stringStringTuple("First", "Second");
  181. auto resultTuple = AZStd::tuple_cat(intFloatDoubleTuple, emptyTuple, stringStringTuple);
  182. EXPECT_EQ(5, AZStd::tuple_size<decltype(resultTuple)>::value);
  183. }
  184. TEST_F(TupleTest, TupleGetTest)
  185. {
  186. AZStd::tuple<int, float, double> intFloatDoubleTuple{ 1, 2.0f, 4.0 };
  187. EXPECT_EQ(AZStd::get<0>(intFloatDoubleTuple), AZStd::get<int>(intFloatDoubleTuple));
  188. EXPECT_EQ(AZStd::get<1>(intFloatDoubleTuple), AZStd::get<float>(intFloatDoubleTuple));
  189. EXPECT_EQ(AZStd::get<2>(intFloatDoubleTuple), AZStd::get<double>(intFloatDoubleTuple));
  190. const AZStd::tuple<AZStd::string, float, int> stringFloatIntTuple("Test", 2.0f, 8);
  191. EXPECT_EQ(AZStd::get<0>(stringFloatIntTuple), AZStd::get<AZStd::string>(stringFloatIntTuple));
  192. EXPECT_EQ(AZStd::get<1>(stringFloatIntTuple), AZStd::get<float>(stringFloatIntTuple));
  193. EXPECT_EQ(AZStd::get<2>(stringFloatIntTuple), AZStd::get<int>(stringFloatIntTuple));
  194. AZStd::tuple<AZStd::string, bool, AZStd::string> rValueTuple("FirstTest", false, "SecondTest");
  195. EXPECT_EQ(AZStd::get<1>(AZStd::move(rValueTuple)), AZStd::get<bool>(AZStd::move(rValueTuple)));
  196. // Type template version of get is only supported for types that are in the template exactly once
  197. // It is a static assert to attempt to access an element using AZStd::get<AZStd::string> as there are two of those types in the tuple
  198. EXPECT_NE(AZStd::get<0>(AZStd::move(AZStd::move(rValueTuple))), AZStd::get<2>(AZStd::move(rValueTuple)));
  199. }
  200. TEST_F(TupleTest, TupleHashTest)
  201. {
  202. AZStd::string testString("Test1");
  203. AZStd::string superDuperString("SuperDuperString");
  204. AZStd::unordered_map<AZStd::tuple<AZStd::string, int, bool>, AZStd::string> tupleToBoolMap;
  205. tupleToBoolMap.emplace(AZStd::make_tuple(testString, 234, true), "MappedValue");
  206. tupleToBoolMap.insert({ AZStd::make_tuple(superDuperString, -8345, false), "SecondHallPass" });
  207. EXPECT_EQ(2, tupleToBoolMap.size());
  208. auto foundIt = tupleToBoolMap.find(AZStd::make_tuple(testString, 234, true));
  209. ASSERT_NE(tupleToBoolMap.end(), foundIt);
  210. EXPECT_EQ("MappedValue", foundIt->second);
  211. foundIt = tupleToBoolMap.find(AZStd::make_tuple(superDuperString, -8345, false));
  212. ASSERT_NE(tupleToBoolMap.end(), foundIt);
  213. EXPECT_EQ("SecondHallPass", foundIt->second);
  214. // Not found case
  215. foundIt = tupleToBoolMap.find(AZStd::make_tuple(superDuperString, -8345, true));
  216. EXPECT_EQ(tupleToBoolMap.end(), foundIt);
  217. foundIt = tupleToBoolMap.find(AZStd::make_tuple(superDuperString, -8344, false));
  218. EXPECT_EQ(tupleToBoolMap.end(), foundIt);
  219. foundIt = tupleToBoolMap.find(AZStd::make_tuple("SuperDuperString1", -8345, false));
  220. EXPECT_EQ(tupleToBoolMap.end(), foundIt);
  221. }
  222. }
  223. namespace AssignTest
  224. {
  225. struct BaseIntWrapper
  226. {
  227. explicit BaseIntWrapper(AZ::s32 num = 0) : m_num(num) {}
  228. virtual ~BaseIntWrapper() = default;
  229. AZ::s32 m_num;
  230. };
  231. struct DerivedIntWrapper
  232. : BaseIntWrapper
  233. {
  234. explicit DerivedIntWrapper(AZ::s32 num = 0) : BaseIntWrapper(num) {}
  235. };
  236. struct IntAssignWrapper
  237. {
  238. IntAssignWrapper() = default;
  239. IntAssignWrapper& operator=(int)
  240. {
  241. return *this;
  242. }
  243. };
  244. TEST_F(TupleTest, CopyPair_AssignTest)
  245. {
  246. AZStd::pair<AZ::s64, char> pair0(2U, 'a');
  247. AZStd::tuple<AZ::s64, AZ::s16> tuple0;
  248. tuple0 = to_std_pair(pair0);
  249. EXPECT_EQ(2U, AZStd::get<0>(tuple0));
  250. EXPECT_EQ(AZ::s16('a'), AZStd::get<1>(tuple0));
  251. }
  252. TEST_F(TupleTest, MovePair_AssignTest)
  253. {
  254. AZStd::pair<AZ::s64, AZStd::unique_ptr<DerivedIntWrapper>> pair0(2U, AZStd::make_unique<DerivedIntWrapper>(3));
  255. AZStd::tuple<AZ::s64, AZStd::unique_ptr<BaseIntWrapper>> tuple0;
  256. tuple0 = to_std_pair(AZStd::move(pair0));
  257. EXPECT_EQ(2U, AZStd::get<0>(tuple0));
  258. EXPECT_EQ(3, AZStd::get<1>(tuple0)->m_num);
  259. }
  260. TEST_F(TupleTest, ConversionCopy_AssignTest)
  261. {
  262. {
  263. AZStd::tuple<AZ::s32> tuple0(2U);
  264. AZStd::tuple<AZ::s64> tuple1;
  265. tuple1 = tuple0;
  266. EXPECT_EQ(2U, AZStd::get<0>(tuple1));
  267. }
  268. {
  269. AZStd::tuple<AZ::s32, char> tuple0(2U, 'a');
  270. AZStd::tuple<AZ::s64, AZ::s32> tuple1;
  271. tuple1 = tuple0;
  272. EXPECT_EQ(2U, AZStd::get<0>(tuple1));
  273. EXPECT_EQ(AZ::s32('a'), AZStd::get<1>(tuple1));
  274. }
  275. {
  276. AZStd::tuple<AZ::s32, char, DerivedIntWrapper> tuple0(2U, 'a', DerivedIntWrapper(3));
  277. AZStd::tuple<AZ::s64, AZ::s32, BaseIntWrapper> tuple1;
  278. tuple1 = tuple0;
  279. EXPECT_EQ(2U, AZStd::get<0>(tuple1));
  280. EXPECT_EQ(AZ::s32('a'), AZStd::get<1>(tuple1));
  281. EXPECT_EQ(3, AZStd::get<2>(tuple1).m_num);
  282. }
  283. {
  284. DerivedIntWrapper derived0(3);
  285. DerivedIntWrapper derived1(2);
  286. AZStd::tuple<AZ::s32, char, DerivedIntWrapper&> tuple0(2U, 'a', derived1);
  287. AZStd::tuple<AZ::s64, AZ::s32, BaseIntWrapper&> tuple1(1, 'b', derived0);
  288. tuple1 = tuple0;
  289. EXPECT_EQ(2U, AZStd::get<0>(tuple1));
  290. EXPECT_EQ(AZ::s32('a'), AZStd::get<1>(tuple1));
  291. EXPECT_EQ(2, AZStd::get<2>(tuple1).m_num);
  292. }
  293. {
  294. AZ::s32 x = 42;
  295. AZ::s32 y = 43;
  296. AZStd::tuple<AZ::s32&&> tuple0(AZStd::move(x));
  297. AZStd::tuple<AZ::s32&> tuple1(y);
  298. tuple0 = tuple1;
  299. EXPECT_EQ(43, AZStd::get<0>(tuple0));
  300. EXPECT_EQ(&x, &AZStd::get<0>(tuple0));
  301. }
  302. }
  303. TEST_F(TupleTest, ConversionMove_AssignTest)
  304. {
  305. {
  306. AZStd::tuple<AZ::s32> tuple0(2U);
  307. AZStd::tuple<AZ::s64> tuple1;
  308. tuple1 = AZStd::move(tuple0);
  309. EXPECT_EQ(2U, AZStd::get<0>(tuple1));
  310. }
  311. {
  312. AZStd::tuple<AZ::s32, char> tuple0(2U, 'a');
  313. AZStd::tuple<AZ::s64, AZ::s32> tuple1;
  314. tuple1 = AZStd::move(tuple0);
  315. EXPECT_EQ(2U, AZStd::get<0>(tuple1));
  316. EXPECT_EQ(AZ::s32('a'), AZStd::get<1>(tuple1));
  317. }
  318. {
  319. AZStd::tuple<AZ::s32, char, DerivedIntWrapper> tuple0(2U, 'a', DerivedIntWrapper(3));
  320. AZStd::tuple<AZ::s64, AZ::s32, BaseIntWrapper> tuple1;
  321. tuple1 = AZStd::move(tuple0);
  322. EXPECT_EQ(2U, AZStd::get<0>(tuple1));
  323. EXPECT_EQ(AZ::s32('a'), AZStd::get<1>(tuple1));
  324. EXPECT_EQ(3, AZStd::get<2>(tuple1).m_num);
  325. }
  326. {
  327. DerivedIntWrapper derived0(3);
  328. DerivedIntWrapper derived1(2);
  329. AZStd::tuple<AZ::s32, char, DerivedIntWrapper&> tuple0(2U, 'a', derived1);
  330. AZStd::tuple<AZ::s64, AZ::s32, BaseIntWrapper&> tuple1(1, 'b', derived0);
  331. tuple1 = AZStd::move(tuple0);
  332. EXPECT_EQ(2U, AZStd::get<0>(tuple1));
  333. EXPECT_EQ(AZ::s32('a'), AZStd::get<1>(tuple1));
  334. EXPECT_EQ(2, AZStd::get<2>(tuple1).m_num);
  335. }
  336. {
  337. AZStd::tuple<AZ::s32, char, AZStd::unique_ptr<DerivedIntWrapper>> tuple0(2U, 'a', AZStd::make_unique<DerivedIntWrapper>(3));
  338. AZStd::tuple<AZ::s64, AZ::s32, AZStd::unique_ptr<BaseIntWrapper>> tuple1;
  339. tuple1 = AZStd::move(tuple0);
  340. EXPECT_EQ(2U, AZStd::get<0>(tuple1));
  341. EXPECT_EQ(AZ::s32('a'), AZStd::get<1>(tuple1));
  342. EXPECT_EQ(3, AZStd::get<2>(tuple1)->m_num);
  343. }
  344. {
  345. AZ::s32 x = 42;
  346. AZ::s32 y = 43;
  347. AZStd::tuple<AZ::s32&&, IntAssignWrapper> tuple0(AZStd::move(x), IntAssignWrapper{});
  348. AZStd::tuple<AZ::s32&&, AZ::s32> tuple1(AZStd::move(y), 44);
  349. tuple0 = AZStd::move(tuple1);
  350. EXPECT_EQ(43, AZStd::get<0>(tuple0));
  351. EXPECT_EQ(&x, &AZStd::get<0>(tuple0));
  352. }
  353. }
  354. struct NonAssignable
  355. {
  356. private:
  357. NonAssignable& operator=(const NonAssignable&) = delete;
  358. NonAssignable& operator=(NonAssignable&&) = delete;
  359. };
  360. struct CopyAssignable
  361. {
  362. CopyAssignable& operator=(const CopyAssignable&) = default;
  363. CopyAssignable& operator=(CopyAssignable&&) = delete;
  364. };
  365. AZ_TEST_STATIC_ASSERT((AZStd::is_copy_assignable<CopyAssignable>::value));
  366. struct MoveAssignable
  367. {
  368. MoveAssignable& operator=(MoveAssignable&&) { return *this; }
  369. private:
  370. MoveAssignable& operator=(const MoveAssignable&) = delete;
  371. };
  372. TEST_F(TupleTest, Copy_AssignTest)
  373. {
  374. {
  375. AZStd::tuple<AZ::s32> t0(2);
  376. AZStd::tuple<AZ::s32> t;
  377. t = t0;
  378. EXPECT_EQ(2, AZStd::get<0>(t));
  379. }
  380. {
  381. AZStd::tuple<AZ::s32, char> t0(2, 'a');
  382. AZStd::tuple<AZ::s32, char> t;
  383. t = t0;
  384. EXPECT_EQ(2, AZStd::get<0>(t));
  385. EXPECT_EQ('a', AZStd::get<1>(t));
  386. }
  387. {
  388. using T = AZStd::tuple<AZ::s32, char, AZStd::string>;
  389. const T t0(2, 'a', "some text");
  390. T t;
  391. t = t0;
  392. EXPECT_EQ(2, AZStd::get<0>(t));
  393. EXPECT_EQ('a', AZStd::get<1>(t));
  394. EXPECT_EQ("some text", AZStd::get<2>(t));
  395. }
  396. {
  397. // test reference assignment.
  398. using T = AZStd::tuple<AZ::s32&, AZ::s32&&>;
  399. AZ::s32 x = 42;
  400. AZ::s32 y = 100;
  401. AZ::s32 x2 = -1;
  402. AZ::s32 y2 = 500;
  403. T t(x, AZStd::move(y));
  404. T t2(x2, AZStd::move(y2));
  405. t = t2;
  406. EXPECT_EQ(x2, AZStd::get<0>(t));
  407. EXPECT_EQ(&x, &AZStd::get<0>(t));
  408. EXPECT_EQ(y2, AZStd::get<1>(t));
  409. EXPECT_EQ(&y, &AZStd::get<1>(t));
  410. }
  411. }
  412. struct CountAssign
  413. {
  414. CountAssign() = default;
  415. CountAssign& operator=(const CountAssign &)
  416. {
  417. ++copied;
  418. return *this;
  419. }
  420. CountAssign& operator=(CountAssign&&)
  421. {
  422. ++moved;
  423. return *this;
  424. }
  425. static void reset()
  426. {
  427. copied = moved = 0;
  428. }
  429. static AZ::s32 copied;
  430. static AZ::s32 moved;
  431. };
  432. AZ::s32 CountAssign::copied = 0;
  433. AZ::s32 CountAssign::moved = 0;
  434. struct MoveOnly
  435. {
  436. MoveOnly() = default;
  437. MoveOnly(const MoveOnly&) = delete;
  438. MoveOnly(MoveOnly&& other) : m_num(AZStd::move(other.m_num)) {}
  439. MoveOnly& operator=(MoveOnly&& other)
  440. {
  441. m_num = other.m_num;
  442. return *this;
  443. }
  444. MoveOnly(AZ::s32 num) : m_num(num) {}
  445. friend bool operator==(AZ::s32 lhs, const MoveOnly& rhs) { return lhs == rhs.m_num; }
  446. friend bool operator==(const MoveOnly& lhs, AZ::s32 rhs) { return lhs.m_num == rhs; }
  447. AZ::s32 m_num;
  448. };
  449. TEST_F(TupleTest, Move_AssignTest)
  450. {
  451. {
  452. using T = AZStd::tuple<>;
  453. T t0;
  454. T t;
  455. t = AZStd::move(t0);
  456. }
  457. {
  458. using T = AZStd::tuple<MoveOnly>;
  459. T t0(MoveOnly(0));
  460. T t;
  461. t = AZStd::move(t0);
  462. EXPECT_EQ(0, AZStd::get<0>(t));
  463. }
  464. {
  465. using T = AZStd::tuple<MoveOnly, MoveOnly>;
  466. T t0(MoveOnly(0), MoveOnly(1));
  467. T t;
  468. t = AZStd::move(t0);
  469. EXPECT_EQ(0, AZStd::get<0>(t));
  470. EXPECT_EQ(1, AZStd::get<1>(t));
  471. }
  472. {
  473. using T = AZStd::tuple<MoveOnly, MoveOnly, MoveOnly>;
  474. T t0(MoveOnly(0), MoveOnly(1), MoveOnly(2));
  475. T t;
  476. t = AZStd::move(t0);
  477. EXPECT_EQ(0, AZStd::get<0>(t));
  478. EXPECT_EQ(1, AZStd::get<1>(t));
  479. EXPECT_EQ(2, AZStd::get<2>(t));
  480. }
  481. {
  482. // test reference assignment.
  483. using T = AZStd::tuple<AZ::s32&, AZ::s32&&>;
  484. AZ::s32 x = 42;
  485. AZ::s32 y = 100;
  486. AZ::s32 x2 = -1;
  487. AZ::s32 y2 = 500;
  488. T t(x, AZStd::move(y));
  489. T t2(x2, AZStd::move(y2));
  490. t = AZStd::move(t2);
  491. EXPECT_EQ(x2, AZStd::get<0>(t));
  492. EXPECT_EQ(&x, &AZStd::get<0>(t));
  493. EXPECT_EQ(y2, AZStd::get<1>(t));
  494. EXPECT_EQ(&y, &AZStd::get<1>(t));
  495. }
  496. {
  497. // test reference assignment.
  498. using T = AZStd::tuple<AZ::s32&, AZ::s32&&>;
  499. AZ::s32 x = 42;
  500. AZ::s32 y = 100;
  501. AZ::s32 x2 = -1;
  502. AZ::s32 y2 = 500;
  503. T t(x, AZStd::move(y));
  504. T t2(x2, AZStd::move(y2));
  505. t = AZStd::move(t2);
  506. EXPECT_EQ(x2, AZStd::get<0>(t));
  507. EXPECT_EQ(&x, &AZStd::get<0>(t));
  508. EXPECT_EQ(y2, AZStd::get<1>(t));
  509. EXPECT_EQ(&y, &AZStd::get<1>(t));
  510. }
  511. }
  512. }
  513. namespace ConstructTest
  514. {
  515. struct Empty {};
  516. struct Explicit
  517. {
  518. explicit Explicit(AZ::s32 x) : m_value(x) {}
  519. AZ::s32 m_value;
  520. };
  521. struct Implicit
  522. {
  523. Implicit(AZ::s32 x) : m_value(x) {}
  524. int m_value;
  525. };
  526. struct BaseIntWrapper
  527. {
  528. BaseIntWrapper(AZ::s32 num = 0) : m_num(num) {}
  529. virtual ~BaseIntWrapper() = default;
  530. AZ::s32 m_num;
  531. };
  532. struct DerivedIntWrapper
  533. : BaseIntWrapper
  534. {
  535. explicit DerivedIntWrapper(AZ::s32 num = 0) : BaseIntWrapper(num) {}
  536. };
  537. struct IntAssignWrapper
  538. {
  539. IntAssignWrapper() = default;
  540. IntAssignWrapper& operator=(int)
  541. {
  542. return *this;
  543. }
  544. };
  545. struct DefaultOnly
  546. {
  547. DefaultOnly() = default;
  548. friend bool operator==(const DefaultOnly&, const DefaultOnly&) { return true; }
  549. };
  550. struct NoDefault
  551. {
  552. private:
  553. NoDefault() = delete;
  554. public:
  555. explicit NoDefault(int) {}
  556. };
  557. struct IllFormedDefault
  558. {
  559. IllFormedDefault(AZ::s32 x) : value(x) {}
  560. template <bool Pred = false>
  561. IllFormedDefault()
  562. {
  563. AZ_TEST_STATIC_ASSERT(Pred);
  564. }
  565. AZ::s32 value;
  566. };
  567. struct ConstructsWithTupleLeaf
  568. {
  569. ConstructsWithTupleLeaf() {}
  570. ConstructsWithTupleLeaf(const ConstructsWithTupleLeaf &) { GTEST_NONFATAL_FAILURE_("Copy Constructor should not be invoked"); }
  571. ConstructsWithTupleLeaf(ConstructsWithTupleLeaf &&) {}
  572. template <class T>
  573. ConstructsWithTupleLeaf(T)
  574. {
  575. static_assert((!AZStd::is_same<T, T>::value), "Constructor instantiated for type other than int");
  576. }
  577. };
  578. struct MoveOnly
  579. {
  580. MoveOnly() = default;
  581. MoveOnly(const MoveOnly&) = delete;
  582. MoveOnly(MoveOnly&& other) : m_num(AZStd::move(other.m_num)) {}
  583. MoveOnly& operator=(MoveOnly&& other)
  584. {
  585. m_num = other.m_num;
  586. return *this;
  587. }
  588. MoveOnly(AZ::s32 num) : m_num(num) {}
  589. friend bool operator==(AZ::s32 lhs, const MoveOnly& rhs) { return lhs == rhs.m_num; }
  590. friend bool operator==(const MoveOnly& lhs, AZ::s32 rhs) { return lhs.m_num == rhs; }
  591. AZ::s32 m_num;
  592. };
  593. struct ImplicitConstexpr
  594. {
  595. constexpr ImplicitConstexpr(int i) : m_num(i) {}
  596. friend constexpr bool operator==(const ImplicitConstexpr& x, const ImplicitConstexpr& y) { return x.m_num == y.m_num; }
  597. int m_num;
  598. };
  599. struct ExplicitConstexpr
  600. {
  601. constexpr explicit ExplicitConstexpr(int i) : m_num(i) {}
  602. friend constexpr bool operator==(const ExplicitConstexpr& x, const ExplicitConstexpr& y) { return x.m_num == y.m_num; }
  603. int m_num;
  604. };
  605. TEST_F(TupleTest, Default_ConstructTest)
  606. {
  607. {
  608. AZStd::tuple<> t;
  609. (void)t;
  610. }
  611. {
  612. AZStd::tuple<AZ::s32> t;
  613. EXPECT_EQ(0, AZStd::get<0>(t));
  614. }
  615. {
  616. AZStd::tuple<AZ::s32, char*> t;
  617. EXPECT_EQ(0, AZStd::get<0>(t));
  618. EXPECT_EQ(nullptr, AZStd::get<1>(t));
  619. }
  620. {
  621. AZStd::tuple<AZ::s32, char*, AZStd::string> t;
  622. EXPECT_EQ(0, AZStd::get<0>(t));
  623. EXPECT_EQ(nullptr, AZStd::get<1>(t));
  624. EXPECT_EQ("", AZStd::get<2>(t));
  625. }
  626. {
  627. AZStd::tuple<AZ::s32, char*, AZStd::string, DefaultOnly> t;
  628. EXPECT_EQ(0, AZStd::get<0>(t));
  629. EXPECT_EQ(nullptr, AZStd::get<1>(t));
  630. EXPECT_EQ("", AZStd::get<2>(t));
  631. EXPECT_EQ(DefaultOnly(), AZStd::get<3>(t));
  632. }
  633. {
  634. AZ_TEST_STATIC_ASSERT((!std::is_default_constructible<AZStd::tuple<NoDefault>>::value));
  635. AZ_TEST_STATIC_ASSERT((!std::is_default_constructible<AZStd::tuple<DefaultOnly, NoDefault>>::value));
  636. AZ_TEST_STATIC_ASSERT((!std::is_default_constructible<AZStd::tuple<NoDefault, DefaultOnly, NoDefault>>::value));
  637. }
  638. {
  639. const AZStd::tuple<> t;
  640. (void)t;
  641. }
  642. {
  643. const AZStd::tuple<AZ::s32> t;
  644. EXPECT_EQ(0, AZStd::get<0>(t));
  645. }
  646. {
  647. const AZStd::tuple<AZ::s32, char*> t;
  648. EXPECT_EQ(0, AZStd::get<0>(t));
  649. EXPECT_EQ(nullptr, AZStd::get<1>(t));
  650. }
  651. {
  652. // Check that the SFINAE on the default constructor is not evaluated when
  653. // it isn't needed. If the default constructor is evaluated then this test
  654. // should fail to compile.
  655. IllFormedDefault v(0);
  656. AZStd::tuple<IllFormedDefault> t(v);
  657. }
  658. }
  659. TEST_F(TupleTest, IsDestructible_ConstructTest)
  660. {
  661. AZ_TEST_STATIC_ASSERT((std::is_trivially_destructible<AZStd::tuple<> >::value));
  662. AZ_TEST_STATIC_ASSERT((std::is_trivially_destructible<AZStd::tuple<void*> >::value));
  663. AZ_TEST_STATIC_ASSERT((std::is_trivially_destructible<AZStd::tuple<AZ::s32, float> >::value));
  664. AZ_TEST_STATIC_ASSERT((!std::is_trivially_destructible<AZStd::tuple<AZStd::string> >::value));
  665. AZ_TEST_STATIC_ASSERT((!std::is_trivially_destructible<AZStd::tuple<AZ::s32, AZStd::string> >::value));
  666. }
  667. TEST_F(TupleTest, CopyPair_ConstructTest)
  668. {
  669. {
  670. using T0 = AZStd::pair<AZ::s32, char>;
  671. using T1 = AZStd::tuple<AZ::s64, AZ::s16>;
  672. T0 t0(2, 'a');
  673. T1 t1 = to_std_pair(t0);
  674. EXPECT_EQ(2, AZStd::get<0>(t1));
  675. EXPECT_EQ(AZ::s16('a'), AZStd::get<1>(t1));
  676. }
  677. {
  678. using P0 = AZStd::pair<AZ::s32, char>;
  679. using T1 = AZStd::tuple<AZ::s64, AZ::s16>;
  680. const P0 p0(2, 'a');
  681. const T1 t1 = to_std_pair(p0);
  682. EXPECT_EQ(AZStd::get<0>(p0), AZStd::get<0>(t1));
  683. EXPECT_EQ(AZStd::get<1>(p0), AZStd::get<1>(t1));
  684. EXPECT_EQ(2, AZStd::get<0>(t1));
  685. EXPECT_EQ(AZ::s16('a'), AZStd::get<1>(t1));
  686. }
  687. }
  688. TEST_F(TupleTest, MovePair_ConstructTest)
  689. {
  690. {
  691. using T0 = AZStd::pair<long, AZStd::unique_ptr<DerivedIntWrapper>>;
  692. using T1 = AZStd::tuple<long long, AZStd::unique_ptr<BaseIntWrapper>>;
  693. T0 t0(2, AZStd::make_unique<DerivedIntWrapper>(3));
  694. T1 t1 = to_std_pair(AZStd::move(t0));
  695. EXPECT_EQ(2, AZStd::get<0>(t1));
  696. EXPECT_EQ(3, AZStd::get<1>(t1)->m_num);
  697. }
  698. }
  699. TEST_F(TupleTest, ConversionCopy_ConstructTest)
  700. {
  701. {
  702. using T0 = AZStd::tuple<AZ::s32>;
  703. using T1 = AZStd::tuple<AZ::s64>;
  704. T0 t0(2);
  705. T1 t1 = t0;
  706. EXPECT_EQ(2, AZStd::get<0>(t1));
  707. }
  708. {
  709. using T0 = AZStd::tuple<AZ::s32, char>;
  710. using T1 = AZStd::tuple<AZ::s64, AZ::s32>;
  711. T0 t0(2, 'a');
  712. T1 t1 = t0;
  713. EXPECT_EQ(2, AZStd::get<0>(t1));
  714. EXPECT_EQ(AZ::s32('a'), AZStd::get<1>(t1));
  715. }
  716. {
  717. using T0 = AZStd::tuple<AZ::s32, char, DerivedIntWrapper>;
  718. using T1 = AZStd::tuple<AZ::s64, AZ::s32, BaseIntWrapper>;
  719. T0 t0(2, 'a', DerivedIntWrapper(3));
  720. T1 t1(t0);
  721. EXPECT_EQ(2, AZStd::get<0>(t1));
  722. EXPECT_EQ(AZ::s32('a'), AZStd::get<1>(t1));
  723. EXPECT_EQ(3, AZStd::get<2>(t1).m_num);
  724. }
  725. {
  726. DerivedIntWrapper d(3);
  727. using T0 = AZStd::tuple<AZ::s32, char, DerivedIntWrapper&>;
  728. using T1 = AZStd::tuple<AZ::s64, AZ::s32, BaseIntWrapper&>;
  729. T0 t0(2, 'a', d);
  730. T1 t1(t0);
  731. d.m_num = 2;
  732. EXPECT_EQ(2, AZStd::get<0>(t1));
  733. EXPECT_EQ(AZ::s32('a'), AZStd::get<1>(t1));
  734. EXPECT_EQ(2, AZStd::get<2>(t1).m_num);
  735. }
  736. {
  737. using T0 = AZStd::tuple<AZ::s32, char, AZ::s32>;
  738. using T1 = AZStd::tuple<AZ::s64, AZ::s32, BaseIntWrapper>;
  739. T0 t0(2, 'a', 3);
  740. T1 t1(t0);
  741. EXPECT_EQ(2, AZStd::get<0>(t1));
  742. EXPECT_EQ(AZ::s32('a'), AZStd::get<1>(t1));
  743. EXPECT_EQ(3, AZStd::get<2>(t1).m_num);
  744. }
  745. {
  746. const AZStd::tuple<int> t1(42);
  747. AZStd::tuple<Explicit> t2(t1);
  748. EXPECT_EQ(42, AZStd::get<0>(t2).m_value);
  749. }
  750. {
  751. const AZStd::tuple<int> t1(42);
  752. AZStd::tuple<Implicit> t2 = t1;
  753. EXPECT_EQ(42, AZStd::get<0>(t2).m_value);
  754. }
  755. }
  756. TEST_F(TupleTest, ConversionMove_ConstructTest)
  757. {
  758. {
  759. using T0 = AZStd::tuple<AZ::s32>;
  760. using T1 = AZStd::tuple<AZ::s64>;
  761. T0 t0(2);
  762. T1 t1 = AZStd::move(t0);
  763. EXPECT_EQ(2, AZStd::get<0>(t1));
  764. }
  765. {
  766. using T0 = AZStd::tuple<AZ::s32, char>;
  767. using T1 = AZStd::tuple<AZ::s64, AZ::s32>;
  768. T0 t0(2, 'a');
  769. T1 t1 = AZStd::move(t0);
  770. EXPECT_EQ(2, AZStd::get<0>(t1));
  771. EXPECT_EQ(AZ::s32('a'), AZStd::get<1>(t1));
  772. }
  773. {
  774. using T0 = AZStd::tuple<AZ::s32, char, DerivedIntWrapper>;
  775. using T1 = AZStd::tuple<AZ::s64, AZ::s32, BaseIntWrapper>;
  776. T0 t0(2, 'a', DerivedIntWrapper(3));
  777. T1 t1 = AZStd::move(t0);
  778. EXPECT_EQ(2, AZStd::get<0>(t1));
  779. EXPECT_EQ(AZ::s32('a'), AZStd::get<1>(t1));
  780. EXPECT_EQ(3, AZStd::get<2>(t1).m_num);
  781. }
  782. {
  783. DerivedIntWrapper d(3);
  784. using T0 = AZStd::tuple<AZ::s32, char, DerivedIntWrapper&>;
  785. using T1 = AZStd::tuple<AZ::s64, AZ::s32, BaseIntWrapper&>;
  786. T0 t0(2, 'a', d);
  787. T1 t1 = AZStd::move(t0);
  788. d.m_num = 2;
  789. EXPECT_EQ(2, AZStd::get<0>(t1));
  790. EXPECT_EQ(AZ::s32('a'), AZStd::get<1>(t1));
  791. EXPECT_EQ(2, AZStd::get<2>(t1).m_num);
  792. }
  793. {
  794. using T0 = AZStd::tuple<AZ::s32, char, AZStd::unique_ptr<DerivedIntWrapper>>;
  795. using T1 = AZStd::tuple<AZ::s64, AZ::s32, AZStd::unique_ptr<BaseIntWrapper>>;
  796. T0 t0(2, 'a', AZStd::make_unique<DerivedIntWrapper>(3));
  797. T1 t1 = AZStd::move(t0);
  798. EXPECT_EQ(2, AZStd::get<0>(t1));
  799. EXPECT_EQ(AZ::s32('a'), AZStd::get<1>(t1));
  800. EXPECT_EQ(3, AZStd::get<2>(t1)->m_num);
  801. }
  802. {
  803. AZStd::tuple<int> t1(42);
  804. AZStd::tuple<Explicit> t2(AZStd::move(t1));
  805. EXPECT_EQ(42, AZStd::get<0>(t2).m_value);
  806. }
  807. {
  808. AZStd::tuple<int> t1(42);
  809. AZStd::tuple<Implicit> t2 = AZStd::move(t1);
  810. EXPECT_EQ(42, AZStd::get<0>(t2).m_value);
  811. }
  812. }
  813. TEST_F(TupleTest, Copy_ConstructTest)
  814. {
  815. {
  816. using T = AZStd::tuple<>;
  817. T t0;
  818. T t = t0;
  819. ((void)t); // Prevent unused warning
  820. }
  821. {
  822. using T = AZStd::tuple<AZ::s32>;
  823. T t0(2);
  824. T t = t0;
  825. EXPECT_EQ(2, AZStd::get<0>(t));
  826. }
  827. {
  828. using T = AZStd::tuple<AZ::s32, char>;
  829. T t0(2, 'a');
  830. T t = t0;
  831. EXPECT_EQ(2, AZStd::get<0>(t));
  832. EXPECT_EQ('a', AZStd::get<1>(t));
  833. }
  834. {
  835. using T = AZStd::tuple<AZ::s32, char, AZStd::string>;
  836. const T t0(2, 'a', "some text");
  837. T t = t0;
  838. EXPECT_EQ(2, AZStd::get<0>(t));
  839. EXPECT_EQ('a', AZStd::get<1>(t));
  840. EXPECT_EQ("some text", AZStd::get<2>(t));
  841. }
  842. {
  843. using T = AZStd::tuple<AZ::s32>;
  844. const T t0(2);
  845. const T t = t0;
  846. EXPECT_EQ(2, AZStd::get<0>(t));
  847. }
  848. {
  849. using T = AZStd::tuple<Empty>;
  850. const T t0;
  851. const T t = t0;
  852. const Empty e = AZStd::get<0>(t);
  853. ((void)e); // Prevent unused warning
  854. }
  855. }
  856. TEST_F(TupleTest, Move_ConstructTest)
  857. {
  858. {
  859. using T = AZStd::tuple<>;
  860. T t0;
  861. T t = AZStd::move(t0);
  862. ((void)t); // Prevent unused warning
  863. }
  864. {
  865. using T = AZStd::tuple<MoveOnly>;
  866. T t0(MoveOnly(0));
  867. T t = AZStd::move(t0);
  868. EXPECT_EQ(0, AZStd::get<0>(t));
  869. }
  870. {
  871. using T = AZStd::tuple<MoveOnly, MoveOnly>;
  872. T t0(MoveOnly(0), MoveOnly(1));
  873. T t = AZStd::move(t0);
  874. EXPECT_EQ(0, AZStd::get<0>(t));
  875. EXPECT_EQ(1, AZStd::get<1>(t));
  876. }
  877. {
  878. using T = AZStd::tuple<MoveOnly, MoveOnly, MoveOnly>;
  879. T t0(MoveOnly(0), MoveOnly(1), MoveOnly(2));
  880. T t = AZStd::move(t0);
  881. EXPECT_EQ(0, AZStd::get<0>(t));
  882. EXPECT_EQ(1, AZStd::get<1>(t));
  883. EXPECT_EQ(2, AZStd::get<2>(t));
  884. }
  885. {
  886. using d_t = AZStd::tuple<ConstructsWithTupleLeaf>;
  887. d_t d((ConstructsWithTupleLeaf()));
  888. d_t d2(static_cast<d_t &&>(d));
  889. }
  890. }
  891. TEST_F(TupleTest, TemplateDepth_ConstructTest)
  892. {
  893. AZStd::array<char, 1256> source;
  894. AZStd::tuple<AZStd::array<char, 1256>> resultTuple(source);
  895. }
  896. }
  897. namespace ApplyTest
  898. {
  899. static AZ::s32 const_sum_fn() { return 0; }
  900. template <class FirstInt, class ...Ints>
  901. static AZ::s32 const_sum_fn(FirstInt x1, Ints... rest) { return static_cast<AZ::s32>(x1 + const_sum_fn(rest...)); }
  902. struct ConstSumT
  903. {
  904. ConstSumT() = default;
  905. template <class ...Ints>
  906. int operator()(Ints... values) const
  907. {
  908. return const_sum_fn(values...);
  909. }
  910. };
  911. TEST_F(TupleTest, ConstEvaluation_ApplyTest)
  912. {
  913. ConstSumT sum_obj{};
  914. {
  915. using Tup = AZStd::tuple<>;
  916. using Fn = AZ::s32(&)();
  917. const Tup t;
  918. EXPECT_EQ(0, AZStd::apply(static_cast<Fn>(const_sum_fn), t));
  919. EXPECT_EQ(0, AZStd::apply(sum_obj, t));
  920. }
  921. {
  922. using Tup = AZStd::tuple<AZ::s32>;
  923. using Fn = AZ::s32(&)(AZ::s32);
  924. const Tup t(42);
  925. EXPECT_EQ(42, AZStd::apply(static_cast<Fn>(const_sum_fn<>), t));
  926. EXPECT_EQ(42, AZStd::apply(sum_obj, t));
  927. }
  928. {
  929. using Tup = AZStd::tuple<AZ::s32, AZ::s64>;
  930. using Fn = AZ::s32(&)(AZ::s32, AZ::s64);
  931. const Tup t(42, 101);
  932. EXPECT_EQ(143, AZStd::apply(static_cast<Fn>(const_sum_fn), t));
  933. EXPECT_EQ(143, AZStd::apply(sum_obj, t));
  934. }
  935. {
  936. using Tup = AZStd::pair<AZ::s32, AZ::s64>;
  937. using Fn = AZ::s32(&)(AZ::s32, AZ::s64);
  938. const Tup t(42, 101);
  939. EXPECT_EQ(143, AZStd::apply(static_cast<Fn>(const_sum_fn), t));
  940. EXPECT_EQ(143, AZStd::apply(sum_obj, t));
  941. }
  942. {
  943. using Tup = std::tuple<AZ::s32, AZ::s64, AZ::s32>;
  944. using Fn = AZ::s32(&)(AZ::s32, AZ::s64, AZ::s32);
  945. const Tup t(42, 101, -1);
  946. EXPECT_EQ(142, AZStd::apply(static_cast<Fn>(const_sum_fn), t));
  947. EXPECT_EQ(142, AZStd::apply(sum_obj, t));
  948. }
  949. {
  950. using Tup = AZStd::array<AZ::s32, 3>;
  951. using Fn = AZ::s32(&)(AZ::s32, AZ::s32, AZ::s32);
  952. const Tup t = { { 42, 101, -1 } };
  953. AZ_TEST_STATIC_ASSERT(AZStd::tuple_size<Tup>::value == 3);
  954. EXPECT_EQ(42, AZStd::get<0>(t));
  955. EXPECT_EQ(142, AZStd::apply(static_cast<Fn>(const_sum_fn), t));
  956. EXPECT_EQ(142, AZStd::apply(sum_obj, t));
  957. }
  958. }
  959. static int my_int = 42;
  960. template <int N> struct index {};
  961. void RawFunc(index<0>) {}
  962. int RawFunc(index<1>) { return 0; }
  963. int & RawFunc(index<2>) { return static_cast<int &>(my_int); }
  964. int const & RawFunc(index<3>) { return static_cast<int const &>(my_int); }
  965. int volatile & RawFunc(index<4>) { return static_cast<int volatile &>(my_int); }
  966. int const volatile & RawFunc(index<5>) { return static_cast<int const volatile &>(my_int); }
  967. int && RawFunc(index<6>) { return static_cast<int &&>(my_int); }
  968. int const && RawFunc(index<7>) { return static_cast<int const &&>(my_int); }
  969. int volatile && RawFunc(index<8>) { return static_cast<int volatile &&>(my_int); }
  970. int const volatile && RawFunc(index<9>) { return static_cast<int const volatile &&>(my_int); }
  971. int * RawFunc(index<10>) { return static_cast<int *>(&my_int); }
  972. int const * RawFunc(index<11>) { return static_cast<int const *>(&my_int); }
  973. int volatile * RawFunc(index<12>) { return static_cast<int volatile *>(&my_int); }
  974. int const volatile * RawFunc(index<13>) { return static_cast<int const volatile *>(&my_int); }
  975. template <int Func, class Expect>
  976. void ReturnTypeTest()
  977. {
  978. using RawInvokeResult = decltype(RawFunc(index<Func>{}));
  979. AZ_TEST_STATIC_ASSERT((AZStd::is_same<RawInvokeResult, Expect>::value));
  980. using FnType = RawInvokeResult(*) (index<Func>);
  981. FnType fn = RawFunc;
  982. (void)fn;
  983. AZStd::tuple<index<Func>> t;
  984. (void)t;
  985. using InvokeResult = decltype(AZStd::apply(fn, t));
  986. AZ_TEST_STATIC_ASSERT((AZStd::is_same<InvokeResult, Expect>::value));
  987. }
  988. TEST_F(TupleTest, ReturnType_ApplyTest)
  989. {
  990. ReturnTypeTest<0, void>();
  991. ReturnTypeTest<1, int>();
  992. ReturnTypeTest<2, int &>();
  993. ReturnTypeTest<3, int const &>();
  994. ReturnTypeTest<4, int volatile &>();
  995. ReturnTypeTest<5, int const volatile &>();
  996. ReturnTypeTest<6, int &&>();
  997. ReturnTypeTest<7, int const &&>();
  998. ReturnTypeTest<8, int volatile &&>();
  999. ReturnTypeTest<9, int const volatile &&>();
  1000. ReturnTypeTest<10, int *>();
  1001. ReturnTypeTest<11, int const *>();
  1002. ReturnTypeTest<12, int volatile *>();
  1003. ReturnTypeTest<13, int const volatile *>();
  1004. }
  1005. }
  1006. namespace ExtendedApplyTest
  1007. {
  1008. class ExtendedTupleTest
  1009. : public LeakDetectionFixture
  1010. {
  1011. protected:
  1012. static void SetUpTestCase()
  1013. {
  1014. ExtendedTupleTest::m_count = 0;
  1015. }
  1016. public:
  1017. static AZ::s32 m_count;
  1018. };
  1019. AZ::s32 ExtendedTupleTest::m_count = 0;
  1020. struct A_int_0
  1021. {
  1022. A_int_0() : obj1(0) {}
  1023. A_int_0(AZ::s32 x) : obj1(x) {}
  1024. AZ::s32 mem1() { return ++ExtendedTupleTest::m_count; }
  1025. AZ::s32 mem2() const { return ++ExtendedTupleTest::m_count; }
  1026. const AZ::s32 obj1;
  1027. A_int_0& operator=(const A_int_0&) = delete;
  1028. };
  1029. struct A_int_1
  1030. {
  1031. A_int_1() {}
  1032. A_int_1(AZ::s32) {}
  1033. AZ::s32 mem1(AZ::s32 x) { return ExtendedTupleTest::m_count += x; }
  1034. AZ::s32 mem2(AZ::s32 x) const { return ExtendedTupleTest::m_count += x; }
  1035. };
  1036. struct A_int_2
  1037. {
  1038. A_int_2() {}
  1039. A_int_2(AZ::s32) {}
  1040. AZ::s32 mem1(AZ::s32 x, AZ::s32 y) { return ExtendedTupleTest::m_count += (x + y); }
  1041. AZ::s32 mem2(AZ::s32 x, AZ::s32 y) const { return ExtendedTupleTest::m_count += (x + y); }
  1042. };
  1043. template <class A>
  1044. struct A_wrap
  1045. {
  1046. A_wrap() {}
  1047. A_wrap(AZ::s32 x) : m_a(x) {}
  1048. A & operator*() { return m_a; }
  1049. A const & operator*() const { return m_a; }
  1050. A m_a;
  1051. };
  1052. using A_wrap_0 = A_wrap<A_int_0>;
  1053. using A_wrap_1 = A_wrap<A_int_1>;
  1054. using A_wrap_2 = A_wrap<A_int_2>;
  1055. template <class A>
  1056. struct A_base : A
  1057. {
  1058. A_base() : A() {}
  1059. A_base(AZ::s32 x) : A(x) {}
  1060. };
  1061. using A_base_0 = A_base<A_int_0>;
  1062. using A_base_1 = A_base<A_int_1>;
  1063. using A_base_2 = A_base<A_int_2>;
  1064. template <
  1065. class Tuple, class ConstTuple
  1066. , class TuplePtr, class ConstTuplePtr
  1067. , class TupleWrap, class ConstTupleWrap
  1068. , class TupleBase, class ConstTupleBase
  1069. >
  1070. void test_ext_int_0()
  1071. {
  1072. ExtendedTupleTest::m_count = 0;
  1073. using T = A_int_0;
  1074. using Wrap = A_wrap_0;
  1075. using Base = A_base_0;
  1076. using mem1_t = AZ::s32(T::*)();
  1077. mem1_t mem1 = &T::mem1;
  1078. using mem2_t = AZ::s32(T::*)() const;
  1079. mem2_t mem2 = &T::mem2;
  1080. using obj1_t = AZ::s32 const T::*;
  1081. obj1_t obj1 = &T::obj1;
  1082. // member function w/ref
  1083. {
  1084. T a;
  1085. Tuple t{ { a } };
  1086. EXPECT_EQ(1, AZStd::apply(mem1, t));
  1087. EXPECT_EQ(1, ExtendedTupleTest::m_count);
  1088. }
  1089. ExtendedTupleTest::m_count = 0;
  1090. // member function w/pointer
  1091. {
  1092. T a;
  1093. TuplePtr t{ { &a } };
  1094. EXPECT_EQ(1, AZStd::apply(mem1, t));
  1095. EXPECT_EQ(1, ExtendedTupleTest::m_count);
  1096. }
  1097. ExtendedTupleTest::m_count = 0;
  1098. // member function w/base
  1099. {
  1100. Base a;
  1101. TupleBase t{ { a } };
  1102. EXPECT_EQ(1, AZStd::apply(mem1, t));
  1103. EXPECT_EQ(1, ExtendedTupleTest::m_count);
  1104. }
  1105. ExtendedTupleTest::m_count = 0;
  1106. // member function w/wrap
  1107. {
  1108. Wrap a;
  1109. TupleWrap t{ { a } };
  1110. EXPECT_EQ(1, AZStd::apply(mem1, t));
  1111. EXPECT_EQ(1, ExtendedTupleTest::m_count);
  1112. }
  1113. ExtendedTupleTest::m_count = 0;
  1114. // const member function w/ref
  1115. {
  1116. T const a;
  1117. ConstTuple t{ { a } };
  1118. EXPECT_EQ(1, AZStd::apply(mem2, t));
  1119. EXPECT_EQ(1, ExtendedTupleTest::m_count);
  1120. }
  1121. ExtendedTupleTest::m_count = 0;
  1122. // const member function w/pointer
  1123. {
  1124. T const a;
  1125. ConstTuplePtr t{ { &a } };
  1126. EXPECT_EQ(1, AZStd::apply(mem2, t));
  1127. EXPECT_EQ(1, ExtendedTupleTest::m_count);
  1128. }
  1129. ExtendedTupleTest::m_count = 0;
  1130. // const member function w/base
  1131. {
  1132. Base const a;
  1133. ConstTupleBase t{ { a } };
  1134. EXPECT_EQ(1, AZStd::apply(mem2, t));
  1135. EXPECT_EQ(1, ExtendedTupleTest::m_count);
  1136. }
  1137. ExtendedTupleTest::m_count = 0;
  1138. // const member function w/wrapper
  1139. {
  1140. Wrap const a;
  1141. ConstTupleWrap t{ { a } };
  1142. EXPECT_EQ(1, AZStd::apply(mem2, t));
  1143. EXPECT_EQ(1, ExtendedTupleTest::m_count);
  1144. }
  1145. // member object w/ref
  1146. {
  1147. T a{ 42 };
  1148. Tuple t{ { a } };
  1149. EXPECT_EQ(42, AZStd::apply(obj1, t));
  1150. }
  1151. // member object w/pointer
  1152. {
  1153. T a{ 42 };
  1154. TuplePtr t{ { &a } };
  1155. EXPECT_EQ(42, AZStd::apply(obj1, t));
  1156. }
  1157. // member object w/base
  1158. {
  1159. Base a{ 42 };
  1160. TupleBase t{ { a } };
  1161. EXPECT_EQ(42, AZStd::apply(obj1, t));
  1162. }
  1163. // member object w/wrapper
  1164. {
  1165. Wrap a{ 42 };
  1166. TupleWrap t{ { a } };
  1167. EXPECT_EQ(42, AZStd::apply(obj1, t));
  1168. }
  1169. }
  1170. template <
  1171. class Tuple, class ConstTuple
  1172. , class TuplePtr, class ConstTuplePtr
  1173. , class TupleWrap, class ConstTupleWrap
  1174. , class TupleBase, class ConstTupleBase
  1175. >
  1176. void test_ext_int_1()
  1177. {
  1178. ExtendedTupleTest::m_count = 0;
  1179. typedef A_int_1 T;
  1180. typedef A_wrap_1 Wrap;
  1181. typedef A_base_1 Base;
  1182. using mem1_t = AZ::s32(T::*)(AZ::s32);
  1183. mem1_t mem1 = &T::mem1;
  1184. using mem2_t = AZ::s32(T::*)(AZ::s32) const;
  1185. mem2_t mem2 = &T::mem2;
  1186. // member function w/ref
  1187. {
  1188. T a;
  1189. Tuple t{ a, 2 };
  1190. EXPECT_EQ(2, AZStd::apply(mem1, t));
  1191. EXPECT_EQ(2, ExtendedTupleTest::m_count);
  1192. }
  1193. ExtendedTupleTest::m_count = 0;
  1194. // member function w/pointer
  1195. {
  1196. T a;
  1197. TuplePtr t{ &a, 3 };
  1198. EXPECT_EQ(3, AZStd::apply(mem1, t));
  1199. EXPECT_EQ(3, ExtendedTupleTest::m_count);
  1200. }
  1201. ExtendedTupleTest::m_count = 0;
  1202. // member function w/base
  1203. {
  1204. Base a;
  1205. TupleBase t{ a, 4 };
  1206. EXPECT_EQ(4, AZStd::apply(mem1, t));
  1207. EXPECT_EQ(4, ExtendedTupleTest::m_count);
  1208. }
  1209. ExtendedTupleTest::m_count = 0;
  1210. // member function w/wrap
  1211. {
  1212. Wrap a;
  1213. TupleWrap t{ a, 5 };
  1214. EXPECT_EQ(5, AZStd::apply(mem1, t));
  1215. EXPECT_EQ(5, ExtendedTupleTest::m_count);
  1216. }
  1217. ExtendedTupleTest::m_count = 0;
  1218. // const member function w/ref
  1219. {
  1220. T const a;
  1221. ConstTuple t{ a, 6 };
  1222. EXPECT_EQ(6, AZStd::apply(mem2, t));
  1223. EXPECT_EQ(6, ExtendedTupleTest::m_count);
  1224. }
  1225. ExtendedTupleTest::m_count = 0;
  1226. // const member function w/pointer
  1227. {
  1228. T const a;
  1229. ConstTuplePtr t{ &a, 7 };
  1230. EXPECT_EQ(7, AZStd::apply(mem2, t));
  1231. EXPECT_EQ(7, ExtendedTupleTest::m_count);
  1232. }
  1233. ExtendedTupleTest::m_count = 0;
  1234. // const member function w/base
  1235. {
  1236. Base const a;
  1237. ConstTupleBase t{ a, 8 };
  1238. EXPECT_EQ(8, AZStd::apply(mem2, t));
  1239. EXPECT_EQ(8, ExtendedTupleTest::m_count);
  1240. }
  1241. ExtendedTupleTest::m_count = 0;
  1242. // const member function w/wrapper
  1243. {
  1244. Wrap const a;
  1245. ConstTupleWrap t{ a, 9 };
  1246. EXPECT_EQ(9, AZStd::apply(mem2, t));
  1247. EXPECT_EQ(9, ExtendedTupleTest::m_count);
  1248. }
  1249. }
  1250. template <
  1251. class Tuple, class ConstTuple
  1252. , class TuplePtr, class ConstTuplePtr
  1253. , class TupleWrap, class ConstTupleWrap
  1254. , class TupleBase, class ConstTupleBase
  1255. >
  1256. void test_ext_int_2()
  1257. {
  1258. ExtendedTupleTest::m_count = 0;
  1259. typedef A_int_2 T;
  1260. typedef A_wrap_2 Wrap;
  1261. typedef A_base_2 Base;
  1262. using mem1_t = AZ::s32(T::*)(AZ::s32, AZ::s32);
  1263. mem1_t mem1 = &T::mem1;
  1264. using mem2_t = AZ::s32(T::*)(AZ::s32, int) const;
  1265. mem2_t mem2 = &T::mem2;
  1266. // member function w/ref
  1267. {
  1268. T a;
  1269. Tuple t{ a, 1, 1 };
  1270. EXPECT_EQ(2, AZStd::apply(mem1, t));
  1271. EXPECT_EQ(2, ExtendedTupleTest::m_count);
  1272. }
  1273. ExtendedTupleTest::m_count = 0;
  1274. // member function w/pointer
  1275. {
  1276. T a;
  1277. TuplePtr t{ &a, 1, 2 };
  1278. EXPECT_EQ(3, AZStd::apply(mem1, t));
  1279. EXPECT_EQ(3, ExtendedTupleTest::m_count);
  1280. }
  1281. ExtendedTupleTest::m_count = 0;
  1282. // member function w/base
  1283. {
  1284. Base a;
  1285. TupleBase t{ a, 2, 2 };
  1286. EXPECT_EQ(4, AZStd::apply(mem1, t));
  1287. EXPECT_EQ(4, ExtendedTupleTest::m_count);
  1288. }
  1289. ExtendedTupleTest::m_count = 0;
  1290. // member function w/wrap
  1291. {
  1292. Wrap a;
  1293. TupleWrap t{ a, 2, 3 };
  1294. EXPECT_EQ(5, AZStd::apply(mem1, t));
  1295. EXPECT_EQ(5, ExtendedTupleTest::m_count);
  1296. }
  1297. ExtendedTupleTest::m_count = 0;
  1298. // const member function w/ref
  1299. {
  1300. T const a;
  1301. ConstTuple t{ a, 3, 3 };
  1302. EXPECT_EQ(6, AZStd::apply(mem2, t));
  1303. EXPECT_EQ(6, ExtendedTupleTest::m_count);
  1304. }
  1305. ExtendedTupleTest::m_count = 0;
  1306. // const member function w/pointer
  1307. {
  1308. T const a;
  1309. ConstTuplePtr t{ &a, 3, 4 };
  1310. EXPECT_EQ(7, AZStd::apply(mem2, t));
  1311. EXPECT_EQ(7, ExtendedTupleTest::m_count);
  1312. }
  1313. ExtendedTupleTest::m_count = 0;
  1314. // const member function w/base
  1315. {
  1316. Base const a;
  1317. ConstTupleBase t{ a, 4, 4 };
  1318. EXPECT_EQ(8, AZStd::apply(mem2, t));
  1319. EXPECT_EQ(8, ExtendedTupleTest::m_count);
  1320. }
  1321. ExtendedTupleTest::m_count = 0;
  1322. // const member function w/wrapper
  1323. {
  1324. Wrap const a;
  1325. ConstTupleWrap t{ a, 4, 5 };
  1326. EXPECT_EQ(9, AZStd::apply(mem2, t));
  1327. EXPECT_EQ(9, ExtendedTupleTest::m_count);
  1328. }
  1329. }
  1330. TEST_F(ExtendedTupleTest, Int0_ExtendedApplyTest)
  1331. {
  1332. test_ext_int_0<
  1333. AZStd::tuple<A_int_0 &>, AZStd::tuple<A_int_0 const &>
  1334. , AZStd::tuple<A_int_0 *>, AZStd::tuple<A_int_0 const *>
  1335. , AZStd::tuple<A_wrap_0 &>, AZStd::tuple<A_wrap_0 const &>
  1336. , AZStd::tuple<A_base_0 &>, AZStd::tuple<A_base_0 const &>
  1337. >();
  1338. test_ext_int_0<
  1339. AZStd::tuple<A_int_0>, AZStd::tuple<A_int_0 const>
  1340. , AZStd::tuple<A_int_0 *>, AZStd::tuple<A_int_0 const *>
  1341. , AZStd::tuple<A_wrap_0>, AZStd::tuple<A_wrap_0 const>
  1342. , AZStd::tuple<A_base_0>, AZStd::tuple<A_base_0 const>
  1343. >();
  1344. test_ext_int_0<
  1345. AZStd::array<A_int_0, 1>, AZStd::array<A_int_0 const, 1>
  1346. , AZStd::array<A_int_0*, 1>, AZStd::array<A_int_0 const*, 1>
  1347. , AZStd::array<A_wrap_0, 1>, AZStd::array<A_wrap_0 const, 1>
  1348. , AZStd::array<A_base_0, 1>, AZStd::array<A_base_0 const, 1>
  1349. >();
  1350. }
  1351. TEST_F(ExtendedTupleTest, Int1_ExtendedApplyTest)
  1352. {
  1353. test_ext_int_1<
  1354. AZStd::tuple<A_int_1 &, int>, AZStd::tuple<A_int_1 const &, int>
  1355. , AZStd::tuple<A_int_1 *, int>, AZStd::tuple<A_int_1 const *, int>
  1356. , AZStd::tuple<A_wrap_1 &, int>, AZStd::tuple<A_wrap_1 const &, int>
  1357. , AZStd::tuple<A_base_1 &, int>, AZStd::tuple<A_base_1 const &, int>
  1358. >();
  1359. test_ext_int_1<
  1360. AZStd::tuple<A_int_1, int>, AZStd::tuple<A_int_1 const, int>
  1361. , AZStd::tuple<A_int_1 *, int>, AZStd::tuple<A_int_1 const *, int>
  1362. , AZStd::tuple<A_wrap_1, int>, AZStd::tuple<A_wrap_1 const, int>
  1363. , AZStd::tuple<A_base_1, int>, AZStd::tuple<A_base_1 const, int>
  1364. >();
  1365. test_ext_int_1<
  1366. AZStd::pair<A_int_1 &, int>, AZStd::pair<A_int_1 const &, int>
  1367. , AZStd::pair<A_int_1 *, int>, AZStd::pair<A_int_1 const *, int>
  1368. , AZStd::pair<A_wrap_1 &, int>, AZStd::pair<A_wrap_1 const &, int>
  1369. , AZStd::pair<A_base_1 &, int>, AZStd::pair<A_base_1 const &, int>
  1370. >();
  1371. test_ext_int_1<
  1372. AZStd::pair<A_int_1, int>, AZStd::pair<A_int_1 const, int>
  1373. , AZStd::pair<A_int_1 *, int>, AZStd::pair<A_int_1 const *, int>
  1374. , AZStd::pair<A_wrap_1, int>, AZStd::pair<A_wrap_1 const, int>
  1375. , AZStd::pair<A_base_1, int>, AZStd::pair<A_base_1 const, int>
  1376. >();
  1377. }
  1378. TEST_F(ExtendedTupleTest, Int2_ExtendedApplyTest)
  1379. {
  1380. test_ext_int_2<
  1381. AZStd::tuple<A_int_2 &, int, int>, AZStd::tuple<A_int_2 const &, int, int>
  1382. , AZStd::tuple<A_int_2 *, int, int>, AZStd::tuple<A_int_2 const *, int, int>
  1383. , AZStd::tuple<A_wrap_2 &, int, int>, AZStd::tuple<A_wrap_2 const &, int, int>
  1384. , AZStd::tuple<A_base_2 &, int, int>, AZStd::tuple<A_base_2 const &, int, int>
  1385. >();
  1386. test_ext_int_2<
  1387. AZStd::tuple<A_int_2, int, int>, AZStd::tuple<A_int_2 const, int, int>
  1388. , AZStd::tuple<A_int_2 *, int, int>, AZStd::tuple<A_int_2 const *, int, int>
  1389. , AZStd::tuple<A_wrap_2, int, int>, AZStd::tuple<A_wrap_2 const, int, int>
  1390. , AZStd::tuple<A_base_2, int, int>, AZStd::tuple<A_base_2 const, int, int>
  1391. >();
  1392. }
  1393. }
  1394. }