1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) Electronic Arts Inc. All rights reserved.
3 ///////////////////////////////////////////////////////////////////////////////
4 
5 
6 #ifndef EASTL_UTILITY_H
7 #define EASTL_UTILITY_H
8 
9 
10 #include <EASTL/internal/config.h>
11 #include <EASTL/type_traits.h>
12 #include <EASTL/iterator.h>
13 #include <EASTL/functional.h>
14 #include <EASTL/internal/move_help.h>
15 #include <EABase/eahave.h>
16 
17 #include <EASTL/internal/integer_sequence.h>
18 #include <EASTL/internal/tuple_fwd_decls.h>
19 #include <EASTL/internal/in_place_t.h>
20 #include <EASTL/internal/piecewise_construct_t.h>
21 
22 #ifdef _MSC_VER
23 	#pragma warning(push)           // VC++ generates a bogus warning that you cannot code away.
24 	#pragma warning(disable: 4619)  // There is no warning number 'number'.
25 	#pragma warning(disable: 4217)  // Member template functions cannot be used for copy-assignment or copy-construction.
26 	#pragma warning(disable: 4512)  // 'class' : assignment operator could not be generated.  // This disabling would best be put elsewhere.
27 #endif
28 
29 #if defined(EA_PRAGMA_ONCE_SUPPORTED)
30 	#pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.
31 #endif
32 
33 
34 
35 namespace eastl
36 {
37 
38 	/// swap
39 	///
40 	/// Assigns the contents of a to b and the contents of b to a.
41 	/// A temporary instance of type T is created and destroyed
42 	/// in the process.
43 	///
44 	/// This function is used by numerous other algorithms, and as
45 	/// such it may in some cases be feasible and useful for the user
46 	/// to implement an override version of this function which is
47 	/// more efficient in some way.
48 	///
49 
50 	template <typename T>
swap(T & a,T & b)51 	inline void swap(T& a, T& b) EA_NOEXCEPT_IF(eastl::is_nothrow_move_constructible<T>::value && eastl::is_nothrow_move_assignable<T>::value)
52 	{
53 		T temp(EASTL_MOVE(a));  // EASTL_MOVE uses EASTL::move when available, else is a no-op.
54 		a = EASTL_MOVE(b);
55 		b = EASTL_MOVE(temp);
56 	}
57 
58 
59 	/// is_swappable
60 	///
61 	/// Determines if two types can be swapped via the swap function. This determines
62 	/// only if there is a swap function that matches the types and not if the assignments
63 	/// within the swap implementation are valid.
64 	/// Returns false for pre-C++11 compilers that don't support decltype.
65 	///
66 	/// This is a type trait, but it's not currently found within <type_traits.h>,
67 	/// as it's dependent on the swap algorithm, which is at a higher level than
68 	/// type traits.
69 	///
70 	/// Example usage:
71 	///     static_assert(is_swappable<int>::value, "int should be swappable");
72 	///
73 	#if defined(EA_COMPILER_NO_DECLTYPE)
74 		#define EASTL_TYPE_TRAIT_is_swappable_CONFORMANCE 0
75 
76 		template <typename>
77 		struct is_swappable
78 			: public eastl::false_type {};
79 	#else
80 		#define EASTL_TYPE_TRAIT_is_swappable_CONFORMANCE 1
81 
82 		// We declare this version of 'eastl::swap' to make compile-time existance checks for swap functions possible.
83 		//
84 		#if EASTL_VARIADIC_TEMPLATES_ENABLED
85 			eastl::unused swap(eastl::argument_sink, eastl::argument_sink);
86 		#else
87 			// Compilers that do not support variadic templates suffer from a bug with variable arguments list that
88 			// causes the construction of aligned types in unaligned memory. To prevent the aligned type construction we
89 			// accept the parameters by reference.
90 			eastl::unused swap(eastl::argument_sink&, eastl::argument_sink&);
91 		#endif
92 
93 		template <typename T>
94 		struct is_swappable
95 			: public integral_constant<bool, !eastl::is_same<decltype(swap(eastl::declval<T&>(), eastl::declval<T&>())), eastl::unused>::value> {}; // Don't prefix swap with eastl:: as we want to allow user-defined swaps via argument-dependent lookup.
96 	#endif
97 
98 	#if EASTL_VARIABLE_TEMPLATES_ENABLED
99         template <class T>
100         EA_CONSTEXPR bool is_swappable_v = is_swappable<T>::value;
101     #endif
102 
103 
104 
105 	/// is_nothrow_swappable
106 	///
107 	/// Evaluates to true if is_swappable, and swap is a nothrow function.
108 	/// returns false for pre-C++11 compilers that don't support nothrow.
109 	///
110 	/// This is a type trait, but it's not currently found within <type_traits.h>,
111 	/// as it's dependent on the swap algorithm, which is at a higher level than
112 	/// type traits.
113 	///
114 	#define EASTL_TYPE_TRAIT_is_nothrow_swappable_CONFORMANCE EASTL_TYPE_TRAIT_is_swappable_CONFORMANCE
115 
116 	template <typename T>
117 	struct is_nothrow_swappable_helper_noexcept_wrapper
118 		{ const static bool value = noexcept(swap(eastl::declval<T&>(), eastl::declval<T&>())); };
119 
120 	template <typename T, bool>
121 	struct is_nothrow_swappable_helper
122 		: public eastl::integral_constant<bool, is_nothrow_swappable_helper_noexcept_wrapper<T>::value> {}; // Don't prefix swap with eastl:: as we want to allow user-defined swaps via argument-dependent lookup.
123 
124 	template <typename T>
125 	struct is_nothrow_swappable_helper<T, false>
126 		: public eastl::false_type {};
127 
128 	template <typename T>
129 	struct is_nothrow_swappable
130 		: public eastl::is_nothrow_swappable_helper<T, eastl::is_swappable<T>::value> {};
131 
132 	#if EASTL_VARIABLE_TEMPLATES_ENABLED
133         template <class T>
134         EA_CONSTEXPR bool is_nothrow_swappable_v = is_nothrow_swappable<T>::value;
135     #endif
136 
137 
138 
139 	/// is_swappable_with
140 	///
141 	///
142 	template <typename T, typename U, bool OneTypeIsVoid = (eastl::is_void<T>::value || eastl::is_void<U>::value)>
143 	struct is_swappable_with_helper
144 	{
145 		// Don't prefix swap with eastl:: as we want to allow user-defined swaps via argument-dependent lookup.
146 	    static const bool value =
147 	        !eastl::is_same<decltype(swap(eastl::declval<T>(), eastl::declval<U>())), eastl::unused>::value &&
148 	        !eastl::is_same<decltype(swap(eastl::declval<U>(), eastl::declval<T>())), eastl::unused>::value;
149     };
150 
151 	template <typename T, typename U>
152 	struct is_swappable_with_helper<T,U, true> { static const bool value = false; };
153 
154     template<typename T, typename U>
155 	struct is_swappable_with
156 			: public eastl::bool_constant<is_swappable_with_helper<T, U>::value> {};
157 
158 	#if EASTL_VARIABLE_TEMPLATES_ENABLED
159         template <class T, class U>
160         EA_CONSTEXPR bool is_swappable_with_v = is_swappable_with<T, U>::value;
161     #endif
162 
163 
164 
165 	/// is_nothrow_swappable_with
166 	///
167 	///
168 	#if defined(EA_COMPILER_NO_DECLTYPE) || defined(EA_COMPILER_NO_NOEXCEPT)
169 		#define EASTL_TYPE_TRAIT_is_nothrow_swappable_with_CONFORMANCE 0
170 		template <typename T, typename U>
171 		struct is_nothrow_swappable_with_helper { static const bool value = false; };
172 	#else
173 		#define EASTL_TYPE_TRAIT_is_nothrow_swappable_with_CONFORMANCE 1
174 		template <typename T, typename U, bool OneTypeIsVoid = (eastl::is_void<T>::value || eastl::is_void<U>::value)>
175 		struct is_nothrow_swappable_with_helper
176 		{
177 	        // Don't prefix swap with eastl:: as we want to allow user-defined swaps via argument-dependent lookup.
178 	        static const bool value = noexcept(swap(eastl::declval<T>(), eastl::declval<U>())) &&
179 	                                  noexcept(swap(eastl::declval<U>(), eastl::declval<T>()));
180         };
181 
182 		template <typename T, typename U>
183 		struct is_nothrow_swappable_with_helper<T,U, true> { static const bool value = false; };
184 	#endif
185 
186     template <typename T, typename U>
187     struct is_nothrow_swappable_with : public eastl::bool_constant<is_nothrow_swappable_with_helper<T, U>::value> {};
188 
189     #if EASTL_VARIABLE_TEMPLATES_ENABLED
190         template <class T, class U>
191         EA_CONSTEXPR bool is_nothrow_swappable_with_v = is_nothrow_swappable_with<T, U>::value;
192     #endif
193 
194 
195 
196 	// iter_swap helper functions
197 	//
198 	template <bool bTypesAreEqual>
199 	struct iter_swap_impl
200 	{
201 		// Handles the false case, where *a and *b are different types.
202 		template <typename ForwardIterator1, typename ForwardIterator2>
203 		static void iter_swap(ForwardIterator1 a, ForwardIterator2 b)
204 		{
205 			typedef typename eastl::iterator_traits<ForwardIterator1>::value_type value_type_a;
206 
207 			value_type_a temp(EASTL_MOVE(*a)); // EASTL_MOVE uses EASTL::move when available, else is a no-op.
208 			*a = EASTL_MOVE(*b);
209 			*b = EASTL_MOVE(temp);
210 		}
211 	};
212 
213 	template <>
214 	struct iter_swap_impl<true>
215 	{
216 		template <typename ForwardIterator1, typename ForwardIterator2>
217 		static void iter_swap(ForwardIterator1 a, ForwardIterator2 b)
218 		{
219 			swap(*a, *b);  // Don't prefix swap with eastl:: as we want to allow user-defined swaps via argument-dependent lookup.
220 		}
221 	};
222 
223 
224 	/// iter_swap
225 	///
226 	/// Swaps the values of the elements the given iterators are pointing to.
227 	///
228 	/// Equivalent to swap(*a, *b), though the user can provide an override to
229 	/// iter_swap that is independent of an override which may exist for swap.
230 	///
231 	/// We provide a version of iter_swap which uses swap when the swapped types
232 	/// are equal but a manual implementation otherwise. We do this because the
233 	/// C++ standard defect report says that iter_swap(a, b) must be implemented
234 	/// as swap(*a, *b) when possible.
235 	///
236 	template <typename ForwardIterator1, typename ForwardIterator2>
237 	inline void iter_swap(ForwardIterator1 a, ForwardIterator2 b)
238 	{
239 		typedef typename eastl::iterator_traits<ForwardIterator1>::value_type value_type_a;
240 		typedef typename eastl::iterator_traits<ForwardIterator2>::value_type value_type_b;
241 		typedef typename eastl::iterator_traits<ForwardIterator1>::reference  reference_a;
242 		typedef typename eastl::iterator_traits<ForwardIterator2>::reference  reference_b;
243 
244 		eastl::iter_swap_impl<eastl::type_and<eastl::is_same<value_type_a, value_type_b>::value, eastl::is_same<value_type_a&, reference_a>::value, eastl::is_same<value_type_b&, reference_b>::value >::value >::iter_swap(a, b);
245 	}
246 
247 
248 
249 	/// swap_ranges
250 	///
251 	/// Swaps each of the elements in the range [first1, last1) with the
252 	/// corresponding element in the range [first2, first2 + (last1 - first1)).
253 	///
254 	/// Effects: For each nonnegative integer n < (last1 - first1),
255 	/// performs: swap(*(first1 + n), *(first2 + n)).
256 	///
257 	/// Requires: The two ranges [first1, last1) and [first2, first2 + (last1 - first1))
258 	/// shall not overlap.
259 	///
260 	/// Returns: first2 + (last1 - first1). That is, returns the end of the second range.
261 	///
262 	/// Complexity: Exactly 'last1 - first1' swaps.
263 	///
264 	template <typename ForwardIterator1, typename ForwardIterator2>
265 	inline ForwardIterator2
266 	swap_ranges(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2)
267 	{
268 		for(; first1 != last1; ++first1, ++first2)
269 			iter_swap(first1, first2); // Don't prefix swap with eastl:: as we want to allow user-defined swaps via argument-dependent lookup.
270 		return first2;
271 	}
272 
273 
274 	/// swap
275 	///
276 	/// C++11 array swap
277 	/// http://en.cppreference.com/w/cpp/algorithm/swap
278 	///
279 	template <typename T, size_t N>
280 	inline void
281 	swap(T (&a)[N], T (&b)[N]) EA_NOEXCEPT_IF(eastl::is_nothrow_swappable<T>::value)
282 	{
283 		eastl::swap_ranges(a, a + N, b);
284 	}
285 
286 
287 	/// exchange
288 	///
289 	/// Replaces the value of the first argument with the new value provided.
290 	/// The return value is the previous value of first argument.
291 	///
292 	/// http://en.cppreference.com/w/cpp/utility/exchange
293 	///
294 	template <typename T, typename U = T>
295 	inline T exchange(T& obj, U&& new_value)
296 	{
297 		T old_value = eastl::move(obj);
298 		obj = eastl::forward<U>(new_value);
299 		return old_value;
300 	}
301 
302 
303 	/// as_const
304 	///
305 	/// Converts a 'T&' into a 'const T&' which simplifies calling const functions on non-const objects.
306 	///
307 	/// http://en.cppreference.com/w/cpp/utility/as_const
308 	///
309 	/// C++ proposal paper:
310 	/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4380.html
311 	///
312 	template <class T>
313 	EA_CONSTEXPR typename eastl::add_const<T>::type& as_const(T& t) EA_NOEXCEPT
314 		{ return t; }
315 
316 	// The C++17 forbids 'eastl::as_const' from accepting rvalues.  Passing an rvalue reference to 'eastl::as_const'
317 	// generates an 'const T&' or const lvalue reference to a temporary object.
318 	template <class T>
319 	void as_const(const T&&) = delete;
320 
321 
322     ///////////////////////////////////////////////////////////////////////
323 	/// rel_ops
324 	///
325 	/// rel_ops allow the automatic generation of operators !=, >, <=, >= from
326 	/// just operators == and <. These are intentionally in the rel_ops namespace
327 	/// so that they don't conflict with other similar operators. To use these
328 	/// operators, add "using namespace std::rel_ops;" to an appropriate place in
329 	/// your code, usually right in the function that you need them to work.
330 	/// In fact, you will very likely have collision problems if you put such
331 	/// using statements anywhere other than in the .cpp file like so and may
332 	/// also have collisions when you do, as the using statement will affect all
333 	/// code in the module. You need to be careful about use of rel_ops.
334 	///
335 	namespace rel_ops
336 	{
337 		template <typename T>
338 		inline bool operator!=(const T& x, const T& y)
339 			{ return !(x == y); }
340 
341 		template <typename T>
342 		inline bool operator>(const T& x, const T& y)
343 			{ return (y < x); }
344 
345 		template <typename T>
346 		inline bool operator<=(const T& x, const T& y)
347 			{ return !(y < x); }
348 
349 		template <typename T>
350 		inline bool operator>=(const T& x, const T& y)
351 			{ return !(x < y); }
352 	}
353 
354 
355 	///////////////////////////////////////////////////////////////////////
356 	/// pair_first_construct
357 	///
358 	/// Disambiguates when a user is requesting the 'single first element' pair constructor.
359 	///
360 	struct pair_first_construct_t {};
361 	EA_CONSTEXPR pair_first_construct_t pair_first_construct = pair_first_construct_t();
362 
363 
364 	///////////////////////////////////////////////////////////////////////
365 	/// pair
366 	///
367 	/// Implements a simple pair, just like the C++ std::pair.
368 	///
369 	template <typename T1, typename T2>
370 	struct pair
371 	{
372 		typedef T1           first_type;
373 		typedef T2           second_type;
374 		typedef pair<T1, T2> this_type;
375 
376 		T1 first;
377 		T2 second;
378 
379 		template <typename TT1 = T1,
380 		          typename TT2 = T2,
381 		          class = eastl::enable_if_t<eastl::is_default_constructible_v<TT1> &&
382 		                                     eastl::is_default_constructible_v<TT2>>>
383 		EA_CONSTEXPR pair()
384 		    : first(), second()
385 		{
386 		}
387 
388 	#if EASTL_ENABLE_PAIR_FIRST_ELEMENT_CONSTRUCTOR
389 		template <typename TT2 = T2, typename = eastl::enable_if_t<eastl::is_default_constructible_v<TT2>>>
390 		EA_CPP14_CONSTEXPR pair(const T1& x)
391 		    : first(x), second()
392 		{
393 		}
394 
395 		// GCC has a bug with overloading rvalue and lvalue function templates.
396 		// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54425
397 		//
398 		// error: 'eastl::pair<T1, T2>::pair(T1&&) [with T1 = const int&; T2 = const int&]' cannot be overloaded
399 		// error: with 'eastl::pair<T1, T2>::pair(const T1&) [with T1 = const int&; T2 = const int&]'
400 		#if !defined(EA_COMPILER_GNUC)
401 			template <typename TT2 = T2, typename = eastl::enable_if_t<eastl::is_default_constructible_v<TT2>>>
402 			EA_CPP14_CONSTEXPR pair(T1&& x)
403 				: first(eastl::move(x)), second()
404 			{
405 			}
406 		#endif
407 	#endif
408 
409 
410 	// NOTE(rparolin):
411 	// This is a workaround to a compiler intrinic bug which fails to correctly identify a nested class using
412 	// non-static data member initialization as default constructible.
413 	//
414 	// See bug submitted to LLVM for more details.
415 	// https://bugs.llvm.org/show_bug.cgi?id=38374
416 	#if !defined(EA_COMPILER_CLANG)
417 		template<typename T>
418 		using single_pair_ctor_sfinae = eastl::enable_if_t<eastl::is_default_constructible_v<T>>;
419 	#else
420 		template<typename>
421 		using single_pair_ctor_sfinae = void;
422 	#endif
423 
424 		template <typename TT2 = T2, typename = single_pair_ctor_sfinae<TT2>>
425 		EA_CPP14_CONSTEXPR pair(pair_first_construct_t, const T1& x)
426 		    : first(x), second()
427 		{
428 		}
429 
430 		// GCC has a bug with overloading rvalue and lvalue function templates.
431 		// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54425
432 		//
433 		// error: 'eastl::pair<T1, T2>::pair(T1&&) [with T1 = const int&; T2 = const int&]' cannot be overloaded
434 		// error: with 'eastl::pair<T1, T2>::pair(const T1&) [with T1 = const int&; T2 = const int&]'
435 		#if !defined(EA_COMPILER_GNUC)
436 			template <typename TT2 = T2, typename = single_pair_ctor_sfinae<TT2>>
437 			EA_CPP14_CONSTEXPR pair(pair_first_construct_t, T1&& x)
438 				: first(eastl::move(x)), second()
439 			{
440 			}
441 		#endif
442 
443 		template <
444 		    typename TT1 = T1,
445 		    typename TT2 = T2,
446 		    class = eastl::enable_if_t<eastl::is_copy_constructible_v<TT1> && eastl::is_copy_constructible_v<TT2>>>
447 		EA_CPP14_CONSTEXPR pair(const T1& x, const T2& y)
448 		    : first(x), second(y)
449 		{
450 		}
451 
452 		EA_CPP14_CONSTEXPR pair(pair&& p) = default;
453 		EA_CPP14_CONSTEXPR pair(const pair&) = default;
454 
455 		template <
456 		    typename U,
457 		    typename V,
458 		    class = eastl::enable_if_t<eastl::is_convertible_v<const U&, T1> && eastl::is_convertible_v<const V&, T2>>>
459 		EA_CPP14_CONSTEXPR pair(const pair<U, V>& p)
460 		    : first(p.first), second(p.second)
461 		{
462 		}
463 
464 		template <typename U,
465 		          typename V,
466 		          typename = eastl::enable_if_t<eastl::is_convertible_v<U, T1> && eastl::is_convertible_v<V, T2>>>
467 		EA_CPP14_CONSTEXPR pair(U&& u, V&& v)
468 		    : first(eastl::forward<U>(u)), second(eastl::forward<V>(v))
469 		{
470 		}
471 
472 		template <typename U, typename = eastl::enable_if_t<eastl::is_convertible_v<U, T1>>>
473 		EA_CPP14_CONSTEXPR pair(U&& x, const T2& y)
474 			: first(eastl::forward<U>(x)), second(y)
475 		{
476 		}
477 
478 		template <typename V, typename = eastl::enable_if_t<eastl::is_convertible_v<V, T2>>>
479 		EA_CPP14_CONSTEXPR pair(const T1& x, V&& y)
480 			: first(x), second(eastl::forward<V>(y))
481 		{
482 		}
483 
484 		template <typename U,
485 		          typename V,
486 		          typename = eastl::enable_if_t<eastl::is_convertible_v<U, T1> && eastl::is_convertible_v<V, T2>>>
487 		EA_CPP14_CONSTEXPR pair(pair<U, V>&& p)
488 		    : first(eastl::forward<U>(p.first)), second(eastl::forward<V>(p.second))
489 		{
490 		}
491 
492 		// Initializes first with arguments of types Args1... obtained by forwarding the elements of first_args and
493 		// initializes second with arguments of types Args2... obtained by forwarding the elements of second_args.
494 		template <class... Args1,
495 		          class... Args2,
496 		          typename = eastl::enable_if_t<eastl::is_constructible_v<first_type, Args1&&...> &&
497 		                                        eastl::is_constructible_v<second_type, Args2&&...>>>
498 		pair(eastl::piecewise_construct_t pwc, eastl::tuple<Args1...> first_args, eastl::tuple<Args2...> second_args)
499 		    : pair(pwc,
500 		           eastl::move(first_args),
501 		           eastl::move(second_args),
502 		           eastl::make_index_sequence<sizeof...(Args1)>(),
503 		           eastl::make_index_sequence<sizeof...(Args2)>())
504 		{
505 		}
506 
507 	private:
508 		// NOTE(rparolin): Internal constructor used to expand the index_sequence required to expand the tuple elements.
509 		template <class... Args1, class... Args2, size_t... I1, size_t... I2>
510 		pair(eastl::piecewise_construct_t,
511 			 eastl::tuple<Args1...> first_args,
512 			 eastl::tuple<Args2...> second_args,
513 			 eastl::index_sequence<I1...>,
514 			 eastl::index_sequence<I2...>)
515 			: first(eastl::forward<Args1>(eastl::get<I1>(first_args))...)
516 			, second(eastl::forward<Args2>(eastl::get<I2>(second_args))...)
517 		{
518 		}
519 
520 	public:
521 		pair& operator=(const pair& p)
522 		    EA_NOEXCEPT_IF(eastl::is_nothrow_copy_assignable_v<T1>&& eastl::is_nothrow_copy_assignable_v<T2>)
523 		{
524 			first = p.first;
525 			second = p.second;
526 			return *this;
527 		}
528 
529 		template <typename U,
530 		          typename V,
531 		          typename = eastl::enable_if_t<eastl::is_convertible_v<U, T1> && eastl::is_convertible_v<V, T2>>>
532 		pair& operator=(const pair<U, V>& p)
533 		{
534 			first = p.first;
535 			second = p.second;
536 			return *this;
537 		}
538 
539 		pair& operator=(pair&& p)
540 		    EA_NOEXCEPT_IF(eastl::is_nothrow_move_assignable_v<T1>&& eastl::is_nothrow_move_assignable_v<T2>)
541 		{
542 			first = eastl::forward<T1>(p.first);
543 			second = eastl::forward<T2>(p.second);
544 			return *this;
545 		}
546 
547 		template <typename U,
548 		          typename V,
549 		          typename = eastl::enable_if_t<eastl::is_convertible_v<U, T1> && eastl::is_convertible_v<V, T2>>>
550 		pair& operator=(pair<U, V>&& p)
551 		{
552 			first = eastl::forward<U>(p.first);
553 			second = eastl::forward<V>(p.second);
554 			return *this;
555 		}
556 
557 		void swap(pair& p) EA_NOEXCEPT_IF(eastl::is_nothrow_swappable_v<T1>&& eastl::is_nothrow_swappable_v<T2>)
558 		{
559 			eastl::iter_swap(&first, &p.first);
560 			eastl::iter_swap(&second, &p.second);
561 		}
562 	};
563 
564 	#define EASTL_PAIR_CONFORMANCE 1
565 
566 
567 
568 	/// use_self
569 	///
570 	/// operator()(x) simply returns x. Used in sets, as opposed to maps.
571 	/// This is a template policy implementation; it is an alternative to
572 	/// the use_first template implementation.
573 	///
574 	/// The existance of use_self may seem odd, given that it does nothing,
575 	/// but these kinds of things are useful, virtually required, for optimal
576 	/// generic programming.
577 	///
578 	template <typename T>
579 	struct use_self             // : public unary_function<T, T> // Perhaps we want to make it a subclass of unary_function.
580 	{
581 		typedef T result_type;
582 
583 		const T& operator()(const T& x) const
584 			{ return x; }
585 	};
586 
587 	/// use_first
588 	///
589 	/// operator()(x) simply returns x.first. Used in maps, as opposed to sets.
590 	/// This is a template policy implementation; it is an alternative to
591 	/// the use_self template implementation. This is the same thing as the
592 	/// SGI SGL select1st utility.
593 	///
594 	template <typename Pair>
595 	struct use_first
596 	{
597 		typedef Pair argument_type;
598 		typedef typename Pair::first_type result_type;
599 
600 		const result_type& operator()(const Pair& x) const
601 			{ return x.first; }
602 	};
603 
604 	/// use_second
605 	///
606 	/// operator()(x) simply returns x.second.
607 	/// This is the same thing as the SGI SGL select2nd utility
608 	///
609 	template <typename Pair>
610 	struct use_second           // : public unary_function<Pair, typename Pair::second_type> // Perhaps we want to make it a subclass of unary_function.
611 	{
612 		typedef Pair argument_type;
613 		typedef typename Pair::second_type result_type;
614 
615 		const result_type& operator()(const Pair& x) const
616 			{ return x.second; }
617 	};
618 
619 
620 
621 
622 
623 	///////////////////////////////////////////////////////////////////////
624 	// global operators
625 	///////////////////////////////////////////////////////////////////////
626 
627 	template <typename T1, typename T2>
628 	EA_CPP14_CONSTEXPR inline bool operator==(const pair<T1, T2>& a, const pair<T1, T2>& b)
629 	{
630 		return ((a.first == b.first) && (a.second == b.second));
631 	}
632 
633 
634 	template <typename T1, typename T2>
635 	EA_CPP14_CONSTEXPR inline bool operator<(const pair<T1, T2>& a, const pair<T1, T2>& b)
636 	{
637 		// Note that we use only operator < in this expression. Otherwise we could
638 		// use the simpler: return (a.m1 == b.m1) ? (a.m2 < b.m2) : (a.m1 < b.m1);
639 		// The user can write a specialization for this operator to get around this
640 		// in cases where the highest performance is required.
641 		return ((a.first < b.first) || (!(b.first < a.first) && (a.second < b.second)));
642 	}
643 
644 
645 	template <typename T1, typename T2>
646 	EA_CPP14_CONSTEXPR inline bool operator!=(const pair<T1, T2>& a, const pair<T1, T2>& b)
647 	{
648 		return !(a == b);
649 	}
650 
651 
652 	template <typename T1, typename T2>
653 	EA_CPP14_CONSTEXPR inline bool operator>(const pair<T1, T2>& a, const pair<T1, T2>& b)
654 	{
655 		return b < a;
656 	}
657 
658 
659 	template <typename T1, typename T2>
660 	EA_CPP14_CONSTEXPR inline bool operator>=(const pair<T1, T2>& a, const pair<T1, T2>& b)
661 	{
662 		return !(a < b);
663 	}
664 
665 
666 	template <typename T1, typename T2>
667 	EA_CPP14_CONSTEXPR inline bool operator<=(const pair<T1, T2>& a, const pair<T1, T2>& b)
668 	{
669 		return !(b < a);
670 	}
671 
672 
673 
674 
675 	///////////////////////////////////////////////////////////////////////
676 	/// make_pair / make_pair_ref
677 	///
678 	/// make_pair is the same as std::make_pair specified by the C++ standard.
679 	/// If you look at the C++ standard, you'll see that it specifies T& instead of T.
680 	/// However, it has been determined that the C++ standard is incorrect and has
681 	/// flagged it as a defect (http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#181).
682 	/// In case you feel that you want a more efficient version that uses references,
683 	/// we provide the make_pair_ref function below, though C++11 move support
684 	/// makes that no longer necessary.
685 	///
686 	/// Note: You don't usually need to use make_pair in order to make a pair.
687 	/// The following code is equivalent, and the latter avoids one more level of inlining:
688 	///     return make_pair(charPtr, charPtr);
689 	///     return pair<char*, char*>(charPtr, charPtr);
690 	///
691 	template <typename T1, typename T2>
692 	EA_CPP14_CONSTEXPR inline pair<typename eastl::remove_reference_wrapper<typename eastl::decay<T1>::type>::type,
693 								   typename eastl::remove_reference_wrapper<typename eastl::decay<T2>::type>::type>
694 	make_pair(T1&& a, T2&& b)
695 	{
696 		typedef typename eastl::remove_reference_wrapper<typename eastl::decay<T1>::type>::type T1Type;
697 		typedef typename eastl::remove_reference_wrapper<typename eastl::decay<T2>::type>::type T2Type;
698 
699 		return eastl::pair<T1Type, T2Type>(eastl::forward<T1>(a), eastl::forward<T2>(b));
700 	}
701 
702 
703 	// Without the following, VC++ fails to compile code like this: pair<const char*, int> p = eastl::make_pair<const char*, int>("hello", 0);
704 	// We define a const reference version alternative to the above. "hello" is of type char const(&)[6] (array of 6 const chars),
705 	// but VC++ decays it to const char* and allows this make_pair to be called with that. VC++ fails below with make_pair("hello", "people")
706 	// because you can't assign arrays and until we have a better solution we just disable this make_pair specialization for when T1 or T2
707 	// are of type char const(&)[].
708 	#if defined(_MSC_VER)
709 		template <typename T1, typename T2>
710 		EA_CPP14_CONSTEXPR inline pair<T1, T2> make_pair(
711 			const T1& a,
712 			const T2& b,
713 			typename eastl::enable_if<!eastl::is_array<T1>::value && !eastl::is_array<T2>::value>::type* = 0)
714 		{
715 			return eastl::pair<T1, T2>(a, b);
716 		}
717     #endif
718 
719 	// For backwards compatibility
720 	template <typename T1, typename T2>
721 	EA_CPP14_CONSTEXPR inline pair<typename eastl::remove_reference_wrapper<typename eastl::decay<T1>::type>::type,
722 								   typename eastl::remove_reference_wrapper<typename eastl::decay<T2>::type>::type>
723 	make_pair_ref(T1&& a, T2&& b)
724 	{
725 		typedef typename eastl::remove_reference_wrapper<typename eastl::decay<T1>::type>::type T1Type;
726 		typedef typename eastl::remove_reference_wrapper<typename eastl::decay<T2>::type>::type T2Type;
727 
728 		return eastl::pair<T1Type, T2Type>(eastl::forward<T1>(a), eastl::forward<T2>(b));
729 	}
730 
731 #if EASTL_TUPLE_ENABLED
732 
733 		template <typename T1, typename T2>
734 		class tuple_size<pair<T1, T2>> : public integral_constant<size_t, 2>
735 		{
736 		};
737 
738 		template <typename T1, typename T2>
739 		class tuple_size<const pair<T1, T2>> : public integral_constant<size_t, 2>
740 		{
741 		};
742 
743 		template <typename T1, typename T2>
744 		class tuple_element<0, pair<T1, T2>>
745 		{
746 		public:
747 			typedef T1 type;
748 		};
749 
750 		template <typename T1, typename T2>
751 		class tuple_element<1, pair<T1, T2>>
752 		{
753 		public:
754 			typedef T2 type;
755 		};
756 
757 		template <typename T1, typename T2>
758 		class tuple_element<0, const pair<T1, T2>>
759 		{
760 		public:
761 			typedef const T1 type;
762 		};
763 
764 		template <typename T1, typename T2>
765 		class tuple_element<1, const pair<T1, T2>>
766 		{
767 		public:
768 			typedef const T2 type;
769 		};
770 
771 		template <size_t I>
772 		struct GetPair;
773 
774 		template <>
775 		struct GetPair<0>
776 		{
777 			template <typename T1, typename T2>
778 			static EA_CONSTEXPR T1& getInternal(pair<T1, T2>& p)
779 			{
780 				return p.first;
781 			}
782 
783 			template <typename T1, typename T2>
784 			static EA_CONSTEXPR const T1& getInternal(const pair<T1, T2>& p)
785 			{
786 				return p.first;
787 			}
788 
789 			template <typename T1, typename T2>
790 			static EA_CONSTEXPR T1&& getInternal(pair<T1, T2>&& p)
791 			{
792 				return forward<T1>(p.first);
793 			}
794 		};
795 
796 		template <>
797 		struct GetPair<1>
798 		{
799 			template <typename T1, typename T2>
800 			static EA_CONSTEXPR T2& getInternal(pair<T1, T2>& p)
801 			{
802 				return p.second;
803 			}
804 
805 			template <typename T1, typename T2>
806 			static EA_CONSTEXPR const T2& getInternal(const pair<T1, T2>& p)
807 			{
808 				return p.second;
809 			}
810 
811 			template <typename T1, typename T2>
812 			static EA_CONSTEXPR T2&& getInternal(pair<T1, T2>&& p)
813 			{
814 				return forward<T2>(p.second);
815 			}
816 		};
817 
818 		template <size_t I, typename T1, typename T2>
819 		tuple_element_t<I, pair<T1, T2>>& get(pair<T1, T2>& p)
820 		{
821 			return GetPair<I>::getInternal(p);
822 		}
823 
824 		template <size_t I, typename T1, typename T2>
825 		const tuple_element_t<I, pair<T1, T2>>& get(const pair<T1, T2>& p)
826 		{
827 			return GetPair<I>::getInternal(p);
828 		}
829 
830 		template <size_t I, typename T1, typename T2>
831 		tuple_element_t<I, pair<T1, T2>>&& get(pair<T1, T2>&& p)
832 		{
833 			return GetPair<I>::getInternal(move(p));
834 		}
835 
836 #endif  // EASTL_TUPLE_ENABLED
837 
838 
839 }  // namespace eastl
840 
841 #ifdef _MSC_VER
842 	#pragma warning(pop)
843 #endif
844 
845 
846 #endif // Header include guard
847 
848 
849 
850 
851 
852 
853 
854 
855 
856 
857 
858 
859 
860 
861 
862