meta.h 6.6 KB

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