Home | History | Annotate | Download | only in internal
      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 // NOLINT: Do not add parentheses around 'type'.
    152 #define RAPIDJSON_REMOVEFPTR_(type) \
    153     typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \
    154         < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type  // NOLINT
    155 
    156 // NOLINT: Do not add parentheses around a statement.
    157 #define RAPIDJSON_ENABLEIF(cond) \
    158     typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
    159         <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL  // NOLINT
    160 
    161 // NOLINT: Do not add parentheses around a statement.
    162 #define RAPIDJSON_DISABLEIF(cond) \
    163     typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
    164         <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL  // NOLINT
    165 
    166 #define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \
    167     typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \
    168         <RAPIDJSON_REMOVEFPTR_(cond), \
    169          RAPIDJSON_REMOVEFPTR_(returntype)>::Type
    170 
    171 #define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \
    172     typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \
    173         <RAPIDJSON_REMOVEFPTR_(cond), \
    174          RAPIDJSON_REMOVEFPTR_(returntype)>::Type
    175 
    176 } // namespace internal
    177 RAPIDJSON_NAMESPACE_END
    178 //@endcond
    179 
    180 #if defined(__GNUC__) || defined(_MSC_VER)
    181 RAPIDJSON_DIAG_POP
    182 #endif
    183 
    184 #endif // RAPIDJSON_INTERNAL_META_H_
    185