2021-04-10 16:59:06 +03:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
2021-04-22 23:13:01 +03:00
|
|
|
* Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org>
|
2021-07-02 18:15:59 +03:00
|
|
|
* Copyright (c) 2021, Daniel Bertalan <dani@danielbertalan.dev>
|
2021-04-10 16:59:06 +03:00
|
|
|
*
|
2021-04-22 11:24:48 +03:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2021-04-10 16:59:06 +03:00
|
|
|
*/
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2022-10-04 22:04:13 +03:00
|
|
|
#include <AK/Platform.h>
|
2024-02-09 02:52:03 +03:00
|
|
|
#include <AK/Types.h>
|
2022-10-04 22:04:13 +03:00
|
|
|
|
2021-04-10 16:59:06 +03:00
|
|
|
namespace AK::Detail {
|
|
|
|
|
|
|
|
template<class T, T v>
|
|
|
|
struct IntegralConstant {
|
|
|
|
static constexpr T value = v;
|
|
|
|
using ValueType = T;
|
|
|
|
using Type = IntegralConstant;
|
|
|
|
constexpr operator ValueType() const { return value; }
|
|
|
|
constexpr ValueType operator()() const { return value; }
|
|
|
|
};
|
|
|
|
|
|
|
|
using FalseType = IntegralConstant<bool, false>;
|
|
|
|
using TrueType = IntegralConstant<bool, true>;
|
|
|
|
|
|
|
|
template<class T>
|
2024-03-13 03:48:01 +03:00
|
|
|
using AddConst = T const;
|
2021-04-10 16:59:06 +03:00
|
|
|
|
2022-04-03 14:06:34 +03:00
|
|
|
template<class T>
|
|
|
|
struct __AddConstToReferencedType {
|
|
|
|
using Type = T;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
struct __AddConstToReferencedType<T&> {
|
|
|
|
using Type = AddConst<T>&;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
struct __AddConstToReferencedType<T&&> {
|
|
|
|
using Type = AddConst<T>&&;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
using AddConstToReferencedType = typename __AddConstToReferencedType<T>::Type;
|
|
|
|
|
2021-04-10 16:59:06 +03:00
|
|
|
template<class T>
|
|
|
|
struct __RemoveConst {
|
|
|
|
using Type = T;
|
|
|
|
};
|
|
|
|
template<class T>
|
2022-10-17 01:06:11 +03:00
|
|
|
struct __RemoveConst<T const> {
|
2021-04-10 16:59:06 +03:00
|
|
|
using Type = T;
|
|
|
|
};
|
|
|
|
template<class T>
|
|
|
|
using RemoveConst = typename __RemoveConst<T>::Type;
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
struct __RemoveVolatile {
|
|
|
|
using Type = T;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class T>
|
2022-10-17 01:06:11 +03:00
|
|
|
struct __RemoveVolatile<T volatile> {
|
2021-04-10 16:59:06 +03:00
|
|
|
using Type = T;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
using RemoveVolatile = typename __RemoveVolatile<T>::Type;
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
using RemoveCV = RemoveVolatile<RemoveConst<T>>;
|
|
|
|
|
|
|
|
template<typename...>
|
|
|
|
using VoidType = void;
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
inline constexpr bool IsLvalueReference = false;
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
inline constexpr bool IsLvalueReference<T&> = true;
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
inline constexpr bool __IsPointerHelper = false;
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
inline constexpr bool __IsPointerHelper<T*> = true;
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
inline constexpr bool IsPointer = __IsPointerHelper<RemoveCV<T>>;
|
|
|
|
|
|
|
|
template<class>
|
|
|
|
inline constexpr bool IsFunction = false;
|
|
|
|
template<class Ret, class... Args>
|
|
|
|
inline constexpr bool IsFunction<Ret(Args...)> = true;
|
|
|
|
template<class Ret, class... Args>
|
|
|
|
inline constexpr bool IsFunction<Ret(Args..., ...)> = true;
|
|
|
|
template<class Ret, class... Args>
|
|
|
|
inline constexpr bool IsFunction<Ret(Args...) const> = true;
|
|
|
|
template<class Ret, class... Args>
|
|
|
|
inline constexpr bool IsFunction<Ret(Args..., ...) const> = true;
|
|
|
|
template<class Ret, class... Args>
|
|
|
|
inline constexpr bool IsFunction<Ret(Args...) volatile> = true;
|
|
|
|
template<class Ret, class... Args>
|
|
|
|
inline constexpr bool IsFunction<Ret(Args..., ...) volatile> = true;
|
|
|
|
template<class Ret, class... Args>
|
|
|
|
inline constexpr bool IsFunction<Ret(Args...) const volatile> = true;
|
|
|
|
template<class Ret, class... Args>
|
|
|
|
inline constexpr bool IsFunction<Ret(Args..., ...) const volatile> = true;
|
|
|
|
template<class Ret, class... Args>
|
|
|
|
inline constexpr bool IsFunction<Ret(Args...)&> = true;
|
|
|
|
template<class Ret, class... Args>
|
|
|
|
inline constexpr bool IsFunction<Ret(Args..., ...)&> = true;
|
|
|
|
template<class Ret, class... Args>
|
|
|
|
inline constexpr bool IsFunction<Ret(Args...) const&> = true;
|
|
|
|
template<class Ret, class... Args>
|
|
|
|
inline constexpr bool IsFunction<Ret(Args..., ...) const&> = true;
|
|
|
|
template<class Ret, class... Args>
|
|
|
|
inline constexpr bool IsFunction<Ret(Args...) volatile&> = true;
|
|
|
|
template<class Ret, class... Args>
|
|
|
|
inline constexpr bool IsFunction<Ret(Args..., ...) volatile&> = true;
|
|
|
|
template<class Ret, class... Args>
|
|
|
|
inline constexpr bool IsFunction<Ret(Args...) const volatile&> = true;
|
|
|
|
template<class Ret, class... Args>
|
|
|
|
inline constexpr bool IsFunction<Ret(Args..., ...) const volatile&> = true;
|
|
|
|
template<class Ret, class... Args>
|
2022-10-17 01:06:11 +03:00
|
|
|
inline constexpr bool IsFunction<Ret(Args...)&&> = true;
|
2021-04-10 16:59:06 +03:00
|
|
|
template<class Ret, class... Args>
|
2022-10-17 01:06:11 +03:00
|
|
|
inline constexpr bool IsFunction<Ret(Args..., ...)&&> = true;
|
2021-04-10 16:59:06 +03:00
|
|
|
template<class Ret, class... Args>
|
|
|
|
inline constexpr bool IsFunction<Ret(Args...) const&&> = true;
|
|
|
|
template<class Ret, class... Args>
|
|
|
|
inline constexpr bool IsFunction<Ret(Args..., ...) const&&> = true;
|
|
|
|
template<class Ret, class... Args>
|
|
|
|
inline constexpr bool IsFunction<Ret(Args...) volatile&&> = true;
|
|
|
|
template<class Ret, class... Args>
|
|
|
|
inline constexpr bool IsFunction<Ret(Args..., ...) volatile&&> = true;
|
|
|
|
template<class Ret, class... Args>
|
|
|
|
inline constexpr bool IsFunction<Ret(Args...) const volatile&&> = true;
|
|
|
|
template<class Ret, class... Args>
|
|
|
|
inline constexpr bool IsFunction<Ret(Args..., ...) const volatile&&> = true;
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
inline constexpr bool IsRvalueReference = false;
|
|
|
|
template<class T>
|
|
|
|
inline constexpr bool IsRvalueReference<T&&> = true;
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
struct __RemovePointer {
|
|
|
|
using Type = T;
|
|
|
|
};
|
|
|
|
template<class T>
|
|
|
|
struct __RemovePointer<T*> {
|
|
|
|
using Type = T;
|
|
|
|
};
|
|
|
|
template<class T>
|
|
|
|
struct __RemovePointer<T* const> {
|
|
|
|
using Type = T;
|
|
|
|
};
|
|
|
|
template<class T>
|
|
|
|
struct __RemovePointer<T* volatile> {
|
|
|
|
using Type = T;
|
|
|
|
};
|
|
|
|
template<class T>
|
|
|
|
struct __RemovePointer<T* const volatile> {
|
|
|
|
using Type = T;
|
|
|
|
};
|
|
|
|
template<typename T>
|
|
|
|
using RemovePointer = typename __RemovePointer<T>::Type;
|
|
|
|
|
|
|
|
template<typename T, typename U>
|
|
|
|
inline constexpr bool IsSame = false;
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool IsSame<T, T> = true;
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool IsNullPointer = IsSame<decltype(nullptr), RemoveCV<T>>;
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct __RemoveReference {
|
|
|
|
using Type = T;
|
|
|
|
};
|
|
|
|
template<class T>
|
|
|
|
struct __RemoveReference<T&> {
|
|
|
|
using Type = T;
|
|
|
|
};
|
|
|
|
template<class T>
|
|
|
|
struct __RemoveReference<T&&> {
|
|
|
|
using Type = T;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
using RemoveReference = typename __RemoveReference<T>::Type;
|
|
|
|
|
2021-06-27 22:22:36 +03:00
|
|
|
template<typename T>
|
|
|
|
using RemoveCVReference = RemoveCV<RemoveReference<T>>;
|
|
|
|
|
2021-04-10 16:59:06 +03:00
|
|
|
template<typename T>
|
|
|
|
struct __MakeUnsigned {
|
|
|
|
using Type = void;
|
|
|
|
};
|
|
|
|
template<>
|
|
|
|
struct __MakeUnsigned<signed char> {
|
|
|
|
using Type = unsigned char;
|
|
|
|
};
|
|
|
|
template<>
|
|
|
|
struct __MakeUnsigned<short> {
|
|
|
|
using Type = unsigned short;
|
|
|
|
};
|
|
|
|
template<>
|
|
|
|
struct __MakeUnsigned<int> {
|
|
|
|
using Type = unsigned int;
|
|
|
|
};
|
|
|
|
template<>
|
|
|
|
struct __MakeUnsigned<long> {
|
|
|
|
using Type = unsigned long;
|
|
|
|
};
|
|
|
|
template<>
|
|
|
|
struct __MakeUnsigned<long long> {
|
|
|
|
using Type = unsigned long long;
|
|
|
|
};
|
|
|
|
template<>
|
|
|
|
struct __MakeUnsigned<unsigned char> {
|
|
|
|
using Type = unsigned char;
|
|
|
|
};
|
|
|
|
template<>
|
|
|
|
struct __MakeUnsigned<unsigned short> {
|
|
|
|
using Type = unsigned short;
|
|
|
|
};
|
|
|
|
template<>
|
|
|
|
struct __MakeUnsigned<unsigned int> {
|
|
|
|
using Type = unsigned int;
|
|
|
|
};
|
|
|
|
template<>
|
|
|
|
struct __MakeUnsigned<unsigned long> {
|
|
|
|
using Type = unsigned long;
|
|
|
|
};
|
|
|
|
template<>
|
|
|
|
struct __MakeUnsigned<unsigned long long> {
|
|
|
|
using Type = unsigned long long;
|
|
|
|
};
|
|
|
|
template<>
|
|
|
|
struct __MakeUnsigned<char> {
|
|
|
|
using Type = unsigned char;
|
|
|
|
};
|
|
|
|
template<>
|
|
|
|
struct __MakeUnsigned<char8_t> {
|
|
|
|
using Type = char8_t;
|
|
|
|
};
|
|
|
|
template<>
|
|
|
|
struct __MakeUnsigned<char16_t> {
|
|
|
|
using Type = char16_t;
|
|
|
|
};
|
|
|
|
template<>
|
|
|
|
struct __MakeUnsigned<char32_t> {
|
|
|
|
using Type = char32_t;
|
|
|
|
};
|
|
|
|
template<>
|
|
|
|
struct __MakeUnsigned<bool> {
|
|
|
|
using Type = bool;
|
|
|
|
};
|
2023-04-14 17:44:17 +03:00
|
|
|
#if ARCH(AARCH64)
|
2022-10-12 23:00:21 +03:00
|
|
|
template<>
|
|
|
|
struct __MakeUnsigned<wchar_t> {
|
|
|
|
using Type = wchar_t;
|
|
|
|
};
|
|
|
|
#endif
|
2021-04-10 16:59:06 +03:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
using MakeUnsigned = typename __MakeUnsigned<T>::Type;
|
|
|
|
|
2021-07-22 17:31:05 +03:00
|
|
|
template<typename T>
|
|
|
|
auto declval() -> T;
|
|
|
|
|
|
|
|
template<typename...>
|
|
|
|
struct __CommonType;
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct __CommonType<T> {
|
|
|
|
using Type = T;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T1, typename T2>
|
|
|
|
struct __CommonType<T1, T2> {
|
|
|
|
using Type = decltype(true ? declval<T1>() : declval<T2>());
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T1, typename T2, typename... Ts>
|
|
|
|
struct __CommonType<T1, T2, Ts...> {
|
|
|
|
using Type = typename __CommonType<typename __CommonType<T1, T2>::Type, Ts...>::Type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename... Ts>
|
|
|
|
using CommonType = typename __CommonType<Ts...>::Type;
|
|
|
|
|
2021-04-10 16:59:06 +03:00
|
|
|
template<class T>
|
|
|
|
inline constexpr bool IsVoid = IsSame<void, RemoveCV<T>>;
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
inline constexpr bool IsConst = false;
|
|
|
|
|
|
|
|
template<class T>
|
2022-10-17 01:06:11 +03:00
|
|
|
inline constexpr bool IsConst<T const> = true;
|
2021-04-10 16:59:06 +03:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool IsEnum = __is_enum(T);
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool IsUnion = __is_union(T);
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool IsClass = __is_class(T);
|
|
|
|
|
|
|
|
template<typename Base, typename Derived>
|
|
|
|
inline constexpr bool IsBaseOf = __is_base_of(Base, Derived);
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool __IsIntegral = false;
|
|
|
|
|
|
|
|
template<>
|
|
|
|
inline constexpr bool __IsIntegral<bool> = true;
|
|
|
|
template<>
|
|
|
|
inline constexpr bool __IsIntegral<unsigned char> = true;
|
|
|
|
template<>
|
|
|
|
inline constexpr bool __IsIntegral<char8_t> = true;
|
|
|
|
template<>
|
|
|
|
inline constexpr bool __IsIntegral<char16_t> = true;
|
|
|
|
template<>
|
|
|
|
inline constexpr bool __IsIntegral<char32_t> = true;
|
|
|
|
template<>
|
|
|
|
inline constexpr bool __IsIntegral<unsigned short> = true;
|
|
|
|
template<>
|
|
|
|
inline constexpr bool __IsIntegral<unsigned int> = true;
|
|
|
|
template<>
|
|
|
|
inline constexpr bool __IsIntegral<unsigned long> = true;
|
|
|
|
template<>
|
|
|
|
inline constexpr bool __IsIntegral<unsigned long long> = true;
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool IsIntegral = __IsIntegral<MakeUnsigned<RemoveCV<T>>>;
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool __IsFloatingPoint = false;
|
|
|
|
template<>
|
|
|
|
inline constexpr bool __IsFloatingPoint<float> = true;
|
|
|
|
template<>
|
|
|
|
inline constexpr bool __IsFloatingPoint<double> = true;
|
|
|
|
template<>
|
|
|
|
inline constexpr bool __IsFloatingPoint<long double> = true;
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool IsFloatingPoint = __IsFloatingPoint<RemoveCV<T>>;
|
|
|
|
|
|
|
|
template<typename ReferenceType, typename T>
|
|
|
|
using CopyConst = Conditional<IsConst<ReferenceType>, AddConst<T>, RemoveConst<T>>;
|
|
|
|
|
|
|
|
template<typename... Ts>
|
|
|
|
using Void = void;
|
|
|
|
|
|
|
|
template<typename... _Ignored>
|
|
|
|
constexpr auto DependentFalse = false;
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool IsSigned = IsSame<T, MakeSigned<T>>;
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool IsUnsigned = IsSame<T, MakeUnsigned<T>>;
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool IsArithmetic = IsIntegral<T> || IsFloatingPoint<T>;
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool IsFundamental = IsArithmetic<T> || IsVoid<T> || IsNullPointer<T>;
|
|
|
|
|
|
|
|
template<typename T, T... Ts>
|
|
|
|
struct IntegerSequence {
|
|
|
|
using Type = T;
|
2023-07-08 05:48:11 +03:00
|
|
|
static constexpr unsigned size() noexcept { return sizeof...(Ts); }
|
2021-04-10 16:59:06 +03:00
|
|
|
};
|
|
|
|
|
2024-02-09 02:52:03 +03:00
|
|
|
template<size_t... Indices>
|
|
|
|
using IndexSequence = IntegerSequence<size_t, Indices...>;
|
2021-04-10 16:59:06 +03:00
|
|
|
|
2023-06-27 08:48:39 +03:00
|
|
|
#if __has_builtin(__make_integer_seq)
|
|
|
|
template<typename T, T N>
|
|
|
|
using MakeIntegerSequence = __make_integer_seq<IntegerSequence, T, N>;
|
|
|
|
#elif __has_builtin(__integer_pack)
|
|
|
|
template<typename T, T N>
|
|
|
|
using MakeIntegerSequence = IntegerSequence<T, __integer_pack(N)...>;
|
|
|
|
#else
|
2021-04-10 16:59:06 +03:00
|
|
|
template<typename T, T N, T... Ts>
|
|
|
|
auto make_integer_sequence_impl()
|
|
|
|
{
|
|
|
|
if constexpr (N == 0)
|
|
|
|
return IntegerSequence<T, Ts...> {};
|
|
|
|
else
|
|
|
|
return make_integer_sequence_impl<T, N - 1, N - 1, Ts...>();
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T, T N>
|
|
|
|
using MakeIntegerSequence = decltype(make_integer_sequence_impl<T, N>());
|
2023-06-27 08:48:39 +03:00
|
|
|
#endif
|
2021-04-10 16:59:06 +03:00
|
|
|
|
2024-02-09 02:52:03 +03:00
|
|
|
template<size_t N>
|
|
|
|
using MakeIndexSequence = MakeIntegerSequence<size_t, N>;
|
2021-04-10 16:59:06 +03:00
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct __IdentityType {
|
|
|
|
using Type = T;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
using IdentityType = typename __IdentityType<T>::Type;
|
|
|
|
|
2021-07-02 18:15:59 +03:00
|
|
|
template<typename T, typename = void>
|
|
|
|
struct __AddReference {
|
|
|
|
using LvalueType = T;
|
|
|
|
using TvalueType = T;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
struct __AddReference<T, VoidType<T&>> {
|
|
|
|
using LvalueType = T&;
|
|
|
|
using RvalueType = T&&;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
using AddLvalueReference = typename __AddReference<T>::LvalueType;
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
using AddRvalueReference = typename __AddReference<T>::RvalueType;
|
|
|
|
|
2021-04-10 16:59:06 +03:00
|
|
|
template<class T>
|
|
|
|
requires(IsEnum<T>) using UnderlyingType = __underlying_type(T);
|
|
|
|
|
2021-09-05 10:55:16 +03:00
|
|
|
template<typename T, unsigned ExpectedSize, unsigned ActualSize>
|
|
|
|
struct __AssertSize : TrueType {
|
|
|
|
static_assert(ActualSize == ExpectedSize,
|
|
|
|
"actual size does not match expected size");
|
|
|
|
|
|
|
|
consteval explicit operator bool() const { return value; }
|
|
|
|
};
|
|
|
|
|
|
|
|
// Note: This type is useful, as the sizes will be visible in the
|
|
|
|
// compiler error messages, as they will be part of the
|
|
|
|
// template parameters. This is not possible with a
|
|
|
|
// static_assert on the sizeof a type.
|
|
|
|
template<typename T, unsigned ExpectedSize>
|
|
|
|
using AssertSize = __AssertSize<T, ExpectedSize, sizeof(T)>;
|
|
|
|
|
2021-10-20 21:11:24 +03:00
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool IsPOD = __is_pod(T);
|
|
|
|
|
2021-04-10 16:59:06 +03:00
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool IsTrivial = __is_trivial(T);
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool IsTriviallyCopyable = __is_trivially_copyable(T);
|
|
|
|
|
2021-07-01 11:21:14 +03:00
|
|
|
template<typename T, typename... Args>
|
|
|
|
inline constexpr bool IsConstructible = requires { ::new T(declval<Args>()...); };
|
|
|
|
|
2021-07-02 18:15:59 +03:00
|
|
|
template<typename T, typename... Args>
|
|
|
|
inline constexpr bool IsTriviallyConstructible = __is_trivially_constructible(T, Args...);
|
|
|
|
|
|
|
|
template<typename From, typename To>
|
|
|
|
inline constexpr bool IsConvertible = requires { declval<void (*)(To)>()(declval<From>()); };
|
|
|
|
|
|
|
|
template<typename T, typename U>
|
|
|
|
inline constexpr bool IsAssignable = requires { declval<T>() = declval<U>(); };
|
|
|
|
|
|
|
|
template<typename T, typename U>
|
|
|
|
inline constexpr bool IsTriviallyAssignable = __is_trivially_assignable(T, U);
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool IsDestructible = requires { declval<T>().~T(); };
|
|
|
|
|
|
|
|
template<typename T>
|
2022-10-04 22:04:13 +03:00
|
|
|
#if defined(AK_COMPILER_CLANG)
|
2021-07-02 18:15:59 +03:00
|
|
|
inline constexpr bool IsTriviallyDestructible = __is_trivially_destructible(T);
|
|
|
|
#else
|
|
|
|
inline constexpr bool IsTriviallyDestructible = __has_trivial_destructor(T) && IsDestructible<T>;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool IsCopyConstructible = IsConstructible<T, AddLvalueReference<AddConst<T>>>;
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool IsTriviallyCopyConstructible = IsTriviallyConstructible<T, AddLvalueReference<AddConst<T>>>;
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool IsCopyAssignable = IsAssignable<AddLvalueReference<T>, AddLvalueReference<AddConst<T>>>;
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool IsTriviallyCopyAssignable = IsTriviallyAssignable<AddLvalueReference<T>, AddLvalueReference<AddConst<T>>>;
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool IsMoveConstructible = IsConstructible<T, AddRvalueReference<T>>;
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool IsTriviallyMoveConstructible = IsTriviallyConstructible<T, AddRvalueReference<T>>;
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool IsMoveAssignable = IsAssignable<AddLvalueReference<T>, AddRvalueReference<T>>;
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool IsTriviallyMoveAssignable = IsTriviallyAssignable<AddLvalueReference<T>, AddRvalueReference<T>>;
|
2021-08-09 01:22:35 +03:00
|
|
|
|
|
|
|
template<typename T, template<typename...> typename U>
|
|
|
|
inline constexpr bool IsSpecializationOf = false;
|
|
|
|
|
|
|
|
template<template<typename...> typename U, typename... Us>
|
|
|
|
inline constexpr bool IsSpecializationOf<U<Us...>, U> = true;
|
|
|
|
|
2021-11-07 16:34:55 +03:00
|
|
|
template<typename T>
|
2022-10-01 17:10:03 +03:00
|
|
|
struct __Decay {
|
2022-11-14 21:25:18 +03:00
|
|
|
typedef RemoveCVReference<T> type;
|
2021-11-07 16:34:55 +03:00
|
|
|
};
|
|
|
|
template<typename T>
|
2022-10-01 17:10:03 +03:00
|
|
|
struct __Decay<T[]> {
|
2021-11-07 16:34:55 +03:00
|
|
|
typedef T* type;
|
|
|
|
};
|
|
|
|
template<typename T, decltype(sizeof(T)) N>
|
2022-10-01 17:10:03 +03:00
|
|
|
struct __Decay<T[N]> {
|
2021-11-07 16:34:55 +03:00
|
|
|
typedef T* type;
|
|
|
|
};
|
|
|
|
// FIXME: Function decay
|
|
|
|
template<typename T>
|
2022-10-01 17:10:03 +03:00
|
|
|
using Decay = typename __Decay<T>::type;
|
2021-11-07 16:34:55 +03:00
|
|
|
|
2021-11-08 17:02:04 +03:00
|
|
|
template<typename T, typename U>
|
2022-10-17 01:06:11 +03:00
|
|
|
inline constexpr bool IsPointerOfType = IsPointer<Decay<U>> && IsSame<T, RemoveCV<RemovePointer<Decay<U>>>>;
|
2021-11-07 16:50:41 +03:00
|
|
|
|
|
|
|
template<typename T, typename U>
|
|
|
|
inline constexpr bool IsHashCompatible = false;
|
|
|
|
template<typename T>
|
|
|
|
inline constexpr bool IsHashCompatible<T, T> = true;
|
|
|
|
|
2022-03-28 14:52:00 +03:00
|
|
|
template<typename T, typename... Ts>
|
|
|
|
inline constexpr bool IsOneOf = (IsSame<T, Ts> || ...);
|
|
|
|
|
2022-04-17 07:51:55 +03:00
|
|
|
template<typename T, typename U>
|
|
|
|
inline constexpr bool IsSameIgnoringCV = IsSame<RemoveCV<T>, RemoveCV<U>>;
|
|
|
|
|
|
|
|
template<typename T, typename... Ts>
|
|
|
|
inline constexpr bool IsOneOfIgnoringCV = (IsSameIgnoringCV<T, Ts> || ...);
|
|
|
|
|
2023-09-02 15:49:50 +03:00
|
|
|
template<typename...>
|
|
|
|
struct __InvokeResult { };
|
|
|
|
|
|
|
|
template<typename MethodDefBaseType, typename MethodType, typename InstanceType, typename... Args>
|
|
|
|
struct __InvokeResult<MethodType MethodDefBaseType::*, InstanceType, Args...> {
|
|
|
|
using type = decltype((
|
|
|
|
declval<InstanceType>()
|
|
|
|
.*declval<MethodType MethodDefBaseType::*>())(declval<Args>()...));
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename F, typename... Args>
|
|
|
|
struct __InvokeResult<F, Args...> {
|
|
|
|
using type = decltype((declval<F>())(declval<Args>()...));
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename F, typename... Args>
|
|
|
|
using InvokeResult = typename __InvokeResult<F, Args...>::type;
|
|
|
|
|
2024-01-26 12:41:45 +03:00
|
|
|
template<typename Callable>
|
|
|
|
struct EquivalentFunctionTypeImpl;
|
|
|
|
|
|
|
|
template<template<typename> class Function, typename T, typename... Args>
|
|
|
|
struct EquivalentFunctionTypeImpl<Function<T(Args...)>> {
|
|
|
|
using Type = T(Args...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T, typename... Args>
|
|
|
|
struct EquivalentFunctionTypeImpl<T(Args...)> {
|
|
|
|
using Type = T(Args...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T, typename... Args>
|
|
|
|
struct EquivalentFunctionTypeImpl<T (*)(Args...)> {
|
|
|
|
using Type = T(Args...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename L>
|
|
|
|
struct EquivalentFunctionTypeImpl {
|
|
|
|
using Type = typename EquivalentFunctionTypeImpl<decltype(&L::operator())>::Type;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T, typename C, typename... Args>
|
|
|
|
struct EquivalentFunctionTypeImpl<T (C::*)(Args...)> {
|
|
|
|
using Type = T(Args...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T, typename C, typename... Args>
|
|
|
|
struct EquivalentFunctionTypeImpl<T (C::*)(Args...) const> {
|
|
|
|
using Type = T(Args...);
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename Callable>
|
|
|
|
using EquivalentFunctionType = typename EquivalentFunctionTypeImpl<Callable>::Type;
|
|
|
|
|
2021-04-10 16:59:06 +03:00
|
|
|
}
|
2022-11-26 14:18:30 +03:00
|
|
|
|
2022-11-27 18:35:35 +03:00
|
|
|
#if !USING_AK_GLOBALLY
|
|
|
|
namespace AK {
|
|
|
|
#endif
|
2021-04-10 16:59:06 +03:00
|
|
|
using AK::Detail::AddConst;
|
2022-04-03 14:06:34 +03:00
|
|
|
using AK::Detail::AddConstToReferencedType;
|
2021-07-02 18:15:59 +03:00
|
|
|
using AK::Detail::AddLvalueReference;
|
|
|
|
using AK::Detail::AddRvalueReference;
|
2021-09-05 10:55:16 +03:00
|
|
|
using AK::Detail::AssertSize;
|
2021-07-22 17:31:05 +03:00
|
|
|
using AK::Detail::CommonType;
|
2021-04-10 16:59:06 +03:00
|
|
|
using AK::Detail::Conditional;
|
|
|
|
using AK::Detail::CopyConst;
|
AK+Everywhere: Disallow constructing Functions from incompatible types
Previously, AK::Function would accept _any_ callable type, and try to
call it when called, first with the given set of arguments, then with
zero arguments, and if all of those failed, it would simply not call the
function and **return a value-constructed Out type**.
This lead to many, many, many hard to debug situations when someone
forgot a `const` in their lambda argument types, and many cases of
people taking zero arguments in their lambdas to ignore them.
This commit reworks the Function interface to not include any such
surprising behaviour, if your function instance is not callable with
the declared argument set of the Function, it can simply not be
assigned to that Function instance, end of story.
2021-06-05 21:34:31 +03:00
|
|
|
using AK::Detail::declval;
|
2021-04-10 16:59:06 +03:00
|
|
|
using AK::Detail::DependentFalse;
|
2024-01-26 12:41:45 +03:00
|
|
|
using AK::Detail::EquivalentFunctionType;
|
2021-04-10 16:59:06 +03:00
|
|
|
using AK::Detail::FalseType;
|
|
|
|
using AK::Detail::IdentityType;
|
|
|
|
using AK::Detail::IndexSequence;
|
|
|
|
using AK::Detail::IntegerSequence;
|
2023-09-02 15:49:50 +03:00
|
|
|
using AK::Detail::InvokeResult;
|
2021-04-10 16:59:06 +03:00
|
|
|
using AK::Detail::IsArithmetic;
|
2021-07-02 18:15:59 +03:00
|
|
|
using AK::Detail::IsAssignable;
|
2021-04-10 16:59:06 +03:00
|
|
|
using AK::Detail::IsBaseOf;
|
|
|
|
using AK::Detail::IsClass;
|
|
|
|
using AK::Detail::IsConst;
|
2021-07-01 11:21:14 +03:00
|
|
|
using AK::Detail::IsConstructible;
|
2021-07-02 18:15:59 +03:00
|
|
|
using AK::Detail::IsConvertible;
|
|
|
|
using AK::Detail::IsCopyAssignable;
|
|
|
|
using AK::Detail::IsCopyConstructible;
|
|
|
|
using AK::Detail::IsDestructible;
|
2021-04-10 16:59:06 +03:00
|
|
|
using AK::Detail::IsEnum;
|
|
|
|
using AK::Detail::IsFloatingPoint;
|
|
|
|
using AK::Detail::IsFunction;
|
|
|
|
using AK::Detail::IsFundamental;
|
2021-11-07 16:50:41 +03:00
|
|
|
using AK::Detail::IsHashCompatible;
|
2021-04-10 16:59:06 +03:00
|
|
|
using AK::Detail::IsIntegral;
|
|
|
|
using AK::Detail::IsLvalueReference;
|
2021-07-02 18:15:59 +03:00
|
|
|
using AK::Detail::IsMoveAssignable;
|
|
|
|
using AK::Detail::IsMoveConstructible;
|
2021-04-10 16:59:06 +03:00
|
|
|
using AK::Detail::IsNullPointer;
|
2022-03-28 14:52:00 +03:00
|
|
|
using AK::Detail::IsOneOf;
|
2022-04-17 07:51:55 +03:00
|
|
|
using AK::Detail::IsOneOfIgnoringCV;
|
2021-10-20 21:11:24 +03:00
|
|
|
using AK::Detail::IsPOD;
|
2021-04-10 16:59:06 +03:00
|
|
|
using AK::Detail::IsPointer;
|
|
|
|
using AK::Detail::IsRvalueReference;
|
|
|
|
using AK::Detail::IsSame;
|
2022-04-17 07:51:55 +03:00
|
|
|
using AK::Detail::IsSameIgnoringCV;
|
2021-04-10 16:59:06 +03:00
|
|
|
using AK::Detail::IsSigned;
|
2021-08-09 01:22:35 +03:00
|
|
|
using AK::Detail::IsSpecializationOf;
|
2021-04-10 16:59:06 +03:00
|
|
|
using AK::Detail::IsTrivial;
|
2021-07-02 18:15:59 +03:00
|
|
|
using AK::Detail::IsTriviallyAssignable;
|
|
|
|
using AK::Detail::IsTriviallyConstructible;
|
2021-04-10 16:59:06 +03:00
|
|
|
using AK::Detail::IsTriviallyCopyable;
|
2021-07-02 18:15:59 +03:00
|
|
|
using AK::Detail::IsTriviallyCopyAssignable;
|
|
|
|
using AK::Detail::IsTriviallyCopyConstructible;
|
|
|
|
using AK::Detail::IsTriviallyDestructible;
|
|
|
|
using AK::Detail::IsTriviallyMoveAssignable;
|
|
|
|
using AK::Detail::IsTriviallyMoveConstructible;
|
2021-04-10 16:59:06 +03:00
|
|
|
using AK::Detail::IsUnion;
|
|
|
|
using AK::Detail::IsUnsigned;
|
|
|
|
using AK::Detail::IsVoid;
|
|
|
|
using AK::Detail::MakeIndexSequence;
|
|
|
|
using AK::Detail::MakeIntegerSequence;
|
|
|
|
using AK::Detail::MakeSigned;
|
|
|
|
using AK::Detail::MakeUnsigned;
|
|
|
|
using AK::Detail::RemoveConst;
|
|
|
|
using AK::Detail::RemoveCV;
|
2021-06-27 22:22:36 +03:00
|
|
|
using AK::Detail::RemoveCVReference;
|
2021-04-10 16:59:06 +03:00
|
|
|
using AK::Detail::RemovePointer;
|
|
|
|
using AK::Detail::RemoveReference;
|
|
|
|
using AK::Detail::RemoveVolatile;
|
|
|
|
using AK::Detail::TrueType;
|
|
|
|
using AK::Detail::UnderlyingType;
|
|
|
|
using AK::Detail::Void;
|
2022-11-27 18:35:35 +03:00
|
|
|
#if !USING_AK_GLOBALLY
|
|
|
|
}
|
2022-11-26 14:18:30 +03:00
|
|
|
#endif
|