/* * Copyright (c) 2018-2021, Andreas Kling * Copyright (c) 2021, Ali Mohammad Pur * Copyright (c) 2021, Daniel Bertalan * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include namespace AK::Detail { template 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; using TrueType = IntegralConstant; template using AddConst = T const; template struct __AddConstToReferencedType { using Type = T; }; template struct __AddConstToReferencedType { using Type = AddConst&; }; template struct __AddConstToReferencedType { using Type = AddConst&&; }; template using AddConstToReferencedType = typename __AddConstToReferencedType::Type; template struct __RemoveConst { using Type = T; }; template struct __RemoveConst { using Type = T; }; template using RemoveConst = typename __RemoveConst::Type; template struct __RemoveVolatile { using Type = T; }; template struct __RemoveVolatile { using Type = T; }; template using RemoveVolatile = typename __RemoveVolatile::Type; template using RemoveCV = RemoveVolatile>; template using VoidType = void; template inline constexpr bool IsLvalueReference = false; template inline constexpr bool IsLvalueReference = true; template inline constexpr bool __IsPointerHelper = false; template inline constexpr bool __IsPointerHelper = true; template inline constexpr bool IsPointer = __IsPointerHelper>; template inline constexpr bool IsFunction = false; template inline constexpr bool IsFunction = true; template inline constexpr bool IsFunction = true; template inline constexpr bool IsFunction = true; template inline constexpr bool IsFunction = true; template inline constexpr bool IsFunction = true; template inline constexpr bool IsFunction = true; template inline constexpr bool IsFunction = true; template inline constexpr bool IsFunction = true; template inline constexpr bool IsFunction = true; template inline constexpr bool IsFunction = true; template inline constexpr bool IsFunction = true; template inline constexpr bool IsFunction = true; template inline constexpr bool IsFunction = true; template inline constexpr bool IsFunction = true; template inline constexpr bool IsFunction = true; template inline constexpr bool IsFunction = true; template inline constexpr bool IsFunction = true; template inline constexpr bool IsFunction = true; template inline constexpr bool IsFunction = true; template inline constexpr bool IsFunction = true; template inline constexpr bool IsFunction = true; template inline constexpr bool IsFunction = true; template inline constexpr bool IsFunction = true; template inline constexpr bool IsFunction = true; template inline constexpr bool IsRvalueReference = false; template inline constexpr bool IsRvalueReference = true; template struct __RemovePointer { using Type = T; }; template struct __RemovePointer { using Type = T; }; template struct __RemovePointer { using Type = T; }; template struct __RemovePointer { using Type = T; }; template struct __RemovePointer { using Type = T; }; template using RemovePointer = typename __RemovePointer::Type; template inline constexpr bool IsSame = false; template inline constexpr bool IsSame = true; template inline constexpr bool IsNullPointer = IsSame>; template struct __RemoveReference { using Type = T; }; template struct __RemoveReference { using Type = T; }; template struct __RemoveReference { using Type = T; }; template using RemoveReference = typename __RemoveReference::Type; template using RemoveCVReference = RemoveCV>; template struct __MakeUnsigned { using Type = void; }; template<> struct __MakeUnsigned { using Type = unsigned char; }; template<> struct __MakeUnsigned { using Type = unsigned short; }; template<> struct __MakeUnsigned { using Type = unsigned int; }; template<> struct __MakeUnsigned { using Type = unsigned long; }; template<> struct __MakeUnsigned { using Type = unsigned long long; }; template<> struct __MakeUnsigned { using Type = unsigned char; }; template<> struct __MakeUnsigned { using Type = unsigned short; }; template<> struct __MakeUnsigned { using Type = unsigned int; }; template<> struct __MakeUnsigned { using Type = unsigned long; }; template<> struct __MakeUnsigned { using Type = unsigned long long; }; template<> struct __MakeUnsigned { using Type = unsigned char; }; template<> struct __MakeUnsigned { using Type = char8_t; }; template<> struct __MakeUnsigned { using Type = char16_t; }; template<> struct __MakeUnsigned { using Type = char32_t; }; template<> struct __MakeUnsigned { using Type = bool; }; #if ARCH(AARCH64) template<> struct __MakeUnsigned { using Type = wchar_t; }; #endif template using MakeUnsigned = typename __MakeUnsigned::Type; template auto declval() -> T; template struct __CommonType; template struct __CommonType { using Type = T; }; template struct __CommonType { using Type = decltype(true ? declval() : declval()); }; template struct __CommonType { using Type = typename __CommonType::Type, Ts...>::Type; }; template using CommonType = typename __CommonType::Type; template inline constexpr bool IsVoid = IsSame>; template inline constexpr bool IsConst = false; template inline constexpr bool IsConst = true; template inline constexpr bool IsEnum = __is_enum(T); template inline constexpr bool IsUnion = __is_union(T); template inline constexpr bool IsClass = __is_class(T); template inline constexpr bool IsBaseOf = __is_base_of(Base, Derived); template inline constexpr bool __IsIntegral = false; template<> inline constexpr bool __IsIntegral = true; template<> inline constexpr bool __IsIntegral = true; template<> inline constexpr bool __IsIntegral = true; template<> inline constexpr bool __IsIntegral = true; template<> inline constexpr bool __IsIntegral = true; template<> inline constexpr bool __IsIntegral = true; template<> inline constexpr bool __IsIntegral = true; template<> inline constexpr bool __IsIntegral = true; template<> inline constexpr bool __IsIntegral = true; template inline constexpr bool IsIntegral = __IsIntegral>>; template inline constexpr bool __IsFloatingPoint = false; template<> inline constexpr bool __IsFloatingPoint = true; template<> inline constexpr bool __IsFloatingPoint = true; template<> inline constexpr bool __IsFloatingPoint = true; template<> inline constexpr bool __IsFloatingPoint = true; template inline constexpr bool IsFloatingPoint = __IsFloatingPoint>; template using CopyConst = Conditional, AddConst, RemoveConst>; template using Void = void; template constexpr auto DependentFalse = false; template inline constexpr bool IsSigned = IsSame>; template inline constexpr bool IsUnsigned = IsSame>; template inline constexpr bool IsArithmetic = IsIntegral || IsFloatingPoint; template inline constexpr bool IsFundamental = IsArithmetic || IsVoid || IsNullPointer; template struct IntegerSequence { using Type = T; static constexpr unsigned size() noexcept { return sizeof...(Ts); } }; template using IndexSequence = IntegerSequence; #if __has_builtin(__make_integer_seq) template using MakeIntegerSequence = __make_integer_seq; #elif __has_builtin(__integer_pack) template using MakeIntegerSequence = IntegerSequence; #else template auto make_integer_sequence_impl() { if constexpr (N == 0) return IntegerSequence {}; else return make_integer_sequence_impl(); } template using MakeIntegerSequence = decltype(make_integer_sequence_impl()); #endif template using MakeIndexSequence = MakeIntegerSequence; template struct __IdentityType { using Type = T; }; template using IdentityType = typename __IdentityType::Type; template struct __AddReference { using LvalueType = T; using TvalueType = T; }; template struct __AddReference> { using LvalueType = T&; using RvalueType = T&&; }; template using AddLvalueReference = typename __AddReference::LvalueType; template using AddRvalueReference = typename __AddReference::RvalueType; template requires(IsEnum) using UnderlyingType = __underlying_type(T); template 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 using AssertSize = __AssertSize; template inline constexpr bool IsPOD = __is_pod(T); template class Base, typename Derived> struct __IsTemplateBaseOf { template static TrueType test(Base const*); static FalseType test(...); using type = decltype(test(declval())); }; template class Base, typename Derived> inline constexpr bool IsTemplateBaseOf = __IsTemplateBaseOf::type::value; template inline constexpr bool IsTrivial = __is_trivial(T); template inline constexpr bool IsTriviallyCopyable = __is_trivially_copyable(T); template inline constexpr bool IsConstructible = requires { ::new T(declval()...); }; template inline constexpr bool IsTriviallyConstructible = __is_trivially_constructible(T, Args...); template inline constexpr bool IsConvertible = requires { declval()(declval()); }; template inline constexpr bool IsAssignable = requires { declval() = declval(); }; template inline constexpr bool IsTriviallyAssignable = __is_trivially_assignable(T, U); template inline constexpr bool IsDestructible = requires { declval().~T(); }; template #if defined(AK_COMPILER_CLANG) inline constexpr bool IsTriviallyDestructible = __is_trivially_destructible(T); #else inline constexpr bool IsTriviallyDestructible = __has_trivial_destructor(T) && IsDestructible; #endif template inline constexpr bool IsCopyConstructible = IsConstructible>>; template inline constexpr bool IsTriviallyCopyConstructible = IsTriviallyConstructible>>; template inline constexpr bool IsCopyAssignable = IsAssignable, AddLvalueReference>>; template inline constexpr bool IsTriviallyCopyAssignable = IsTriviallyAssignable, AddLvalueReference>>; template inline constexpr bool IsMoveConstructible = IsConstructible>; template inline constexpr bool IsTriviallyMoveConstructible = IsTriviallyConstructible>; template inline constexpr bool IsMoveAssignable = IsAssignable, AddRvalueReference>; template inline constexpr bool IsTriviallyMoveAssignable = IsTriviallyAssignable, AddRvalueReference>; template typename U> inline constexpr bool IsSpecializationOf = false; template typename U, typename... Us> inline constexpr bool IsSpecializationOf, U> = true; template struct __Decay { typedef RemoveCVReference type; }; template struct __Decay { typedef T* type; }; template struct __Decay { typedef T* type; }; // FIXME: Function decay template using Decay = typename __Decay::type; template inline constexpr bool IsPointerOfType = IsPointer> && IsSame>>>; template inline constexpr bool IsHashCompatible = false; template inline constexpr bool IsHashCompatible = true; template inline constexpr bool IsOneOf = (IsSame || ...); template inline constexpr bool IsSameIgnoringCV = IsSame, RemoveCV>; template inline constexpr bool IsOneOfIgnoringCV = (IsSameIgnoringCV || ...); template struct __InvokeResult { }; template struct __InvokeResult { using type = decltype(( declval() .*declval())(declval()...)); }; template struct __InvokeResult { using type = decltype((declval())(declval()...)); }; template using InvokeResult = typename __InvokeResult::type; template struct EquivalentFunctionTypeImpl; template class Function, typename T, typename... Args> struct EquivalentFunctionTypeImpl> { using Type = T(Args...); }; template struct EquivalentFunctionTypeImpl { using Type = T(Args...); }; template struct EquivalentFunctionTypeImpl { using Type = T(Args...); }; template struct EquivalentFunctionTypeImpl { using Type = typename EquivalentFunctionTypeImpl::Type; }; template struct EquivalentFunctionTypeImpl { using Type = T(Args...); }; template struct EquivalentFunctionTypeImpl { using Type = T(Args...); }; template using EquivalentFunctionType = typename EquivalentFunctionTypeImpl::Type; } #if !USING_AK_GLOBALLY namespace AK { #endif using AK::Detail::AddConst; using AK::Detail::AddConstToReferencedType; using AK::Detail::AddLvalueReference; using AK::Detail::AddRvalueReference; using AK::Detail::AssertSize; using AK::Detail::CommonType; using AK::Detail::Conditional; using AK::Detail::CopyConst; using AK::Detail::declval; using AK::Detail::DependentFalse; using AK::Detail::EquivalentFunctionType; using AK::Detail::FalseType; using AK::Detail::IdentityType; using AK::Detail::IndexSequence; using AK::Detail::IntegerSequence; using AK::Detail::InvokeResult; using AK::Detail::IsArithmetic; using AK::Detail::IsAssignable; using AK::Detail::IsBaseOf; using AK::Detail::IsClass; using AK::Detail::IsConst; using AK::Detail::IsConstructible; using AK::Detail::IsConvertible; using AK::Detail::IsCopyAssignable; using AK::Detail::IsCopyConstructible; using AK::Detail::IsDestructible; using AK::Detail::IsEnum; using AK::Detail::IsFloatingPoint; using AK::Detail::IsFunction; using AK::Detail::IsFundamental; using AK::Detail::IsHashCompatible; using AK::Detail::IsIntegral; using AK::Detail::IsLvalueReference; using AK::Detail::IsMoveAssignable; using AK::Detail::IsMoveConstructible; using AK::Detail::IsNullPointer; using AK::Detail::IsOneOf; using AK::Detail::IsOneOfIgnoringCV; using AK::Detail::IsPOD; using AK::Detail::IsPointer; using AK::Detail::IsRvalueReference; using AK::Detail::IsSame; using AK::Detail::IsSameIgnoringCV; using AK::Detail::IsSigned; using AK::Detail::IsSpecializationOf; using AK::Detail::IsTemplateBaseOf; using AK::Detail::IsTrivial; using AK::Detail::IsTriviallyAssignable; using AK::Detail::IsTriviallyConstructible; using AK::Detail::IsTriviallyCopyable; using AK::Detail::IsTriviallyCopyAssignable; using AK::Detail::IsTriviallyCopyConstructible; using AK::Detail::IsTriviallyDestructible; using AK::Detail::IsTriviallyMoveAssignable; using AK::Detail::IsTriviallyMoveConstructible; 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; using AK::Detail::RemoveCVReference; using AK::Detail::RemovePointer; using AK::Detail::RemoveReference; using AK::Detail::RemoveVolatile; using AK::Detail::TrueType; using AK::Detail::UnderlyingType; using AK::Detail::Void; #if !USING_AK_GLOBALLY } #endif