#pragma once
#include <type_traits>
namespace WTF {
template <typename ExpectedType, typename ArgType, bool isBaseType = std::is_base_of_v<ExpectedType, ArgType>>
struct TypeCastTraits {
static bool isOfType(ArgType&)
{
static_assert(std::is_void_v<ExpectedType>, "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_v<ArgType, ExpectedType>, "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_v<ArgType, ExpectedType>, "Unnecessary type check");
return source && TypeCastTraits<const ExpectedType, const ArgType>::isOfType(*source);
}
template <typename Reference, typename T>
using match_constness_t =
typename std::conditional_t<std::is_const_v<Reference>, typename std::add_const_t<T>, typename std::remove_const_t<T>>;
template<typename Target, typename Source>
inline match_constness_t<Source, Target>& downcast(Source& source)
{
static_assert(!std::is_same_v<Source, Target>, "Unnecessary cast to same type");
static_assert(std::is_base_of_v<Source, Target>, "Should be a downcast");
ASSERT_WITH_SECURITY_IMPLICATION(is<Target>(source));
return static_cast<match_constness_t<Source, Target>&>(source);
}
template<typename Target, typename Source>
inline match_constness_t<Source, Target>* downcast(Source* source)
{
static_assert(!std::is_same_v<Source, Target>, "Unnecessary cast to same type");
static_assert(std::is_base_of_v<Source, Target>, "Should be a downcast");
ASSERT_WITH_SECURITY_IMPLICATION(!source || is<Target>(*source));
return static_cast<match_constness_t<Source, Target>*>(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;