/* EWL
 * Copyright © 1995-2009 Freescale Corporation.  All rights reserved.
 *
 * $Date: 2012/06/28 06:42:30 $
 * $Revision: 1.2 $
 */

#ifndef  _TYPE_TRAITS
#define  _TYPE_TRAITS

/*  type_traits

namespace std
{
namespace tr1
{

// [4.3] helper class:
template <class T, T v> struct integral_constant;
typedef integral_constant<bool, true> true_type;
typedef integral_constant<bool, false> false_type;

// [4.5.1] primary type categories:
template <class T> struct is_void;
template <class T> struct is_integral;
template <class T> struct is_floating_point;
template <class T> struct is_array;
template <class T> struct is_pointer;
template <class T> struct is_lvalue_reference;
template <class T> struct is_rvalue_reference;
template <class T> struct is_member_object_pointer;
template <class T> struct is_member_function_pointer;
template <class T> struct is_enum;
template <class T> struct is_union;
template <class T> struct is_class;
template <class T> struct is_function;

// [4.5.2] composite type categories:
template <class T> struct is_reference;
template <class T> struct is_arithmetic;
template <class T> struct is_fundamental;
template <class T> struct is_object;
template <class T> struct is_scalar;
template <class T> struct is_compound;
template <class T> struct is_member_pointer;

// [20.5.4.3] type properties:
template <class T> struct is_const;
template <class T> struct is_volatile;
template <class T> struct is_trivial;
template <class T> struct is_standard_layout;
template <class T> struct is_pod;
template <class T> struct is_empty;
template <class T> struct is_polymorphic;
template <class T> struct is_abstract;
template <class T> struct has_trivial_default_constructor;
template <class T> struct has_trivial_copy_constructor;
template <class T> struct has_trivial_assign;
template <class T> struct has_trivial_destructor;
template <class T> struct has_nothrow_default_constructor;
template <class T> struct has_nothrow_copy_constructor;
template <class T> struct has_nothrow_assign;
template <class T> struct has_virtual_destructor;
template <class T> struct is_signed;
template <class T> struct is_unsigned;
template <class T> struct alignment_of;
template <class T> struct rank;
template <class T, unsigned I = 0> struct extent;

// [4.6] type relations:
template <class T, class U> struct is_same;
template <class Base, class Derived> struct is_base_of;
template <class From, class To> struct is_convertible;

// [4.7.1] const-volatile modifications:
template <class T> struct remove_const;
template <class T> struct remove_volatile;
template <class T> struct remove_cv;
template <class T> struct add_const;
template <class T> struct add_volatile;
template <class T> struct add_cv;

// [20.5.6.2] reference modifications:
template <class T> struct remove_reference;
template <class T> struct add_reference;
template <class T> struct add_lvalue_reference;
template <class T> struct add_rvalue_reference;

// [20.5.6.3] sign modifications
template <class T> struct make_signed;
template <class T> struct make_unsigned;

// [4.7.3] array modifications:
template <class T> struct remove_extent;
template <class T> struct remove_all_extents;

// [4.7.4] pointer modifications:
template <class T> struct remove_pointer;
template <class T> struct add_pointer;

// [20.5.7] other transformations:
template <std::size_t Len, std::size_t Align> struct aligned_storage;
template<std::size_t Len, class... Types> struct aligned_union;
template <typename T> struct decay;
template <bool, class T = void> struct enable_if;
template <bool, class T, class F> struct conditional;
template <class ...T> struct common_type;

}  // tr1
}  // std
*/

#include <ewlconfig>
#include <cstddef>
#include <ewl_utility>

#ifdef __CWCC__
#pragma options align=native

#ifdef _EWL_FORCE_ENUMS_ALWAYS_INT
	#if _EWL_FORCE_ENUMS_ALWAYS_INT
		#pragma enumsalwaysint on
	#else
		#pragma enumsalwaysint off
	#endif
#endif  // _EWL_FORCE_ENUMS_ALWAYS_INT

#ifdef _EWL_FORCE_ENABLE_BOOL_SUPPORT
	#if _EWL_FORCE_ENABLE_BOOL_SUPPORT
		#pragma bool on
	#else
		#pragma bool off
	#endif
#endif  // _EWL_FORCE_ENABLE_BOOL_SUPPORT
#endif

#ifdef __GNUC__
extern "C++" {
#endif // __GNUC__

_EWL_START_TR1_NAMESPACE

// enable_if
template<bool Condition, class Type = void>
struct enable_if;

template<class Type>
struct enable_if<false,Type>{};

template<class Type>
struct enable_if<true,Type>
{ typedef Type type; };

// integral_constant

template <class T, T v>
struct integral_constant
{
	static const T                  value = v;
	typedef T                       value_type;
	typedef integral_constant<T, v> type;
};

template<class T, T v>
const T integral_constant<T,v>::value;

typedef integral_constant<bool, true>  true_type;
typedef integral_constant<bool, false> false_type;

namespace detail
{
	struct two {char x; char y;};
}

// is_convertible

template <class From, class To>
struct is_convertible
	: public integral_constant<bool, CodeWarrior::is_convertible<From, To>::value>
{};


// remove_const

template <class T> struct remove_const          {typedef T type;};
template <class T> struct remove_const<T const> {typedef T type;};

// remove_volatile

template <class T> struct remove_volatile             {typedef T type;};
template <class T> struct remove_volatile<T volatile> {typedef T type;};

// remove_cv

template <class T> struct remove_cv
	{typedef typename remove_const<typename remove_volatile<T>::type>::type type;};

// is_void

namespace detail
{

template <class T> struct is_void : public integral_constant<bool, false> {};
template <> struct is_void<void> : public integral_constant<bool, true> {};

} // detail

template <class T> struct is_void
	: public integral_constant
	         <bool,
	         detail::is_void<typename remove_cv<T>::type>::value>
{};

// is_integral;

namespace detail
{

template <class T> struct is_integral : public integral_constant<bool, false> {};

#ifndef _EWL_NO_BOOL
template <> struct is_integral<bool> : public integral_constant<bool, true> {};
#endif

template <> struct is_integral<char>          : public integral_constant<bool, true> {};
template <> struct is_integral<signed char>   : public integral_constant<bool, true> {};
template <> struct is_integral<unsigned char> : public integral_constant<bool, true> {};

#if !defined(_EWL_NO_WCHART_CPP_SUPPORT)
template <> struct is_integral<wchar_t> : public integral_constant<bool, true> {};
#endif

template <> struct is_integral<short>          : public integral_constant<bool, true> {};
template <> struct is_integral<unsigned short> : public integral_constant<bool, true> {};

template <> struct is_integral<int>          : public integral_constant<bool, true> {};
template <> struct is_integral<unsigned int> : public integral_constant<bool, true> {};

template <> struct is_integral<long>          : public integral_constant<bool, true> {};
template <> struct is_integral<unsigned long> : public integral_constant<bool, true> {};

#if _EWL_LONGLONG
template <> struct is_integral<long long>          : public integral_constant<bool, true> {};
template <> struct is_integral<unsigned long long> : public integral_constant<bool, true> {};
#endif  // _EWL_LONGLONG

} // detail

template <class T> struct is_integral
	: public integral_constant
	         <bool,
	         detail::is_integral<typename remove_cv<T>::type>::value>
{};

// is_floating_point

namespace detail
{

template <class T> struct is_floating_point : public integral_constant<bool, false> {};

template <> struct is_floating_point<float>       : public integral_constant<bool, true> {};
template <> struct is_floating_point<double>      : public integral_constant<bool, true> {};
template <> struct is_floating_point<long double> : public integral_constant<bool, true> {};

} // detail

template <class T> struct is_floating_point
	: public integral_constant
	         <bool,
	         detail::is_floating_point<typename remove_cv<T>::type>::value>
{};

// is_array

template <class T> struct is_array                 : public integral_constant<bool, false> {};
template <class T> struct is_array<T[]>            : public integral_constant<bool, true> {};
template <class T, std::size_t N> struct is_array<T[N]> : public integral_constant<bool, true> {};

// is_pointer

namespace detail
{

template <class T> struct is_pointer     : public integral_constant<bool, false> {};
template <class T> struct is_pointer<T*> : public integral_constant<bool, true> {};

} // detail

template <class T> struct is_pointer
	: public integral_constant
	         <bool,
	         detail::is_pointer<typename remove_cv<T>::type>::value>
{};

// is_reference

template <class T> struct is_reference     : public integral_constant<bool, false> {};
template <class T> struct is_reference<T&> : public integral_constant<bool, true> {};

#ifdef _EWL_MOVE

template <class T> struct is_reference<T&&> : public integral_constant<bool, true> {};

template <class T> struct is_lvalue_reference     : public integral_constant<bool, false> {};
template <class T> struct is_lvalue_reference<T&> : public integral_constant<bool, true> {};

template <class T> struct is_rvalue_reference      : public integral_constant<bool, false> {};
template <class T> struct is_rvalue_reference<T&&> : public integral_constant<bool, true> {};

#endif  // _EWL_MOVE

// is_member_function_pointer

#ifdef __CWCC__

template <class T> struct is_member_function_pointer
: public integral_constant<bool, ((__builtin_type(T) & 0xF000) == 0x4000) &&
	                              (__builtin_classify_type(T) == 12)> {};

#else  // __CWCC__

namespace detail
{

template <class T> struct is_member_function_pointer : public integral_constant<bool, false> {};

template <class R, class T> struct is_member_function_pointer<R (T::*)()>
	: public integral_constant<bool, true> {};
template <class R, class T> struct is_member_function_pointer<R (T::*)() const>
	: public integral_constant<bool, true> {};
template <class R, class T> struct is_member_function_pointer<R (T::*)() volatile>
	: public integral_constant<bool, true> {};
template <class R, class T> struct is_member_function_pointer<R (T::*)() const volatile>
	: public integral_constant<bool, true> {};

template <class R, class T, class A0> struct is_member_function_pointer<R (T::*)(A0)>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0> struct is_member_function_pointer<R (T::*)(A0) const>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0> struct is_member_function_pointer<R (T::*)(A0) volatile>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0> struct is_member_function_pointer<R (T::*)(A0) const volatile>
	: public integral_constant<bool, true> {};

template <class R, class T, class A0, class A1>
	struct is_member_function_pointer<R (T::*)(A0, A1)>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1>
	struct is_member_function_pointer<R (T::*)(A0, A1) const>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1>
	struct is_member_function_pointer<R (T::*)(A0, A1) volatile>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1>
	struct is_member_function_pointer<R (T::*)(A0, A1) const volatile>
	: public integral_constant<bool, true> {};

template <class R, class T, class A0, class A1, class A2>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2)>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1, class A2>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2) const>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1, class A2>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2) volatile>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1, class A2>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2) const volatile>
	: public integral_constant<bool, true> {};

template <class R, class T, class A0, class A1, class A2, class A3>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3)>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1, class A2, class A3>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3) const>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1, class A2, class A3>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3) volatile>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1, class A2, class A3>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3) const volatile>
	: public integral_constant<bool, true> {};

template <class R, class T, class A0, class A1, class A2, class A3, class A4>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3, A4)>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1, class A2, class A3, class A4>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3, A4) const>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1, class A2, class A3, class A4>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3, A4) volatile>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1, class A2, class A3, class A4>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3, A4) const volatile>
	: public integral_constant<bool, true> {};

template <class R, class T, class A0, class A1, class A2, class A3, class A4,
                            class A5>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3, A4,
	                                           A5)>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1, class A2, class A3, class A4,
                            class A5>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3, A4,
	                                           A5) const>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1, class A2, class A3, class A4,
                            class A5>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3, A4,
	                                           A5) volatile>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1, class A2, class A3, class A4,
                            class A5>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3, A4,
	                                           A5) const volatile>
	: public integral_constant<bool, true> {};

template <class R, class T, class A0, class A1, class A2, class A3, class A4,
                            class A5, class A6>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3, A4,
	                                           A5, A6)>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1, class A2, class A3, class A4,
                            class A5, class A6>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3, A4,
	                                           A5, A6) const>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1, class A2, class A3, class A4,
                            class A5, class A6>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3, A4,
	                                           A5, A6) volatile>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1, class A2, class A3, class A4,
                            class A5, class A6>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3, A4,
	                                           A5, A6) const volatile>
	: public integral_constant<bool, true> {};

template <class R, class T, class A0, class A1, class A2, class A3, class A4,
                            class A5, class A6, class A7>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3, A4,
	                                           A5, A6, A7)>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1, class A2, class A3, class A4,
                            class A5, class A6, class A7>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3, A4,
	                                           A5, A6, A7) const>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1, class A2, class A3, class A4,
                            class A5, class A6, class A7>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3, A4,
	                                           A5, A6, A7) volatile>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1, class A2, class A3, class A4,
                            class A5, class A6, class A7>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3, A4,
	                                           A5, A6, A7) const volatile>
	: public integral_constant<bool, true> {};

template <class R, class T, class A0, class A1, class A2, class A3, class A4,
                            class A5, class A6, class A7, class A8>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3, A4,
	                                           A5, A6, A7, A8)>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1, class A2, class A3, class A4,
                            class A5, class A6, class A7, class A8>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3, A4,
	                                           A5, A6, A7, A8) const>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1, class A2, class A3, class A4,
                            class A5, class A6, class A7, class A8>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3, A4,
	                                           A5, A6, A7, A8) volatile>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1, class A2, class A3, class A4,
                            class A5, class A6, class A7, class A8>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3, A4,
	                                           A5, A6, A7, A8) const volatile>
	: public integral_constant<bool, true> {};

template <class R, class T, class A0, class A1, class A2, class A3, class A4,
                            class A5, class A6, class A7, class A8, class A9>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3, A4,
	                                           A5, A6, A7, A8, A9)>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1, class A2, class A3, class A4,
                            class A5, class A6, class A7, class A8, class A9>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3, A4,
	                                           A5, A6, A7, A8, A9) const>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1, class A2, class A3, class A4,
                            class A5, class A6, class A7, class A8, class A9>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3, A4,
	                                           A5, A6, A7, A8, A9) volatile>
	: public integral_constant<bool, true> {};
template <class R, class T, class A0, class A1, class A2, class A3, class A4,
                            class A5, class A6, class A7, class A8, class A9>
	struct is_member_function_pointer<R (T::*)(A0, A1, A2, A3, A4,
	                                           A5, A6, A7, A8, A9) const volatile>
	: public integral_constant<bool, true> {};

}  // detail

template <class T> struct is_member_function_pointer
	: public integral_constant
	         <bool,
	         detail::is_member_function_pointer<typename remove_cv<T>::type>::value>
{};

#endif  // __CWCC__

// is_member_pointer

namespace detail
{

template <class T> struct is_member_pointer                  : public integral_constant<bool, false> {};
template <class T, class U> struct is_member_pointer<U T::*> : public integral_constant<bool, true> {};

}  // detail

template <class T> struct is_member_pointer
	: public integral_constant
	         <bool,
	         detail::is_member_pointer<typename remove_cv<T>::type>::value>
{};

// is_member_object_pointer

template <class T> struct is_member_object_pointer
	: public integral_constant
		<
			bool,
			is_member_pointer<T>::value &&
			!is_member_function_pointer<T>::value
		> {};

// is_union

#ifdef __CWCC__

template <class T> struct is_union : public integral_constant<bool, __builtin_type(T) == 0x2001> {};

#else  // __CWCC__

namespace detail
{

template <class T> struct is_union : public integral_constant<bool, false> {};  // hook

}  // detail

template <class T>
struct is_union
	: public integral_constant<bool, detail::is_union<typename remove_cv<T>::type>::value>
{};

#endif  // __CWCC__

// is_class

#ifdef __CWCC__

template <class T>
struct is_class
	: public integral_constant<bool, !is_reference<T>::value && __builtin_type(T) == 0x2000>
{};

#else  // __CWCC__

namespace detail
{

template <class T>
struct is_class
{
	template <class U> static char test(void (U::*)());
	template <class U> static detail::two test(...);

	static const bool value = sizeof(test<T>(0)) == 1 && !is_union<T>::value;
};

}  // detail

template <class T>
struct is_class
	: public integral_constant<bool, detail::is_class<typename remove_cv<T>::type>::value>
{};

#endif  // __CWCC__

// is_function

#ifdef __CWCC__

template <class T> struct is_function : public integral_constant<bool, __builtin_type(T) == 0x8000> {};

#else  // __CWCC__

template <class T> struct is_function : public integral_constant<bool, false> {};

template <class R> struct is_function<R ()> : public integral_constant<bool, true> {};
template <class R, class A0> struct is_function<R (A0)> : public integral_constant<bool, true> {};
template <class R, class A0, class A1> struct is_function<R (A0, A1)>
	: public integral_constant<bool, true> {};
template <class R, class A0, class A1, class A2> struct is_function<R (A0, A1, A2)>
	: public integral_constant<bool, true> {};
template <class R, class A0, class A1, class A2, class A3> struct is_function<R (A0, A1, A2, A3)>
	: public integral_constant<bool, true> {};
template <class R, class A0, class A1, class A2, class A3, class A4>
struct is_function<R (A0, A1, A2, A3, A4)>
	: public integral_constant<bool, true> {};
template <class R, class A0, class A1, class A2, class A3, class A4,
                   class A5>
struct is_function<R (A0, A1, A2, A3, A4, A5)>
	: public integral_constant<bool, true> {};
template <class R, class A0, class A1, class A2, class A3, class A4,
                   class A5, class A6>
struct is_function<R (A0, A1, A2, A3, A4, A5, A6)>
	: public integral_constant<bool, true> {};
template <class R, class A0, class A1, class A2, class A3, class A4,
                   class A5, class A6, class A7>
struct is_function<R (A0, A1, A2, A3, A4, A5, A6, A7)>
	: public integral_constant<bool, true> {};
template <class R, class A0, class A1, class A2, class A3, class A4,
                   class A5, class A6, class A7, class A8>
struct is_function<R (A0, A1, A2, A3, A4, A5, A6, A7, A8)>
	: public integral_constant<bool, true> {};
template <class R, class A0, class A1, class A2, class A3, class A4,
                   class A5, class A6, class A7, class A8, class A9>
struct is_function<R (A0, A1, A2, A3, A4, A5, A6, A7, A8, A9)>
	: public integral_constant<bool, true> {};

#endif  // __CWCC__

// is_enum

#ifdef __CWCC__

template <class T>
struct is_enum
	: public integral_constant<bool, (__builtin_type(T) & 0xff00) == 0x0400>
{};

#else  // __CWCC__

namespace detail
{

template <class T>
struct is_enum
{
	static const bool value = !is_integral<T>::value &&
	                          !is_floating_point<T>::value &&
	                          !is_reference<T>::value &&
	                          !is_class<T>::value &&
	                          !is_union<T>::value &&
	                          !is_function<T>::value &&
	                          is_convertible<T, int>::value;
};

}  // detail

template <class T>
struct is_enum
	: public integral_constant<bool, detail::is_enum<typename remove_cv<T>::type>::value>
{};

#endif  // __CWCC__

// is_arithmetic

template <class T>
struct is_arithmetic
	: public integral_constant<bool, is_integral<T>::value || is_floating_point<T>::value>
{};

// is_fundamental

template <class T>
struct is_fundamental
	: public integral_constant<bool, is_arithmetic<T>::value || is_void<T>::value>
{};

// is_scalar

template <class T>
struct is_scalar
	: public integral_constant<bool, is_arithmetic<T>::value     ||
	                                 is_member_pointer<T>::value ||
	                                 is_pointer<T>::value        ||
	                                 is_enum<T>::value           >

{};

// is_object

template <class T>
struct is_object
	: public integral_constant<bool, !(is_void<T>::value      ||
	                                   is_reference<T>::value ||
	                                   is_function<T>::value  )>

{};

// is_compound

template <class T>
struct is_compound
	: public integral_constant<bool, !is_fundamental<T>::value>

{};

// is_const

template <class T> struct is_const          : public integral_constant<bool, false> {};
template <class T> struct is_const<T const> : public integral_constant<bool, true> {};

// add_const

namespace detail
{

template <class T, bool add = !(is_reference<T>::value ||
                                is_function<T>::value  ||
                                is_const<T>::value     )>
struct add_const
{
	typedef T const type;
};

template <class T>
struct add_const<T, false>
{
	typedef T type;
};

}  // detail

template <class T>
struct add_const
{
	typedef typename detail::add_const<T>::type type;
};

// is_volatile

template <class T> struct is_volatile             : public integral_constant<bool, false> {};
template <class T> struct is_volatile<T volatile> : public integral_constant<bool, true> {};

// add_volatile

namespace detail
{

template <class T, bool add = !(is_reference<T>::value ||
                                is_function<T>::value  ||
                                is_volatile<T>::value  )>
struct add_volatile
{
	typedef T volatile type;
};

template <class T>
struct add_volatile<T, false>
{
	typedef T type;
};

}  // detail

template <class T>
struct add_volatile
{
	typedef typename detail::add_volatile<T>::type type;
};

// add_cv

template <class T>
struct add_cv
{
	typedef typename add_const<typename add_volatile<T>::type>::type type;
};

// remove_reference

template <class T> struct remove_reference     {typedef T type;};
template <class T> struct remove_reference<T&> {typedef T type;};
#ifdef _EWL_MOVE
template <class T> struct remove_reference<T&&> {typedef T type;};
#endif

// add_reference

template <class T> struct add_reference     {typedef T& type;};
template <class T> struct add_reference<T&> {typedef T& type;};
#ifdef _EWL_MOVE
template <class T> struct add_reference<T&&> {typedef T&& type;};
#endif
template <>        struct add_reference<void>                {typedef void type;};
template <>        struct add_reference<const void>          {typedef void type;};
template <>        struct add_reference<volatile void>       {typedef void type;};
template <>        struct add_reference<const volatile void> {typedef void type;};

// add_lvalue_reference

namespace detail
{
  template<typename T, typename Default = void>
  struct
  add_lvalue_reference
  {
    typedef T type;
  };

  template<typename T>
  struct
  add_lvalue_reference<T,
                       typename enable_if<is_object<T>::value ||
                                          is_function<T>::value>::type >
  {
    typedef T& type;
  };
}

template<typename T>
struct
add_lvalue_reference
{
  typedef typename detail::add_lvalue_reference<T>::type type;
};

#ifdef _EWL_MOVE

template<typename T>
struct
add_lvalue_reference<T&&>
{
  typedef T& type;
};

#endif

#ifdef _EWL_MOVE

namespace detail
{
  template<typename T, typename Default = void>
  struct
  add_rvalue_reference
  {
    typedef T type;
  };

  template<typename T>
  struct
  add_rvalue_reference<T,
                       typename enable_if<is_object<T>::value ||
                                          is_function<T>::value>::type >
  {
    typedef T && type;
  };
}

template<typename T>
struct
add_rvalue_reference
{
  typedef typename detail::add_rvalue_reference<T>::type type;
};

#endif


// remove_extent

template <class T>           struct remove_extent       {typedef T type;};
template <class T, std::size_t N> struct remove_extent<T[N]> {typedef T type;};
template <class T>           struct remove_extent<T[]>  {typedef T type;};

// remove_all_extents

template <class T>           struct remove_all_extents       {typedef T type;};
template <class T, std::size_t N> struct remove_all_extents<T[N]>
	{typedef typename remove_all_extents<T>::type type;};
template <class T>                  struct remove_all_extents<T[]>
	{typedef typename remove_all_extents<T>::type type;};

// rank

template <class T> struct rank : public integral_constant<unsigned, 0> {};

template <class T> struct rank<T[]>
	: public integral_constant<unsigned, rank<T>::value + 1> {};

template <class T, std::size_t N> struct rank<T[N]>
	: public integral_constant<unsigned, rank<T>::value + 1> {};

// extent

template <class T, unsigned I = 0>       struct extent          : public integral_constant<std::size_t, 0> {};
template <class T>                       struct extent<T, 0>    : public integral_constant<std::size_t, 0> {};
template <class T>                       struct extent<T[], 0>  : public integral_constant<std::size_t, 0> {};
template <class T, unsigned I>           struct extent<T[], I>  : public integral_constant<std::size_t, extent<T, I-1>::value> {};
template <class T, std::size_t N>        struct extent<T[N], 0> : public integral_constant<std::size_t, N> {};
template <class T, std::size_t N, unsigned I> struct extent<T[N], I> : public integral_constant<std::size_t, extent<T, I-1>::value> {};

// is_signed

namespace detail
{

template <class T, bool integral = is_integral<T>::value>
struct is_signed
{
	static const bool value = T(-1) < T(0);
};

template <class T>
struct is_signed<T, false>
{
	static const bool value = false;
};

}  // detail

template <class T> struct is_signed : public integral_constant<bool, detail::is_signed<T>::value> {};

// is_unsigned

namespace detail
{

template <class T, bool integral = is_integral<T>::value>
struct is_unsigned
{
	static const bool value = !(T(-1) < T(0));
};

template <class T>
struct is_unsigned<T, false>
{
	static const bool value = false;
};

}  // detail

template <class T> struct is_unsigned : public integral_constant<bool, detail::is_unsigned<T>::value> {};

// remove_pointer

template <class T> struct remove_pointer                   {typedef T type;};
template <class T> struct remove_pointer<T*>               {typedef T type;};
template <class T> struct remove_pointer<T*const>          {typedef T type;};
template <class T> struct remove_pointer<T*volatile>       {typedef T type;};
template <class T> struct remove_pointer<T*const volatile> {typedef T type;};

// add_pointer

template <class T> struct add_pointer {typedef typename remove_reference<T>::type* type;};

// is_same

template <class T, class U> struct is_same : public integral_constant<bool, false> {};
template <class T> struct is_same<T, T>    : public integral_constant<bool, true> {};

// is_base_of

template <class Base, class Derived>
struct is_base_of
	: public integral_constant<bool,
		is_same<Base, Derived>::value ||
		(
		is_class<Base>::value &&
		is_class<Derived>::value &&
		is_convertible<
			typename add_pointer<Derived>::type,
			typename add_pointer<Base>::type
		>::value
		)>
{};

// has_trivial_copy_constructor

#ifdef __CWCC__

template <class T> struct has_trivial_copy_constructor
	: public integral_constant<bool,
		is_reference<T>::value || bool(__builtin_trivial_members(T) & 0x4)> {};

#else  // __CWCC__

template <class T> struct has_trivial_copy_constructor
	: public integral_constant<bool,
		is_scalar<T>::value   ||
		is_union<T>::value    ||
		is_reference<T>::value
	> {};

#endif  // __CWCC__

// has_trivial_assign

#ifdef __CWCC__

template <class T> struct has_trivial_assign
	: public integral_constant<bool, 
		!is_const<T>::value && !is_reference<T>::value && bool(__builtin_trivial_members(T) & 0x2)> {};

#else  // __CWCC__

template <class T> struct has_trivial_assign
	: public integral_constant<bool,
		!is_const<T>::value &&
		!is_reference<T>::value &&
		(
		is_scalar<T>::value ||
		is_union<T>::value
		)
	> {};

#endif  // __CWCC__

// has_trivial_destructor

#ifdef __CWCC__

template <class T> struct has_trivial_destructor
	: public integral_constant<bool,
		is_reference<T>::value || bool(__builtin_trivial_members(T) & 0x1)
	>
{};

#else  // __CWCC__

namespace detail
{

template <class T>
struct has_trivial_destructor
{
	static const bool value = is_scalar<T>::value
	                       || is_union<T>::value
	                       || is_reference<T>::value;
};

}  // detail

template <class T> struct has_trivial_destructor
	: public integral_constant<bool,
		detail::has_trivial_destructor<typename remove_all_extents<T>::type>::value
	>
{};

#endif  // __CWCC__

// has_trivial_default_constructor

#if defined(__CWCC__) && __CWCC__ >= 0x4010

template <class T> struct has_trivial_default_constructor
	: public integral_constant<bool,
		is_object<T>::value && bool(__builtin_trivial_members(T) & 0x8)
	>
{};

#else  // defined(__CWCC__) && __CWCC__ >= 0x4010

namespace detail
{

template <class T>
struct has_trivial_default_constructor
{
	static const bool value = is_scalar<T>::value || is_union<T>::value;
};

}  // detail

template <class T>
struct has_trivial_default_constructor
	: public integral_constant<bool,
		detail::has_trivial_default_constructor<typename remove_all_extents<T>::type>::value
	>
{};

#endif  // defined(__CWCC__) && __CWCC__ >= 0x4010

// is_pod

#if defined(__CWCC__) && __CWCC__ >= 0x4010

template <class T>
struct is_pod
	: public integral_constant<bool, is_object<T>::value && __builtin_is_pod(T)>
{};

#else  // defined(__CWCC__) && __CWCC__ >= 0x4010

template <class T>
struct is_pod
	: public integral_constant<bool,
		has_trivial_default_constructor<T>::value &&
		has_trivial_copy_constructor<T>::value    &&
		has_trivial_assign<T>::value              &&
		has_trivial_destructor<T>::value
	>
{};

#endif  // defined(__CWCC__) && __CWCC__ >= 0x4010

// is_trivial defined lower

// NOTE: is_standard_layout is not yet implemented as an
// intrinsic. For your own types specialize this trait.
template <class T>
struct is_standard_layout;

// is_empty

namespace detail
{

template <class T, bool b = is_class<T>::value>
struct is_empty1
	: T
{
	double d_;
};

template <class T>
struct is_empty1<T, false>
{
	T t_;
	double d_;
};

template <class T>
struct is_empty2
{
	double d_;
};

}  // detail

template <class T> struct is_empty
	: public integral_constant<bool,
		sizeof(detail::is_empty1<T>) == sizeof(detail::is_empty2<T>) &&
		has_trivial_assign<T>::value
	>
{};

// is_polymorphic

#if defined(__CWCC__) && __CWCC__ >= 0x4010

template <class T>
struct is_polymorphic
	: public integral_constant<bool, is_class<T>::value && __builtin_is_polymorphic(T)>
{};

#else  // defined(__CWCC__) && __CWCC__ >= 0x4010

namespace detail
{

template <class T>
struct is_polymorphic_test1
	: T
{
};

template <class T>
struct is_polymorphic_test2
	: T
{
	virtual ~is_polymorphic_test2();
};

template <class T, bool b = is_class<T>::value>
struct is_polymorphic
{
	static const bool value = sizeof(is_polymorphic_test1<T>) == sizeof(is_polymorphic_test2<T>);
};

template <class T>
struct is_polymorphic<T, false>
{
	static const bool value = false;
};

}  // detail

template <class T> struct is_polymorphic : public integral_constant<bool, detail::is_polymorphic<T>::value> {};

#endif  // defined(__CWCC__) && __CWCC__ >= 0x4010

namespace detail
{

template <class T>
struct is_trivial
{
  typedef typename remove_cv<T>::type bare_type;
  static const bool value =
    has_trivial_default_constructor<bare_type>::value &&
    has_trivial_copy_constructor<bare_type>::value &&
    has_trivial_assign<bare_type>::value &&
    has_trivial_destructor<bare_type>::value &&
    !is_polymorphic<bare_type>::value;
};

}

template<class T>
struct is_trivial : integral_constant<bool,detail::is_trivial<T>::value> {};

// is_abstract

#if defined(__CWCC__) && __CWCC__ >= 0x4010

template <class T>
struct is_abstract 
	: public integral_constant<bool, is_class<T>::value && __builtin_is_abstract(T)>
{};

#else  // defined(__CWCC__) && __CWCC__ >= 0x4010

namespace detail
{

template <class T>
struct is_abstract
{
private:
    template <class U> static detail::two test(U (*)[1]);
    template <class U> static char test(...);
public:
    static const bool value = sizeof(test<T>(0)) == 1;
};

}  // detail

template <class T> struct is_abstract : public integral_constant<bool, detail::is_abstract<T>::value> {};

#endif  // defined(__CWCC__) && __CWCC__ >= 0x4010

// has_nothrow_default_constructor

#if defined(__CWCC__) && __CWCC__ >= 0x4010

template <class T> struct has_nothrow_default_constructor
	: public integral_constant<bool,
		is_object<T>::value && __builtin_has_nothrow_default_constructor(T)> {};

#else  // defined(__CWCC__) && __CWCC__ >= 0x4010

template <class T> struct has_nothrow_default_constructor
	: public integral_constant<bool, has_trivial_default_constructor<T>::value> {};

#endif  // defined(__CWCC__) && __CWCC__ >= 0x4010

// has_nothrow_copy_constructor

#if defined(__CWCC__) && __CWCC__ >= 0x4010

template <class T> struct has_nothrow_copy_constructor
	: public integral_constant<bool,
		is_reference<T>::value || __builtin_has_nothrow_copy(T)> {};

#else  // defined(__CWCC__) && __CWCC__ >= 0x4010

template <class T> struct has_nothrow_copy_constructor
	: public integral_constant<bool, has_trivial_copy_constructor<T>::value> {};

#endif  // defined(__CWCC__) && __CWCC__ >= 0x4010

// has_nothrow_assign

#if defined(__CWCC__) && __CWCC__ >= 0x4010

template <class T> struct has_nothrow_assign
	: public integral_constant<bool,
		!is_const<T>::value && !is_reference<T>::value &&  __builtin_has_nothrow_assign(T)> {};

#else  // defined(__CWCC__) && __CWCC__ >= 0x4010

template <class T> struct has_nothrow_assign
	: public integral_constant<bool, has_trivial_assign<T>::value> {};

#endif  // defined(__CWCC__) && __CWCC__ >= 0x4010

// has_virtual_destructor

#if defined(__CWCC__) && __CWCC__ >= 0x4010

template <class T> struct has_virtual_destructor
	: public integral_constant<bool, __builtin_has_virtual_destructor(T)> {};

#else  // defined(__CWCC__) && __CWCC__ >= 0x4010

template <class T> struct has_virtual_destructor
	: public integral_constant<bool, false> {};

#endif  // defined(__CWCC__) && __CWCC__ >= 0x4010

// alignment_of

#ifdef __CWCC__

namespace detail
{

template <class T, bool b = is_reference<T>::value>
struct alignment_of
	: public integral_constant<size_t, __builtin_align(typename remove_reference<T>::type*)> {};

template <class T>
struct alignment_of<T, false>
	: public integral_constant<size_t, __builtin_align(T)> {};

}  // detail

template <class T> struct alignment_of
	: public integral_constant<size_t, detail::alignment_of<T>::value> {};

#elif defined(__GNUC__)// __CWCC__

namespace detail
{

template <class T, bool b = is_reference<T>::value>
struct alignment_of
	: public integral_constant<std::size_t, __alignof__(typename remove_reference<T>::type*)> {};

template <class T>
struct alignment_of<T, false>
	: public integral_constant<std::size_t, __alignof__(T)> {};

}  // detail

template <class T> struct alignment_of
	: public integral_constant<std::size_t, detail::alignment_of<T>::value> {};


#else // __CWCC__

#endif  // __CWCC__

// aligned_storage

namespace detail
{

template <bool b, class T1, class T2>
struct select
{
	typedef T1 type;
};

template <class T1, class T2>
struct select<false, T1, T2>
{
	typedef T2 type;
};

template <class H, class T>
struct type_list
{
	typedef H head;
	typedef T tail;
};

struct nat_ {};

template <class T>
struct align_type
{
	static const std::size_t value = alignment_of<T>::value;
	typedef T type;
};

struct align_8
{
	double d;
};

typedef
	type_list<align_type<unsigned char>,
	type_list<align_type<unsigned short>,
	type_list<align_type<unsigned int>,
	type_list<align_type<unsigned long>,
#if _EWL_LONGLONG
	type_list<align_type<unsigned long long>,
#endif
	type_list<align_type<double>,
	type_list<align_type<align_8>,
#if __VEC__
	type_list<align_type<vector unsigned int>,
#endif
	nat_
#if __VEC__
	>
#endif
	> >
#if _EWL_LONGLONG
	>
#endif
	> > > >
	all_aligning_types;

template <class TL, std::size_t Align>
struct find_pod
{
	typedef void type;
};

template <class H, class T, std::size_t Align>
struct find_pod<type_list<H, T>, Align>
{
	typedef typename select<
		Align == H::value,
		typename H::type,
		typename find_pod<T, Align>::type
	>::type type;
};

template <class H, std::size_t Align>
struct find_pod<type_list<H, nat_>, Align>
{
	typedef typename select<
		Align == H::value,
		typename H::type,
		void
	>::type type;
};

template <class TL>
struct find_max_pod;

template <class H, class T>
struct find_max_pod<type_list<H, T> >
{
private:
	typedef typename find_max_pod<T>::type tmax;
public:
	typedef typename select<
		tmax::value < H::value,
		H,
		tmax
	>::type type;
};

template <class H>
struct find_max_pod<type_list<H, nat_> >
{
	typedef H type;
};

template<bool C, typename T1, typename T2>
struct lazy_if;

template<typename T1, typename T2>
struct lazy_if<true,T1,T2>
{
  typedef typename T1::type type;
};

template<typename T1, typename T2>
struct lazy_if<false,T1,T2>
{
  typedef typename T2::type type;
};

// type_list<T,type_list<nat,type_list<nat...> > => type_list<T,nat>
template<typename TypeList>
struct cleanup_typelist;

template<typename T>
struct cleanup_typelist<type_list<T,nat_ > >
{
  typedef type_list<T,nat_> type;
};

template<typename T,
         typename Rest>
struct cleanup_typelist<type_list<T,Rest> >
{
  typedef typename cleanup_typelist<Rest>::type rest_type;
  typedef type_list<T,rest_type> type;
};

template<typename T,
         typename Rest>
struct cleanup_typelist<type_list<T,type_list<nat_,Rest> > >
{
  typedef type_list<T,nat_> type;
};

template<typename T0=nat_, typename T1=nat_, typename T2=nat_, typename T3=nat_, typename T4=nat_,
         typename T5=nat_, typename T6=nat_, typename T7=nat_, typename T8=nat_, typename T9=nat_>
struct to_typelist
{
  // This is a very long line to prevent writing other very long lines below.
  typedef type_list<T0,type_list<T1,type_list<T2, type_list<T3, type_list<T4, type_list<T5, type_list<T6,type_list<T7, type_list<T8, type_list<T9, nat_ > > > > > > > > > > type1;

  typedef typename cleanup_typelist<type1>::type type;
};

template<typename T> struct identity{ typedef T type; };

template<template<class> class Func, typename TypeList>
struct find_first;

template<template<class> class Func,
         typename T1,
         typename Rest>
struct find_first<Func,
                  type_list<T1,Rest> >
{
  typedef typename
  lazy_if<Func<T1>::value,
          identity<T1>,
          find_first<Func,Rest> >::type type;

};

template<template<class> class Func,
         typename T1>
struct find_first<Func,type_list<T1,nat_> >
{
  typedef T1 type;
};

template<template<class> class Func,
         typename Rest>
struct find_first<Func,type_list<nat_,Rest> >
{}; // Not found

}  // detail

template <std::size_t Len, std::size_t Align = detail::find_max_pod<detail::all_aligning_types>::type::value>
struct aligned_storage
{
	union type
	{
		unsigned char __data[Len];
		typedef typename detail::find_pod<detail::all_aligning_types, Align>::type __align_type;
#if 0
		__static_assert(!is_same<__align_type, void>::value, "Alignment not supported for this value");
#endif
		__align_type __align;
	};
};

// conditional
template<bool B, class T, class F>
struct conditional;

template<class T, class F>
struct conditional<true,T,F>
{ typedef T type; };

template<class T, class F>
struct conditional<false,T,F>
{ typedef F type; };

// make_signed

namespace detail
{
  // Specializations to map known signed types to unsigned.
  template<typename T>
  struct to_unsigned;

  template<typename T>
  struct to_signed;

  // Define maps from signed -> unsigned, signed -> signed,
  // unsigned -> signed, unsigned -> unsigned
#define _MAP_SIGNED_UNSIGNED(signed,unsigned)                                   \
  template<> struct to_unsigned<signed>{typedef unsigned type; };       \
  template<> struct to_unsigned<unsigned>{typedef unsigned type; };     \
  template<> struct to_signed<unsigned>{typedef signed type; };       \
  template<> struct to_signed<signed>{typedef signed type; }

  _MAP_SIGNED_UNSIGNED(signed char, unsigned char);
  _MAP_SIGNED_UNSIGNED(signed short, unsigned short);
  _MAP_SIGNED_UNSIGNED(signed int, unsigned int);
  _MAP_SIGNED_UNSIGNED(signed long, unsigned long);
#if _EWL_LONGLONG
  _MAP_SIGNED_UNSIGNED(signed long long, unsigned long long);
#endif

#undef _MAP_SIGNED_UNSIGNED

  // Fallthrough:
  //
  // For finding the signed version of char/wchar_t/enums, we need to
  // find an unsigned type that is the same size as char/wchar_t/enums
  // and use that type's signed counterpart. Similarly for finding the
  // unsigned counterpart. Admittedly, the counterparts for
  // char/wchar_t are fixed for a certain version of the compiler. If
  // we can find out that to_signed<wchar_t>::type should always be some
  // specific type, then this would not be necessary for wchar_t/char
  // (but is still necessary for enum)
  typedef to_typelist<signed char,
                      signed short,
                      signed int,
                      signed long
#if _EWL_LONGLONG
                      , signed long long
#endif
                      >::type all_signed_types;

  typedef to_typelist<unsigned char,
                      unsigned short,
                      unsigned int,
                      unsigned long
#if _EWL_LONGLONG
                      , unsigned long long
#endif
                      >::type all_unsigned_types;

  template<typename T1>
  struct is_same_size
  {
    template<typename T2>
    struct apply : integral_constant<bool,sizeof(T1) == sizeof(T2)>
    { };
  };

  template<typename T,typename TypeList,
           template<typename> class Func>
  struct to_signed_helper
  {
    typedef typename
#if __GNUC__
    find_first< Func, TypeList>::type type1;
#else
    find_first< is_same_size<T>::apply, TypeList>::type type1;
#endif
    typedef typename Func<type1>::type type;
  };

  template<typename T>
  struct to_signed : to_signed_helper<T,all_unsigned_types,to_signed> {};

  template<typename T>
  struct to_unsigned : to_signed_helper<T,all_signed_types,to_unsigned> {};

  template<typename From, typename To>
  struct copy_cv
  {
    // Add const qualification (if any)
    typedef typename conditional<
      is_const<From>::value,
      typename add_const<To>::type,
      To>
    ::type signed_nov_type;

    // Ditto for volatile
    typedef typename conditional<
      is_volatile<From>::value,
      typename add_volatile<signed_nov_type>::type,
      signed_nov_type>
    ::type type;
  };
}

template<typename T>
struct make_signed
{
#if 0
  __static_assert(is_integral<T>::value || is_enum<T>::value,
                  "make_signed only supported for integral types");
#endif
  typedef typename remove_cv<T>::type T_nocv_type;

#if 0
  __static_assert(!is_same<bool,T_nocv_type>::value,
                  "make_signed not supported for bool");
#endif

  typedef typename
  detail::to_signed<T_nocv_type>::type signed_nocv_type;

  typedef typename
  detail::copy_cv<T,signed_nocv_type>::type type;
};

template<typename T>
struct make_unsigned
{
#if 0
  __static_assert(is_integral<T>::value || is_enum<T>::value,
                  "make_unsigned only supported for integral types");
#endif

  typedef typename remove_cv<T>::type T_nocv_type;

#if 0
  __static_assert(!is_same<bool,T_nocv_type>::value,
                  "make_unsigned not supported for bool");
#endif

  typedef typename
  detail::to_unsigned<T_nocv_type>::type unsigned_nocv_type;

  typedef typename
  detail::copy_cv<T,unsigned_nocv_type>::type type;
};

// enable_if (higher up in file)

// conditional (higher up in file)

#if defined(_EWL_MOVE)

// common_type
namespace detail
{
  template<typename T, typename U>
  struct common_type
  {
  private:
    // Turns out if we use the direct definition from the standard the
    // conditional operator gets optimized before decltype ever sees
    // it so the result type is wrong. __b() prevents the compiler
    // from optimizing unnecessarily.
    static bool __b();
    static T&& __t();
    static U&& __u();
  public:
    typedef __decltype__(__b() ? __t() : __u()) type;
  };
}

template<class T0,
         class T1=detail::nat_,class T2=detail::nat_,
         class T3=detail::nat_,class T4=detail::nat_,class T5=detail::nat_,
         class T6=detail::nat_,class T7=detail::nat_,class T8=detail::nat_,
         class T9=detail::nat_>
struct common_type
{
private:
  typedef typename detail::common_type<T0,T1>::type type0;
public:
  typedef typename common_type<type0,T2,T3,T4,T5,T6,T7,T8,T9>::type type;
};

template<class T0>
struct common_type<T0,
                   detail::nat_,detail::nat_,detail::nat_,
                   detail::nat_,detail::nat_,detail::nat_,
                   detail::nat_,detail::nat_,detail::nat_>
{
  typedef T0 type;
};

#endif // _EWL_MOVE

namespace detail
{
  template<typename T0, typename T1>
  struct result
  {
    typedef T0 largest;
    typedef T1 align;
  };

  template<typename T0,typename T1>
  struct max_alignment
  {
    enum an_enum
    {
      T0_alignment = ::std::tr1::alignment_of<T0>::value,
      T1_alignment = ::std::tr1::alignment_of<T1>::value,
      T0_greater = T0_alignment > T1_alignment ? true : false
    };

    typedef typename
    conditional<(T0_greater ? true : false),
                T0,
                T1>::type type;
  };

  template<typename T0, typename T1>
  struct largest
  {
    typedef typename
    conditional<(sizeof(T0) > sizeof(T1)),
      T0,
      T1>::type type;

  };

  template<typename T0, typename T1>
  struct aligned_union_helper2
  {
    typedef typename
    largest<T0,T1>::type largest;

    typedef typename
    max_alignment<T0,T1>::type align;

    typedef result<largest,align> type;
  };

  template<typename T0, typename T1, typename T2>
  struct aligned_union_helper2<result<T0,T1>,T2>
  {
    typedef result<
      typename largest<T0,T2>::type,
      typename max_alignment<T1,T2>::type
      > type;
  };

  template<typename T0,
           typename T1 = nat_,
           typename T2 = nat_,
           typename T3 = nat_,
           typename T4 = nat_,
           typename T5 = nat_,
           typename T6 = nat_,
           typename T7 = nat_,
           typename T8 = nat_,
           typename T9 = nat_ >
  struct aligned_union_helper
  {
    typedef typename
    aligned_union_helper2<T0,T1>::type type0;

    typedef typename
    aligned_union_helper<type0,T2,T3,T4,T5,T6,T7,T8,T9>::type type;
  };

  template<typename T0>
  struct aligned_union_helper<T0,nat_,nat_,nat_,nat_,nat_,nat_,nat_,nat_,nat_>
  {
    typedef result<T0,T0> type;
  };

  template<typename T0,
           typename T1>
  struct aligned_union_helper<result<T0,T1>,nat_,nat_,nat_,nat_,nat_,nat_,nat_,nat_,nat_>
  {
    typedef result<T0,T1> type;
  };
}

// aligned_union
template<std::size_t Len,
         typename T0,
         typename T1 = detail::nat_,
         typename T2 = detail::nat_,
         typename T3 = detail::nat_,
         typename T4 = detail::nat_,
         typename T5 = detail::nat_,
         typename T6 = detail::nat_,
         typename T7 = detail::nat_,
         typename T8 = detail::nat_,
         typename T9 = detail::nat_>
struct aligned_union
{
private:
  typedef typename
  detail::aligned_union_helper<T0,T1,T2,T3,T4,
                               T5,T6,T7,T8,T9>::type result;

  typedef typename
  result::largest largest_type;

  typedef typename
  result::align max_align_type;

  enum an_enum
  {
    sizeof_largest = sizeof(largest_type),
    max_align = alignment_of<max_align_type>::value
  };

public:
  typedef typename
  aligned_storage< ( Len < sizeof_largest ? sizeof_largest : Len ),
    max_align>::type type;

  static const std::size_t alignment_value = max_align;
};

template<std::size_t Len, typename T0,
         typename T1, typename T2, typename T3,
         typename T4, typename T5, typename T6,
         typename T7, typename T8, typename T9>
const std::size_t aligned_union<Len,T0,T1,T2,T3,T4,T5,T6,T7,T8,T9>::alignment_value;

namespace detail
{
  // Default
  template<class U, class Enable = void>
  struct decay_impl
  {
    typedef typename remove_cv<U>::type type;
  };

  // Array
  template<class U>
  struct decay_impl<U,
                    typename enable_if<is_array<U>::value>::type>
  {
    typedef typename remove_extent<U>::type* type;
  };

  // Function
  template<class U>
  struct decay_impl<U,
                    typename enable_if<is_function<U>::value>::type>
  {
    typedef U * type;
  };
}

template<class T>
struct decay
{
  typedef typename remove_reference<T>::type U;
  typedef typename detail::decay_impl<U>::type type;
};

_EWL_END_TR1_NAMESPACE

#ifdef __GNUC__
} // extern "C++"
#endif // __GNUC__

#ifdef __CWCC__
#ifdef _EWL_FORCE_ENUMS_ALWAYS_INT
	#pragma enumsalwaysint reset
#endif

#ifdef _EWL_FORCE_ENABLE_BOOL_SUPPORT
	#pragma bool reset
#endif

#pragma options align=reset
#endif

#endif // _TYPE_TRAITS
