182 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			C
		
	
	
	
		
		
			
		
	
	
			182 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			C
		
	
	
	
|  | // 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_
 |