// 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; }; | |
// NOLINT: Do not add parentheses around 'type'. | |
#define RAPIDJSON_REMOVEFPTR_(type) \ | |
typename ::RAPIDJSON_NAMESPACE::internal::RemoveSfinaeTag \ | |
< ::RAPIDJSON_NAMESPACE::internal::SfinaeTag&(*) type>::Type // NOLINT | |
// NOLINT: Do not add parentheses around a statement. | |
#define RAPIDJSON_ENABLEIF(cond) \ | |
typename ::RAPIDJSON_NAMESPACE::internal::EnableIf \ | |
<RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL // NOLINT | |
// NOLINT: Do not add parentheses around a statement. | |
#define RAPIDJSON_DISABLEIF(cond) \ | |
typename ::RAPIDJSON_NAMESPACE::internal::DisableIf \ | |
<RAPIDJSON_REMOVEFPTR_(cond)>::Type * = NULL // NOLINT | |
#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_ |