1 // Tencent is pleased to support the open source community by making RapidJSON available.
3 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip.
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
8 // http://opensource.org/licenses/MIT
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.
15 #ifndef RAPIDJSON_INTERNAL_META_H_
16 #define RAPIDJSON_INTERNAL_META_H_
18 #include "../rapidjson.h"
22 RAPIDJSON_DIAG_OFF(effc
++)
25 #if defined(_MSC_VER) && !defined(__clang__)
27 RAPIDJSON_DIAG_OFF(6334)
30 #if RAPIDJSON_HAS_CXX11_TYPETRAITS
31 #include <type_traits>
34 //@cond RAPIDJSON_INTERNAL
35 RAPIDJSON_NAMESPACE_BEGIN
38 // Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
39 template <typename T
> struct Void
{ typedef void Type
; };
41 ///////////////////////////////////////////////////////////////////////////////
42 // BoolType, TrueType, FalseType
44 template <bool Cond
> struct BoolType
{
45 static const bool Value
= Cond
;
46 typedef BoolType Type
;
48 typedef BoolType
<true> TrueType
;
49 typedef BoolType
<false> FalseType
;
52 ///////////////////////////////////////////////////////////////////////////////
53 // SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr
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
> {};
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
{};
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
{};
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
; };
80 ///////////////////////////////////////////////////////////////////////////////
81 // IsSame, IsConst, IsMoreConst, IsPointer
83 template <typename T
, typename U
> struct IsSame
: FalseType
{};
84 template <typename T
> struct IsSame
<T
, T
> : TrueType
{};
86 template <typename T
> struct IsConst
: FalseType
{};
87 template <typename T
> struct IsConst
<const T
> : TrueType
{};
89 template <typename CT
, typename T
>
91 : AndExpr
<IsSame
<typename RemoveConst
<CT
>::Type
, typename RemoveConst
<T
>::Type
>,
92 BoolType
<IsConst
<CT
>::Value
>= IsConst
<T
>::Value
> >::Type
{};
94 template <typename T
> struct IsPointer
: FalseType
{};
95 template <typename T
> struct IsPointer
<T
*> : TrueType
{};
97 ///////////////////////////////////////////////////////////////////////////////
100 #if RAPIDJSON_HAS_CXX11_TYPETRAITS
102 template <typename B
, typename D
> struct IsBaseOf
103 : BoolType
< ::std::is_base_of
<B
,D
>::value
> {};
105 #else // simplified version adopted from Boost
107 template<typename B
, typename D
> struct IsBaseOfImpl
{
108 RAPIDJSON_STATIC_ASSERT(sizeof(B
) != 0);
109 RAPIDJSON_STATIC_ASSERT(sizeof(D
) != 0);
111 typedef char (&Yes
)[1];
112 typedef char (&No
) [2];
114 template <typename T
>
115 static Yes
Check(const D
*, T
);
116 static No
Check(const B
*, int);
119 operator const B
*() const;
123 enum { Value
= (sizeof(Check(Host(), 0)) == sizeof(Yes
)) };
126 template <typename B
, typename D
> struct IsBaseOf
127 : OrExpr
<IsSame
<B
, D
>, BoolExpr
<IsBaseOfImpl
<B
, D
> > >::Type
{};
129 #endif // RAPIDJSON_HAS_CXX11_TYPETRAITS
132 //////////////////////////////////////////////////////////////////////////
133 // EnableIf / DisableIf
135 template <bool Condition
, typename T
= void> struct EnableIfCond
{ typedef T Type
; };
136 template <typename T
> struct EnableIfCond
<false, T
> { /* empty */ };
138 template <bool Condition
, typename T
= void> struct DisableIfCond
{ typedef T Type
; };
139 template <typename T
> struct DisableIfCond
<true, T
> { /* empty */ };
141 template <typename Condition
, typename T
= void>
142 struct EnableIf
: EnableIfCond
<Condition::Value
, T
> {};
144 template <typename Condition
, typename T
= void>
145 struct DisableIf
: DisableIfCond
<Condition::Value
, T
> {};
149 template <typename T
> struct RemoveSfinaeTag
;
150 template <typename T
> struct RemoveSfinaeTag
<SfinaeTag
&(*)(T
)> { typedef T Type
; };
152 #define RAPIDJSON_REMOVEFPTR_(type) \
153 typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \
154 < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type
156 #define RAPIDJSON_ENABLEIF(cond) \
157 typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
158 <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
160 #define RAPIDJSON_DISABLEIF(cond) \
161 typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
162 <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
164 #define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \
165 typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
166 <RAPIDJSON_REMOVEFPTR_(cond), \
167 RAPIDJSON_REMOVEFPTR_(returntype)>::Type
169 #define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \
170 typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
171 <RAPIDJSON_REMOVEFPTR_(cond), \
172 RAPIDJSON_REMOVEFPTR_(returntype)>::Type
174 } // namespace internal
175 RAPIDJSON_NAMESPACE_END
178 #if defined(_MSC_VER) && !defined(__clang__)
186 #endif // RAPIDJSON_INTERNAL_META_H_