1 // Tencent is pleased to support the open source community by making RapidJSON available. 2 // 3 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 // 5 // Licensed under the MIT License (the "License"); you may not use this file except 6 // in compliance with the License. You may obtain a copy of the License at 7 // 8 // http://opensource.org/licenses/MIT 9 // 10 // Unless required by applicable law or agreed to in writing, software distributed 11 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 // specific language governing permissions and limitations under the License. 14 15 #ifndef RAPIDJSON_INTERNAL_META_H_ 16 #define RAPIDJSON_INTERNAL_META_H_ 17 18 #include "../rapidjson.h" 19 20 #ifdef __GNUC__ 21 RAPIDJSON_DIAG_PUSH 22 RAPIDJSON_DIAG_OFF(effc++) 23 #endif 24 25 #if defined(_MSC_VER) && !defined(__clang__) 26 RAPIDJSON_DIAG_PUSH 27 RAPIDJSON_DIAG_OFF(6334) 28 #endif 29 30 #if RAPIDJSON_HAS_CXX11_TYPETRAITS 31 #include <type_traits> 32 #endif 33 34 //@cond RAPIDJSON_INTERNAL 35 RAPIDJSON_NAMESPACE_BEGIN 36 namespace internal { 37 38 // Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching 39 template <typename T> struct Void { typedef void Type; }; 40 41 /////////////////////////////////////////////////////////////////////////////// 42 // BoolType, TrueType, FalseType 43 // 44 template <bool Cond> struct BoolType { 45 static const bool Value = Cond; 46 typedef BoolType Type; 47 }; 48 typedef BoolType<true> TrueType; 49 typedef BoolType<false> FalseType; 50 51 52 /////////////////////////////////////////////////////////////////////////////// 53 // SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr 54 // 55 56 template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; }; 57 template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; }; 58 template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {}; 59 template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {}; 60 61 template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {}; 62 template <> struct AndExprCond<true, true> : TrueType {}; 63 template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {}; 64 template <> struct OrExprCond<false, false> : FalseType {}; 65 66 template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {}; 67 template <typename C> struct NotExpr : SelectIf<C,FalseType,TrueType>::Type {}; 68 template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {}; 69 template <typename C1, typename C2> struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {}; 70 71 72 /////////////////////////////////////////////////////////////////////////////// 73 // AddConst, MaybeAddConst, RemoveConst 74 template <typename T> struct AddConst { typedef const T Type; }; 75 template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {}; 76 template <typename T> struct RemoveConst { typedef T Type; }; 77 template <typename T> struct RemoveConst<const T> { typedef T Type; }; 78 79 80 /////////////////////////////////////////////////////////////////////////////// 81 // IsSame, IsConst, IsMoreConst, IsPointer 82 // 83 template <typename T, typename U> struct IsSame : FalseType {}; 84 template <typename T> struct IsSame<T, T> : TrueType {}; 85 86 template <typename T> struct IsConst : FalseType {}; 87 template <typename T> struct IsConst<const T> : TrueType {}; 88 89 template <typename CT, typename T> 90 struct IsMoreConst 91 : AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>, 92 BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {}; 93 94 template <typename T> struct IsPointer : FalseType {}; 95 template <typename T> struct IsPointer<T*> : TrueType {}; 96 97 /////////////////////////////////////////////////////////////////////////////// 98 // IsBaseOf 99 // 100 #if RAPIDJSON_HAS_CXX11_TYPETRAITS 101 102 template <typename B, typename D> struct IsBaseOf 103 : BoolType< ::std::is_base_of<B,D>::value> {}; 104 105 #else // simplified version adopted from Boost 106 107 template<typename B, typename D> struct IsBaseOfImpl { 108 RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0); 109 RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0); 110 111 typedef char (&Yes)[1]; 112 typedef char (&No) [2]; 113 114 template <typename T> 115 static Yes Check(const D*, T); 116 static No Check(const B*, int); 117 118 struct Host { 119 operator const B*() const; 120 operator const D*(); 121 }; 122 123 enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) }; 124 }; 125 126 template <typename B, typename D> struct IsBaseOf 127 : OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {}; 128 129 #endif // RAPIDJSON_HAS_CXX11_TYPETRAITS 130 131 132 ////////////////////////////////////////////////////////////////////////// 133 // EnableIf / DisableIf 134 // 135 template <bool Condition, typename T = void> struct EnableIfCond { typedef T Type; }; 136 template <typename T> struct EnableIfCond<false, T> { /* empty */ }; 137 138 template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; }; 139 template <typename T> struct DisableIfCond<true, T> { /* empty */ }; 140 141 template <typename Condition, typename T = void> 142 struct EnableIf : EnableIfCond<Condition::Value, T> {}; 143 144 template <typename Condition, typename T = void> 145 struct DisableIf : DisableIfCond<Condition::Value, T> {}; 146 147 // SFINAE helpers 148 struct SfinaeTag {}; 149 template <typename T> struct RemoveSfinaeTag; 150 template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; }; 151 152 #define RAPIDJSON_REMOVEFPTR_(type) \ 153 typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \ 154 < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type 155 156 #define RAPIDJSON_ENABLEIF(cond) \ 157 typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ 158 <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL 159 160 #define RAPIDJSON_DISABLEIF(cond) \ 161 typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ 162 <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL 163 164 #define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \ 165 typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ 166 <RAPIDJSON_REMOVEFPTR_(cond), \ 167 RAPIDJSON_REMOVEFPTR_(returntype)>::Type 168 169 #define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \ 170 typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ 171 <RAPIDJSON_REMOVEFPTR_(cond), \ 172 RAPIDJSON_REMOVEFPTR_(returntype)>::Type 173 174 } // namespace internal 175 RAPIDJSON_NAMESPACE_END 176 //@endcond 177 178 #if defined(_MSC_VER) && !defined(__clang__) 179 RAPIDJSON_DIAG_POP 180 #endif 181 182 #ifdef __GNUC__ 183 RAPIDJSON_DIAG_POP 184 #endif 185 186 #endif // RAPIDJSON_INTERNAL_META_H_ 187