AuROXTL/Include/auROXTL/Utility/auIsCallable.hpp

128 lines
4.6 KiB
C++

/***
Copyright (C) 2022-2024 Jamie Reece Wilson (a/k/a "Reece"). All rights reserved.
File: auIsCallable.hpp
File: auTemplateMeta.hpp
Date: 2024-11-30
Date: 2022-11-17
Author: Reece
***/
#pragma once
#if !defined(AU_LANG_CPP_14_)
template<typename T, typename = void>
struct AuCallable : AuIsFunction<T> { };
template<typename T>
struct AuCallable<T, typename AuEnableIf<AuIsSame<decltype(void(&T::operator())), void>::value>::type> : AuTrueType
{
#elif defined(AU_LANG_CPP_20_)
template <class Func, class ...Params>
struct AuCallable : decltype(__audetail::IsCallable<Func, Params...>(0))
{
#else
template<typename T, typename U = void>
struct AuCallable
{
static bool const constexpr value = AuConditional_t<
AuIsClass<AuRemoveReference_t<T>>::value,
AuCallable<AuRemoveReference_t<T>, int>, std::false_type>::value;
};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(Args...), U> : AuTrueType {};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(*)(Args...), U> : AuTrueType {};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(&)(Args...), U> : AuTrueType {};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(Args......), U> : AuTrueType {};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(*)(Args......), U> : AuTrueType {};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(&)(Args......), U> : AuTrueType {};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(Args...)const, U> : AuTrueType {};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(Args...)volatile, U> : AuTrueType {};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(Args...)const volatile, U> : AuTrueType {};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(Args......)const, U> : AuTrueType {};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(Args......)volatile, U> : AuTrueType{};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(Args......)const volatile, U> : AuTrueType {};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(Args...)&, U> : AuTrueType {};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(Args...)const&, U> : AuTrueType{};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(Args...)volatile&, U> : AuTrueType{};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(Args...)const volatile&, U> : AuTrueType{};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(Args......)&, U> : AuTrueType {};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(Args......)const&, U> : AuTrueType{};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(Args......)volatile&, U> : AuTrueType{};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(Args......)const volatile&, U> : AuTrueType{};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(Args...)&&, U> : AuTrueType{};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(Args...)const&&, U> : AuTrueType{};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(Args...)volatile&&, U> : AuTrueType{};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(Args...)const volatile&&, U> : AuTrueType{};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(Args......)&&, U> : AuTrueType{};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(Args......)const&&, U> : AuTrueType{};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(Args......)volatile&&, U> : AuTrueType{};
template<typename T, typename U, typename ...Args>
struct AuCallable<T(Args......)const volatile&&, U> : AuTrueType{};
template<typename T>
struct AuCallable<T, int>
{
private:
using YesType = char(&)[1];
using NoType = char(&)[2];
struct Fallback { void operator()(); };
struct Derived : T, Fallback {};
template<typename U, U>
struct Check;
template<typename>
static YesType Test(...);
template<typename C>
static NoType Test(Check<void (Fallback::*)(), &C::operator()>*);
public:
static bool const constexpr value = sizeof(Test<Derived>(0)) == sizeof(YesType);
#endif
};
#if defined(AU_LANG_CPP_14_)
template <typename F, class... Args>
AUROXTL_CONSTEXPR auto AuIsCallable_v = AuCallable<F, Args...>::value;
#define AuIsCallable_mv(F, ...) (AuIsCallable_v<F, __VA_ARGS__>)
#else
#define AuIsCallable_mv(F, ...) (AuCallable<F, __VA_ARGS__>::value)
#endif