aboutsummaryrefslogtreecommitdiff
path: root/EASTL/test/source/TestUtility.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'EASTL/test/source/TestUtility.cpp')
-rw-r--r--EASTL/test/source/TestUtility.cpp632
1 files changed, 632 insertions, 0 deletions
diff --git a/EASTL/test/source/TestUtility.cpp b/EASTL/test/source/TestUtility.cpp
new file mode 100644
index 0000000..363f409
--- /dev/null
+++ b/EASTL/test/source/TestUtility.cpp
@@ -0,0 +1,632 @@
+/////////////////////////////////////////////////////////////////////////////
+// Copyright (c) Electronic Arts Inc. All rights reserved.
+/////////////////////////////////////////////////////////////////////////////
+
+#include "EASTLTest.h"
+#include <EASTL/utility.h>
+#include <EAStdC/EAString.h>
+
+struct BasicObject
+{
+ int mX;
+ BasicObject(int x) : mX(x) {}
+};
+
+inline bool operator==(const BasicObject& t1, const BasicObject& t2) { return t1.mX == t2.mX; }
+
+inline bool operator<(const BasicObject& t1, const BasicObject& t2) { return t1.mX < t2.mX; }
+
+///////////////////////////////////////////////////////////////////////////////
+// TestUtilityPair
+//
+static int TestUtilityPair()
+{
+ using namespace eastl;
+
+ int nErrorCount = 0;
+
+ {
+ int _0 = 0, _2 = 2, _3 = 3;
+ float _1f = 1.f;
+
+ // pair();
+ pair<int, float> ifPair1;
+ EATEST_VERIFY((ifPair1.first == 0) && (ifPair1.second == 0.f));
+
+ // pair(const T1& x, const T2& y);
+ pair<int, float> ifPair2(_0, _1f);
+ EATEST_VERIFY((ifPair2.first == 0) && (ifPair2.second == 1.f));
+
+ // template <typename U, typename V>
+ // pair(U&& u, V&& v);
+ pair<int, float> ifPair3(int(0), float(1.f));
+ EATEST_VERIFY((ifPair3.first == 0) && (ifPair3.second == 1.f));
+
+ // template <typename U>
+ // pair(U&& x, const T2& y);
+ const float fConst1 = 1.f;
+ pair<int, float> ifPair4(int(0), fConst1);
+ EATEST_VERIFY((ifPair4.first == 0) && (ifPair4.second == 1.f));
+
+ // template <typename V>
+ // pair(const T1& x, V&& y);
+ const int intConst0 = 0;
+ pair<int, float> ifPair5(intConst0, float(1.f));
+ EATEST_VERIFY((ifPair5.first == 0) && (ifPair5.second == 1.f));
+
+ pair<const int, const int> constIntPair(_2, _3);
+ EATEST_VERIFY((constIntPair.first == 2) && (constIntPair.second == 3));
+
+ // pair(const pair&) = default;
+ pair<int, float> ifPair2Copy(ifPair2);
+ EATEST_VERIFY((ifPair2Copy.first == 0) && (ifPair2Copy.second == 1.f));
+
+ pair<const int, const int> constIntPairCopy(constIntPair);
+ EATEST_VERIFY((constIntPairCopy.first == 2) && (constIntPairCopy.second == 3));
+
+ // template<typename U, typename V>
+ // pair(const pair<U, V>& p);
+ pair<long, double> idPair2(ifPair2);
+ EATEST_VERIFY((idPair2.first == 0) && (idPair2.second == 1.0));
+
+ // pair(pair&& p);
+
+ // template<typename U, typename V>
+ // pair(pair<U, V>&& p);
+
+ // pair& operator=(const pair& p);
+
+ // template<typename U, typename V>
+ // pair& operator=(const pair<U, V>& p);
+
+ // pair& operator=(pair&& p);
+
+ // template<typename U, typename V>
+ // pair& operator=(pair<U, V>&& p);
+
+ // void swap(pair& p);
+
+ // use_self, use_first, use_second
+ use_self<pair<int, float> > usIFPair;
+ use_first<pair<int, float> > u1IFPair;
+ use_second<pair<int, float> > u2IFPair;
+
+ ifPair2 = usIFPair(ifPair2);
+ EATEST_VERIFY((ifPair2.first == 0) && (ifPair2.second == 1));
+
+ int first = u1IFPair(ifPair2);
+ EATEST_VERIFY(first == 0);
+
+ float second = u2IFPair(ifPair2);
+ EATEST_VERIFY(second == 1);
+
+ // make_pair
+ pair<int, float> p1 = make_pair(int(0), float(1));
+ EATEST_VERIFY((p1.first == 0) && (p1.second == 1.f));
+
+ pair<int, float> p2 = make_pair_ref(int(0), float(1));
+ EATEST_VERIFY((p2.first == 0) && (p2.second == 1.f));
+
+ pair<const char*, int> p3 = eastl::make_pair("a", 1);
+ EATEST_VERIFY((EA::StdC::Strcmp(p3.first, "a") == 0) && (p2.second == 1));
+
+ pair<const char*, int> p4 = eastl::make_pair<const char*, int>("a", 1);
+ EATEST_VERIFY((EA::StdC::Strcmp(p4.first, "a") == 0) && (p4.second == 1));
+
+ pair<int, const char*> p5 = eastl::make_pair<int, const char*>(1, "b");
+ EATEST_VERIFY((p5.first == 1) && (EA::StdC::Strcmp(p5.second, "b") == 0));
+
+#if !defined(EA_COMPILER_NO_AUTO)
+ auto p60 = eastl::make_pair("a", "b"); // Different strings of same length of 1.
+ EATEST_VERIFY((EA::StdC::Strcmp(p60.first, "a") == 0) && (EA::StdC::Strcmp(p60.second, "b") == 0));
+
+ auto p61 = eastl::make_pair("ab", "cd"); // Different strings of same length > 1.
+ EATEST_VERIFY((EA::StdC::Strcmp(p61.first, "ab") == 0) && (EA::StdC::Strcmp(p61.second, "cd") == 0));
+
+ auto p62 = eastl::make_pair("abc", "bcdef"); // Different strings of different length.
+ EATEST_VERIFY((EA::StdC::Strcmp(p62.first, "abc") == 0) && (EA::StdC::Strcmp(p62.second, "bcdef") == 0));
+
+ char strA[] = "a";
+ auto p70 = eastl::make_pair(strA, strA);
+ EATEST_VERIFY((EA::StdC::Strcmp(p70.first, "a") == 0) && (EA::StdC::Strcmp(p70.second, "a") == 0));
+
+ char strBC[] = "bc";
+ auto p71 = eastl::make_pair(strA, strBC);
+ EATEST_VERIFY((EA::StdC::Strcmp(p71.first, "a") == 0) && (EA::StdC::Strcmp(p71.second, "bc") == 0));
+
+ const char cstrA[] = "a";
+ auto p80 = eastl::make_pair(cstrA, cstrA);
+ EATEST_VERIFY((EA::StdC::Strcmp(p80.first, "a") == 0) && (EA::StdC::Strcmp(p80.second, "a") == 0));
+
+ const char cstrBC[] = "bc";
+ auto p81 = eastl::make_pair(cstrA, cstrBC);
+ EATEST_VERIFY((EA::StdC::Strcmp(p81.first, "a") == 0) && (EA::StdC::Strcmp(p81.second, "bc") == 0));
+#endif
+ }
+
+ {
+// One-off tests and regressions
+
+#if EASTL_PAIR_CONFORMANCE // See http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#811
+ pair<char*, char*> zeroLiteralPair(0, 0);
+ EATEST_VERIFY((zeroLiteralPair.first == NULL) && (zeroLiteralPair.second == NULL));
+#endif
+
+ // template<typename U>
+ // pair(U&& x, const T2& y)
+ typedef eastl::pair<uint16_t, const char8_t*> LCIDMapping;
+ LCIDMapping lcidMappingArray[1] = {LCIDMapping(0x0036, EA_CHAR8("af"))}; // Note that 0x0036 is of type int.
+ EATEST_VERIFY((lcidMappingArray[0].first == 0x0036));
+
+ // template<typename V>
+ // pair(const T1& x, V&& y)
+ typedef eastl::pair<const char8_t*, uint16_t> LCIDMapping2;
+ LCIDMapping2 lcidMapping2Array[1] = {LCIDMapping2(EA_CHAR8("af"), 0x0036)};
+ EATEST_VERIFY((lcidMapping2Array[0].second == 0x0036));
+
+// The following code was giving an EDG compiler:
+// error 145: a value of type "int" cannot be used to initialize
+// an entity of type "void *" second(eastl::forward<V>(v)) {}
+// template <typename U, typename V>
+// pair(U&& u, V&& v);
+#if EASTL_PAIR_CONFORMANCE
+ typedef eastl::pair<float*, void*> TestPair1;
+ float fOne = 1.f;
+ TestPair1 testPair1(&fOne, NULL);
+ EATEST_VERIFY(*testPair1.first == 1.f);
+#endif
+ }
+
+#ifndef EA_COMPILER_NO_STRUCTURED_BINDING
+ // pair structured bindings test
+ {
+ eastl::pair<int, int> t = {1,2};
+ auto [x,y] = t;
+ EATEST_VERIFY(x == 1);
+ EATEST_VERIFY(y == 2);
+ }
+
+ {
+ auto t = eastl::make_pair(1, 2);
+ auto [x,y] = t;
+ EATEST_VERIFY(x == 1);
+ EATEST_VERIFY(y == 2);
+ }
+
+ { // reported user-regression structured binding unpacking for iterators
+ eastl::vector<int> v = {1,2,3,4,5,6};
+ auto t = eastl::make_pair(v.begin(), v.end() - 1);
+ auto [x,y] = t;
+ EATEST_VERIFY(*x == 1);
+ EATEST_VERIFY(*y == 6);
+ }
+
+ { // reported user-regression structured binding unpacking for iterators
+ eastl::vector<int> v = {1,2,3,4,5,6};
+ auto t = eastl::make_pair(v.begin(), v.end());
+ auto [x,y] = t;
+ EATEST_VERIFY(*x == 1);
+ EA_UNUSED(y);
+ }
+
+ { // reported user-regression for const structured binding unpacking for iterators
+ eastl::vector<int> v = {1,2,3,4,5,6};
+ const auto [x,y] = eastl::make_pair(v.begin(), v.end());;
+ EATEST_VERIFY(*x == 1);
+ EA_UNUSED(y);
+ }
+#endif
+
+ return nErrorCount;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// TestUtilityRelops
+//
+static int TestUtilityRelops()
+{
+ int nErrorCount = 0;
+
+ {
+ using namespace eastl::rel_ops; // Defines default versions of operators !=, <, >, <=, >= based on == and <.
+
+ BasicObject bo1(1), bo2(2);
+
+ EATEST_VERIFY(!(bo1 == bo2));
+ EATEST_VERIFY((bo1 != bo2));
+ EATEST_VERIFY((bo1 < bo2));
+ EATEST_VERIFY(!(bo1 > bo2));
+ EATEST_VERIFY((bo1 <= bo2));
+ EATEST_VERIFY(!(bo1 >= bo2));
+ }
+
+ return nErrorCount;
+}
+
+// ThrowSwappable
+struct ThrowSwappable
+{
+};
+
+void swap(ThrowSwappable& x, ThrowSwappable& y) EA_NOEXCEPT_IF(false)
+{
+ ThrowSwappable temp(x);
+ x = y;
+ y = temp;
+
+#if EASTL_EXCEPTIONS_ENABLED
+ throw int();
+#endif
+}
+
+#if EASTL_TYPE_TRAIT_is_nothrow_swappable_CONFORMANCE
+// NoThrowSwappable
+struct NoThrowSwappable
+{
+};
+
+void swap(NoThrowSwappable& x, NoThrowSwappable& y) EA_NOEXCEPT_IF(true)
+{
+ NoThrowSwappable temp(x);
+ x = y;
+ y = temp;
+}
+#endif
+
+struct Swappable1 {};
+struct Swappable2 {};
+struct Swappable3 {};
+void swap(Swappable1&, Swappable2&) {}
+void swap(Swappable2&, Swappable1&) {}
+void swap(Swappable1&, Swappable3&) {} // intentionally missing 'swap(Swappable3, Swappable1)'
+
+
+static int TestUtilitySwap()
+{
+ int nErrorCount = 0;
+
+// is_swappable
+// is_nothrow_swappable
+#if EASTL_TYPE_TRAIT_is_swappable_CONFORMANCE
+ static_assert((eastl::is_swappable<int>::value == true), "is_swappable failure");
+ static_assert((eastl::is_swappable<eastl::vector<int> >::value == true), "is_swappable failure");
+ static_assert((eastl::is_swappable<ThrowSwappable>::value == true), "is_swappable failure");
+ #if EASTL_VARIABLE_TEMPLATES_ENABLED
+ static_assert((eastl::is_swappable_v<int> == true), "is_swappable failure");
+ static_assert((eastl::is_swappable_v<eastl::vector<int> > == true), "is_swappable failure");
+ static_assert((eastl::is_swappable_v<ThrowSwappable> == true), "is_swappable failure");
+ #endif
+// Need to come up with a class that's not swappable. How do we do that, given the universal swap template?
+// static_assert((eastl::is_swappable<?>::value == false), "is_swappable failure");
+#endif
+
+#if EASTL_TYPE_TRAIT_is_nothrow_swappable_CONFORMANCE
+ static_assert((eastl::is_nothrow_swappable<int>::value == true), "is_nothrow_swappable failure"); // There currently isn't any specialization for swap of scalar types that's nothrow.
+ static_assert((eastl::is_nothrow_swappable<eastl::vector<int> >::value == false), "is_nothrow_swappable failure");
+ static_assert((eastl::is_nothrow_swappable<ThrowSwappable>::value == false), "is_nothrow_swappable failure");
+ static_assert((eastl::is_nothrow_swappable<NoThrowSwappable>::value == true), "is_nothrow_swappable failure");
+ #if EASTL_VARIABLE_TEMPLATES_ENABLED
+ static_assert((eastl::is_nothrow_swappable_v<int> == true), "is_nothrow_swappable failure"); // There currently isn't any specialization for swap of scalar types that's nothrow.
+ static_assert((eastl::is_nothrow_swappable_v<eastl::vector<int>> == false), "is_nothrow_swappable failure");
+ static_assert((eastl::is_nothrow_swappable_v<ThrowSwappable> == false), "is_nothrow_swappable failure");
+ static_assert((eastl::is_nothrow_swappable_v<NoThrowSwappable> == true), "is_nothrow_swappable failure");
+ #endif
+#endif
+
+#if EASTL_VARIADIC_TEMPLATES_ENABLED
+// is_swappable_with
+// is_nothrow_swappable_with
+ static_assert(eastl::is_swappable_with<int&, int&>::value, "is_swappable_with failure");
+ static_assert(!eastl::is_swappable_with<int, int>::value, "is_swappable_with failure");
+ static_assert(!eastl::is_swappable_with<int&, int>::value, "is_swappable_with failure");
+ static_assert(!eastl::is_swappable_with<int, int&>::value, "is_swappable_with failure");
+ static_assert(!eastl::is_swappable_with<int, short>::value, "is_swappable_with failure");
+ static_assert(!eastl::is_swappable_with<int, long>::value, "is_swappable_with failure");
+ static_assert(!eastl::is_swappable_with<int, eastl::vector<int>>::value, "is_swappable_with failure");
+ static_assert(!eastl::is_swappable_with<void, void>::value, "is_swappable_with failure");
+ static_assert(!eastl::is_swappable_with<int, void>::value, "is_swappable_with failure");
+ static_assert(!eastl::is_swappable_with<void, int>::value, "is_swappable_with failure");
+ static_assert(!eastl::is_swappable_with<ThrowSwappable, ThrowSwappable>::value, "is_swappable_with failure");
+ static_assert(eastl::is_swappable_with<ThrowSwappable&, ThrowSwappable&>::value, "is_swappable_with failure");
+ static_assert(eastl::is_swappable_with<Swappable1&, Swappable1&>::value, "is_swappable_with failure");
+ static_assert(eastl::is_swappable_with<Swappable1&, Swappable2&>::value, "is_swappable_with failure");
+ static_assert(eastl::is_swappable_with<Swappable2&, Swappable1&>::value, "is_swappable_with failure");
+
+ #if EASTL_VARIABLE_TEMPLATES_ENABLED
+ static_assert(eastl::is_swappable_with_v<int&, int&>, "is_swappable_with_v failure");
+ static_assert(!eastl::is_swappable_with_v<int, int>, "is_swappable_with_v failure");
+ static_assert(!eastl::is_swappable_with_v<int&, int>, "is_swappable_with_v failure");
+ static_assert(!eastl::is_swappable_with_v<int, int&>, "is_swappable_with_v failure");
+ static_assert(!eastl::is_swappable_with_v<int, short>, "is_swappable_with_v failure");
+ static_assert(!eastl::is_swappable_with_v<int, long>, "is_swappable_with_v failure");
+ static_assert(!eastl::is_swappable_with_v<int, eastl::vector<int>>, "is_swappable_with_v failure");
+ static_assert(!eastl::is_swappable_with_v<void, void>, "is_swappable_with_v failure");
+ static_assert(!eastl::is_swappable_with_v<int, void>, "is_swappable_with_v failure");
+ static_assert(!eastl::is_swappable_with_v<void, int>, "is_swappable_with_v failure");
+ static_assert(!eastl::is_swappable_with_v<ThrowSwappable, ThrowSwappable>, "is_swappable_with_v failure");
+ static_assert(eastl::is_swappable_with_v<ThrowSwappable&, ThrowSwappable&>, "is_swappable_with_v failure");
+ static_assert(eastl::is_swappable_with_v<Swappable1&, Swappable1&>, "is_swappable_with_v failure");
+ static_assert(eastl::is_swappable_with_v<Swappable1&, Swappable2&>, "is_swappable_with_v failure");
+ static_assert(eastl::is_swappable_with_v<Swappable2&, Swappable1&>, "is_swappable_with_v failure");
+ #endif // EASTL_VARIABLE_TEMPLATES_ENABLED
+
+#if EASTL_TYPE_TRAIT_is_nothrow_swappable_with_CONFORMANCE
+ static_assert(eastl::is_nothrow_swappable_with<int&, int&>::value, "is_nothrow_swappable_with failure");
+ static_assert(!eastl::is_nothrow_swappable_with<int, int>::value, "is_nothrow_swappable_with failure");
+ static_assert(!eastl::is_nothrow_swappable_with<int&, int>::value, "is_nothrow_swappable_with failure");
+ static_assert(!eastl::is_nothrow_swappable_with<int, int&>::value, "is_nothrow_swappable_with failure");
+ static_assert(!eastl::is_nothrow_swappable_with<int, short>::value, "is_nothrow_swappable_with failure");
+ static_assert(!eastl::is_nothrow_swappable_with<int, long>::value, "is_nothrow_swappable_with failure");
+ static_assert(!eastl::is_nothrow_swappable_with<int, eastl::vector<int>>::value, "is_nothrow_swappable_with failure");
+ static_assert(!eastl::is_nothrow_swappable_with<void, void>::value, "is_nothrow_swappable_with failure");
+ static_assert(!eastl::is_nothrow_swappable_with<int, void>::value, "is_nothrow_swappable_with failure");
+ static_assert(!eastl::is_nothrow_swappable_with<void, int>::value, "is_nothrow_swappable_with failure");
+ static_assert(!eastl::is_nothrow_swappable_with<ThrowSwappable, ThrowSwappable>::value, "is_nothrow_swappable_with failure");
+ static_assert(!eastl::is_nothrow_swappable_with<ThrowSwappable&, ThrowSwappable&>::value, "is_nothrow_swappable_with failure");
+ static_assert(!eastl::is_nothrow_swappable_with<NoThrowSwappable, NoThrowSwappable>::value, "is_nothrow_swappable_with failure");
+ static_assert(eastl::is_nothrow_swappable_with<NoThrowSwappable&, NoThrowSwappable&>::value, "is_nothrow_swappable_with failure");
+
+ #if EASTL_VARIABLE_TEMPLATES_ENABLED
+ static_assert(eastl::is_nothrow_swappable_with_v<int&, int&>, "is_nothrow_swappable_with_v failure");
+ static_assert(!eastl::is_nothrow_swappable_with_v<int, int>, "is_nothrow_swappable_with_v failure");
+ static_assert(!eastl::is_nothrow_swappable_with_v<int&, int>, "is_nothrow_swappable_with_v failure");
+ static_assert(!eastl::is_nothrow_swappable_with_v<int, int&>, "is_nothrow_swappable_with_v failure");
+ static_assert(!eastl::is_nothrow_swappable_with_v<int, short>, "is_nothrow_swappable_with_v failure");
+ static_assert(!eastl::is_nothrow_swappable_with_v<int, long>, "is_nothrow_swappable_with_v failure");
+ static_assert(!eastl::is_nothrow_swappable_with_v<int, eastl::vector<int>>, "is_nothrow_swappable_with_v failure");
+ static_assert(!eastl::is_nothrow_swappable_with_v<void, void>, "is_nothrow_swappable_with_v failure");
+ static_assert(!eastl::is_nothrow_swappable_with_v<int, void>, "is_nothrow_swappable_with_v failure");
+ static_assert(!eastl::is_nothrow_swappable_with_v<void, int>, "is_nothrow_swappable_with_v failure");
+ static_assert(!eastl::is_nothrow_swappable_with_v<ThrowSwappable, ThrowSwappable>, "is_nothrow_swappable_with_v failure");
+ static_assert(!eastl::is_nothrow_swappable_with_v<ThrowSwappable&, ThrowSwappable&>, "is_nothrow_swappable_with_v failure");
+ static_assert(!eastl::is_nothrow_swappable_with_v<NoThrowSwappable, NoThrowSwappable>, "is_nothrow_swappable_with_v failure");
+ static_assert(eastl::is_nothrow_swappable_with_v<NoThrowSwappable&, NoThrowSwappable&>, "is_nothrow_swappable_with_v failure");
+ #endif // EASTL_VARIABLE_TEMPLATES_ENABLED
+#endif
+#endif // EASTL_VARIADIC_TEMPLATES_ENABLED
+
+ return nErrorCount;
+}
+
+#if !defined(EA_COMPILER_NO_NOEXCEPT)
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Warning C4626 warns against an implicitly deleted move assignment operator.
+// This warning was disabled by default in VS2013. It was enabled by default in
+// VS2015. Since the the tests below are explicitly testing move construction
+// of the various classes explicitly deleting the move assignment to remove the
+// warning is safe.
+//
+// https://msdn.microsoft.com/en-us/library/23k5d385.aspx
+
+struct noexcept_move_copy
+{
+ bool mStatus;
+
+ noexcept_move_copy() : mStatus(true) {}
+
+ noexcept_move_copy(const noexcept_move_copy&) = default;
+
+ noexcept_move_copy(noexcept_move_copy&& r) noexcept { r.mStatus = false; }
+
+ noexcept_move_copy& operator=(const noexcept_move_copy&) = delete; // required as VS2015 enabled C4626 by default.
+};
+
+struct noexcept_move_no_copy
+{
+ bool mStatus;
+
+ noexcept_move_no_copy() : mStatus(true) {}
+
+ noexcept_move_no_copy(const noexcept_move_no_copy&) = delete;
+
+ noexcept_move_no_copy(noexcept_move_no_copy&& r) noexcept { r.mStatus = false; };
+
+ noexcept_move_no_copy& operator=(const noexcept_move_no_copy&) = delete; // required as VS2015 enabled C4626 by default.
+};
+
+struct except_move_copy
+{
+ bool mStatus;
+
+ except_move_copy() : mStatus(true) {}
+
+ except_move_copy(const except_move_copy&) = default;
+
+ except_move_copy(except_move_copy&& r) noexcept(false) { r.mStatus = false; };
+
+ except_move_copy& operator=(const except_move_copy&) = delete; // required as VS2015 enabled C4626 by default.
+};
+
+struct except_move_no_copy
+{
+ bool mStatus;
+
+ except_move_no_copy() : mStatus(true) {}
+
+ except_move_no_copy(const except_move_no_copy&) = delete;
+
+ except_move_no_copy(except_move_no_copy&& r) noexcept(false) { r.mStatus = false; };
+
+ except_move_no_copy& operator=(const except_move_no_copy&) = delete; // required as VS2015 enabled C4626 by default.
+};
+#endif
+
+static int TestUtilityMove()
+{
+ int nErrorCount = 0;
+
+// move_if_noexcept
+#if !defined(EA_COMPILER_NO_NOEXCEPT)
+ noexcept_move_copy nemcA;
+ noexcept_move_copy nemcB =
+ eastl::move_if_noexcept(nemcA); // nemcB should be constructed via noexcept_move_copy(noexcept_move_copy&&)
+ EATEST_VERIFY(nemcA.mStatus == false);
+ EA_UNUSED(nemcB);
+
+ noexcept_move_no_copy nemncA;
+ noexcept_move_no_copy nemncB = eastl::move_if_noexcept(
+ nemncA); // nemncB should be constructed via noexcept_move_no_copy(noexcept_move_no_copy&&)
+ EATEST_VERIFY(nemncA.mStatus == false);
+ EA_UNUSED(nemncB);
+
+ except_move_copy emcA;
+ except_move_copy emcB = eastl::move_if_noexcept(
+ emcA); // emcB should be constructed via except_move_copy(const except_move_copy&) if exceptions are enabled.
+#if EASTL_EXCEPTIONS_ENABLED
+ EATEST_VERIFY(emcA.mStatus == true);
+#else
+ EATEST_VERIFY(emcA.mStatus == false);
+#endif
+ EA_UNUSED(emcB);
+
+ except_move_no_copy emncA;
+ except_move_no_copy emncB =
+ eastl::move_if_noexcept(emncA); // emncB should be constructed via except_move_no_copy(except_move_no_copy&&)
+ EATEST_VERIFY(emncA.mStatus == false);
+ EA_UNUSED(emncB);
+#endif
+
+ return nErrorCount;
+}
+
+static int TestUtilityIntegerSequence()
+{
+ using namespace eastl;
+ int nErrorCount = 0;
+#if EASTL_VARIADIC_TEMPLATES_ENABLED
+// Android clang chokes with an internal compiler error on make_integer_sequence
+#if !defined(EA_PLATFORM_ANDROID)
+ EATEST_VERIFY((integer_sequence<int, 0, 1, 2, 3, 4>::size() == 5));
+ EATEST_VERIFY((make_integer_sequence<int, 5>::size() == 5));
+#endif
+ EATEST_VERIFY((index_sequence<0, 1, 2, 3, 4>::size() == 5));
+ EATEST_VERIFY((make_index_sequence<5>::size() == 5));
+#endif // EASTL_VARIADIC_TEMPLATES_ENABLED
+
+ return nErrorCount;
+}
+
+static int TestUtilityExchange()
+{
+ int nErrorCount = 0;
+
+ {
+ int a = 0;
+ auto r = eastl::exchange(a, 1);
+
+ EATEST_VERIFY(r == 0);
+ EATEST_VERIFY(a == 1);
+ }
+
+ {
+ int a = 0;
+ auto r = eastl::exchange(a, 1.78);
+
+ EATEST_VERIFY(r == 0);
+ EATEST_VERIFY(a == 1);
+ }
+
+ {
+ int a = 0;
+ auto r = eastl::exchange(a, 1.78f);
+
+ EATEST_VERIFY(r == 0);
+ EATEST_VERIFY(a == 1);
+ }
+
+ {
+ int a = 0, b = 1;
+ auto r = eastl::exchange(a, b);
+
+ EATEST_VERIFY(r == 0);
+ EATEST_VERIFY(a == 1);
+ EATEST_VERIFY(b == 1);
+ }
+
+ {
+ bool b = true;
+
+ auto r = eastl::exchange(b, true);
+ EATEST_VERIFY(r);
+
+ r = eastl::exchange(b, false);
+ EATEST_VERIFY(r);
+ EATEST_VERIFY(!b);
+
+ r = eastl::exchange(b, true);
+ EATEST_VERIFY(!r);
+ EATEST_VERIFY(b);
+ }
+
+ {
+ TestObject::Reset();
+
+ TestObject a(42);
+ auto r = eastl::exchange(a, TestObject(24));
+
+ EATEST_VERIFY(r.mX == 42);
+ EATEST_VERIFY(a.mX == 24);
+ }
+
+ {
+ const char* const pElectronicArts = "Electronic Arts";
+ const char* const pEAVancouver = "EA Vancouver";
+
+ eastl::string a(pElectronicArts);
+ auto r = eastl::exchange(a, pEAVancouver);
+
+ EATEST_VERIFY(r == pElectronicArts);
+ EATEST_VERIFY(a == pEAVancouver);
+
+ r = eastl::exchange(a, "EA Standard Template Library");
+ EATEST_VERIFY(a == "EA Standard Template Library");
+ }
+
+ // Construct pair using single move constructor
+ {
+ struct TestPairSingleMoveConstructor
+ {
+ void test(int&& val)
+ {
+ eastl::pair<int,int> p(eastl::pair_first_construct, eastl::move(val));
+ }
+ };
+
+ int i1 = 1;
+ TestPairSingleMoveConstructor test;
+ test.test(eastl::move(i1));
+ }
+
+ // User reported regression where via reference collapsing, we see the same single element ctor defined twice.
+ //
+ // T = const U&
+ // pair(const T&) -> pair(const const U& &) -> pair(const U&)
+ // pair(T&&) -> pair(const U& &&) -> pair(const U&)
+ {
+ struct FooType {};
+
+ using VectorOfPairWithReference = eastl::vector<eastl::pair<const FooType&, float>>;
+
+ VectorOfPairWithReference v;
+ }
+
+ return nErrorCount;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// TestUtility
+//
+int TestUtility()
+{
+ int nErrorCount = 0;
+
+ nErrorCount += TestUtilityPair();
+ nErrorCount += TestUtilityRelops();
+ nErrorCount += TestUtilitySwap();
+ nErrorCount += TestUtilityMove();
+ nErrorCount += TestUtilityIntegerSequence();
+ nErrorCount += TestUtilityExchange();
+
+ return nErrorCount;
+}