Jamie Reece Wilson
f6bcade29c
[+] AuGetAmbiguousMethodNoArgs [+] AuGetAmbiguousStaticFunction [+] AuGetAmbiguousStaticFunctionNoArgs
840 lines
22 KiB
C++
840 lines
22 KiB
C++
/***
|
|
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
|
|
|
File: auTemplateMeta.hpp
|
|
Date: 2022-2-1
|
|
Author: Reece
|
|
Note: most of this code assumes C++17 or greater
|
|
***/
|
|
#pragma once
|
|
|
|
template <bool v>
|
|
struct AuBoolType
|
|
{
|
|
static AUROXTL_CONSTEXPR bool value = v;
|
|
using value_type = bool;
|
|
using type = AuBoolType;
|
|
|
|
AUROXTL_CONSTEXPR operator value_type() const noexcept
|
|
{
|
|
return value;
|
|
}
|
|
|
|
AUROXTL_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;
|
|
|
|
template <typename T>
|
|
static AuToIterator_t<T> AuToIterator(const T &a); // intended use case: `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);
|
|
|
|
template <class T, class U>
|
|
struct AuIsSame : AuFalseType
|
|
{};
|
|
|
|
template <class T>
|
|
struct AuIsSame<T, T> : AuTrueType
|
|
{};
|
|
|
|
template <class T, class U>
|
|
inline AUROXTL_CONSTEXPR bool AuIsSame_v = AuIsSame<T, U>::value;
|
|
|
|
template <class>
|
|
inline AUROXTL_CONSTEXPR bool AuIsConst_v = false;
|
|
|
|
template <class T>
|
|
inline AUROXTL_CONSTEXPR bool AuIsConst_v<const T> = true;
|
|
|
|
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)));
|
|
|
|
// 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(...);
|
|
}
|
|
|
|
template <class T>
|
|
struct AuIsClass : decltype(_audetail::IsClass<T>(nullptr))
|
|
{};
|
|
|
|
template <class T>
|
|
inline AUROXTL_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 AUROXTL_CONSTEXPR bool AuIsBaseOf_v = AuIsBaseOf<Base, Derived>::value;
|
|
|
|
template <class>
|
|
inline AUROXTL_CONSTEXPR bool AuIsPointer_v = false;
|
|
|
|
template <class T>
|
|
inline AUROXTL_CONSTEXPR bool AuIsPointer_v<T *> = true;
|
|
|
|
template <class T>
|
|
inline AUROXTL_CONSTEXPR bool AuIsPointer_v<T *const> = true;
|
|
|
|
template <class T>
|
|
inline AUROXTL_CONSTEXPR bool AuIsPointer_v<T *volatile> = true;
|
|
|
|
template <class T>
|
|
inline AUROXTL_CONSTEXPR bool AuIsPointer_v<T *const volatile> = true;
|
|
|
|
template <class>
|
|
inline AUROXTL_CONSTEXPR bool AuIsReference_v = false;
|
|
|
|
template <class T>
|
|
inline AUROXTL_CONSTEXPR bool AuIsReference_v<T &> = true;
|
|
|
|
template <class T>
|
|
inline AUROXTL_CONSTEXPR bool AuIsReference_v<T &&> = true;
|
|
|
|
template <class>
|
|
inline AUROXTL_CONSTEXPR bool AuIsLValueReference_v = false;
|
|
|
|
template <class T>
|
|
inline AUROXTL_CONSTEXPR bool AuIsLValueReference_v<T &> = true;
|
|
|
|
template <class>
|
|
inline AUROXTL_CONSTEXPR bool AuIsRValueReference_v = false;
|
|
|
|
template <class T>
|
|
inline AUROXTL_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 AUROXTL_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 <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;
|
|
|
|
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>
|
|
T &&AuDeclVal();
|
|
|
|
template <class T>
|
|
struct AuAddConst
|
|
{
|
|
using type = const T;
|
|
};
|
|
|
|
template <class T>
|
|
using AuAddConst_t = typename AuAddConst<T>::type;
|
|
|
|
template <class T>
|
|
using AuRemoveCV_t = AuRemoveConst_t<AuRemoveReference_t<T>>;
|
|
|
|
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 ... Ts>
|
|
using AuVoid_t = void;
|
|
|
|
template <class>
|
|
AUROXTL_CONSTEXPR inline bool AuIsArray_v = false;
|
|
|
|
template <class T, size_t Len>
|
|
inline AUROXTL_CONSTEXPR bool AuIsArray_v<T[Len]> = true;
|
|
|
|
template <class T>
|
|
inline AUROXTL_CONSTEXPR bool AuIsArray_v<T[]> = true;
|
|
|
|
template <bool Test, class T = void>
|
|
using AuEnableIf_t = typename AuEnableIf<Test, T>::type;
|
|
|
|
#if !defined(AURORA_COMPILER_CLANG) && !defined(AURORA_COMPILER_MSVC)
|
|
template <class T, class ... Args>
|
|
struct AuIsConstructible
|
|
{
|
|
template <class C, class ... Args2> static AUROXTL_CONSTEXPR AuTrueType Test(decltype(::new C(AuDeclVal<Args2>()...)));
|
|
template <class C, class ... Args2> static AUROXTL_CONSTEXPR AuFalseType Test(...);
|
|
using type = decltype(Test<T, Args...>(0));
|
|
};
|
|
|
|
template <class T, class ... Args>
|
|
using AuIsConstructible_t = typename AuIsConstructible<T, Args ...>::type;
|
|
|
|
#else
|
|
template <class T, class ... Args>
|
|
struct AuIsConstructible : AuBoolType<__is_constructible(T, Args...)>
|
|
{
|
|
};
|
|
|
|
template <class T, class ... Args>
|
|
using AuIsConstructible_t = typename AuIsConstructible<T, Args ...>::type;
|
|
|
|
#endif
|
|
|
|
template <class T, class ... Args>
|
|
inline AUROXTL_CONSTEXPR bool AuIsConstructible_v = AuIsConstructible<T, Args ...>::type::value;
|
|
|
|
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>,
|
|
AuRemoveCV_t<T>
|
|
>
|
|
>;
|
|
|
|
template <class T>
|
|
struct AuDecay
|
|
{
|
|
using type = AuDecay_t<T>;
|
|
};
|
|
|
|
template <template <class...> class Base, typename Derived>
|
|
struct AuIsBaseOfTemplateImpl
|
|
{
|
|
template <class... Ts>
|
|
static AUROXTL_CONSTEXPR AuTrueType Test(const Base<Ts...> *);
|
|
static AUROXTL_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>
|
|
inline AUROXTL_CONSTEXPR bool AuIsBaseOfTemplate_v = AuIsBaseOfTemplateImpl<Base, Derived>::type::value;
|
|
|
|
#if !defined(AURORA_ROXTL_NO_STD)
|
|
|
|
// :(
|
|
// 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
|
|
|
|
#endif
|
|
|
|
template <class Func, class ...Params>
|
|
struct AuCallable : decltype(_audetail::IsCallable<Func, Params...>(0))
|
|
{
|
|
};
|
|
|
|
template <class F, class... Args>
|
|
AUROXTL_CONSTEXPR auto AuIsCallable_v = AuCallable<F, Args...>::value;
|
|
|
|
#include "auCopyMoveUtils.hpp"
|
|
|
|
template <AuUInt uSize, class T>
|
|
struct AU_ALIGN(uSize)
|
|
AuAlignTo : T
|
|
{
|
|
inline AuAlignTo() : T()
|
|
{
|
|
|
|
}
|
|
|
|
inline AuAlignTo(T &&t) : T(AuForward<T&&>(t))
|
|
{
|
|
|
|
}
|
|
|
|
inline AuAlignTo(const T &t) : T(t)
|
|
{
|
|
|
|
}
|
|
};
|
|
|
|
template <class Ret_t, class T, class ...Args>
|
|
static auto AuGetAmbiguousMethod2(Ret_t(T :: *a)(Args...))
|
|
{
|
|
return a;
|
|
}
|
|
|
|
template <class Ret_t, class ...Args>
|
|
static auto AuGetAmbiguousFunction2(Ret_t(*a)(Args...))
|
|
{
|
|
return a;
|
|
}
|
|
|
|
// According to MSVC: "only function types and reference types can't be const qualified"
|
|
|
|
#if 0
|
|
// MSVCs implementation is as follows:
|
|
// Our implementation is found in ./auTemplateMetaIsFunction.hpp
|
|
template <class T>
|
|
AUROXTL_CONSTEXPR bool AuIsFunction_v = !AuIsConst_v<const T> && !AuIsReference_v<T>;
|
|
|
|
template <class T>
|
|
struct AuIsFunction : AuBoolType<AuIsFunction_v<T>>
|
|
{ };
|
|
#endif
|
|
|
|
// Continuing on: this is how MSVC defines std::is_object in contrast to std::is_function
|
|
template <class T>
|
|
AUROXTL_CONSTEXPR bool AuIsObject_v = AuIsConst_v<const T> && !AuIsVoid_v<T>;
|
|
|
|
template <class T>
|
|
struct AuIsObject : AuBoolType<AuIsObject_v<T>>
|
|
{ };
|
|
|
|
#if defined(AURORA_COMPILER_CLANG)
|
|
template <class T>
|
|
AUROXTL_CONSTEXPR bool AuIsMemberFunctionPointer_v = __is_member_function_pointer(T);
|
|
|
|
template <class T>
|
|
AUROXTL_CONSTEXPR bool AuIsMemberPointer_v = __is_member_pointer(T);
|
|
|
|
|
|
#elif defined(AURORA_COMPILER_MSVC) || defined(AURORA_ROXTL_NO_NO_STD)
|
|
template <class T>
|
|
AUROXTL_CONSTEXPR bool AuIsMemberFunctionPointer_v = std::is_member_function_pointer_v<T>;
|
|
|
|
template <class T>
|
|
AUROXTL_CONSTEXPR bool AuIsMemberPointer_v = std::is_member_object_pointer_v<T> || AuIsMemberFunctionPointer_v<T>;
|
|
#endif
|
|
|
|
// I dont think I can easily implement these in templates
|
|
// For the sake of syntax sugar, these will be macros for now
|
|
#define AuGetAmbiguousMethod(Ret_t, Args, T, Method) AuGetAmbiguousMethod2<Ret_t, T, AU_BRACKET_SCOPE Args>(&T::Method)
|
|
#define AuGetAmbiguousMethodNoArgs(Ret_t, T, Method) AuGetAmbiguousMethod2<Ret_t, T> (&T::Method)
|
|
#define AuGetAmbiguousStaticFunction(Ret_t, Args, T, Func) AuGetAmbiguousFunction2<Ret_t, AU_BRACKET_SCOPE Args> (&T::Func)
|
|
#define AuGetAmbiguousStaticFunctionNoArgs(Ret_t, T, Func) AuGetAmbiguousFunction2<Ret_t> (&T::Func)
|
|
|
|
namespace _audetail
|
|
{
|
|
// yoinking https://en.cppreference.com/w/cpp/types/common_type
|
|
template<class...>
|
|
struct common_type
|
|
{ };
|
|
|
|
template<class T>
|
|
struct common_type<T> : common_type<T, T>
|
|
{ };
|
|
|
|
namespace ctdetail
|
|
{
|
|
template<class...>
|
|
using void_t = void;
|
|
|
|
template<class T1, class T2>
|
|
using conditional_result_t = decltype(false ? AuDeclVal<T1>() : AuDeclVal<T2>());
|
|
|
|
template<class, class, class = void>
|
|
struct decay_conditional_result
|
|
{ };
|
|
|
|
template<class T1, class T2>
|
|
struct decay_conditional_result<T1, T2, void_t<conditional_result_t<T1, T2>>>
|
|
: AuDecay<conditional_result_t<T1, T2>>
|
|
{ };
|
|
|
|
template<class T1, class T2, class = void>
|
|
struct common_type_2_impl : decay_conditional_result<const T1 &, const T2 &>
|
|
{ };
|
|
|
|
template<class T1, class T2>
|
|
struct common_type_2_impl<T1, T2, void_t<conditional_result_t<T1, T2>>>
|
|
: decay_conditional_result<T1, T2>
|
|
{ };
|
|
}
|
|
|
|
template<class T1, class T2>
|
|
struct common_type<T1, T2>
|
|
: AuConditional<AuIsSame_v<T1, AuDecay_t<T1>> && AuIsSame_v<T2, AuDecay_t<T2>>,
|
|
ctdetail::common_type_2_impl<T1, T2>,
|
|
common_type<AuDecay_t<T1>, AuDecay_t<T2>>>::type
|
|
{};
|
|
|
|
namespace ctdetail
|
|
{
|
|
template<class AlwaysVoid, class T1, class T2, class...R>
|
|
struct common_type_multi_impl
|
|
{ };
|
|
template<class T1, class T2, class...R>
|
|
struct common_type_multi_impl<void_t<typename common_type<T1, T2>::type>, T1, T2, R...>
|
|
: common_type<typename common_type<T1, T2>::type, R...>
|
|
{ };
|
|
}
|
|
|
|
// yoinking: https://en.cppreference.com/w/cpp/utility/functional/invoke
|
|
|
|
template<class>
|
|
AUROXTL_CONSTEXPR bool is_reference_wrapper_v = false;
|
|
|
|
#if !defined(AURORA_ROXTL_NO_STD)
|
|
template<class U>
|
|
AUROXTL_CONSTEXPR bool is_reference_wrapper_v<std::reference_wrapper<U>> = true;
|
|
#endif
|
|
|
|
#if !defined(AU_LANG_CPP_14)
|
|
template<class T>
|
|
using remove_cvref_t = AuRemoveCV_t<AuRemoveReference_t<T>>;
|
|
|
|
template<class C, class Pointed, class Object, class... Args>
|
|
AUROXTL_CONSTEXPR decltype(auto) invoke_memptr(Pointed C:: *member, Object &&object,
|
|
Args&&... args)
|
|
{
|
|
using object_t = remove_cvref_t<Object>;
|
|
|
|
AUROXTL_CONSTEXPR bool bIsMemberFunction = AuIsFunction_v<Pointed>;
|
|
AUROXTL_CONSTEXPR bool bIsWrapped = is_reference_wrapper_v<object_t>;
|
|
AUROXTL_CONSTEXPR bool bIsDerivedObject = AuIsSame_v<C, object_t> || AuIsBaseOf_v<C, object_t>;
|
|
|
|
if AUROXTL_CONSTEXPR (bIsMemberFunction)
|
|
{
|
|
if AUROXTL_CONSTEXPR (bIsDerivedObject)
|
|
{
|
|
return (AuForward<Object>(object).*member)(AuForward<Args>(args)...);
|
|
}
|
|
else if AUROXTL_CONSTEXPR (bIsWrapped)
|
|
{
|
|
return (object.get().*member)(AuForward<Args>(args)...);
|
|
}
|
|
else
|
|
{
|
|
return ((*AuForward<Object>(object)).*member)(AuForward<Args>(args)...);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
static_assert(AuIsObject_v<Pointed> && sizeof...(args) == 0);
|
|
|
|
if AUROXTL_CONSTEXPR (bIsDerivedObject)
|
|
{
|
|
return AuForward<Object>(object).*member;
|
|
}
|
|
else if AUROXTL_CONSTEXPR (bIsWrapped)
|
|
{
|
|
return object.get().*member;
|
|
}
|
|
else
|
|
{
|
|
return (*AuForward<Object>(object)).*member;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
template<class T>
|
|
auto test_returnable(int) -> decltype(void(static_cast<T(*)()>(nullptr)), AuTrueType {});
|
|
|
|
template<class>
|
|
auto test_returnable(...) -> AuFalseType;
|
|
|
|
template<class From, class To>
|
|
auto test_implicitly_convertible(int) -> decltype(void(AuDeclType<void(&)(To)>()(AuDeclType<From>())), AuTrueType {});
|
|
|
|
template<class, class>
|
|
auto test_implicitly_convertible(...) -> AuFalseType;
|
|
}
|
|
|
|
template <class T, class T2>
|
|
using AuCommonType = typename _audetail::common_type<T, T2>;
|
|
|
|
template <class T, class T2>
|
|
using AuCommonType_t = typename _audetail::common_type<T, T2>::type;
|
|
|
|
#if !defined(AU_LANG_CPP_14)
|
|
|
|
template <class F, class... Args>
|
|
AUROXTL_CONSTEXPR AuResultOf_t<F, Args...> AuInvoke(F &&f, Args&&... args)
|
|
{
|
|
if AUROXTL_CONSTEXPR (AuIsMemberPointer_v<_audetail::remove_cvref_t<F>>)
|
|
{
|
|
return _audetail::invoke_memptr(f, AuForward<Args>(args)...);
|
|
}
|
|
else
|
|
{
|
|
return AuForward<F>(f)(AuForward<Args>(args)...);
|
|
}
|
|
}
|
|
|
|
#else
|
|
|
|
template <class F, class... Args>
|
|
AuResultOf_t<F, Args...> AuInvoke(F &&f, Args&&... args)
|
|
{
|
|
return AuForward<F>(std::invoke(f, AuForward<Args>(args)...));
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
template <class T, class Z>
|
|
struct AuIsAssignable : AuBoolType<__is_assignable(T, Z)>
|
|
{ };
|
|
|
|
template <class T, class Z>
|
|
constexpr bool AuIsAssignable_v = AuIsAssignable<T, Z>::value;
|
|
|
|
template <class T>
|
|
struct AuIsCopyAssignable : AuIsAssignable<AuAddLReference_t<T>, AuAddRReference_t<const T>>
|
|
{ };
|
|
|
|
template <class T>
|
|
constexpr bool AuIsCopyAssignable_v = AuIsCopyAssignable<T>::value;
|
|
|
|
template<class T>
|
|
struct AuIsMoveAssignable : AuIsAssignable<AuAddLReference_t<T>, AuAddRReference_t<T>>
|
|
{ };
|
|
|
|
template <class T>
|
|
constexpr bool AuIsMoveAssignable_v = AuIsMoveAssignable<T>::value;
|
|
|
|
template <class T, class Z>
|
|
struct AuIsTriviallyAssignable : AuBoolType<__is_trivially_assignable(T, Z)>
|
|
{ };
|
|
|
|
template <class T, class Z>
|
|
constexpr bool AuIsTriviallyAssignable_v = AuIsTriviallyAssignable<T, Z>::value;
|
|
|
|
template<class T>
|
|
struct AuIsTriviallyCopyAssignable
|
|
: AuIsTriviallyAssignable<AuAddLReference_t<T>, AuAddRReference_t<const T>>
|
|
{ };
|
|
|
|
template<class T>
|
|
constexpr bool AuIsTriviallyCopyAssignable_v = AuIsTriviallyCopyAssignable<T>::value;
|
|
|
|
template<class T>
|
|
struct AuIsTriviallyMoveAssignable
|
|
: AuIsTriviallyAssignable<AuAddLReference_t<T>, AuAddRReference_t<T>>
|
|
{ };
|
|
|
|
template<class T>
|
|
constexpr bool AuIsTriviallyMoveAssignable_v = AuIsTriviallyMoveAssignable<T>::value;
|
|
|
|
template <class T>
|
|
struct AuIsMoveConstructible : AuIsConstructible<T, T>
|
|
{ };
|
|
|
|
template <class T>
|
|
constexpr bool AuIsMoveConstructible_v = AuIsMoveConstructible<T>::value;
|
|
|
|
template <class T>
|
|
struct AuIsCopyConstructible : AuIsConstructible<T, AuAddLReference_t<const T>>
|
|
{ };
|
|
|
|
template <class T>
|
|
constexpr bool AuIsCopyConstructible_v = AuIsCopyConstructible<T>::value;
|
|
|
|
template <class T>
|
|
struct AuIsDefaultConstructible : AuIsConstructible<T>
|
|
{ };
|
|
|
|
template <class T>
|
|
constexpr bool AuIsDefaultConstructible_v = AuIsDefaultConstructible<T>::value;
|
|
|
|
template <class T>
|
|
struct AuIsTriviallyDestructible : AuBoolType<__is_trivially_destructible(T)>
|
|
{ };
|
|
|
|
template <class T>
|
|
constexpr bool AuIsTriviallyDestructible_v = AuIsTriviallyDestructible<T>::value;
|
|
|
|
//template<class From, class To>
|
|
//struct AuIsConvertible : AuBoolType<
|
|
// (decltype(_audetail::test_returnable<To>(0))::value &&
|
|
// decltype(_audetail::test_implicitly_convertible<From, To>(0))::value) ||
|
|
// (AuIsVoid<From>::value && AuIsVoid<To>::value)
|
|
//>
|
|
//{ };
|
|
template<class From, class To>
|
|
struct AuIsConvertible : AuBoolType<__is_convertible_to(From, To)>
|
|
{ };
|
|
|
|
template <class T, class Z>
|
|
constexpr bool AuIsConvertible_v = AuIsConvertible<T, Z>::value;
|
|
|
|
template <class T, class Z>
|
|
struct AuIsNothrowAssignable : AuBoolType<__is_nothrow_assignable(T, Z)>
|
|
{ };
|
|
|
|
template <class T, class Z>
|
|
constexpr bool AuIsNothrowAssignable_v = AuIsNothrowAssignable<T, Z>::value;
|
|
|
|
template <class T>
|
|
struct AuIsNothrowCopyAssignable : AuIsNothrowAssignable<AuAddLReference_t<T>, AuAddLReference_t<const T>>
|
|
{ };
|
|
|
|
template <class T>
|
|
constexpr bool AuIsNothrowCopyAssignable_v = AuIsNothrowCopyAssignable<T>::value;
|
|
|
|
template <class T>
|
|
struct AuIsNothrowMoveAssignable : AuIsNothrowAssignable<AuAddLReference_t<T>, T>
|
|
{ };
|
|
|
|
template <class T>
|
|
constexpr bool AuIsNothrowMoveAssignable_v = AuIsNothrowMoveAssignable<T>::value;
|
|
|
|
template <class T>
|
|
struct AuIsTriviallyCopyable : AuBoolType<__is_trivially_copyable(T)>
|
|
{ };
|
|
|
|
template <class T>
|
|
constexpr bool AuIsTriviallyCopyable_v = AuIsTriviallyCopyable<T>::value;
|
|
|
|
template <class T, class ... Args>
|
|
struct AuIsTriviallyConstructible : AuBoolType<__is_trivially_constructible(T, Args...)>
|
|
{ };
|
|
|
|
template <class T, class ... Args>
|
|
constexpr bool AuIsTriviallyConstructible_v = AuIsTriviallyConstructible<T, Args...>::value;
|
|
|
|
template <class T>
|
|
struct AuIsTriviallyMoveConstructible : AuIsTriviallyConstructible<T, T>
|
|
{ };
|
|
|
|
template <class T>
|
|
constexpr bool AuIsTriviallyMoveConstructible_v = AuIsTriviallyMoveConstructible<T>::value;
|
|
|
|
template <class T>
|
|
struct AuIsTriviallyCopyConstructible : AuIsTriviallyConstructible<T, AuAddLReference_t<const T>>
|
|
{ };
|
|
|
|
template <class T>
|
|
constexpr bool AuIsTriviallyCopyConstructible_v = AuIsTriviallyCopyConstructible<T>::value;
|
|
|
|
template <class T>
|
|
struct AuIsTriviallyDefaultConstructible : AuIsTriviallyConstructible<T>
|
|
{ };
|
|
|
|
template <class T>
|
|
constexpr bool AuIsTriviallyDefaultConstructible_v = AuIsTriviallyDefaultConstructible<T>::value;
|
|
|
|
template <class T, class ... Args>
|
|
struct AuIsNothrowConstructible : AuBoolType<__is_nothrow_constructible(T, Args...)>
|
|
{ };
|
|
|
|
template <class T, class ... Args>
|
|
constexpr bool AuIsNothrowConstructible_v = AuIsNothrowConstructible<T, Args...>::value;
|
|
|
|
template <class T>
|
|
struct AuIsNothrowMoveConstructible : AuIsNothrowConstructible<T, T>
|
|
{ };
|
|
|
|
template <class T>
|
|
constexpr bool AuIsNothrowMoveConstructible_v = AuIsNothrowMoveConstructible<T>::value;
|
|
|
|
template <class T>
|
|
struct AuIsNothrowCopyConstructible : AuIsNothrowConstructible<T, AuAddLReference_t<const T>>
|
|
{ };
|
|
|
|
template <class T>
|
|
constexpr bool AuIsNothrowCopyConstructible_v = AuIsNothrowCopyConstructible<T>::value;
|
|
|
|
template <class T>
|
|
struct AuIsNothrowDefaultConstructible : AuIsNothrowConstructible<T>
|
|
{ };
|
|
|
|
template <class T>
|
|
constexpr bool AuIsNothrowDefaultConstructible_v = AuIsNothrowDefaultConstructible<T>::value;
|
|
|
|
template <class T>
|
|
constexpr bool AuIsEqualOfEnum(T cmp)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
template <class T, T e, T... args>
|
|
constexpr bool AuIsEqualOfEnum(T cmp)
|
|
{
|
|
return e == cmp || AuIsEqualOfEnum<T, args...>(cmp);
|
|
} |