1 /////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) Electronic Arts Inc. All rights reserved.
3 /////////////////////////////////////////////////////////////////////////////
4 
5 
6 #ifndef EASTL_INTERNAL_TYPE_TRANFORMATIONS_H
7 #define EASTL_INTERNAL_TYPE_TRANFORMATIONS_H
8 
9 
10 #include <EABase/eabase.h>
11 #if defined(EA_PRAGMA_ONCE_SUPPORTED)
12 	#pragma once
13 #endif
14 
15 #include <limits.h>
16 
17 
18 namespace eastl
19 {
20 
21 	///////////////////////////////////////////////////////////////////////
22 	// add_const
23 	//
24 	// Add const to a type.
25 	//
26 	// Tor a given type T, add_const<T>::type is equivalent to T
27 	// const if is_const<T>::value == false, and
28 	//    - is_void<T>::value == true, or
29 	//    - is_object<T>::value == true.
30 	//
31 	// Otherwise, add_const<T>::type is equivalent to T.
32 	//
33 	///////////////////////////////////////////////////////////////////////
34 
35 	#define EASTL_TYPE_TRAIT_add_const_CONFORMANCE 1    // add_const is conforming.
36 
37 	template <typename T, bool = eastl::is_const<T>::value || eastl::is_reference<T>::value || eastl::is_function<T>::value>
38 	struct add_const_helper
39 		{ typedef T type; };
40 
41 	template <typename T>
42 	struct add_const_helper<T, false>
43 		{ typedef const T type; };
44 
45 	template <typename T>
46 	struct  add_const
47 		{ typedef typename eastl::add_const_helper<T>::type type; };
48 
49 	// add_const_t is the C++17 using typedef for typename add_const<T>::type.
50 	// We provide a backwards-compatible means to access it through a macro for pre-C++11 compilers.
51 	#if defined(EA_COMPILER_NO_TEMPLATE_ALIASES)
52 		#define EASTL_ADD_CONST_T(T) typename add_const<T>::type
53 	#else
54 		template <typename T>
55 		using add_const_t = typename add_const<T>::type;
56 		#define EASTL_ADD_CONST_T(T) add_const_t<T>
57 	#endif
58 
59 
60 	///////////////////////////////////////////////////////////////////////
61 	// add_volatile
62 	//
63 	// Add volatile to a type.
64 	//
65 	// For a given type T, add_volatile<T>::type is equivalent to T volatile
66 	// if is_volatile<T>::value == false, and
67 	//   - is_void<T>::value == true, or
68 	//   - is_object<T>::value == true.
69 	//
70 	// Otherwise, add_volatile<T>::type is equivalent to T.
71 	//
72 	///////////////////////////////////////////////////////////////////////
73 
74 	#define EASTL_TYPE_TRAIT_add_volatile_CONFORMANCE 1    // add_volatile is conforming.
75 
76 	template <typename T, bool = eastl::is_volatile<T>::value || eastl::is_reference<T>::value || eastl::is_function<T>::value>
77 	struct add_volatile_helper
78 		{ typedef T type; };
79 
80 	template <typename T>
81 	struct add_volatile_helper<T, false>
82 		{ typedef volatile T type; };
83 
84 	template <typename T> struct add_volatile
85 		{ typedef typename eastl::add_volatile_helper<T>::type type; };
86 
87 	template <class T> using add_volatile_t = typename add_volatile<T>::type;
88 
89 
90     ///////////////////////////////////////////////////////////////////////
91 	// add_cv
92 	//
93 	// The add_cv transformation trait adds const and volatile qualification
94 	// to the type to which it is applied. For a given type T,
95 	// add_volatile<T>::type is equivalent to add_const<add_volatile<T>::type>::type.
96 	//
97 	///////////////////////////////////////////////////////////////////////
98 
99 	#define EASTL_TYPE_TRAIT_add_cv_CONFORMANCE 1    // add_cv is conforming.
100 
101 	template<typename T>
102 	struct add_cv
103 	{
104 		typedef typename add_const<typename add_volatile<T>::type>::type type;
105 	};
106 
107 	template <class T> using add_cv_t = typename add_cv<T>::type;
108 
109 
110     ///////////////////////////////////////////////////////////////////////
111 	// make_signed
112 	//
113 	// Used to convert an integral type to its signed equivalent, if not already.
114 	// T shall be a (possibly const and/or volatile-qualified) integral type
115 	// or enumeration but not a bool type.;
116 	//
117 	// The user can define their own make_signed overrides for their own
118 	// types by making a template specialization like done below and adding
119 	// it to the user's code.
120 	///////////////////////////////////////////////////////////////////////
121 
122 	// To do: This implementation needs to be updated to support C++11 conformance (recognition of enums) and
123 	// to support volatile-qualified types. It will probably be useful to have it fail for unsupported types.
124 	#define EASTL_TYPE_TRAIT_make_signed_CONFORMANCE 0    // make_signed is only partially conforming.
125 
126 	template <typename T> struct make_signed { typedef T type; };
127 
128 	template <> struct make_signed<unsigned char>            { typedef signed char            type; };
129 	template <> struct make_signed<const unsigned char>      { typedef const signed char      type; };
130 	template <> struct make_signed<unsigned short>           { typedef signed short           type; };
131 	template <> struct make_signed<const unsigned short>     { typedef const signed short     type; };
132 	template <> struct make_signed<unsigned int>             { typedef signed int             type; };
133 	template <> struct make_signed<const unsigned int>       { typedef const signed int       type; };
134 	template <> struct make_signed<unsigned long>            { typedef signed long            type; };
135 	template <> struct make_signed<const unsigned long>      { typedef const signed long      type; };
136 	template <> struct make_signed<unsigned long long>       { typedef signed long long       type; };
137 	template <> struct make_signed<const unsigned long long> { typedef const signed long long type; };
138 
139 	#if (defined(CHAR_MAX) && defined(UCHAR_MAX) && (CHAR_MAX == UCHAR_MAX)) // If char is unsigned, we convert char to signed char. However, if char is signed then make_signed returns char itself and not signed char.
140 		template <> struct make_signed<char>                 { typedef signed char            type; };
141 		template <> struct make_signed<const char>           { typedef signed char            type; };
142 	#endif
143 
144 	#ifndef EA_WCHAR_T_NON_NATIVE // If wchar_t is a native type instead of simply a define to an existing type...
145 		#if (defined(__WCHAR_MAX__) && (__WCHAR_MAX__ == 4294967295U)) // If wchar_t is a 32 bit unsigned value...
146 			template<>
147 			struct make_signed<wchar_t>
148 			{ typedef int32_t type; };
149 		#elif (defined(__WCHAR_MAX__) && (__WCHAR_MAX__ == 65535))     // If wchar_t is a 16 bit unsigned value...
150 			template<>
151 			struct make_signed<wchar_t>
152 			{ typedef int16_t type; };
153 		#elif (defined(__WCHAR_MAX__) && (__WCHAR_MAX__ == 255))       // If wchar_t is an 8 bit unsigned value...
154 			template<>
155 			struct make_signed<wchar_t>
156 			{ typedef int8_t type; };
157 		#endif
158 	#endif
159 
160 	#if EASTL_VARIABLE_TEMPLATES_ENABLED
161 		template <class T>
162 		using make_signed_t = typename make_signed<T>::type;
163 	#endif
164 
165 
166 	///////////////////////////////////////////////////////////////////////
167 	// add_signed
168 	//
169 	// This is not a C++11 type trait, and is here for backwards compatibility
170 	// only. Use the C++11 make_unsigned type trait instead.
171 	///////////////////////////////////////////////////////////////////////
172 
173 	template<class T>
174 	struct add_signed : public make_signed<T>
175 	{ typedef typename eastl::make_signed<T>::type type; };
176 
177 
178 
179 
180 	///////////////////////////////////////////////////////////////////////
181 	// make_unsigned
182 	//
183 	// Used to convert an integral type to its signed equivalent, if not already.
184 	// T shall be a (possibly const and/or volatile-qualified) integral type
185 	// or enumeration but not a bool type.;
186 	//
187 	// The user can define their own make_signed overrides for their own
188 	// types by making a template specialization like done below and adding
189 	// it to the user's code.
190 	///////////////////////////////////////////////////////////////////////
191 
192 	// To do: This implementation needs to be updated to support C++11 conformance (recognition of enums) and
193 	// to support volatile-qualified types. It will probably be useful to have it fail for unsupported types.
194 	#define EASTL_TYPE_TRAIT_make_unsigned_CONFORMANCE 0    // make_unsigned is only partially conforming.
195 
196 	template <typename T> struct make_unsigned { typedef T type; };
197 
198 	template <> struct make_unsigned<signed char>            { typedef unsigned char            type; };
199 	template <> struct make_unsigned<const signed char>      { typedef const unsigned char      type; };
200 	template <> struct make_unsigned<signed short>           { typedef unsigned short           type; };
201 	template <> struct make_unsigned<const signed short>     { typedef const unsigned short     type; };
202 	template <> struct make_unsigned<signed int>             { typedef unsigned int             type; };
203 	template <> struct make_unsigned<const signed int>       { typedef const unsigned int       type; };
204 	template <> struct make_unsigned<signed long>            { typedef unsigned long            type; };
205 	template <> struct make_unsigned<const signed long>      { typedef const unsigned long      type; };
206 	template <> struct make_unsigned<signed long long>       { typedef unsigned long long       type; };
207 	template <> struct make_unsigned<const signed long long> { typedef const unsigned long long type; };
208 
209 	#if (CHAR_MIN < 0) // If char is signed, we convert char to unsigned char. However, if char is unsigned then make_unsigned returns char itself and not unsigned char.
210 		template <> struct make_unsigned<char>                 { typedef unsigned char          type; };
211 		template <> struct make_unsigned<const char>           { typedef unsigned char          type; };
212 	#endif
213 
214 	#ifndef EA_WCHAR_T_NON_NATIVE // If wchar_t is a native type instead of simply a define to an existing type...
215 		#if (defined(__WCHAR_MAX__) && (__WCHAR_MAX__ != 4294967295U)) // If wchar_t is a 32 bit signed value...
216 			template<>
217 			struct make_unsigned<wchar_t>
218 			{ typedef uint32_t type; };
219 		#elif (defined(__WCHAR_MAX__) && (__WCHAR_MAX__ != 65535))     // If wchar_t is a 16 bit signed value...
220 			template<>
221 			struct make_unsigned<wchar_t>
222 			{ typedef uint16_t type; };
223 		#elif (defined(__WCHAR_MAX__) && (__WCHAR_MAX__ != 255))       // If wchar_t is an 8 bit signed value...
224 			template<>
225 			struct make_unsigned<wchar_t>
226 			{ typedef uint8_t type; };
227 		#endif
228 	#endif
229 
230 	#if EASTL_VARIABLE_TEMPLATES_ENABLED
231 		template <class T>
232 		using make_unsigned_t = typename make_unsigned<T>::type;
233 	#endif
234 
235 
236 
237 	///////////////////////////////////////////////////////////////////////
238 	// add_unsigned
239 	//
240 	// This is not a C++11 type trait, and is here for backwards compatibility
241 	// only. Use the C++11 make_unsigned type trait instead.
242 	//
243 	// Adds unsigned-ness to the given type.
244 	// Modifies only integral values; has no effect on others.
245 	// add_unsigned<int>::type is unsigned int
246 	// add_unsigned<unsigned int>::type is unsigned int
247 	//
248 	///////////////////////////////////////////////////////////////////////
249 
250 	template<class T>
251 	struct add_unsigned : public make_unsigned<T>
252 	{ typedef typename eastl::make_signed<T>::type type; };
253 
254 
255 
256 	///////////////////////////////////////////////////////////////////////
257 	// remove_pointer
258 	//
259 	// Remove pointer from a type.
260 	//
261 	// The remove_pointer transformation trait removes top-level indirection
262 	// by pointer (if any) from the type to which it is applied. Pointers to
263 	// members are not affected. For a given type T, remove_pointer<T*>::type
264 	// is equivalent to T.
265 	//
266 	///////////////////////////////////////////////////////////////////////
267 
268 	#define EASTL_TYPE_TRAIT_remove_pointer_CONFORMANCE 1
269 
270 	template<typename T> struct remove_pointer                    { typedef T type; };
271 	template<typename T> struct remove_pointer<T*>                { typedef T type; };
272 	template<typename T> struct remove_pointer<T* const>          { typedef T type; };
273 	template<typename T> struct remove_pointer<T* volatile>       { typedef T type; };
274 	template<typename T> struct remove_pointer<T* const volatile> { typedef T type; };
275 
276 	#if EASTL_VARIABLE_TEMPLATES_ENABLED
277 		template <class T>
278 		using remove_pointer_t = typename remove_pointer<T>::type;
279     #endif
280 
281 
282 	///////////////////////////////////////////////////////////////////////
283 	// add_pointer
284 	//
285 	// Add pointer to a type.
286 	// Provides the member typedef type which is the type T*. If T is a
287 	// reference type, then type is a pointer to the referred type.
288 	//
289 	///////////////////////////////////////////////////////////////////////
290 
291 	#define EASTL_TYPE_TRAIT_add_pointer_CONFORMANCE 1
292 
293 	template<class T>
294 	struct add_pointer { typedef typename eastl::remove_reference<T>::type* type; };
295 
296 	#if EASTL_VARIABLE_TEMPLATES_ENABLED
297 		template <class T>
298 		using add_pointer_t = typename add_pointer<T>::type;
299     #endif
300 
301 
302 
303 	///////////////////////////////////////////////////////////////////////
304 	// remove_extent
305 	//
306 	// The remove_extent transformation trait removes a dimension from an array.
307 	// For a given non-array type T, remove_extent<T>::type is equivalent to T.
308 	// For a given array type T[N], remove_extent<T[N]>::type is equivalent to T.
309 	// For a given array type const T[N], remove_extent<const T[N]>::type is equivalent to const T.
310 	// For example, given a multi-dimensional array type T[M][N], remove_extent<T[M][N]>::type is equivalent to T[N].
311 	///////////////////////////////////////////////////////////////////////
312 
313 	#define EASTL_TYPE_TRAIT_remove_extent_CONFORMANCE 1    // remove_extent is conforming.
314 
315 	template<class T>           struct remove_extent       { typedef T type; };
316 	template<class T>           struct remove_extent<T[]>  { typedef T type; };
317 	template<class T, size_t N> struct remove_extent<T[N]> { typedef T type; };
318 
319 	#if !defined(EA_COMPILER_NO_TEMPLATE_ALIASES)
320 		template <typename T>
321 		using remove_extent_t = typename remove_extent<T>::type;
322 	#endif
323 
324 
325 	///////////////////////////////////////////////////////////////////////
326 	// remove_all_extents
327 	//
328 	// The remove_all_extents transformation trait removes all dimensions from an array.
329 	// For a given non-array type T, remove_all_extents<T>::type is equivalent to T.
330 	// For a given array type T[N], remove_all_extents<T[N]>::type is equivalent to T.
331 	// For a given array type const T[N], remove_all_extents<const T[N]>::type is equivalent to const T.
332 	// For example, given a multi-dimensional array type T[M][N], remove_all_extents<T[M][N]>::type is equivalent to T.
333 	///////////////////////////////////////////////////////////////////////
334 
335 	#define EASTL_TYPE_TRAIT_remove_all_extents_CONFORMANCE 1    // remove_all_extents is conforming.
336 
337 	template<typename T>           struct remove_all_extents       { typedef T type; };
338 	template<typename T, size_t N> struct remove_all_extents<T[N]> { typedef typename eastl::remove_all_extents<T>::type type; };
339 	template<typename T>           struct remove_all_extents<T[]>  { typedef typename eastl::remove_all_extents<T>::type type; };
340 
341 	#if !defined(EA_COMPILER_NO_TEMPLATE_ALIASES)
342 		template <typename T>
343 		using remove_all_extents_t = typename remove_all_extents<T>::type;
344 	#endif
345 
346 
347 
348 	///////////////////////////////////////////////////////////////////////
349 	// aligned_storage
350 	//
351 	// The aligned_storage transformation trait provides a type that is
352 	// suitably aligned to store an object whose size is does not exceed length
353 	// and whose alignment is a divisor of alignment. When using aligned_storage,
354 	// length must be non-zero, and alignment must >= alignment_of<T>::value
355 	// for some type T. We require the alignment value to be a power-of-two.
356 	//
357 	// GCC versions prior to 4.4 don't properly support this with stack-based
358 	// variables. The EABase EA_ALIGN_MAX_AUTOMATIC define identifies the
359 	// extent to which stack (automatic) variables can be aligned for the
360 	// given compiler/platform combination.
361 	//
362 	// Example usage:
363 	//     aligned_storage<sizeof(Widget), alignment_of(Widget)>::type widget;
364 	//     Widget* pWidget = new(&widget) Widget;
365 	//
366 	//     aligned_storage<sizeof(Widget), 64>::type widgetAlignedTo64;
367 	//     Widget* pWidget = new(&widgetAlignedTo64) Widget;
368 	//
369 	//     aligned_storage<sizeof(Widget), alignment_of(Widget)>::type widgetArray[37];
370 	//     Widget* pWidgetArray = new(widgetArray) Widget[37];
371 	///////////////////////////////////////////////////////////////////////
372 
373 	#define EASTL_TYPE_TRAIT_aligned_storage_CONFORMANCE 1    // aligned_storage is conforming.
374 
375 	#if defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4008)
376 		// New versions of GCC do not support using 'alignas' with a value greater than 128.
377 		// However, this code using the GNU standard alignment attribute works properly.
378 		template<size_t N, size_t Align = EASTL_ALIGN_OF(double)>
379 		struct aligned_storage
380 		{
381 			struct type { unsigned char mCharData[N]; } EA_ALIGN(Align);
382 		};
383 	#elif (EABASE_VERSION_N >= 20040) && !defined(EA_COMPILER_NO_ALIGNAS) // If C++11 alignas is supported...
384 		template<size_t N, size_t Align = EASTL_ALIGN_OF(double)>
385 		struct aligned_storage
386 		{
387 			typedef struct {
388 				alignas(Align) unsigned char mCharData[N];
389 			} type;
390 		};
391 
392 	#elif defined(EA_COMPILER_MSVC) || (defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION < 4007)) || defined(EA_COMPILER_EDG) // At some point GCC fixed their attribute(align) to support non-literals, though it's not clear what version aside from being no later than 4.7 and no earlier than 4.2.
393 		// Some compilers don't allow you to to use EA_ALIGNED with anything by a numeric literal,
394 		// so we can't use the simpler code like we do further below for other compilers. We support
395 		// only up to so much of an alignment value here.
396 		template<size_t N, size_t Align>
397 		struct aligned_storage_helper { struct type{ unsigned char mCharData[N]; }; };
398 
399 		template<size_t N> struct aligned_storage_helper<N,    2> { struct EA_ALIGN(   2) type{ unsigned char mCharData[N]; }; };
400 		template<size_t N> struct aligned_storage_helper<N,    4> { struct EA_ALIGN(   4) type{ unsigned char mCharData[N]; }; };
401 		template<size_t N> struct aligned_storage_helper<N,    8> { struct EA_ALIGN(   8) type{ unsigned char mCharData[N]; }; };
402 		template<size_t N> struct aligned_storage_helper<N,   16> { struct EA_ALIGN(  16) type{ unsigned char mCharData[N]; }; };
403 		template<size_t N> struct aligned_storage_helper<N,   32> { struct EA_ALIGN(  32) type{ unsigned char mCharData[N]; }; };
404 		template<size_t N> struct aligned_storage_helper<N,   64> { struct EA_ALIGN(  64) type{ unsigned char mCharData[N]; }; };
405 		template<size_t N> struct aligned_storage_helper<N,  128> { struct EA_ALIGN( 128) type{ unsigned char mCharData[N]; }; };
406 		template<size_t N> struct aligned_storage_helper<N,  256> { struct EA_ALIGN( 256) type{ unsigned char mCharData[N]; }; };
407 		template<size_t N> struct aligned_storage_helper<N,  512> { struct EA_ALIGN( 512) type{ unsigned char mCharData[N]; }; };
408 		template<size_t N> struct aligned_storage_helper<N, 1024> { struct EA_ALIGN(1024) type{ unsigned char mCharData[N]; }; };
409 		template<size_t N> struct aligned_storage_helper<N, 2048> { struct EA_ALIGN(2048) type{ unsigned char mCharData[N]; }; };
410 		template<size_t N> struct aligned_storage_helper<N, 4096> { struct EA_ALIGN(4096) type{ unsigned char mCharData[N]; }; };
411 
412 		template<size_t N, size_t Align = EASTL_ALIGN_OF(double)>
413 		struct aligned_storage
414 		{
415 			typedef typename aligned_storage_helper<N, Align>::type type;
416 		};
417 
418 	#else
419 		template<size_t N, size_t Align = EASTL_ALIGN_OF(double)>
420 		struct aligned_storage
421 		{
422 			union type
423 			{
424 				unsigned char mCharData[N];
425 				struct EA_ALIGN(Align) mStruct{ };
426 			};
427 		};
428 	#endif
429 
430 	#if defined(EA_COMPILER_NO_TEMPLATE_ALIASES)
431 		#define EASTL_ALIGNED_STORAGE_T(N, Align) typename eastl::aligned_storage_t<N, Align>::type
432 	#else
433 		template <size_t N, size_t Align = EASTL_ALIGN_OF(double)>
434 		using aligned_storage_t = typename aligned_storage<N, Align>::type;
435 		#define EASTL_ALIGNED_STORAGE_T(N, Align) eastl::aligned_storage_t<N, Align>
436 	#endif
437 
438 
439 
440 	///////////////////////////////////////////////////////////////////////
441 	// aligned_union
442 	//
443 	// The member typedef type shall be a POD type suitable for use as
444 	// uninitialized storage for any object whose type is listed in Types;
445 	// its size shall be at least Len. The static member alignment_value
446 	// shall be an integral constant of type std::size_t whose value is
447 	// the strictest alignment of all types listed in Types.
448 	// Note that the resulting type is not a C/C++ union, but simply memory
449 	// block (of pod type) that can be used to placement-new an actual
450 	// C/C++ union of the types. The actual union you declare can be a non-POD union.
451 	//
452 	// Example usage:
453 	//     union MyUnion {
454 	//         char  c;
455 	//         int   i;
456 	//         float f;
457 	//
458 	//         MyUnion(float fValue) : f(fValue) {}
459 	//     };
460 	//
461 	//     aligned_union<sizeof(MyUnion), char, int, float>::type myUnionStorage;
462 	//     MyUnion* pMyUnion = new(&myUnionStorage) MyUnion(21.4f);
463 	//     pMyUnion->i = 37;
464 	//
465 	///////////////////////////////////////////////////////////////////////
466 
467 	#if defined(EA_COMPILER_NO_VARIADIC_TEMPLATES) || !EASTL_TYPE_TRAIT_static_max_CONFORMANCE
468 		#define EASTL_TYPE_TRAIT_aligned_union_CONFORMANCE 0    // aligned_union is not conforming, as it supports only a two-member unions.
469 
470 		// To consider: Expand this to include more possible types. We may want to convert this to be a recursive
471 		//              template instead of like below.
472 		template <size_t minSize, typename Type0, typename Type1 = char, typename Type2 = char, typename Type3 = char>
473 		struct aligned_union
474 		{
475 			static const size_t size0           = eastl::static_max<minSize, sizeof(Type0)>::value;
476 			static const size_t size1           = eastl::static_max<size0,   sizeof(Type1)>::value;
477 			static const size_t size2           = eastl::static_max<size1,   sizeof(Type2)>::value;
478 			static const size_t size            = eastl::static_max<size2,   sizeof(Type3)>::value;
479 
480 			static const size_t alignment0      = eastl::static_max<EA_ALIGN_OF(Type0), EA_ALIGN_OF(Type1)>::value;
481 			static const size_t alignment1      = eastl::static_max<alignment0,         EA_ALIGN_OF(Type2)>::value;
482 			static const size_t alignment_value = eastl::static_max<alignment1,         EA_ALIGN_OF(Type3)>::value;
483 
484 			typedef typename eastl::aligned_storage<size, alignment_value>::type type;
485 		};
486 
487 		#if defined(EA_COMPILER_NO_TEMPLATE_ALIASES)
488 			// To do: define macro.
489 		#else
490 			template <size_t minSize, typename Type0, typename Type1 = char, typename Type2 = char, typename Type3 = char>
491 			using aligned_union_t = typename aligned_union<minSize, Type0, Type1, Type2, Type3>::type;
492 		#endif
493 	#else
494 		#define EASTL_TYPE_TRAIT_aligned_union_CONFORMANCE 1    // aligned_union is conforming.
495 
496 		template <size_t minSize, typename Type0, typename ...TypeN>
497 		struct aligned_union
498 		{
499 			static const size_t size            = eastl::static_max<minSize, sizeof(Type0), sizeof(TypeN)...>::value;
500 			static const size_t alignment_value = eastl::static_max<EA_ALIGN_OF(Type0), EA_ALIGN_OF(TypeN)...>::value;
501 
502 			typedef typename eastl::aligned_storage<size, alignment_value>::type type;
503 		};
504 
505 		#if defined(EA_COMPILER_NO_TEMPLATE_ALIASES)
506 			// To do: define macro.
507 		#else
508 			template <size_t minSize, typename... TypeN>
509 			using aligned_union_t = typename aligned_union<minSize, TypeN...>::type;
510         #endif
511 
512 	#endif
513 
514 
515 	///////////////////////////////////////////////////////////////////////
516 	// union_cast
517 	//
518 	// Safely converts between unrelated types that have a binary equivalency.
519 	// This appoach is required by strictly conforming C++ compilers because
520 	// directly using a C or C++ cast between unrelated types is fraught with
521 	// the possibility of undefined runtime behavior due to type aliasing.
522 	// The Source and Dest types must be POD types due to the use of a union
523 	// in C++ versions prior to C++11. C++11 relaxes the definition of a POD
524 	// such that it allows a classes with trivial default constructors whereas
525 	// previous versions did not, so beware of this when writing portable code.
526 	//
527 	// Example usage:
528 	//    float f32 = 1.234f;
529 	//    uint32_t n32 = union_cast<uint32_t>(f32);
530 	//
531 	// Example possible mis-usage:
532 	// The following is valid only if you are aliasing the pointer value and
533 	// not what it points to. Most of the time the user intends the latter,
534 	// which isn't strictly possible.
535 	//    Widget* pWidget = CreateWidget();
536 	//    Foo*    pFoo    = union_cast<Foo*>(pWidget);
537 	///////////////////////////////////////////////////////////////////////
538 
539 	template <typename DestType, typename SourceType>
540 	DestType union_cast(SourceType sourceValue)
541 	{
542 		EASTL_CT_ASSERT((sizeof(DestType) == sizeof(SourceType)) &&
543 						(EA_ALIGN_OF(DestType) == EA_ALIGN_OF(SourceType)));               // To support differening alignments, we would need to use a memcpy-based solution or find a way to make the two union members align with each other.
544 		//EASTL_CT_ASSERT(is_pod<DestType>::value && is_pod<SourceType>::value);           // Disabled because we don't want to restrict what the user can do, as some compiler's definitions of is_pod aren't up to C++11 Standards.
545 		//EASTL_CT_ASSERT(!is_pointer<DestType>::value && !is_pointer<SourceType>::value); // Disabled because it's valid to alias pointers as long as you are aliasong the pointer value and not what it points to.
546 
547 		union {
548 			SourceType sourceValue;
549 			DestType   destValue;
550 		} u;
551 		u.sourceValue = sourceValue;
552 
553 		return u.destValue;
554 	}
555 
556 
557 
558 	///////////////////////////////////////////////////////////////////////
559 	// void_t
560 	//
561 	// Maps a sequence of any types to void.  This utility class is used in
562 	// template meta programming to simplify compile time reflection mechanisms
563 	// required by the standard library.
564 	//
565 	// http://en.cppreference.com/w/cpp/types/void_t
566 	//
567 	// Example:
568 	//    template <typename T, typename = void>
569 	//    struct is_iterable : false_type {};
570 	//
571 	//    template <typename T>
572 	//    struct is_iterable<T, void_t<decltype(declval<T>().begin()),
573 	//                                 decltype(declval<T>().end())>> : true_type {};
574 	//
575 	///////////////////////////////////////////////////////////////////////
576 	#if EASTL_VARIABLE_TEMPLATES_ENABLED
577 		template <class...>
578 		using void_t = void;
579 	#endif
580 
581 
582 } // namespace eastl
583 
584 
585 #endif // Header include guard
586 
587 
588 
589 
590 
591 
592 
593 
594 
595 
596 
597 
598 
599 
600 
601 
602 
603 
604 
605 
606 
607