// 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. // // type_traits.hpp // // Type trait metaprogramming utilities. // #ifndef __TYPE_TRAITS_HPP__ #define __TYPE_TRAITS_HPP__ #include "CommonTypes.h" namespace type_traits { namespace imp { struct true_type { static const bool value = true; }; struct false_type { static const bool value = false; }; //////////////////////////////////////////////////////////////////////////////// // Helper types Small and Big - guarantee that sizeof(Small) < sizeof(Big) // template 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::exists // returns (at compile time) true if there is an implicit conversion from T // to U (example: Derived to Base) // b) conversion::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::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 struct conversion { typedef imp::conversion_helper H; static const bool exists = sizeof(typename H::Small) == sizeof((H::Test(H::MakeT()))); static const bool exists2Way = exists && conversion::exists; static const bool sameType = false; }; template struct conversion { static const bool exists = true; static const bool exists2Way = true; static const bool sameType = true; }; template struct conversion { static const bool exists = false; static const bool exists2Way = false; static const bool sameType = false; }; template struct conversion { static const bool exists = false; static const bool exists2Way = false; static const bool sameType = false; }; template <> struct conversion { static const bool exists = true; static const bool exists2Way = true; static const bool sameType = true; }; template struct is_base_of_helper; template <> struct is_base_of_helper : public true_type {} ; template <> struct is_base_of_helper : public false_type {} ; }// imp //////////////////////////////////////////////////////////////////////////////// // is_base_of::value is typedefed to be true if TDerived derives from TBase // and false otherwise. // // // NOTE: use TR1 type_traits::is_base_of when available. // #ifdef _MSC_VER template struct is_base_of : public imp::is_base_of_helper<__is_base_of( TBase, TDerived)> {}; #else // 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 struct is_base_of : public imp::is_base_of_helper::exists> {}; // Specialization to handle type parameters that are already pointers. template struct is_base_of : public imp::is_base_of_helper::exists> {}; // Specialization to handle invalid mixing of pointer types. template struct is_base_of : public imp::false_type {}; // Specialization to handle invalid mixing of pointer types. template struct is_base_of : public imp::false_type {}; #endif //////////////////////////////////////////////////////////////////////////////// // Remove const qualifications, if any. Access using remove_const::type // template struct remove_const { typedef T type; }; template struct remove_const { typedef T type; }; //////////////////////////////////////////////////////////////////////////////// // is_signed::value is true if T is a signed integral type, false otherwise. // template struct is_signed { static const bool value = (static_cast(-1) < 0); }; } //////////////////////////////////////////////////////////////////////////////// // These are related to type traits, but they are more like asserts of type // traits in that the result is that either the compiler does or does not // produce an error. // namespace type_constraints { //////////////////////////////////////////////////////////////////////////////// // derived_from will produce a compiler error if TDerived does not // derive from TBase. // // NOTE: use TR1 type_traits::is_base_of when available. // template struct is_base_of { is_base_of() { static_assert((type_traits::is_base_of::value), "is_base_of() constraint violation: TDerived does not derive from TBase"); } }; }; // namespace type_constraints namespace rh { namespace std { // Import some select components of the STL // TEMPLATE FUNCTION for_each template inline _Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func) { // perform function for each element for (; _First != _Last; ++_First) _Func(*_First); return (_Func); } template inline _InIt find(_InIt _First, _InIt _Last, const _Ty& _Val) { // find first matching _Val for (; _First != _Last; ++_First) if (*_First == _Val) break; return (_First); } template inline _InIt find_if(_InIt _First, _InIt _Last, _Pr _Pred) { // find first satisfying _Pred for (; _First != _Last; ++_First) if (_Pred(*_First)) break; return (_First); } template inline bool exists(_InIt _First, _InIt _Last, const _Ty& _Val) { return find(_First, _Last, _Val) != _Last; } template inline bool exists_if(_InIt _First, _InIt _Last, _Pr _Pred) { return find_if(_First, _Last, _Pred) != _Last; } template inline UIntNative count(_InIt _First, _InIt _Last, const _Ty& _Val) { UIntNative _Ret = 0; for (; _First != _Last; _First++) if (*_First == _Val) ++_Ret; return _Ret; } template inline UIntNative count_if(_InIt _First, _InIt _Last, _Pr _Pred) { UIntNative _Ret = 0; for (; _First != _Last; _First++) if (_Pred(*_First)) ++_Ret; return _Ret; } // Forward declaration, each collection requires specialization template inline _FwdIt remove(_FwdIt _First, _FwdIt _Last, const _Ty& _Val); } // namespace std } // namespace rh #if 0 // ----------------------------------------------------------------- // Holding place for unused-but-possibly-useful-in-the-future code. // ------------------------------------------------- // This belongs in type_traits.hpp // // is_pointer::value is true if the type is a pointer, false otherwise // template struct is_pointer : public false_type {}; template struct is_pointer : public true_type {}; // // Remove pointer from type, if it has one. Use remove_pointer::type // Further specialized in daccess.h // template struct remove_pointer { typedef T type; }; template struct remove_pointer { typedef T type; }; // ------------------------------------------------- // This belongs in daccess.h namespace type_traits { // // is_pointer::value is true if the type is a pointer, false otherwise // specialized from type_traits.hpp // template struct is_pointer > : public type_traits::true_type {}; // // remove_pointer::type is T with one less pointer qualification, if it had one. // specialized from type_traits.hpp // template struct remove_pointer > { typedef T type; }; } // type_traits namespace dac { // // is_dptr::value is true if T is a __DPtr, false otherwise. // This is a partial specialization case for the positive case. // //template struct is_dptr > : public type_traits::true_type {}; } #endif #endif