AuroraRuntime/Include/auROXTL/auTemplateMeta.hpp
2022-03-11 23:18:24 +00:00

227 lines
4.6 KiB
C++

/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: auTemplateMeta.hpp
Date: 2022-2-1
Author: Reece
***/
#pragma once
template<bool v>
struct AuBoolType
{
static constexpr bool value = v;
using value_type = bool;
using type = AuBoolType;
constexpr operator value_type() const noexcept
{
return value;
}
constexpr value_type operator()() const noexcept
{
return value;
}
};
using AuFalseType = AuBoolType<false>;
using AuTrueType = AuBoolType<true>;
template<class T>
using AuToValueType_t = typename T::value_type;
template<class T>
using AuToElementType_t = typename T::element_type;
template<class T, class U>
struct AuIsSame : AuFalseType
{};
template<class T>
struct AuIsSame<T, T> : AuTrueType
{};
template<class T, class U>
inline constexpr bool AuIsSame_v = AuIsSame<T, U>::value;
namespace _audetail
{
template<class T>
AuBoolType<!std::is_union<T>::value> IsClass(int T:: *);
template<class>
AuFalseType IsClass(...);
template<typename B>
AuTrueType TestIsPtrConvertible(const volatile B *);
template<typename>
AuFalseType TestIsPtrConvertible(const volatile void *);
template<typename, typename>
auto TestIsBaseOf(...)->AuTrueType;
template<typename B, typename D>
auto TestIsBaseOf(int) -> decltype(TestIsPtrConvertible<B>(static_cast<D *>(nullptr)));
}
template<class T>
struct AuIsClass : decltype(_audetail::IsClass<T>(nullptr))
{};
template<class T>
inline constexpr bool AuIsClass_v = AuIsClass<T>::value;
template<typename Base, typename Derived>
struct AuIsBaseOf :
AuBoolType<
AuIsClass_v<Base> &&
AuIsClass_v<Derived> &&
decltype(_audetail::TestIsBaseOf<Base, Derived>(0))::value
>
{};
template<typename Base, typename Derived>
inline constexpr bool AuIsBaseOf_v = AuIsBaseOf<Base, Derived>::value;
template<class>
inline constexpr bool AuIsPointer_v = false;
template<class T>
inline constexpr bool AuIsPointer_v<T *> = true;
template<class T>
inline constexpr bool AuIsPointer_v<T *const> = true;
template<class T>
inline constexpr bool AuIsPointer_v<T *volatile> = true;
template<class T>
inline constexpr bool AuIsPointer_v<T *const volatile> = true;
template<class>
inline constexpr bool AuIsReference_v = false;
template<class T>
inline constexpr bool AuIsReference_v<T &> = true;
template<class T>
inline constexpr bool AuIsReference_v<T &&> = true;
template<class T>
struct AuRemovePointer
{
typedef T type;
};
template<class T>
struct AuRemovePointer<T *>
{
typedef T type;
};
template<class T>
struct AuRemovePointer<T *const>
{
typedef T type;
};
template<class T>
struct AuRemovePointer<T *volatile>
{
typedef T type;
};
template<class T>
struct AuRemovePointer<T *const volatile>
{
typedef T type;
};
template<class T>
using AuRemovePointer_t = typename AuRemovePointer<T>::type;
template<class T>
using AuIsVoid = AuIsSame<void, T>;
template<class T>
inline constexpr bool AuIsVoid_v = AuIsVoid<T>::value;
template<class T>
struct AuRemoveReference
{
using type = T;
};
template<class T>
struct AuRemoveReference<T &>
{
using type = T;
};
template<class T>
struct AuRemoveReference<T &&>
{
using type = T;
};
template<class T>
using AuRemoveReference_t = typename AuRemoveReference<T>::type;
template<class T>
struct AuRemoveConst
{
typedef T type;
};
template<class T>
struct AuRemoveConst<const T>
{
typedef T type;
};
template<class T>
using AuRemoveConst_t = typename AuRemoveConst<T>::type;
template<bool Test, class T = void>
struct AuEnableIf
{};
template<class T>
struct AuEnableIf<true, T>
{
using type = T;
};
template<bool Test, class T = void>
using AuEnableIf_t = typename AuEnableIf<Test, T>::type;
template<bool Test, class T, class T2>
struct AuConditional
{
using type = T;
};
template<class T, class T2>
struct AuConditional<false, T, T2>
{
using type = T2;
};
template<bool Test, class T, class T2>
using AuConditional_t = typename AuConditional<Test, T, T2>::type;
template<template<typename...> class Base, typename Derived>
struct AuIsBaseOfTemplateImpl
{
template<typename... Ts>
static constexpr AuTrueType Test(const Base<Ts...> *);
static constexpr AuFalseType Test(...);
using type = decltype(Test(std::declval<AuRemoveReference_t<Derived> *>()));
};
template<template <typename...> class Base, typename Derived>
using AuIsBaseOfTemplate = typename AuIsBaseOfTemplateImpl<Base, Derived>::type;
template<template <typename...> class Base, typename Derived>
inline constexpr bool AuIsBaseOfTemplate_v = AuIsBaseOfTemplateImpl<Base, Derived>::type::value;