// Copyright (C) 2011 Milo Yip // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. #ifndef RAPIDJSON_INTERNAL_META_H_ #define RAPIDJSON_INTERNAL_META_H_ #ifndef RAPIDJSON_RAPIDJSON_H_ #error <rapidjson.h> not yet included. Do not include this file directly. #endif #ifdef __GNUC__ RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(effc++) #endif #if defined(_MSC_VER) RAPIDJSON_DIAG_PUSH RAPIDJSON_DIAG_OFF(6334) #endif #if RAPIDJSON_HAS_CXX11_TYPETRAITS #include <type_traits> #endif //@cond RAPIDJSON_INTERNAL namespace rapidjson { namespace internal { // Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching template <typename T> struct Void { typedef void Type; }; /////////////////////////////////////////////////////////////////////////////// // BoolType, TrueType, FalseType // template <bool Cond> struct BoolType { static const bool Value = Cond; typedef BoolType Type; }; typedef BoolType<true> TrueType; typedef BoolType<false> FalseType; /////////////////////////////////////////////////////////////////////////////// // SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr // template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; }; template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; }; template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {}; template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {}; template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {}; template <> struct AndExprCond<true, true> : TrueType {}; template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {}; template <> struct OrExprCond<false, false> : FalseType {}; template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {}; template <typename C> struct NotExpr : SelectIf<C,FalseType,TrueType>::Type {}; template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {}; template <typename C1, typename C2> struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {}; /////////////////////////////////////////////////////////////////////////////// // AddConst, MaybeAddConst, RemoveConst template <typename T> struct AddConst { typedef const T Type; }; template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {}; template <typename T> struct RemoveConst { typedef T Type; }; template <typename T> struct RemoveConst<const T> { typedef T Type; }; /////////////////////////////////////////////////////////////////////////////// // IsSame, IsConst, IsMoreConst, IsPointer // template <typename T, typename U> struct IsSame : FalseType {}; template <typename T> struct IsSame<T, T> : TrueType {}; template <typename T> struct IsConst : FalseType {}; template <typename T> struct IsConst<const T> : TrueType {}; template <typename CT, typename T> struct IsMoreConst : AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>, BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {}; template <typename T> struct IsPointer : FalseType {}; template <typename T> struct IsPointer<T*> : TrueType {}; /////////////////////////////////////////////////////////////////////////////// // IsBaseOf // #if RAPIDJSON_HAS_CXX11_TYPETRAITS template <typename B, typename D> struct IsBaseOf : BoolType< ::std::is_base_of<B,D>::value> {}; #else // simplified version adopted from Boost template<typename B, typename D> struct IsBaseOfImpl { RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0); RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0); typedef char (&Yes)[1]; typedef char (&No) [2]; template <typename T> static Yes Check(const D*, T); static No Check(const B*, int); struct Host { operator const B*() const; operator const D*(); }; enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) }; }; template <typename B, typename D> struct IsBaseOf : OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {}; #endif // RAPIDJSON_HAS_CXX11_TYPETRAITS ////////////////////////////////////////////////////////////////////////// // EnableIf / DisableIf // template <bool Condition, typename T = void> struct EnableIfCond { typedef T Type; }; template <typename T> struct EnableIfCond<false, T> { /* empty */ }; template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; }; template <typename T> struct DisableIfCond<true, T> { /* empty */ }; template <typename Condition, typename T = void> struct EnableIf : EnableIfCond<Condition::Value, T> {}; template <typename Condition, typename T = void> struct DisableIf : DisableIfCond<Condition::Value, T> {}; // SFINAE helpers struct SfinaeTag {}; template <typename T> struct RemoveSfinaeTag; template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; }; #define RAPIDJSON_REMOVEFPTR_(type) \ typename ::rapidjson::internal::RemoveSfinaeTag \ < ::rapidjson::internal::SfinaeTag&(*) type>::Type #define RAPIDJSON_ENABLEIF(cond) \ typename ::rapidjson::internal::EnableIf \ <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL #define RAPIDJSON_DISABLEIF(cond) \ typename ::rapidjson::internal::DisableIf \ <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL #define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \ typename ::rapidjson::internal::EnableIf \ <RAPIDJSON_REMOVEFPTR_(cond), \ RAPIDJSON_REMOVEFPTR_(returntype)>::Type #define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \ typename ::rapidjson::internal::DisableIf \ <RAPIDJSON_REMOVEFPTR_(cond), \ RAPIDJSON_REMOVEFPTR_(returntype)>::Type } // namespace internal } // namespace rapidjson //@endcond #if defined(__GNUC__) || defined(_MSC_VER) RAPIDJSON_DIAG_POP #endif #endif // RAPIDJSON_INTERNAL_META_H_