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