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 | #if defined(_MSC_VER) |
25 | RAPIDJSON_DIAG_PUSH |
26 | RAPIDJSON_DIAG_OFF(6334) |
27 | #endif |
28 | |
29 | #if RAPIDJSON_HAS_CXX11_TYPETRAITS |
30 | #include <type_traits> |
31 | #endif |
32 | |
33 | //@cond RAPIDJSON_INTERNAL |
34 | RAPIDJSON_NAMESPACE_BEGIN |
35 | namespace internal { |
36 | |
37 | // Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching |
38 | template <typename T> struct Void { typedef void Type; }; |
39 | |
40 | /////////////////////////////////////////////////////////////////////////////// |
41 | // BoolType, TrueType, FalseType |
42 | // |
43 | template <bool Cond> struct BoolType { |
44 | static const bool Value = Cond; |
45 | typedef BoolType Type; |
46 | }; |
47 | typedef BoolType<true> TrueType; |
48 | typedef BoolType<false> FalseType; |
49 | |
50 | |
51 | /////////////////////////////////////////////////////////////////////////////// |
52 | // SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr |
53 | // |
54 | |
55 | template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; }; |
56 | template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; }; |
57 | template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {}; |
58 | template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {}; |
59 | |
60 | template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {}; |
61 | template <> struct AndExprCond<true, true> : TrueType {}; |
62 | template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {}; |
63 | template <> struct OrExprCond<false, false> : FalseType {}; |
64 | |
65 | template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {}; |
66 | template <typename C> struct NotExpr : SelectIf<C,FalseType,TrueType>::Type {}; |
67 | template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {}; |
68 | template <typename C1, typename C2> struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {}; |
69 | |
70 | |
71 | /////////////////////////////////////////////////////////////////////////////// |
72 | // AddConst, MaybeAddConst, RemoveConst |
73 | template <typename T> struct AddConst { typedef const T Type; }; |
74 | template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {}; |
75 | template <typename T> struct RemoveConst { typedef T Type; }; |
76 | template <typename T> struct RemoveConst<const T> { typedef T Type; }; |
77 | |
78 | |
79 | /////////////////////////////////////////////////////////////////////////////// |
80 | // IsSame, IsConst, IsMoreConst, IsPointer |
81 | // |
82 | template <typename T, typename U> struct IsSame : FalseType {}; |
83 | template <typename T> struct IsSame<T, T> : TrueType {}; |
84 | |
85 | template <typename T> struct IsConst : FalseType {}; |
86 | template <typename T> struct IsConst<const T> : TrueType {}; |
87 | |
88 | template <typename CT, typename T> |
89 | struct IsMoreConst |
90 | : AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>, |
91 | BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {}; |
92 | |
93 | template <typename T> struct IsPointer : FalseType {}; |
94 | template <typename T> struct IsPointer<T*> : TrueType {}; |
95 | |
96 | /////////////////////////////////////////////////////////////////////////////// |
97 | // IsBaseOf |
98 | // |
99 | #if RAPIDJSON_HAS_CXX11_TYPETRAITS |
100 | |
101 | template <typename B, typename D> struct IsBaseOf |
102 | : BoolType< ::std::is_base_of<B,D>::value> {}; |
103 | |
104 | #else // simplified version adopted from Boost |
105 | |
106 | template<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 | |
125 | template <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 | // |
134 | template <bool Condition, typename T = void> struct EnableIfCond { typedef T Type; }; |
135 | template <typename T> struct EnableIfCond<false, T> { /* empty */ }; |
136 | |
137 | template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; }; |
138 | template <typename T> struct DisableIfCond<true, T> { /* empty */ }; |
139 | |
140 | template <typename Condition, typename T = void> |
141 | struct EnableIf : EnableIfCond<Condition::Value, T> {}; |
142 | |
143 | template <typename Condition, typename T = void> |
144 | struct DisableIf : DisableIfCond<Condition::Value, T> {}; |
145 | |
146 | // SFINAE helpers |
147 | struct SfinaeTag {}; |
148 | template <typename T> struct RemoveSfinaeTag; |
149 | template <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 |
174 | RAPIDJSON_NAMESPACE_END |
175 | //@endcond |
176 | |
177 | #if defined(__GNUC__) || defined(_MSC_VER) |
178 | RAPIDJSON_DIAG_POP |
179 | #endif |
180 | |
181 | #endif // RAPIDJSON_INTERNAL_META_H_ |
182 | |