1 /////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) Electronic Arts Inc. All rights reserved.
3 /////////////////////////////////////////////////////////////////////////////
4 
5 #include "EASTLTest.h"
6 #include <EASTL/utility.h>
7 #include <EAStdC/EAString.h>
8 
9 struct BasicObject
10 {
11 	int mX;
BasicObjectBasicObject12 	BasicObject(int x) : mX(x) {}
13 };
14 
operator ==(const BasicObject & t1,const BasicObject & t2)15 inline bool operator==(const BasicObject& t1, const BasicObject& t2) { return t1.mX == t2.mX; }
16 
operator <(const BasicObject & t1,const BasicObject & t2)17 inline bool operator<(const BasicObject& t1, const BasicObject& t2) { return t1.mX < t2.mX; }
18 
19 ///////////////////////////////////////////////////////////////////////////////
20 // TestUtilityPair
21 //
TestUtilityPair()22 static int TestUtilityPair()
23 {
24 	using namespace eastl;
25 
26 	int nErrorCount = 0;
27 
28 	{
29 		int _0 = 0, _2 = 2, _3 = 3;
30 		float _1f = 1.f;
31 
32 		// pair();
33 		pair<int, float> ifPair1;
34 		EATEST_VERIFY((ifPair1.first == 0) && (ifPair1.second == 0.f));
35 
36 		// pair(const T1& x, const T2& y);
37 		pair<int, float> ifPair2(_0, _1f);
38 		EATEST_VERIFY((ifPair2.first == 0) && (ifPair2.second == 1.f));
39 
40 		// template <typename U, typename V>
41 		// pair(U&& u, V&& v);
42 		pair<int, float> ifPair3(int(0), float(1.f));
43 		EATEST_VERIFY((ifPair3.first == 0) && (ifPair3.second == 1.f));
44 
45 		// template <typename U>
46 		// pair(U&& x, const T2& y);
47 		const float fConst1 = 1.f;
48 		pair<int, float> ifPair4(int(0), fConst1);
49 		EATEST_VERIFY((ifPair4.first == 0) && (ifPair4.second == 1.f));
50 
51 		// template <typename V>
52 		// pair(const T1& x, V&& y);
53 		const int intConst0 = 0;
54 		pair<int, float> ifPair5(intConst0, float(1.f));
55 		EATEST_VERIFY((ifPair5.first == 0) && (ifPair5.second == 1.f));
56 
57 		pair<const int, const int> constIntPair(_2, _3);
58 		EATEST_VERIFY((constIntPair.first == 2) && (constIntPair.second == 3));
59 
60 		// pair(const pair&) = default;
61 		pair<int, float> ifPair2Copy(ifPair2);
62 		EATEST_VERIFY((ifPair2Copy.first == 0) && (ifPair2Copy.second == 1.f));
63 
64 		pair<const int, const int> constIntPairCopy(constIntPair);
65 		EATEST_VERIFY((constIntPairCopy.first == 2) && (constIntPairCopy.second == 3));
66 
67 		// template<typename U, typename V>
68 		// pair(const pair<U, V>& p);
69 		pair<long, double> idPair2(ifPair2);
70 		EATEST_VERIFY((idPair2.first == 0) && (idPair2.second == 1.0));
71 
72 		// pair(pair&& p);
73 
74 		// template<typename U, typename V>
75 		// pair(pair<U, V>&& p);
76 
77 		// pair& operator=(const pair& p);
78 
79 		// template<typename U, typename V>
80 		// pair& operator=(const pair<U, V>& p);
81 
82 		// pair& operator=(pair&& p);
83 
84 		// template<typename U, typename V>
85 		// pair& operator=(pair<U, V>&& p);
86 
87 		// void swap(pair& p);
88 
89 		// use_self, use_first, use_second
90 		use_self<pair<int, float> > usIFPair;
91 		use_first<pair<int, float> > u1IFPair;
92 		use_second<pair<int, float> > u2IFPair;
93 
94 		ifPair2 = usIFPair(ifPair2);
95 		EATEST_VERIFY((ifPair2.first == 0) && (ifPair2.second == 1));
96 
97 		int first = u1IFPair(ifPair2);
98 		EATEST_VERIFY(first == 0);
99 
100 		float second = u2IFPair(ifPair2);
101 		EATEST_VERIFY(second == 1);
102 
103 		// make_pair
104 		pair<int, float> p1 = make_pair(int(0), float(1));
105 		EATEST_VERIFY((p1.first == 0) && (p1.second == 1.f));
106 
107 		pair<int, float> p2 = make_pair_ref(int(0), float(1));
108 		EATEST_VERIFY((p2.first == 0) && (p2.second == 1.f));
109 
110 		pair<const char*, int> p3 = eastl::make_pair("a", 1);
111 		EATEST_VERIFY((EA::StdC::Strcmp(p3.first, "a") == 0) && (p2.second == 1));
112 
113 		pair<const char*, int> p4 = eastl::make_pair<const char*, int>("a", 1);
114 		EATEST_VERIFY((EA::StdC::Strcmp(p4.first, "a") == 0) && (p4.second == 1));
115 
116 		pair<int, const char*> p5 = eastl::make_pair<int, const char*>(1, "b");
117 		EATEST_VERIFY((p5.first == 1) && (EA::StdC::Strcmp(p5.second, "b") == 0));
118 
119 #if !defined(EA_COMPILER_NO_AUTO)
120 		auto p60 = eastl::make_pair("a", "b");  // Different strings of same length of 1.
121 		EATEST_VERIFY((EA::StdC::Strcmp(p60.first, "a") == 0) && (EA::StdC::Strcmp(p60.second, "b") == 0));
122 
123 		auto p61 = eastl::make_pair("ab", "cd");  // Different strings of same length > 1.
124 		EATEST_VERIFY((EA::StdC::Strcmp(p61.first, "ab") == 0) && (EA::StdC::Strcmp(p61.second, "cd") == 0));
125 
126 		auto p62 = eastl::make_pair("abc", "bcdef");  // Different strings of different length.
127 		EATEST_VERIFY((EA::StdC::Strcmp(p62.first, "abc") == 0) && (EA::StdC::Strcmp(p62.second, "bcdef") == 0));
128 
129 		char strA[] = "a";
130 		auto p70 = eastl::make_pair(strA, strA);
131 		EATEST_VERIFY((EA::StdC::Strcmp(p70.first, "a") == 0) && (EA::StdC::Strcmp(p70.second, "a") == 0));
132 
133 		char strBC[] = "bc";
134 		auto p71 = eastl::make_pair(strA, strBC);
135 		EATEST_VERIFY((EA::StdC::Strcmp(p71.first, "a") == 0) && (EA::StdC::Strcmp(p71.second, "bc") == 0));
136 
137 		const char cstrA[] = "a";
138 		auto p80 = eastl::make_pair(cstrA, cstrA);
139 		EATEST_VERIFY((EA::StdC::Strcmp(p80.first, "a") == 0) && (EA::StdC::Strcmp(p80.second, "a") == 0));
140 
141 		const char cstrBC[] = "bc";
142 		auto p81 = eastl::make_pair(cstrA, cstrBC);
143 		EATEST_VERIFY((EA::StdC::Strcmp(p81.first, "a") == 0) && (EA::StdC::Strcmp(p81.second, "bc") == 0));
144 #endif
145 	}
146 
147 	{
148 // One-off tests and regressions
149 
150 #if EASTL_PAIR_CONFORMANCE  // See http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#811
151 		pair<char*, char*> zeroLiteralPair(0, 0);
152 		EATEST_VERIFY((zeroLiteralPair.first == NULL) && (zeroLiteralPair.second == NULL));
153 #endif
154 
155 		// template<typename U>
156 		// pair(U&& x, const T2& y)
157 		typedef eastl::pair<uint16_t, const char8_t*> LCIDMapping;
158 		LCIDMapping lcidMappingArray[1] = {LCIDMapping(0x0036, "af")};  // Note that 0x0036 is of type int.
159 		EATEST_VERIFY((lcidMappingArray[0].first == 0x0036));
160 
161 		// template<typename V>
162 		// pair(const T1& x, V&& y)
163 		typedef eastl::pair<const char8_t*, uint16_t> LCIDMapping2;
164 		LCIDMapping2 lcidMapping2Array[1] = {LCIDMapping2("af", 0x0036)};
165 		EATEST_VERIFY((lcidMapping2Array[0].second == 0x0036));
166 
167 // The following code was giving an EDG compiler:
168 //       error 145: a value of type "int" cannot be used to initialize
169 //       an entity of type "void *" second(eastl::forward<V>(v)) {}
170 // template <typename U, typename V>
171 // pair(U&& u, V&& v);
172 #if EASTL_PAIR_CONFORMANCE
173 		typedef eastl::pair<float*, void*> TestPair1;
174 		float fOne = 1.f;
175 		TestPair1 testPair1(&fOne, NULL);
176 		EATEST_VERIFY(*testPair1.first == 1.f);
177 #endif
178 	}
179 
180 	return nErrorCount;
181 }
182 
183 ///////////////////////////////////////////////////////////////////////////////
184 // TestUtilityRelops
185 //
TestUtilityRelops()186 static int TestUtilityRelops()
187 {
188 	int nErrorCount = 0;
189 
190 	{
191 		using namespace eastl::rel_ops;  // Defines default versions of operators !=, <, >, <=, >= based on == and <.
192 
193 		BasicObject bo1(1), bo2(2);
194 
195 		EATEST_VERIFY(!(bo1 == bo2));
196 		EATEST_VERIFY((bo1 != bo2));
197 		EATEST_VERIFY((bo1 < bo2));
198 		EATEST_VERIFY(!(bo1 > bo2));
199 		EATEST_VERIFY((bo1 <= bo2));
200 		EATEST_VERIFY(!(bo1 >= bo2));
201 	}
202 
203 	return nErrorCount;
204 }
205 
206 // ThrowSwappable
207 struct ThrowSwappable
208 {
209 };
210 
swap(ThrowSwappable & x,ThrowSwappable & y)211 void swap(ThrowSwappable& x, ThrowSwappable& y) EA_NOEXCEPT_IF(false)
212 {
213 	ThrowSwappable temp(x);
214 	x = y;
215 	y = temp;
216 
217 #if EASTL_EXCEPTIONS_ENABLED
218 	throw int();
219 #endif
220 }
221 
222 #if EASTL_TYPE_TRAIT_is_nothrow_swappable_CONFORMANCE
223 // NoThrowSwappable
224 struct NoThrowSwappable
225 {
226 };
227 
swap(NoThrowSwappable & x,NoThrowSwappable & y)228 void swap(NoThrowSwappable& x, NoThrowSwappable& y) EA_NOEXCEPT_IF(true)
229 {
230 	NoThrowSwappable temp(x);
231 	x = y;
232 	y = temp;
233 }
234 #endif
235 
236 struct Swappable1 {};
237 struct Swappable2 {};
238 struct Swappable3 {};
swap(Swappable1 &,Swappable2 &)239 void swap(Swappable1&, Swappable2&) {}
swap(Swappable2 &,Swappable1 &)240 void swap(Swappable2&, Swappable1&) {}
swap(Swappable1 &,Swappable3 &)241 void swap(Swappable1&, Swappable3&) {} // intentionally missing 'swap(Swappable3, Swappable1)'
242 
243 
TestUtilitySwap()244 static int TestUtilitySwap()
245 {
246 	int nErrorCount = 0;
247 
248 // is_swappable
249 // is_nothrow_swappable
250 #if EASTL_TYPE_TRAIT_is_swappable_CONFORMANCE
251 	static_assert((eastl::is_swappable<int>::value == true), "is_swappable failure");
252 	static_assert((eastl::is_swappable<eastl::vector<int> >::value == true), "is_swappable failure");
253 	static_assert((eastl::is_swappable<ThrowSwappable>::value == true), "is_swappable failure");
254 	#if EASTL_VARIABLE_TEMPLATES_ENABLED
255 		static_assert((eastl::is_swappable_v<int> == true), "is_swappable failure");
256 		static_assert((eastl::is_swappable_v<eastl::vector<int> > == true), "is_swappable failure");
257 		static_assert((eastl::is_swappable_v<ThrowSwappable> == true), "is_swappable failure");
258 	#endif
259 // Need to come up with a class that's not swappable. How do we do that, given the universal swap template?
260 // static_assert((eastl::is_swappable<?>::value  == false), "is_swappable failure");
261 #endif
262 
263 #if EASTL_TYPE_TRAIT_is_nothrow_swappable_CONFORMANCE
264 	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.
265 	static_assert((eastl::is_nothrow_swappable<eastl::vector<int> >::value == false), "is_nothrow_swappable failure");
266 	static_assert((eastl::is_nothrow_swappable<ThrowSwappable>::value == false), "is_nothrow_swappable failure");
267 	static_assert((eastl::is_nothrow_swappable<NoThrowSwappable>::value == true), "is_nothrow_swappable failure");
268 	#if EASTL_VARIABLE_TEMPLATES_ENABLED
269 		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.
270 		static_assert((eastl::is_nothrow_swappable_v<eastl::vector<int>> == false), "is_nothrow_swappable failure");
271 		static_assert((eastl::is_nothrow_swappable_v<ThrowSwappable> == false), "is_nothrow_swappable failure");
272 		static_assert((eastl::is_nothrow_swappable_v<NoThrowSwappable> == true), "is_nothrow_swappable failure");
273 	#endif
274 #endif
275 
276 #if EASTL_VARIADIC_TEMPLATES_ENABLED
277 // is_swappable_with
278 // is_nothrow_swappable_with
279 	static_assert(eastl::is_swappable_with<int&, int&>::value, "is_swappable_with failure");
280 	static_assert(!eastl::is_swappable_with<int, int>::value, "is_swappable_with failure");
281 	static_assert(!eastl::is_swappable_with<int&, int>::value, "is_swappable_with failure");
282 	static_assert(!eastl::is_swappable_with<int, int&>::value, "is_swappable_with failure");
283 	static_assert(!eastl::is_swappable_with<int, short>::value, "is_swappable_with failure");
284 	static_assert(!eastl::is_swappable_with<int, long>::value, "is_swappable_with failure");
285 	static_assert(!eastl::is_swappable_with<int, eastl::vector<int>>::value, "is_swappable_with failure");
286 	static_assert(!eastl::is_swappable_with<void, void>::value, "is_swappable_with failure");
287 	static_assert(!eastl::is_swappable_with<int, void>::value, "is_swappable_with failure");
288 	static_assert(!eastl::is_swappable_with<void, int>::value, "is_swappable_with failure");
289 	static_assert(!eastl::is_swappable_with<ThrowSwappable, ThrowSwappable>::value, "is_swappable_with failure");
290 	static_assert(eastl::is_swappable_with<ThrowSwappable&, ThrowSwappable&>::value, "is_swappable_with failure");
291 	static_assert(eastl::is_swappable_with<Swappable1&, Swappable1&>::value, "is_swappable_with failure");
292 	static_assert(eastl::is_swappable_with<Swappable1&, Swappable2&>::value, "is_swappable_with failure");
293 	static_assert(eastl::is_swappable_with<Swappable2&, Swappable1&>::value, "is_swappable_with failure");
294 
295     #if EASTL_VARIABLE_TEMPLATES_ENABLED
296 		static_assert(eastl::is_swappable_with_v<int&, int&>, "is_swappable_with_v failure");
297 		static_assert(!eastl::is_swappable_with_v<int, int>, "is_swappable_with_v failure");
298 		static_assert(!eastl::is_swappable_with_v<int&, int>, "is_swappable_with_v failure");
299 		static_assert(!eastl::is_swappable_with_v<int, int&>, "is_swappable_with_v failure");
300 		static_assert(!eastl::is_swappable_with_v<int, short>, "is_swappable_with_v failure");
301 		static_assert(!eastl::is_swappable_with_v<int, long>, "is_swappable_with_v failure");
302 		static_assert(!eastl::is_swappable_with_v<int, eastl::vector<int>>, "is_swappable_with_v failure");
303 	    static_assert(!eastl::is_swappable_with_v<void, void>, "is_swappable_with_v failure");
304 	    static_assert(!eastl::is_swappable_with_v<int, void>, "is_swappable_with_v failure");
305 	    static_assert(!eastl::is_swappable_with_v<void, int>, "is_swappable_with_v failure");
306 		static_assert(!eastl::is_swappable_with_v<ThrowSwappable, ThrowSwappable>, "is_swappable_with_v failure");
307 		static_assert(eastl::is_swappable_with_v<ThrowSwappable&, ThrowSwappable&>, "is_swappable_with_v failure");
308 		static_assert(eastl::is_swappable_with_v<Swappable1&, Swappable1&>, "is_swappable_with_v failure");
309 		static_assert(eastl::is_swappable_with_v<Swappable1&, Swappable2&>, "is_swappable_with_v failure");
310 		static_assert(eastl::is_swappable_with_v<Swappable2&, Swappable1&>, "is_swappable_with_v failure");
311     #endif // EASTL_VARIABLE_TEMPLATES_ENABLED
312 
313 #if EASTL_TYPE_TRAIT_is_nothrow_swappable_with_CONFORMANCE
314 	static_assert(eastl::is_nothrow_swappable_with<int&, int&>::value, "is_nothrow_swappable_with failure");
315 	static_assert(!eastl::is_nothrow_swappable_with<int, int>::value, "is_nothrow_swappable_with failure");
316 	static_assert(!eastl::is_nothrow_swappable_with<int&, int>::value, "is_nothrow_swappable_with failure");
317 	static_assert(!eastl::is_nothrow_swappable_with<int, int&>::value, "is_nothrow_swappable_with failure");
318 	static_assert(!eastl::is_nothrow_swappable_with<int, short>::value, "is_nothrow_swappable_with failure");
319 	static_assert(!eastl::is_nothrow_swappable_with<int, long>::value, "is_nothrow_swappable_with failure");
320 	static_assert(!eastl::is_nothrow_swappable_with<int, eastl::vector<int>>::value, "is_nothrow_swappable_with failure");
321 	static_assert(!eastl::is_nothrow_swappable_with<void, void>::value, "is_nothrow_swappable_with failure");
322 	static_assert(!eastl::is_nothrow_swappable_with<int, void>::value, "is_nothrow_swappable_with failure");
323 	static_assert(!eastl::is_nothrow_swappable_with<void, int>::value, "is_nothrow_swappable_with failure");
324 	static_assert(!eastl::is_nothrow_swappable_with<ThrowSwappable, ThrowSwappable>::value, "is_nothrow_swappable_with failure");
325 	static_assert(!eastl::is_nothrow_swappable_with<ThrowSwappable&, ThrowSwappable&>::value, "is_nothrow_swappable_with failure");
326 	static_assert(!eastl::is_nothrow_swappable_with<NoThrowSwappable, NoThrowSwappable>::value, "is_nothrow_swappable_with failure");
327 	static_assert(eastl::is_nothrow_swappable_with<NoThrowSwappable&, NoThrowSwappable&>::value, "is_nothrow_swappable_with failure");
328 
329     #if EASTL_VARIABLE_TEMPLATES_ENABLED
330 		static_assert(eastl::is_nothrow_swappable_with_v<int&, int&>, "is_nothrow_swappable_with_v failure");
331 		static_assert(!eastl::is_nothrow_swappable_with_v<int, int>, "is_nothrow_swappable_with_v failure");
332 		static_assert(!eastl::is_nothrow_swappable_with_v<int&, int>, "is_nothrow_swappable_with_v failure");
333 		static_assert(!eastl::is_nothrow_swappable_with_v<int, int&>, "is_nothrow_swappable_with_v failure");
334 		static_assert(!eastl::is_nothrow_swappable_with_v<int, short>, "is_nothrow_swappable_with_v failure");
335 		static_assert(!eastl::is_nothrow_swappable_with_v<int, long>, "is_nothrow_swappable_with_v failure");
336 		static_assert(!eastl::is_nothrow_swappable_with_v<int, eastl::vector<int>>, "is_nothrow_swappable_with_v failure");
337 	    static_assert(!eastl::is_nothrow_swappable_with_v<void, void>, "is_nothrow_swappable_with_v failure");
338 	    static_assert(!eastl::is_nothrow_swappable_with_v<int, void>, "is_nothrow_swappable_with_v failure");
339 	    static_assert(!eastl::is_nothrow_swappable_with_v<void, int>, "is_nothrow_swappable_with_v failure");
340 		static_assert(!eastl::is_nothrow_swappable_with_v<ThrowSwappable, ThrowSwappable>, "is_nothrow_swappable_with_v failure");
341 		static_assert(!eastl::is_nothrow_swappable_with_v<ThrowSwappable&, ThrowSwappable&>, "is_nothrow_swappable_with_v failure");
342 		static_assert(!eastl::is_nothrow_swappable_with_v<NoThrowSwappable, NoThrowSwappable>, "is_nothrow_swappable_with_v failure");
343 		static_assert(eastl::is_nothrow_swappable_with_v<NoThrowSwappable&, NoThrowSwappable&>, "is_nothrow_swappable_with_v failure");
344     #endif // EASTL_VARIABLE_TEMPLATES_ENABLED
345 #endif
346 #endif // EASTL_VARIADIC_TEMPLATES_ENABLED
347 
348 	return nErrorCount;
349 }
350 
351 #if !defined(EA_COMPILER_NO_NOEXCEPT)
352 
353 ///////////////////////////////////////////////////////////////////////////////////////////////////////////
354 // Warning C4626 warns against an implicitly deleted move assignment operator.
355 // This warning was disabled by default in VS2013. It was enabled by default in
356 // VS2015.  Since the the tests below are explicitly testing move construction
357 // of the various classes explicitly deleting the move assignment to remove the
358 // warning is safe.
359 //
360 // https://msdn.microsoft.com/en-us/library/23k5d385.aspx
361 
362 struct noexcept_move_copy
363 {
364 	bool mStatus;
365 
noexcept_move_copynoexcept_move_copy366 	noexcept_move_copy() : mStatus(true) {}
367 
368 	noexcept_move_copy(const noexcept_move_copy&) = default;
369 
noexcept_move_copynoexcept_move_copy370 	noexcept_move_copy(noexcept_move_copy&& r) noexcept { r.mStatus = false; }
371 
372 	noexcept_move_copy& operator=(const noexcept_move_copy&) = delete;  // required as VS2015 enabled C4626 by default.
373 };
374 
375 struct noexcept_move_no_copy
376 {
377 	bool mStatus;
378 
noexcept_move_no_copynoexcept_move_no_copy379 	noexcept_move_no_copy() : mStatus(true) {}
380 
381 	noexcept_move_no_copy(const noexcept_move_no_copy&) = delete;
382 
noexcept_move_no_copynoexcept_move_no_copy383 	noexcept_move_no_copy(noexcept_move_no_copy&& r) noexcept { r.mStatus = false; };
384 
385 	noexcept_move_no_copy& operator=(const noexcept_move_no_copy&) = delete;  // required as VS2015 enabled C4626 by default.
386 };
387 
388 struct except_move_copy
389 {
390 	bool mStatus;
391 
except_move_copyexcept_move_copy392 	except_move_copy() : mStatus(true) {}
393 
394 	except_move_copy(const except_move_copy&) = default;
395 
except_move_copyexcept_move_copy396 	except_move_copy(except_move_copy&& r) noexcept(false) { r.mStatus = false; };
397 
398 	except_move_copy& operator=(const except_move_copy&) = delete;  // required as VS2015 enabled C4626 by default.
399 };
400 
401 struct except_move_no_copy
402 {
403 	bool mStatus;
404 
except_move_no_copyexcept_move_no_copy405 	except_move_no_copy() : mStatus(true) {}
406 
407 	except_move_no_copy(const except_move_no_copy&) = delete;
408 
except_move_no_copyexcept_move_no_copy409 	except_move_no_copy(except_move_no_copy&& r) noexcept(false) { r.mStatus = false; };
410 
411 	except_move_no_copy& operator=(const except_move_no_copy&) = delete;  // required as VS2015 enabled C4626 by default.
412 };
413 #endif
414 
TestUtilityMove()415 static int TestUtilityMove()
416 {
417 	int nErrorCount = 0;
418 
419 // move_if_noexcept
420 #if !defined(EA_COMPILER_NO_NOEXCEPT)
421 	noexcept_move_copy nemcA;
422 	noexcept_move_copy nemcB =
423 		eastl::move_if_noexcept(nemcA);  // nemcB should be constructed via noexcept_move_copy(noexcept_move_copy&&)
424 	EATEST_VERIFY(nemcA.mStatus == false);
425 	EA_UNUSED(nemcB);
426 
427 	noexcept_move_no_copy nemncA;
428 	noexcept_move_no_copy nemncB = eastl::move_if_noexcept(
429 		nemncA);  // nemncB should be constructed via noexcept_move_no_copy(noexcept_move_no_copy&&)
430 	EATEST_VERIFY(nemncA.mStatus == false);
431 	EA_UNUSED(nemncB);
432 
433 	except_move_copy emcA;
434 	except_move_copy emcB = eastl::move_if_noexcept(
435 		emcA);  // emcB should be constructed via except_move_copy(const except_move_copy&) if exceptions are enabled.
436 #if EASTL_EXCEPTIONS_ENABLED
437 	EATEST_VERIFY(emcA.mStatus == true);
438 #else
439 	EATEST_VERIFY(emcA.mStatus == false);
440 #endif
441 	EA_UNUSED(emcB);
442 
443 	except_move_no_copy emncA;
444 	except_move_no_copy emncB =
445 		eastl::move_if_noexcept(emncA);  // emncB should be constructed via except_move_no_copy(except_move_no_copy&&)
446 	EATEST_VERIFY(emncA.mStatus == false);
447 	EA_UNUSED(emncB);
448 #endif
449 
450 	return nErrorCount;
451 }
452 
TestUtilityIntegerSequence()453 static int TestUtilityIntegerSequence()
454 {
455 	using namespace eastl;
456 	int nErrorCount = 0;
457 #if EASTL_VARIADIC_TEMPLATES_ENABLED
458 // Android clang chokes with an internal compiler error on make_integer_sequence
459 #if !defined(EA_PLATFORM_ANDROID)
460 	EATEST_VERIFY((integer_sequence<int, 0, 1, 2, 3, 4>::size() == 5));
461 	EATEST_VERIFY((make_integer_sequence<int, 5>::size() == 5));
462 #endif
463 	EATEST_VERIFY((index_sequence<0, 1, 2, 3, 4>::size() == 5));
464 	EATEST_VERIFY((make_index_sequence<5>::size() == 5));
465 #endif  // EASTL_VARIADIC_TEMPLATES_ENABLED
466 
467 	return nErrorCount;
468 }
469 
TestUtilityExchange()470 static int TestUtilityExchange()
471 {
472 	int nErrorCount = 0;
473 
474 	{
475 		int a = 0;
476 		auto r = eastl::exchange(a, 1);
477 
478 		EATEST_VERIFY(r == 0);
479 		EATEST_VERIFY(a == 1);
480 	}
481 
482 	{
483 		int a = 0;
484 		auto r = eastl::exchange(a, 1.78);
485 
486 		EATEST_VERIFY(r == 0);
487 		EATEST_VERIFY(a == 1);
488 	}
489 
490 	{
491 		int a = 0;
492 		auto r = eastl::exchange(a, 1.78f);
493 
494 		EATEST_VERIFY(r == 0);
495 		EATEST_VERIFY(a == 1);
496 	}
497 
498 	{
499 		int a = 0, b = 1;
500 		auto r = eastl::exchange(a, b);
501 
502 		EATEST_VERIFY(r == 0);
503 		EATEST_VERIFY(a == 1);
504 		EATEST_VERIFY(b == 1);
505 	}
506 
507 	{
508 		bool b = true;
509 
510 		auto r = eastl::exchange(b, true);
511 		EATEST_VERIFY(r);
512 
513 		r = eastl::exchange(b, false);
514 		EATEST_VERIFY(r);
515 		EATEST_VERIFY(!b);
516 
517 		r = eastl::exchange(b, true);
518 		EATEST_VERIFY(!r);
519 		EATEST_VERIFY(b);
520 	}
521 
522 	{
523 		TestObject::Reset();
524 
525 		TestObject a(42);
526 		auto r = eastl::exchange(a, TestObject(24));
527 
528 		EATEST_VERIFY(r.mX == 42);
529 		EATEST_VERIFY(a.mX == 24);
530 	}
531 
532 	{
533 		const char* const pElectronicArts = "Electronic Arts";
534 		const char* const pEAVancouver = "EA Vancouver";
535 
536 		eastl::string a(pElectronicArts);
537 		auto r = eastl::exchange(a, pEAVancouver);
538 
539 		EATEST_VERIFY(r == pElectronicArts);
540 		EATEST_VERIFY(a == pEAVancouver);
541 
542 		r = eastl::exchange(a, "EA Standard Template Library");
543 		EATEST_VERIFY(a == "EA Standard Template Library");
544 	}
545 
546 	// Construct pair using single move constructor
547 	{
548 		struct TestPairSingleMoveConstructor
549 		{
550 			void test(int&& val)
551 			{
552 				eastl::pair<int,int> p(eastl::pair_first_construct, eastl::move(val));
553 			}
554 		};
555 
556 		int i1 = 1;
557 		TestPairSingleMoveConstructor test;
558 		test.test(eastl::move(i1));
559 	}
560 
561 	return nErrorCount;
562 }
563 
564 ///////////////////////////////////////////////////////////////////////////////
565 // TestUtility
566 //
TestUtility()567 int TestUtility()
568 {
569 	int nErrorCount = 0;
570 
571 	nErrorCount += TestUtilityPair();
572 	nErrorCount += TestUtilityRelops();
573 	nErrorCount += TestUtilitySwap();
574 	nErrorCount += TestUtilityMove();
575 	nErrorCount += TestUtilityIntegerSequence();
576 	nErrorCount += TestUtilityExchange();
577 
578 	return nErrorCount;
579 }
580