meta.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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. #ifndef RAPIDJSON_INTERNAL_META_H_
  15. #define RAPIDJSON_INTERNAL_META_H_
  16. #include "../rapidjson.h"
  17. #ifdef __GNUC__
  18. RAPIDJSON_DIAG_PUSH
  19. RAPIDJSON_DIAG_OFF(effc++)
  20. #endif
  21. #if defined(_MSC_VER) && !defined(__clang__)
  22. RAPIDJSON_DIAG_PUSH
  23. RAPIDJSON_DIAG_OFF(6334)
  24. #endif
  25. #if RAPIDJSON_HAS_CXX11_TYPETRAITS
  26. #include <type_traits>
  27. #endif
  28. //@cond RAPIDJSON_INTERNAL
  29. RAPIDJSON_NAMESPACE_BEGIN
  30. namespace internal {
  31. // Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching
  32. template <typename T> struct Void { typedef void Type; };
  33. ///////////////////////////////////////////////////////////////////////////////
  34. // BoolType, TrueType, FalseType
  35. //
  36. template <bool Cond> struct BoolType {
  37. static const bool Value = Cond;
  38. typedef BoolType Type;
  39. };
  40. typedef BoolType<true> TrueType;
  41. typedef BoolType<false> FalseType;
  42. ///////////////////////////////////////////////////////////////////////////////
  43. // SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr
  44. //
  45. template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; };
  46. template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; };
  47. template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {};
  48. template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {};
  49. template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {};
  50. template <> struct AndExprCond<true, true> : TrueType {};
  51. template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {};
  52. template <> struct OrExprCond<false, false> : FalseType {};
  53. template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {};
  54. template <typename C> struct NotExpr : SelectIf<C,FalseType,TrueType>::Type {};
  55. template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {};
  56. template <typename C1, typename C2> struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {};
  57. ///////////////////////////////////////////////////////////////////////////////
  58. // AddConst, MaybeAddConst, RemoveConst
  59. template <typename T> struct AddConst { typedef const T Type; };
  60. template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {};
  61. template <typename T> struct RemoveConst { typedef T Type; };
  62. template <typename T> struct RemoveConst<const T> { typedef T Type; };
  63. ///////////////////////////////////////////////////////////////////////////////
  64. // IsSame, IsConst, IsMoreConst, IsPointer
  65. //
  66. template <typename T, typename U> struct IsSame : FalseType {};
  67. template <typename T> struct IsSame<T, T> : TrueType {};
  68. template <typename T> struct IsConst : FalseType {};
  69. template <typename T> struct IsConst<const T> : TrueType {};
  70. template <typename CT, typename T>
  71. struct IsMoreConst
  72. : AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>,
  73. BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {};
  74. template <typename T> struct IsPointer : FalseType {};
  75. template <typename T> struct IsPointer<T*> : TrueType {};
  76. ///////////////////////////////////////////////////////////////////////////////
  77. // IsBaseOf
  78. //
  79. #if RAPIDJSON_HAS_CXX11_TYPETRAITS
  80. template <typename B, typename D> struct IsBaseOf
  81. : BoolType< ::std::is_base_of<B,D>::value> {};
  82. #else // simplified version adopted from Boost
  83. template<typename B, typename D> struct IsBaseOfImpl {
  84. RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0);
  85. RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0);
  86. typedef char (&Yes)[1];
  87. typedef char (&No) [2];
  88. template <typename T>
  89. static Yes Check(const D*, T);
  90. static No Check(const B*, int);
  91. struct Host {
  92. operator const B*() const;
  93. operator const D*();
  94. };
  95. enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) };
  96. };
  97. template <typename B, typename D> struct IsBaseOf
  98. : OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {};
  99. #endif // RAPIDJSON_HAS_CXX11_TYPETRAITS
  100. //////////////////////////////////////////////////////////////////////////
  101. // EnableIf / DisableIf
  102. //
  103. template <bool Condition, typename T = void> struct EnableIfCond { typedef T Type; };
  104. template <typename T> struct EnableIfCond<false, T> { /* empty */ };
  105. template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; };
  106. template <typename T> struct DisableIfCond<true, T> { /* empty */ };
  107. template <typename Condition, typename T = void>
  108. struct EnableIf : EnableIfCond<Condition::Value, T> {};
  109. template <typename Condition, typename T = void>
  110. struct DisableIf : DisableIfCond<Condition::Value, T> {};
  111. // SFINAE helpers
  112. struct SfinaeTag {};
  113. template <typename T> struct RemoveSfinaeTag;
  114. template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; };
  115. #define RAPIDJSON_REMOVEFPTR_(type) \
  116. typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \
  117. < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type
  118. #define RAPIDJSON_ENABLEIF(cond) \
  119. typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
  120. <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
  121. #define RAPIDJSON_DISABLEIF(cond) \
  122. typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
  123. <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL
  124. #define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \
  125. typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
  126. <RAPIDJSON_REMOVEFPTR_(cond), \
  127. RAPIDJSON_REMOVEFPTR_(returntype)>::Type
  128. #define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \
  129. typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
  130. <RAPIDJSON_REMOVEFPTR_(cond), \
  131. RAPIDJSON_REMOVEFPTR_(returntype)>::Type
  132. } // namespace internal
  133. RAPIDJSON_NAMESPACE_END
  134. //@endcond
  135. #if defined(_MSC_VER) && !defined(__clang__)
  136. RAPIDJSON_DIAG_POP
  137. #endif
  138. #ifdef __GNUC__
  139. RAPIDJSON_DIAG_POP
  140. #endif
  141. #endif // RAPIDJSON_INTERNAL_META_H_