diff options
Diffstat (limited to 'src/inc/clr_std/type_traits')
-rw-r--r-- | src/inc/clr_std/type_traits | 549 |
1 files changed, 549 insertions, 0 deletions
diff --git a/src/inc/clr_std/type_traits b/src/inc/clr_std/type_traits new file mode 100644 index 0000000000..090694e320 --- /dev/null +++ b/src/inc/clr_std/type_traits @@ -0,0 +1,549 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// +// clr_std/utility +// +// Copy of some key Standard Template Library functionality. +// See http://msdn.microsoft.com/en-us/library/bb982077.aspx for documentation. +// + +#ifdef _MSC_VER +#pragma once +#endif + +#ifndef __clr_std_type_traits_h__ +#define __clr_std_type_traits_h__ + +#ifdef USE_STL + +#include <type_traits> + +#else + +namespace std +{ + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS remove_const + template<class _Ty> + struct remove_const + { // remove top level const qualifier + typedef _Ty type; + }; + + template<class _Ty> + struct remove_const<const _Ty> + { // remove top level const qualifier + typedef _Ty type; + }; + + template<class _Ty> + struct remove_const<const _Ty[]> + { // remove top level const qualifier + typedef _Ty type[]; + }; + + template<class _Ty, unsigned int _Nx> + struct remove_const<const _Ty[_Nx]> + { // remove top level const qualifier + typedef _Ty type[_Nx]; + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS remove_volatile + template<class _Ty> + struct remove_volatile + { // remove top level volatile qualifier + typedef _Ty type; + }; + + template<class _Ty> + struct remove_volatile<volatile _Ty> + { // remove top level volatile qualifier + typedef _Ty type; + }; + + template<class _Ty> + struct remove_volatile<volatile _Ty[]> + { // remove top level volatile qualifier + typedef _Ty type[]; + }; + + template<class _Ty, unsigned int _Nx> + struct remove_volatile<volatile _Ty[_Nx]> + { // remove top level volatile qualifier + typedef _Ty type[_Nx]; + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS remove_cv + template<class _Ty> + struct remove_cv + { // remove top level const and volatile qualifiers + typedef typename remove_const<typename remove_volatile<_Ty>::type>::type type; + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE remove_reference + template<class T> + struct remove_reference + { // remove reference + typedef T type; + }; + + template<class T> + struct remove_reference<T&> + { // remove reference + typedef T type; + }; + + template<class T> + struct remove_reference<T&&> + { // remove rvalue reference + typedef T type; + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE remove_pointer + template<class T> + struct remove_pointer + { // remove pointer + typedef T type; + }; + + template<class T> + struct remove_pointer<T*> + { // remove pointer + typedef T type; + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE FUNCTION identity + template<class T> + struct identity + { // map T to type unchanged + typedef T type; + + inline + const T& operator()(const T& left) const + { // apply identity operator to operand + return (left); + } + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS integral_constant + template<class _Ty, _Ty _Val> + struct integral_constant + { // convenient template for integral constant types + static const _Ty value = _Val; + + typedef _Ty value_type; + typedef integral_constant<_Ty, _Val> type; + }; + + typedef integral_constant<bool, true> true_type; + typedef integral_constant<bool, false> false_type; + + // TEMPLATE CLASS _Cat_base + template<bool> + struct _Cat_base + : false_type + { // base class for type predicates + }; + + template<> + struct _Cat_base<true> + : true_type + { // base class for type predicates + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS enable_if + template<bool _Test, class _Type = void> + struct enable_if + { // type is undefined for assumed !_Test + }; + + template<class _Type> + struct enable_if<true, _Type> + { // type is _Type for _Test + typedef _Type type; + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS conditional + template<bool _Test, class _Ty1, class _Ty2> + struct conditional + { // type is _Ty2 for assumed !_Test + typedef _Ty2 type; + }; + + template<class _Ty1, class _Ty2> + struct conditional<true, _Ty1, _Ty2> + { // type is _Ty1 for _Test + typedef _Ty1 type; + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS is_lvalue_reference + template<class _Ty> + struct is_lvalue_reference + : false_type + { // determine whether _Ty is an lvalue reference + }; + + template<class _Ty> + struct is_lvalue_reference<_Ty&> + : true_type + { // determine whether _Ty is an lvalue reference + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS is_rvalue_reference + template<class _Ty> + struct is_rvalue_reference + : false_type + { // determine whether _Ty is an rvalue reference + }; + + template<class _Ty> + struct is_rvalue_reference<_Ty&&> + : true_type + { // determine whether _Ty is an rvalue reference + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS is_reference + template<class _Ty> + struct is_reference + : conditional< + is_lvalue_reference<_Ty>::value || is_rvalue_reference<_Ty>::value, + true_type, + false_type>::type + { // determine whether _Ty is a reference + }; + + // TEMPLATE CLASS is_pointer + template<class _Ty> + struct is_pointer + : false_type + { // determine whether _Ty is a pointer + }; + + template<class _Ty> + struct is_pointer<_Ty *> + : true_type + { // determine whether _Ty is a pointer + }; + + // TEMPLATE CLASS _Is_integral + template<class _Ty> + struct _Is_integral + : false_type + { // determine whether _Ty is integral + }; + + template<> + struct _Is_integral<bool> + : true_type + { // determine whether _Ty is integral + }; + + template<> + struct _Is_integral<char> + : true_type + { // determine whether _Ty is integral + }; + + template<> + struct _Is_integral<unsigned char> + : true_type + { // determine whether _Ty is integral + }; + + template<> + struct _Is_integral<signed char> + : true_type + { // determine whether _Ty is integral + }; + + #ifdef _NATIVE_WCHAR_T_DEFINED + template<> + struct _Is_integral<wchar_t> + : true_type + { // determine whether _Ty is integral + }; + #endif /* _NATIVE_WCHAR_T_DEFINED */ + + template<> + struct _Is_integral<unsigned short> + : true_type + { // determine whether _Ty is integral + }; + + template<> + struct _Is_integral<signed short> + : true_type + { // determine whether _Ty is integral + }; + + template<> + struct _Is_integral<unsigned int> + : true_type + { // determine whether _Ty is integral + }; + + template<> + struct _Is_integral<signed int> + : true_type + { // determine whether _Ty is integral + }; + +// On Unix 'long' is a 64-bit type (same as __int64) and the following two definitions +// conflict with _Is_integral<unsigned __int64> and _Is_integral<signed __int64>. +#ifndef PLATFORM_UNIX + template<> + struct _Is_integral<unsigned long> + : true_type + { // determine whether _Ty is integral + }; + + template<> + struct _Is_integral<signed long> + : true_type + { // determine whether _Ty is integral + }; +#endif /* PLATFORM_UNIX */ + + #if _HAS_CHAR16_T_LANGUAGE_SUPPORT + template<> + struct _Is_integral<char16_t> + : true_type + { // determine whether _Ty is integral + }; + + template<> + struct _Is_integral<char32_t> + : true_type + { // determine whether _Ty is integral + }; + #endif /* _HAS_CHAR16_T_LANGUAGE_SUPPORT */ + + template<> + struct _Is_integral<unsigned __int64> + : true_type + { // determine whether _Ty is integral + }; + + template<> + struct _Is_integral<signed __int64> + : true_type + { // determine whether _Ty is integral + }; + + // TEMPLATE CLASS is_integral + template<class _Ty> + struct is_integral + : _Is_integral<typename remove_cv<_Ty>::type> + { // determine whether _Ty is integral + }; + + // TEMPLATE CLASS _Is_floating_point + template<class _Ty> + struct _Is_floating_point + : false_type + { // determine whether _Ty is floating point + }; + + template<> + struct _Is_floating_point<float> + : true_type + { // determine whether _Ty is floating point + }; + + template<> + struct _Is_floating_point<double> + : true_type + { // determine whether _Ty is floating point + }; + +// In PAL, we define long as int and so this becomes int double, +// which is a nonsense +#ifndef FEATURE_PAL + template<> + struct _Is_floating_point<long double> + : true_type + { // determine whether _Ty is floating point + }; +#endif + + // TEMPLATE CLASS is_floating_point + template<class _Ty> + struct is_floating_point + : _Is_floating_point<typename remove_cv<_Ty>::type> + { // determine whether _Ty is floating point + }; + + // TEMPLATE CLASS is_arithmetic + template<class _Ty> + struct is_arithmetic + : _Cat_base<is_integral<_Ty>::value + || is_floating_point<_Ty>::value> + { // determine whether _Ty is an arithmetic type + }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS is_signed + template <typename T> + struct is_signed : conditional< + static_cast<typename remove_const<T>::type>(-1) < 0, true_type, false_type>::type {}; + + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS is_same + template<class T1, class T2> + struct is_same : false_type { }; + + //----------------------------------------------------------------------------------------- + template<class T1> + struct is_same<T1, T1> : true_type { }; + + //----------------------------------------------------------------------------------------- + // TEMPLATE CLASS is_base_of +#ifdef _MSC_VER + + template <typename TBase, typename TDerived> + struct is_base_of : + conditional<__is_base_of( TBase, TDerived), true_type, false_type>::type {}; + +#else + namespace detail + { + //------------------------------------------------------------------------------------- + // Helper types Small and Big - guarantee that sizeof(Small) < sizeof(Big) + // + + template <class T, class U> + struct conversion_helper + { + typedef char Small; + struct Big { char dummy[2]; }; + static Big Test(...); + static Small Test(U); + static T MakeT(); + }; + + //------------------------------------------------------------------------------------- + // class template conversion + // Figures out the conversion relationships between two types + // Invocations (T and U are types): + // a) conversion<T, U>::exists + // returns (at compile time) true if there is an implicit conversion from T + // to U (example: Derived to Base) + // b) conversion<T, U>::exists2Way + // returns (at compile time) true if there are both conversions from T + // to U and from U to T (example: int to char and back) + // c) conversion<T, U>::sameType + // returns (at compile time) true if T and U represent the same type + // + // NOTE: might not work if T and U are in a private inheritance hierarchy. + // + + template <class T, class U> + struct conversion + { + typedef detail::conversion_helper<T, U> H; + static const bool exists = sizeof(typename H::Small) == sizeof((H::Test(H::MakeT()))); + static const bool exists2Way = exists && conversion<U, T>::exists; + static const bool sameType = false; + }; + + template <class T> + struct conversion<T, T> + { + static const bool exists = true; + static const bool exists2Way = true; + static const bool sameType = true; + }; + + template <class T> + struct conversion<void, T> + { + static const bool exists = false; + static const bool exists2Way = false; + static const bool sameType = false; + }; + + template <class T> + struct conversion<T, void> + { + static const bool exists = false; + static const bool exists2Way = false; + static const bool sameType = false; + }; + + template <> + struct conversion<void, void> + { + static const bool exists = true; + static const bool exists2Way = true; + static const bool sameType = true; + }; + } // detail + + // Note that we need to compare pointer types here, since conversion of types by-value + // just tells us whether or not an implicit conversion constructor exists. We handle + // type parameters that are already pointers specially; see below. + template <typename TBase, typename TDerived> + struct is_base_of : + conditional<detail::conversion<TDerived *, TBase *>::exists, true_type, false_type>::type {}; + + // Specialization to handle type parameters that are already pointers. + template <typename TBase, typename TDerived> + struct is_base_of<TBase *, TDerived *> : + conditional<detail::conversion<TDerived *, TBase *>::exists, true_type, false_type>::type {}; + + // Specialization to handle invalid mixing of pointer types. + template <typename TBase, typename TDerived> + struct is_base_of<TBase *, TDerived> : + false_type {}; + + // Specialization to handle invalid mixing of pointer types. + template <typename TBase, typename TDerived> + struct is_base_of<TBase, TDerived *> : + false_type {}; + +#endif + + // Use to determine if a template type parameter is a string. + template <typename T> + struct is_cstr + : public std::false_type + {}; + + template <typename T> + struct is_cstr< T* > + : public std::conditional< + std::is_same<typename std::remove_cv<T>::type, char>::value || + std::is_same<typename std::remove_cv<T>::type, wchar_t>::value, + std::true_type, + std::false_type>::type + + { }; + +} // namespace std + +#endif // !USE_STL + +#define REM_CONST(T) typename std::remove_const< T >::type +#define REM_CV(T) typename std::remove_cv< T >::type +#define REM_REF(T) typename std::remove_reference< T >::type + +#define REF_T(T) REM_REF(T) & +#define REF_CT(T) REM_REF(REM_CONST(T)) const & + +#endif // __clr_std_type_traits_h__ + +// Help the VIM editor figure out what kind of file this no-extension file is. +// vim: filetype=cpp |