#ifndef TypeCasts_h
#define TypeCasts_h
#include <type_traits>
namespace WTF {
template <typename ExpectedType, typename ArgType, bool isBaseType = std::is_base_of<ExpectedType, ArgType>::value>
struct TypeCastTraits {
static bool isOfType(ArgType&)
{
static_assert(std::is_void<ExpectedType>::value, "Missing TypeCastTraits specialization");
return false;
}
};
template <typename ExpectedType, typename ArgType>
struct TypeCastTraits<ExpectedType, ArgType, true > {
static bool isOfType(ArgType&) { return true; }
};
template <typename ExpectedType, typename ArgType>
inline bool is(ArgType& source)
{
static_assert(std::is_base_of<ArgType, ExpectedType>::value, "Unnecessary type check");
return TypeCastTraits<const ExpectedType, const ArgType>::isOfType(source);
}
template <typename ExpectedType, typename ArgType>
inline bool is(ArgType* source)
{
static_assert(std::is_base_of<ArgType, ExpectedType>::value, "Unnecessary type check");
return source && TypeCastTraits<const ExpectedType, const ArgType>::isOfType(*source);
}
template <typename Reference, typename T>
struct match_constness {
typedef typename std::conditional<std::is_const<Reference>::value, typename std::add_const<T>::type, typename std::remove_const<T>::type>::type type;
};
template<typename Target, typename Source>
inline typename match_constness<Source, Target>::type& downcast(Source& source)
{
static_assert(!std::is_same<Source, Target>::value, "Unnecessary cast to same type");
static_assert(std::is_base_of<Source, Target>::value, "Should be a downcast");
ASSERT_WITH_SECURITY_IMPLICATION(is<Target>(source));
return static_cast<typename match_constness<Source, Target>::type&>(source);
}
template<typename Target, typename Source>
inline typename match_constness<Source, Target>::type* downcast(Source* source)
{
static_assert(!std::is_same<Source, Target>::value, "Unnecessary cast to same type");
static_assert(std::is_base_of<Source, Target>::value, "Should be a downcast");
ASSERT_WITH_SECURITY_IMPLICATION(!source || is<Target>(*source));
return static_cast<typename match_constness<Source, Target>::type*>(source);
}
#define SPECIALIZE_TYPE_TRAITS_BEGIN(ClassName) \
namespace WTF { \
template <typename ArgType> \
class TypeCastTraits<const ClassName, ArgType, false > { \
public: \
static bool isOfType(ArgType& source) { return isType(source); } \
private:
#define SPECIALIZE_TYPE_TRAITS_END() \
}; \
}
}
using WTF::TypeCastTraits;
using WTF::is;
using WTF::downcast;
#endif // TypeCasts_h