2022-04-01 04:06:53 +00:00
|
|
|
/***
|
|
|
|
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>;
|
|
|
|
|
|
|
|
#include "auTemplateMetaIsFunction.hpp"
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
using AuToValueType_t = typename T::value_type;
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
using AuToElementType_t = typename T::element_type;
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
using AuToIterator_t = typename T::iterator;
|
|
|
|
|
2023-01-18 10:49:32 +00:00
|
|
|
template <typename T>
|
|
|
|
static AuToIterator_t<T> AuToIterator(const T &a); // intended use case: screwing over nasty ass lines of `AuToIterator_t<decltype(muh member)>` or worse.
|
|
|
|
// example usage: `decltype(AuToIterator(myHashMap)) itr;`
|
|
|
|
template <typename T>
|
|
|
|
static AuToElementType_t<T> AuToElementType(const T &a);
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
static AuToValueType_t<T> AuToValueType(const T &a);
|
|
|
|
|
2022-04-01 04:06:53 +00:00
|
|
|
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<!__is_union(T)> IsClass(int T:: *);
|
|
|
|
|
|
|
|
template <class>
|
|
|
|
AuFalseType IsClass(...);
|
|
|
|
|
|
|
|
template <class B>
|
|
|
|
AuTrueType TestIsPtrConvertible(const volatile B *);
|
|
|
|
template <class>
|
|
|
|
AuFalseType TestIsPtrConvertible(const volatile void *);
|
|
|
|
|
|
|
|
template <class, typename>
|
|
|
|
auto TestIsBaseOf(...)->AuTrueType;
|
|
|
|
|
|
|
|
template <class B, typename D>
|
|
|
|
auto TestIsBaseOf(int) -> decltype(TestIsPtrConvertible<B>(static_cast<D *>(nullptr)));
|
2022-11-17 02:28:23 +00:00
|
|
|
|
|
|
|
// yoinked: https://stackoverflow.com/a/40867906
|
|
|
|
template<typename Func, typename...Params> static auto IsCallable(int) -> decltype((void)AuDeclVal<Func>()(AuDeclVal<Params>()...), AuTrueType {});
|
|
|
|
template<typename Func, typename...Params> static AuFalseType IsCallable(...);
|
2022-04-01 04:06:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
struct AuIsClass : decltype(_audetail::IsClass<T>(nullptr))
|
|
|
|
{};
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
inline constexpr bool AuIsClass_v = AuIsClass<T>::value;
|
|
|
|
|
|
|
|
template <class Base, typename Derived>
|
|
|
|
struct AuIsBaseOf :
|
|
|
|
AuBoolType<
|
|
|
|
AuIsClass_v<Base> &&
|
|
|
|
AuIsClass_v<Derived> &&
|
|
|
|
decltype(_audetail::TestIsBaseOf<Base, Derived>(0))::value
|
|
|
|
>
|
|
|
|
{};
|
|
|
|
|
|
|
|
template <class 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>
|
|
|
|
inline constexpr bool AuIsLValueReference_v = false;
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
inline constexpr bool AuIsLValueReference_v<T &> = true;
|
|
|
|
|
|
|
|
template <class>
|
|
|
|
inline constexpr bool AuIsRValueReference_v = false;
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
inline constexpr bool AuIsRValueReference_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;
|
|
|
|
|
2022-09-27 15:37:42 +00:00
|
|
|
template <class T>
|
|
|
|
struct AuRemoveVolatile
|
|
|
|
{
|
|
|
|
typedef T type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
struct AuRemoveVolatile<volatile T>
|
|
|
|
{
|
|
|
|
typedef T type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
using AuRemoveVolatile_t = typename AuRemoveVolatile<T>::type;
|
|
|
|
|
2022-04-01 04:06:53 +00:00
|
|
|
template <bool Test, class T = void>
|
|
|
|
struct AuEnableIf
|
|
|
|
{};
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
struct AuEnableIf<true, T>
|
|
|
|
{
|
|
|
|
using type = T;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
struct AuAddPointer
|
|
|
|
{
|
|
|
|
using type = AuRemoveReference_t<T> *;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
using AuAddPointer_t = typename AuAddPointer<T>::type;
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
struct AuAddLReference
|
|
|
|
{
|
|
|
|
using type = AuRemoveReference_t<T> &;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
using AuAddLReference_t = typename AuAddLReference<T>::type;
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
struct AuAddRReference
|
|
|
|
{
|
|
|
|
using type = AuRemoveReference_t<T> &&;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
using AuAddRReference_t = typename AuAddRReference<T>::type;
|
|
|
|
|
|
|
|
template <class T>
|
2022-11-17 02:28:23 +00:00
|
|
|
T &&AuDeclVal();
|
2022-04-01 04:06:53 +00:00
|
|
|
|
|
|
|
template <class T>
|
|
|
|
struct AuAddConst
|
|
|
|
{
|
|
|
|
using type = const T;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
using AuAddConst_t = typename AuAddConst<T>::type;
|
|
|
|
|
|
|
|
template <class T>
|
2022-05-02 17:16:52 +00:00
|
|
|
using AuRemoveCV_t = AuRemoveConst_t<AuRemoveReference_t<T>>;
|
2022-04-01 04:06:53 +00:00
|
|
|
|
|
|
|
template <class T>
|
|
|
|
struct AuRemoveExtent
|
|
|
|
{
|
|
|
|
using type = T;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
struct AuRemoveExtent<T[]>
|
|
|
|
{
|
|
|
|
using type = T;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class T, AuUInt Len>
|
|
|
|
struct AuRemoveExtent<T[Len]>
|
|
|
|
{
|
|
|
|
using type = T;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
using AuRemoveExtent_t = typename AuRemoveExtent<T>::type;
|
|
|
|
|
|
|
|
template <class>
|
|
|
|
constexpr inline bool AuIsArray_v = false;
|
|
|
|
|
|
|
|
template <class T, size_t Len>
|
|
|
|
inline constexpr bool AuIsArray_v<T[Len]> = true;
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
inline constexpr bool AuIsArray_v<T[]> = true;
|
|
|
|
|
|
|
|
template <bool Test, class T = void>
|
|
|
|
using AuEnableIf_t = typename AuEnableIf<Test, T>::type;
|
|
|
|
|
|
|
|
template <class T, class ... Args>
|
|
|
|
struct AuIsConstructible
|
|
|
|
{
|
2022-04-04 07:44:04 +00:00
|
|
|
template <class C, class ... Args2> static constexpr AuTrueType Test(decltype(::new C(AuDeclVal<Args2>()...)));
|
|
|
|
template <class C, class ... Args2> static constexpr AuFalseType Test(...);
|
2022-04-01 04:06:53 +00:00
|
|
|
using type = decltype(Test<T, Args...>(0));
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class T, class ... Args>
|
|
|
|
using AuIsConstructible_t = typename AuIsConstructible<T, Args ...>::type;
|
|
|
|
|
|
|
|
template <class T, class ... Args>
|
2022-04-04 07:44:04 +00:00
|
|
|
inline constexpr bool AuIsConstructible_v = AuIsConstructible<T, Args ...>::type::value;
|
2022-04-01 04:06:53 +00:00
|
|
|
|
|
|
|
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 <class T>
|
|
|
|
using AuDecay_t = AuConditional_t<
|
|
|
|
AuIsArray_v<T>,
|
|
|
|
AuAddPointer_t<AuRemoveExtent_t<T>>,
|
|
|
|
AuConditional_t<
|
|
|
|
AuIsFunction_v<T>,
|
|
|
|
AuAddPointer_t<T>,
|
2022-05-02 17:16:52 +00:00
|
|
|
AuRemoveCV_t<T>
|
2022-04-01 04:06:53 +00:00
|
|
|
>
|
|
|
|
>;
|
|
|
|
|
|
|
|
template <template <class...> class Base, typename Derived>
|
|
|
|
struct AuIsBaseOfTemplateImpl
|
|
|
|
{
|
|
|
|
template <class... Ts>
|
|
|
|
static constexpr AuTrueType Test(const Base<Ts...> *);
|
|
|
|
static constexpr AuFalseType Test(...);
|
|
|
|
using type = decltype(Test(AuDeclVal<AuRemoveReference_t<Derived> *>()));
|
|
|
|
};
|
|
|
|
|
|
|
|
template <template <class...> class Base, typename Derived>
|
|
|
|
using AuIsBaseOfTemplate = typename AuIsBaseOfTemplateImpl<Base, Derived>::type;
|
|
|
|
|
|
|
|
template <template <class...> class Base, typename Derived>
|
2022-11-17 02:28:23 +00:00
|
|
|
inline constexpr bool AuIsBaseOfTemplate_v = AuIsBaseOfTemplateImpl<Base, Derived>::type::value;
|
|
|
|
|
|
|
|
// :(
|
|
|
|
// we have a boost licensed call traits in auv8pp
|
|
|
|
#include <type_traits>
|
|
|
|
|
|
|
|
#if defined(AU_LANG_CPP_14)
|
|
|
|
template <class T, class... Args>
|
|
|
|
using AuResultOf_t = typename std::result_of_t<T, Args...>;
|
|
|
|
#else
|
|
|
|
template <class T, class... Args>
|
|
|
|
using AuResultOf_t = typename std::invoke_result_t<T, Args...>;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
template <class Func, class ...Params>
|
|
|
|
struct AuCallable : decltype(_audetail::IsCallable<Func, Params...>(0))
|
|
|
|
{
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class F, class... Args>
|
|
|
|
constexpr auto AuIsCallable_v = AuCallable<F, Args...>::value;
|