1e462795ff5d4c7359f9e8637c10544bb2de70107tturney// Tencent is pleased to support the open source community by making RapidJSON available.
2e462795ff5d4c7359f9e8637c10544bb2de70107tturney//
3e462795ff5d4c7359f9e8637c10544bb2de70107tturney// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4e462795ff5d4c7359f9e8637c10544bb2de70107tturney//
5e462795ff5d4c7359f9e8637c10544bb2de70107tturney// Licensed under the MIT License (the "License"); you may not use this file except
6e462795ff5d4c7359f9e8637c10544bb2de70107tturney// in compliance with the License. You may obtain a copy of the License at
7e462795ff5d4c7359f9e8637c10544bb2de70107tturney//
8e462795ff5d4c7359f9e8637c10544bb2de70107tturney// http://opensource.org/licenses/MIT
9e462795ff5d4c7359f9e8637c10544bb2de70107tturney//
10e462795ff5d4c7359f9e8637c10544bb2de70107tturney// Unless required by applicable law or agreed to in writing, software distributed
11e462795ff5d4c7359f9e8637c10544bb2de70107tturney// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12e462795ff5d4c7359f9e8637c10544bb2de70107tturney// CONDITIONS OF ANY KIND, either express or implied. See the License for the
13e462795ff5d4c7359f9e8637c10544bb2de70107tturney// specific language governing permissions and limitations under the License.
14e462795ff5d4c7359f9e8637c10544bb2de70107tturney
15e462795ff5d4c7359f9e8637c10544bb2de70107tturney#ifndef RAPIDJSON_INTERNAL_META_H_
16e462795ff5d4c7359f9e8637c10544bb2de70107tturney#define RAPIDJSON_INTERNAL_META_H_
17e462795ff5d4c7359f9e8637c10544bb2de70107tturney
18e462795ff5d4c7359f9e8637c10544bb2de70107tturney#include "../rapidjson.h"
19e462795ff5d4c7359f9e8637c10544bb2de70107tturney
20e462795ff5d4c7359f9e8637c10544bb2de70107tturney#ifdef __GNUC__
21e462795ff5d4c7359f9e8637c10544bb2de70107tturneyRAPIDJSON_DIAG_PUSH
22e462795ff5d4c7359f9e8637c10544bb2de70107tturneyRAPIDJSON_DIAG_OFF(effc++)
23e462795ff5d4c7359f9e8637c10544bb2de70107tturney#endif
24e462795ff5d4c7359f9e8637c10544bb2de70107tturney#if defined(_MSC_VER)
25e462795ff5d4c7359f9e8637c10544bb2de70107tturneyRAPIDJSON_DIAG_PUSH
26e462795ff5d4c7359f9e8637c10544bb2de70107tturneyRAPIDJSON_DIAG_OFF(6334)
27e462795ff5d4c7359f9e8637c10544bb2de70107tturney#endif
28e462795ff5d4c7359f9e8637c10544bb2de70107tturney
29e462795ff5d4c7359f9e8637c10544bb2de70107tturney#if RAPIDJSON_HAS_CXX11_TYPETRAITS
30e462795ff5d4c7359f9e8637c10544bb2de70107tturney#include <type_traits>
31e462795ff5d4c7359f9e8637c10544bb2de70107tturney#endif
32e462795ff5d4c7359f9e8637c10544bb2de70107tturney
33e462795ff5d4c7359f9e8637c10544bb2de70107tturney//@cond RAPIDJSON_INTERNAL
34e462795ff5d4c7359f9e8637c10544bb2de70107tturneyRAPIDJSON_NAMESPACE_BEGIN
35e462795ff5d4c7359f9e8637c10544bb2de70107tturneynamespace internal {
36e462795ff5d4c7359f9e8637c10544bb2de70107tturney
37e462795ff5d4c7359f9e8637c10544bb2de70107tturney// Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
38e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename T> struct Void { typedef void Type; };
39e462795ff5d4c7359f9e8637c10544bb2de70107tturney
40e462795ff5d4c7359f9e8637c10544bb2de70107tturney///////////////////////////////////////////////////////////////////////////////
41e462795ff5d4c7359f9e8637c10544bb2de70107tturney// BoolType, TrueType, FalseType
42e462795ff5d4c7359f9e8637c10544bb2de70107tturney//
43e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <bool Cond> struct BoolType {
44e462795ff5d4c7359f9e8637c10544bb2de70107tturney    static const bool Value = Cond;
45e462795ff5d4c7359f9e8637c10544bb2de70107tturney    typedef BoolType Type;
46e462795ff5d4c7359f9e8637c10544bb2de70107tturney};
47e462795ff5d4c7359f9e8637c10544bb2de70107tturneytypedef BoolType<true> TrueType;
48e462795ff5d4c7359f9e8637c10544bb2de70107tturneytypedef BoolType<false> FalseType;
49e462795ff5d4c7359f9e8637c10544bb2de70107tturney
50e462795ff5d4c7359f9e8637c10544bb2de70107tturney
51e462795ff5d4c7359f9e8637c10544bb2de70107tturney///////////////////////////////////////////////////////////////////////////////
52e462795ff5d4c7359f9e8637c10544bb2de70107tturney// SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr
53e462795ff5d4c7359f9e8637c10544bb2de70107tturney//
54e462795ff5d4c7359f9e8637c10544bb2de70107tturney
55e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; };
56e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; };
57e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {};
58e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {};
59e462795ff5d4c7359f9e8637c10544bb2de70107tturney
60e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <bool Cond1, bool Cond2> struct AndExprCond : FalseType {};
61e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <> struct AndExprCond<true, true> : TrueType {};
62e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <bool Cond1, bool Cond2> struct OrExprCond : TrueType {};
63e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <> struct OrExprCond<false, false> : FalseType {};
64e462795ff5d4c7359f9e8637c10544bb2de70107tturney
65e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {};
66e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename C> struct NotExpr  : SelectIf<C,FalseType,TrueType>::Type {};
67e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {};
68e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename C1, typename C2> struct OrExpr  : OrExprCond<C1::Value, C2::Value>::Type {};
69e462795ff5d4c7359f9e8637c10544bb2de70107tturney
70e462795ff5d4c7359f9e8637c10544bb2de70107tturney
71e462795ff5d4c7359f9e8637c10544bb2de70107tturney///////////////////////////////////////////////////////////////////////////////
72e462795ff5d4c7359f9e8637c10544bb2de70107tturney// AddConst, MaybeAddConst, RemoveConst
73e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename T> struct AddConst { typedef const T Type; };
74e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {};
75e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename T> struct RemoveConst { typedef T Type; };
76e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename T> struct RemoveConst<const T> { typedef T Type; };
77e462795ff5d4c7359f9e8637c10544bb2de70107tturney
78e462795ff5d4c7359f9e8637c10544bb2de70107tturney
79e462795ff5d4c7359f9e8637c10544bb2de70107tturney///////////////////////////////////////////////////////////////////////////////
80e462795ff5d4c7359f9e8637c10544bb2de70107tturney// IsSame, IsConst, IsMoreConst, IsPointer
81e462795ff5d4c7359f9e8637c10544bb2de70107tturney//
82e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename T, typename U> struct IsSame : FalseType {};
83e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename T> struct IsSame<T, T> : TrueType {};
84e462795ff5d4c7359f9e8637c10544bb2de70107tturney
85e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename T> struct IsConst : FalseType {};
86e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename T> struct IsConst<const T> : TrueType {};
87e462795ff5d4c7359f9e8637c10544bb2de70107tturney
88e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename CT, typename T>
89e462795ff5d4c7359f9e8637c10544bb2de70107tturneystruct IsMoreConst
90e462795ff5d4c7359f9e8637c10544bb2de70107tturney    : AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>,
91e462795ff5d4c7359f9e8637c10544bb2de70107tturney              BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {};
92e462795ff5d4c7359f9e8637c10544bb2de70107tturney
93e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename T> struct IsPointer : FalseType {};
94e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename T> struct IsPointer<T*> : TrueType {};
95e462795ff5d4c7359f9e8637c10544bb2de70107tturney
96e462795ff5d4c7359f9e8637c10544bb2de70107tturney///////////////////////////////////////////////////////////////////////////////
97e462795ff5d4c7359f9e8637c10544bb2de70107tturney// IsBaseOf
98e462795ff5d4c7359f9e8637c10544bb2de70107tturney//
99e462795ff5d4c7359f9e8637c10544bb2de70107tturney#if RAPIDJSON_HAS_CXX11_TYPETRAITS
100e462795ff5d4c7359f9e8637c10544bb2de70107tturney
101e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename B, typename D> struct IsBaseOf
102e462795ff5d4c7359f9e8637c10544bb2de70107tturney    : BoolType< ::std::is_base_of<B,D>::value> {};
103e462795ff5d4c7359f9e8637c10544bb2de70107tturney
104e462795ff5d4c7359f9e8637c10544bb2de70107tturney#else // simplified version adopted from Boost
105e462795ff5d4c7359f9e8637c10544bb2de70107tturney
106e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate<typename B, typename D> struct IsBaseOfImpl {
107e462795ff5d4c7359f9e8637c10544bb2de70107tturney    RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0);
108e462795ff5d4c7359f9e8637c10544bb2de70107tturney    RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0);
109e462795ff5d4c7359f9e8637c10544bb2de70107tturney
110e462795ff5d4c7359f9e8637c10544bb2de70107tturney    typedef char (&Yes)[1];
111e462795ff5d4c7359f9e8637c10544bb2de70107tturney    typedef char (&No) [2];
112e462795ff5d4c7359f9e8637c10544bb2de70107tturney
113e462795ff5d4c7359f9e8637c10544bb2de70107tturney    template <typename T>
114e462795ff5d4c7359f9e8637c10544bb2de70107tturney    static Yes Check(const D*, T);
115e462795ff5d4c7359f9e8637c10544bb2de70107tturney    static No  Check(const B*, int);
116e462795ff5d4c7359f9e8637c10544bb2de70107tturney
117e462795ff5d4c7359f9e8637c10544bb2de70107tturney    struct Host {
118e462795ff5d4c7359f9e8637c10544bb2de70107tturney        operator const B*() const;
119e462795ff5d4c7359f9e8637c10544bb2de70107tturney        operator const D*();
120e462795ff5d4c7359f9e8637c10544bb2de70107tturney    };
121e462795ff5d4c7359f9e8637c10544bb2de70107tturney
122e462795ff5d4c7359f9e8637c10544bb2de70107tturney    enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) };
123e462795ff5d4c7359f9e8637c10544bb2de70107tturney};
124e462795ff5d4c7359f9e8637c10544bb2de70107tturney
125e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename B, typename D> struct IsBaseOf
126e462795ff5d4c7359f9e8637c10544bb2de70107tturney    : OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {};
127e462795ff5d4c7359f9e8637c10544bb2de70107tturney
128e462795ff5d4c7359f9e8637c10544bb2de70107tturney#endif // RAPIDJSON_HAS_CXX11_TYPETRAITS
129e462795ff5d4c7359f9e8637c10544bb2de70107tturney
130e462795ff5d4c7359f9e8637c10544bb2de70107tturney
131e462795ff5d4c7359f9e8637c10544bb2de70107tturney//////////////////////////////////////////////////////////////////////////
132e462795ff5d4c7359f9e8637c10544bb2de70107tturney// EnableIf / DisableIf
133e462795ff5d4c7359f9e8637c10544bb2de70107tturney//
134e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <bool Condition, typename T = void> struct EnableIfCond  { typedef T Type; };
135e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename T> struct EnableIfCond<false, T> { /* empty */ };
136e462795ff5d4c7359f9e8637c10544bb2de70107tturney
137e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; };
138e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename T> struct DisableIfCond<true, T> { /* empty */ };
139e462795ff5d4c7359f9e8637c10544bb2de70107tturney
140e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename Condition, typename T = void>
141e462795ff5d4c7359f9e8637c10544bb2de70107tturneystruct EnableIf : EnableIfCond<Condition::Value, T> {};
142e462795ff5d4c7359f9e8637c10544bb2de70107tturney
143e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename Condition, typename T = void>
144e462795ff5d4c7359f9e8637c10544bb2de70107tturneystruct DisableIf : DisableIfCond<Condition::Value, T> {};
145e462795ff5d4c7359f9e8637c10544bb2de70107tturney
146e462795ff5d4c7359f9e8637c10544bb2de70107tturney// SFINAE helpers
147e462795ff5d4c7359f9e8637c10544bb2de70107tturneystruct SfinaeTag {};
148e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename T> struct RemoveSfinaeTag;
149e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; };
150e462795ff5d4c7359f9e8637c10544bb2de70107tturney
15184fa8835ec83d5d9ce80bd0cfeaa54f4fbaf30a5Chih-Hung Hsieh// NOLINT: Do not add parentheses around 'type'.
152e462795ff5d4c7359f9e8637c10544bb2de70107tturney#define RAPIDJSON_REMOVEFPTR_(type) \
153e462795ff5d4c7359f9e8637c10544bb2de70107tturney    typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \
15484fa8835ec83d5d9ce80bd0cfeaa54f4fbaf30a5Chih-Hung Hsieh        < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type  // NOLINT
155e462795ff5d4c7359f9e8637c10544bb2de70107tturney
15684fa8835ec83d5d9ce80bd0cfeaa54f4fbaf30a5Chih-Hung Hsieh// NOLINT: Do not add parentheses around a statement.
157e462795ff5d4c7359f9e8637c10544bb2de70107tturney#define RAPIDJSON_ENABLEIF(cond) \
158e462795ff5d4c7359f9e8637c10544bb2de70107tturney    typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
15984fa8835ec83d5d9ce80bd0cfeaa54f4fbaf30a5Chih-Hung Hsieh        <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL  // NOLINT
160e462795ff5d4c7359f9e8637c10544bb2de70107tturney
16184fa8835ec83d5d9ce80bd0cfeaa54f4fbaf30a5Chih-Hung Hsieh// NOLINT: Do not add parentheses around a statement.
162e462795ff5d4c7359f9e8637c10544bb2de70107tturney#define RAPIDJSON_DISABLEIF(cond) \
163e462795ff5d4c7359f9e8637c10544bb2de70107tturney    typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
16484fa8835ec83d5d9ce80bd0cfeaa54f4fbaf30a5Chih-Hung Hsieh        <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL  // NOLINT
165e462795ff5d4c7359f9e8637c10544bb2de70107tturney
166e462795ff5d4c7359f9e8637c10544bb2de70107tturney#define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \
167e462795ff5d4c7359f9e8637c10544bb2de70107tturney    typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
168e462795ff5d4c7359f9e8637c10544bb2de70107tturney        <RAPIDJSON_REMOVEFPTR_(cond), \
169e462795ff5d4c7359f9e8637c10544bb2de70107tturney         RAPIDJSON_REMOVEFPTR_(returntype)>::Type
170e462795ff5d4c7359f9e8637c10544bb2de70107tturney
171e462795ff5d4c7359f9e8637c10544bb2de70107tturney#define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \
172e462795ff5d4c7359f9e8637c10544bb2de70107tturney    typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
173e462795ff5d4c7359f9e8637c10544bb2de70107tturney        <RAPIDJSON_REMOVEFPTR_(cond), \
174e462795ff5d4c7359f9e8637c10544bb2de70107tturney         RAPIDJSON_REMOVEFPTR_(returntype)>::Type
175e462795ff5d4c7359f9e8637c10544bb2de70107tturney
176e462795ff5d4c7359f9e8637c10544bb2de70107tturney} // namespace internal
177e462795ff5d4c7359f9e8637c10544bb2de70107tturneyRAPIDJSON_NAMESPACE_END
178e462795ff5d4c7359f9e8637c10544bb2de70107tturney//@endcond
179e462795ff5d4c7359f9e8637c10544bb2de70107tturney
180e462795ff5d4c7359f9e8637c10544bb2de70107tturney#if defined(__GNUC__) || defined(_MSC_VER)
181e462795ff5d4c7359f9e8637c10544bb2de70107tturneyRAPIDJSON_DIAG_POP
182e462795ff5d4c7359f9e8637c10544bb2de70107tturney#endif
183e462795ff5d4c7359f9e8637c10544bb2de70107tturney
184e462795ff5d4c7359f9e8637c10544bb2de70107tturney#endif // RAPIDJSON_INTERNAL_META_H_
185