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__ 21RAPIDJSON_DIAG_PUSH 22RAPIDJSON_DIAG_OFF(effc++) 23#endif 24#if defined(_MSC_VER) 25RAPIDJSON_DIAG_PUSH 26RAPIDJSON_DIAG_OFF(6334) 27#endif 28 29#if RAPIDJSON_HAS_CXX11_TYPETRAITS 30#include <type_traits> 31#endif 32 33//@cond RAPIDJSON_INTERNAL 34RAPIDJSON_NAMESPACE_BEGIN 35namespace internal { 36 37// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching 38template <typename T> struct Void { typedef void Type; }; 39 40/////////////////////////////////////////////////////////////////////////////// 41// BoolType, TrueType, FalseType 42// 43template <bool Cond> struct BoolType { 44 static const bool Value = Cond; 45 typedef BoolType Type; 46}; 47typedef BoolType<true> TrueType; 48typedef BoolType<false> FalseType; 49 50 51/////////////////////////////////////////////////////////////////////////////// 52// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr 53// 54 55template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; }; 56template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; }; 57template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {}; 58template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {}; 59 60template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {}; 61template <> struct AndExprCond<true, true> : TrueType {}; 62template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {}; 63template <> struct OrExprCond<false, false> : FalseType {}; 64 65template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {}; 66template <typename C> struct NotExpr : SelectIf<C,FalseType,TrueType>::Type {}; 67template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {}; 68template <typename C1, typename C2> struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {}; 69 70 71/////////////////////////////////////////////////////////////////////////////// 72// AddConst, MaybeAddConst, RemoveConst 73template <typename T> struct AddConst { typedef const T Type; }; 74template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {}; 75template <typename T> struct RemoveConst { typedef T Type; }; 76template <typename T> struct RemoveConst<const T> { typedef T Type; }; 77 78 79/////////////////////////////////////////////////////////////////////////////// 80// IsSame, IsConst, IsMoreConst, IsPointer 81// 82template <typename T, typename U> struct IsSame : FalseType {}; 83template <typename T> struct IsSame<T, T> : TrueType {}; 84 85template <typename T> struct IsConst : FalseType {}; 86template <typename T> struct IsConst<const T> : TrueType {}; 87 88template <typename CT, typename T> 89struct IsMoreConst 90 : AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>, 91 BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {}; 92 93template <typename T> struct IsPointer : FalseType {}; 94template <typename T> struct IsPointer<T*> : TrueType {}; 95 96/////////////////////////////////////////////////////////////////////////////// 97// IsBaseOf 98// 99#if RAPIDJSON_HAS_CXX11_TYPETRAITS 100 101template <typename B, typename D> struct IsBaseOf 102 : BoolType< ::std::is_base_of<B,D>::value> {}; 103 104#else // simplified version adopted from Boost 105 106template<typename B, typename D> struct IsBaseOfImpl { 107 RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0); 108 RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0); 109 110 typedef char (&Yes)[1]; 111 typedef char (&No) [2]; 112 113 template <typename T> 114 static Yes Check(const D*, T); 115 static No Check(const B*, int); 116 117 struct Host { 118 operator const B*() const; 119 operator const D*(); 120 }; 121 122 enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) }; 123}; 124 125template <typename B, typename D> struct IsBaseOf 126 : OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {}; 127 128#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS 129 130 131////////////////////////////////////////////////////////////////////////// 132// EnableIf / DisableIf 133// 134template <bool Condition, typename T = void> struct EnableIfCond { typedef T Type; }; 135template <typename T> struct EnableIfCond<false, T> { /* empty */ }; 136 137template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; }; 138template <typename T> struct DisableIfCond<true, T> { /* empty */ }; 139 140template <typename Condition, typename T = void> 141struct EnableIf : EnableIfCond<Condition::Value, T> {}; 142 143template <typename Condition, typename T = void> 144struct DisableIf : DisableIfCond<Condition::Value, T> {}; 145 146// SFINAE helpers 147struct SfinaeTag {}; 148template <typename T> struct RemoveSfinaeTag; 149template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; }; 150 151#define RAPIDJSON_REMOVEFPTR_(type) \ 152 typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \ 153 < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type 154 155#define RAPIDJSON_ENABLEIF(cond) \ 156 typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ 157 <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL 158 159#define RAPIDJSON_DISABLEIF(cond) \ 160 typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ 161 <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL 162 163#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \ 164 typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ 165 <RAPIDJSON_REMOVEFPTR_(cond), \ 166 RAPIDJSON_REMOVEFPTR_(returntype)>::Type 167 168#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \ 169 typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ 170 <RAPIDJSON_REMOVEFPTR_(cond), \ 171 RAPIDJSON_REMOVEFPTR_(returntype)>::Type 172 173} // namespace internal 174RAPIDJSON_NAMESPACE_END 175//@endcond 176 177#if defined(__GNUC__) || defined(_MSC_VER) 178RAPIDJSON_DIAG_POP 179#endif 180 181#endif // RAPIDJSON_INTERNAL_META_H_ 182