| // Tencent is pleased to support the open source community by making RapidJSON available. |
| // |
| // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. |
| // |
| // Licensed under the MIT License (the "License"); you may not use this file except |
| // in compliance with the License. You may obtain a copy of the License at |
| // |
| // http://opensource.org/licenses/MIT |
| // |
| // Unless required by applicable law or agreed to in writing, software distributed |
| // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR |
| // CONDITIONS OF ANY KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations under the License. |
| |
| #ifndef RAPIDJSON_INTERNAL_META_H_ |
| #define RAPIDJSON_INTERNAL_META_H_ |
| |
| #include "../rapidjson.h" |
| |
| #ifdef __GNUC__ |
| RAPIDJSON_DIAG_PUSH |
| RAPIDJSON_DIAG_OFF(effc++) |
| #endif |
| #if defined(_MSC_VER) |
| RAPIDJSON_DIAG_PUSH |
| RAPIDJSON_DIAG_OFF(6334) |
| #endif |
| |
| #if RAPIDJSON_HAS_CXX11_TYPETRAITS |
| #include <type_traits> |
| #endif |
| |
| //@cond RAPIDJSON_INTERNAL |
| RAPIDJSON_NAMESPACE_BEGIN |
| namespace internal { |
| |
| // Helper to wrap/convert arbitrary types to void, useful for arbitrary type matching |
| template <typename T> struct Void { typedef void Type; }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // BoolType, TrueType, FalseType |
| // |
| template <bool Cond> struct BoolType { |
| static const bool Value = Cond; |
| typedef BoolType Type; |
| }; |
| typedef BoolType<true> TrueType; |
| typedef BoolType<false> FalseType; |
| |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // SelectIf, BoolExpr, NotExpr, AndExpr, OrExpr |
| // |
| |
| template <bool C> struct SelectIfImpl { template <typename T1, typename T2> struct Apply { typedef T1 Type; }; }; |
| template <> struct SelectIfImpl<false> { template <typename T1, typename T2> struct Apply { typedef T2 Type; }; }; |
| template <bool C, typename T1, typename T2> struct SelectIfCond : SelectIfImpl<C>::template Apply<T1,T2> {}; |
| template <typename C, typename T1, typename T2> struct SelectIf : SelectIfCond<C::Value, T1, T2> {}; |
| |
| template <bool Cond1, bool Cond2> struct AndExprCond : FalseType {}; |
| template <> struct AndExprCond<true, true> : TrueType {}; |
| template <bool Cond1, bool Cond2> struct OrExprCond : TrueType {}; |
| template <> struct OrExprCond<false, false> : FalseType {}; |
| |
| template <typename C> struct BoolExpr : SelectIf<C,TrueType,FalseType>::Type {}; |
| template <typename C> struct NotExpr : SelectIf<C,FalseType,TrueType>::Type {}; |
| template <typename C1, typename C2> struct AndExpr : AndExprCond<C1::Value, C2::Value>::Type {}; |
| template <typename C1, typename C2> struct OrExpr : OrExprCond<C1::Value, C2::Value>::Type {}; |
| |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // AddConst, MaybeAddConst, RemoveConst |
| template <typename T> struct AddConst { typedef const T Type; }; |
| template <bool Constify, typename T> struct MaybeAddConst : SelectIfCond<Constify, const T, T> {}; |
| template <typename T> struct RemoveConst { typedef T Type; }; |
| template <typename T> struct RemoveConst<const T> { typedef T Type; }; |
| |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // IsSame, IsConst, IsMoreConst, IsPointer |
| // |
| template <typename T, typename U> struct IsSame : FalseType {}; |
| template <typename T> struct IsSame<T, T> : TrueType {}; |
| |
| template <typename T> struct IsConst : FalseType {}; |
| template <typename T> struct IsConst<const T> : TrueType {}; |
| |
| template <typename CT, typename T> |
| struct IsMoreConst |
| : AndExpr<IsSame<typename RemoveConst<CT>::Type, typename RemoveConst<T>::Type>, |
| BoolType<IsConst<CT>::Value >= IsConst<T>::Value> >::Type {}; |
| |
| template <typename T> struct IsPointer : FalseType {}; |
| template <typename T> struct IsPointer<T*> : TrueType {}; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // IsBaseOf |
| // |
| #if RAPIDJSON_HAS_CXX11_TYPETRAITS |
| |
| template <typename B, typename D> struct IsBaseOf |
| : BoolType< ::std::is_base_of<B,D>::value> {}; |
| |
| #else // simplified version adopted from Boost |
| |
| template<typename B, typename D> struct IsBaseOfImpl { |
| RAPIDJSON_STATIC_ASSERT(sizeof(B) != 0); |
| RAPIDJSON_STATIC_ASSERT(sizeof(D) != 0); |
| |
| typedef char (&Yes)[1]; |
| typedef char (&No) [2]; |
| |
| template <typename T> |
| static Yes Check(const D*, T); |
| static No Check(const B*, int); |
| |
| struct Host { |
| operator const B*() const; |
| operator const D*(); |
| }; |
| |
| enum { Value = (sizeof(Check(Host(), 0)) == sizeof(Yes)) }; |
| }; |
| |
| template <typename B, typename D> struct IsBaseOf |
| : OrExpr<IsSame<B, D>, BoolExpr<IsBaseOfImpl<B, D> > >::Type {}; |
| |
| #endif // RAPIDJSON_HAS_CXX11_TYPETRAITS |
| |
| |
| ////////////////////////////////////////////////////////////////////////// |
| // EnableIf / DisableIf |
| // |
| template <bool Condition, typename T = void> struct EnableIfCond { typedef T Type; }; |
| template <typename T> struct EnableIfCond<false, T> { /* empty */ }; |
| |
| template <bool Condition, typename T = void> struct DisableIfCond { typedef T Type; }; |
| template <typename T> struct DisableIfCond<true, T> { /* empty */ }; |
| |
| template <typename Condition, typename T = void> |
| struct EnableIf : EnableIfCond<Condition::Value, T> {}; |
| |
| template <typename Condition, typename T = void> |
| struct DisableIf : DisableIfCond<Condition::Value, T> {}; |
| |
| // SFINAE helpers |
| struct SfinaeTag {}; |
| template <typename T> struct RemoveSfinaeTag; |
| template <typename T> struct RemoveSfinaeTag<SfinaeTag&(*)(T)> { typedef T Type; }; |
| |
| #define RAPIDJSON_REMOVEFPTR_(type) \ |
| typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \ |
| < ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type |
| |
| #define RAPIDJSON_ENABLEIF(cond) \ |
| typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ |
| <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL |
| |
| #define RAPIDJSON_DISABLEIF(cond) \ |
| typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ |
| <RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL |
| |
| #define RAPIDJSON_ENABLEIF_RETURN(cond,returntype) \ |
| typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ |
| <RAPIDJSON_REMOVEFPTR_(cond), \ |
| RAPIDJSON_REMOVEFPTR_(returntype)>::Type |
| |
| #define RAPIDJSON_DISABLEIF_RETURN(cond,returntype) \ |
| typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ |
| <RAPIDJSON_REMOVEFPTR_(cond), \ |
| RAPIDJSON_REMOVEFPTR_(returntype)>::Type |
| |
| } // namespace internal |
| RAPIDJSON_NAMESPACE_END |
| //@endcond |
| |
| #if defined(__GNUC__) || defined(_MSC_VER) |
| RAPIDJSON_DIAG_POP |
| #endif |
| |
| #endif // RAPIDJSON_INTERNAL_META_H_ |