// Tencent is pleased to support the open source community by making RapidJSON available. // // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. // // Licensed under the MIT License (the "License"); you may not use this file except // in compliance with the License. You may obtain a copy of the License at // // http://opensource.org/licenses/MIT // // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. #ifndef RAPIDJSON_INTERNAL_META_H_ #define RAPIDJSON_INTERNAL_META_H_ #include "../rapidjson.h" #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 RAPIDJSON_NAMESPACE_BEGIN 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_NAMESPACE::internal::RemoveSfinaeTag \ < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type #define RAPIDJSON_ENABLEIF(cond) \ typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL #define RAPIDJSON_DISABLEIF(cond) \ typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL #define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \ typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ <RAPIDJSON_REMOVEFPTR_(cond), \ RAPIDJSON_REMOVEFPTR_(returntype)>::Type #define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \ typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ <RAPIDJSON_REMOVEFPTR_(cond), \ RAPIDJSON_REMOVEFPTR_(returntype)>::Type } // namespace internal RAPIDJSON_NAMESPACE_END //@endcond #if defined(__GNUC__) || defined(_MSC_VER) RAPIDJSON_DIAG_POP #endif #endif // RAPIDJSON_INTERNAL_META_H_