mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 09:14:58 +00:00
AK+Everywhere: Make StdLibExtras templates less wrapper-y
This commit makes the user-facing StdLibExtras templates and utilities arguably more nice-looking by removing the need to reach into the wrapper structs generated by them to get the value/type needed. The C++ standard library had to invent `_v` and `_t` variants (likely because of backwards compat), but we don't need to cater to any codebase except our own, so might as well have good things for free. :^)
This commit is contained in:
parent
d8d16dea95
commit
a6e4482080
41 changed files with 650 additions and 662 deletions
|
@ -26,6 +26,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <AK/StdLibExtraDetails.h>
|
||||
|
||||
#include <AK/Assertions.h>
|
||||
|
||||
constexpr unsigned round_up_to_power_of_two(unsigned value, unsigned power_of_two)
|
||||
|
@ -52,6 +54,19 @@ namespace AK {
|
|||
template<typename T>
|
||||
auto declval() -> T;
|
||||
|
||||
template<class T>
|
||||
constexpr T&& forward(RemoveReference<T>& param)
|
||||
{
|
||||
return static_cast<T&&>(param);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
constexpr T&& forward(RemoveReference<T>&& param) noexcept
|
||||
{
|
||||
static_assert(!IsLvalueReference<T>, "Can't forward an rvalue as an lvalue.");
|
||||
return static_cast<T&&>(param);
|
||||
}
|
||||
|
||||
template<typename T, typename SizeType = decltype(sizeof(T)), SizeType N>
|
||||
constexpr SizeType array_size(T (&)[N])
|
||||
{
|
||||
|
@ -99,359 +114,6 @@ inline void swap(T& a, U& b)
|
|||
b = move(tmp);
|
||||
}
|
||||
|
||||
template<bool B, class T = void>
|
||||
struct EnableIf {
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct EnableIf<true, T> {
|
||||
using Type = T;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct AddConst {
|
||||
using Type = const T;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct RemoveConst {
|
||||
using Type = T;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct RemoveConst<const T> {
|
||||
using Type = T;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct RemoveVolatile {
|
||||
using Type = T;
|
||||
};
|
||||
template<class T>
|
||||
struct RemoveVolatile<volatile T> {
|
||||
using Type = T;
|
||||
};
|
||||
template<class T>
|
||||
struct RemoveCV {
|
||||
using Type = typename RemoveVolatile<typename RemoveConst<T>::Type>::Type;
|
||||
};
|
||||
|
||||
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<typename...>
|
||||
using VoidType = void;
|
||||
|
||||
template<class T>
|
||||
struct IsLvalueReference : FalseType {
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct IsLvalueReference<T&> : TrueType {
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct __IsPointerHelper : FalseType {
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct __IsPointerHelper<T*> : TrueType {
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct IsPointer : __IsPointerHelper<typename RemoveCV<T>::Type> {
|
||||
};
|
||||
|
||||
template<class>
|
||||
struct IsFunction : FalseType {
|
||||
};
|
||||
|
||||
template<class Ret, class... Args>
|
||||
struct IsFunction<Ret(Args...)> : TrueType {
|
||||
};
|
||||
template<class Ret, class... Args>
|
||||
struct IsFunction<Ret(Args..., ...)> : TrueType {
|
||||
};
|
||||
template<class Ret, class... Args>
|
||||
struct IsFunction<Ret(Args...) const> : TrueType {
|
||||
};
|
||||
template<class Ret, class... Args>
|
||||
struct IsFunction<Ret(Args..., ...) const> : TrueType {
|
||||
};
|
||||
template<class Ret, class... Args>
|
||||
struct IsFunction<Ret(Args...) volatile> : TrueType {
|
||||
};
|
||||
template<class Ret, class... Args>
|
||||
struct IsFunction<Ret(Args..., ...) volatile> : TrueType {
|
||||
};
|
||||
template<class Ret, class... Args>
|
||||
struct IsFunction<Ret(Args...) const volatile> : TrueType {
|
||||
};
|
||||
template<class Ret, class... Args>
|
||||
struct IsFunction<Ret(Args..., ...) const volatile> : TrueType {
|
||||
};
|
||||
|
||||
template<class Ret, class... Args>
|
||||
struct IsFunction<Ret(Args...)&> : TrueType {
|
||||
};
|
||||
template<class Ret, class... Args>
|
||||
struct IsFunction<Ret(Args..., ...)&> : TrueType {
|
||||
};
|
||||
template<class Ret, class... Args>
|
||||
struct IsFunction<Ret(Args...) const&> : TrueType {
|
||||
};
|
||||
template<class Ret, class... Args>
|
||||
struct IsFunction<Ret(Args..., ...) const&> : TrueType {
|
||||
};
|
||||
template<class Ret, class... Args>
|
||||
struct IsFunction<Ret(Args...) volatile&> : TrueType {
|
||||
};
|
||||
template<class Ret, class... Args>
|
||||
struct IsFunction<Ret(Args..., ...) volatile&> : TrueType {
|
||||
};
|
||||
template<class Ret, class... Args>
|
||||
struct IsFunction<Ret(Args...) const volatile&> : TrueType {
|
||||
};
|
||||
template<class Ret, class... Args>
|
||||
struct IsFunction<Ret(Args..., ...) const volatile&> : TrueType {
|
||||
};
|
||||
|
||||
template<class Ret, class... Args>
|
||||
struct IsFunction<Ret(Args...) &&> : TrueType {
|
||||
};
|
||||
template<class Ret, class... Args>
|
||||
struct IsFunction<Ret(Args..., ...) &&> : TrueType {
|
||||
};
|
||||
template<class Ret, class... Args>
|
||||
struct IsFunction<Ret(Args...) const&&> : TrueType {
|
||||
};
|
||||
template<class Ret, class... Args>
|
||||
struct IsFunction<Ret(Args..., ...) const&&> : TrueType {
|
||||
};
|
||||
template<class Ret, class... Args>
|
||||
struct IsFunction<Ret(Args...) volatile&&> : TrueType {
|
||||
};
|
||||
template<class Ret, class... Args>
|
||||
struct IsFunction<Ret(Args..., ...) volatile&&> : TrueType {
|
||||
};
|
||||
template<class Ret, class... Args>
|
||||
struct IsFunction<Ret(Args...) const volatile&&> : TrueType {
|
||||
};
|
||||
template<class Ret, class... Args>
|
||||
struct IsFunction<Ret(Args..., ...) const volatile&&> : TrueType {
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct IsRvalueReference : FalseType {
|
||||
};
|
||||
template<class T>
|
||||
struct IsRvalueReference<T&&> : TrueType {
|
||||
};
|
||||
|
||||
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, typename U>
|
||||
struct IsSame {
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct IsSame<T, T> {
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
template<bool condition, class TrueType, class FalseType>
|
||||
struct Conditional {
|
||||
using Type = TrueType;
|
||||
};
|
||||
|
||||
template<class TrueType, class FalseType>
|
||||
struct Conditional<false, TrueType, FalseType> {
|
||||
using Type = FalseType;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct IsNullPointer : IsSame<decltype(nullptr), typename RemoveCV<T>::Type> {
|
||||
};
|
||||
|
||||
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<class T>
|
||||
constexpr T&& forward(typename RemoveReference<T>::Type& param)
|
||||
{
|
||||
return static_cast<T&&>(param);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
constexpr T&& forward(typename RemoveReference<T>::Type&& param) noexcept
|
||||
{
|
||||
static_assert(!IsLvalueReference<T>::value, "Can't forward an rvalue as an lvalue.");
|
||||
return static_cast<T&&>(param);
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct MakeSigned {
|
||||
};
|
||||
template<>
|
||||
struct MakeSigned<signed char> {
|
||||
using Type = signed char;
|
||||
};
|
||||
template<>
|
||||
struct MakeSigned<short> {
|
||||
using Type = short;
|
||||
};
|
||||
template<>
|
||||
struct MakeSigned<int> {
|
||||
using Type = int;
|
||||
};
|
||||
template<>
|
||||
struct MakeSigned<long> {
|
||||
using Type = long;
|
||||
};
|
||||
template<>
|
||||
struct MakeSigned<long long> {
|
||||
using Type = long long;
|
||||
};
|
||||
template<>
|
||||
struct MakeSigned<unsigned char> {
|
||||
using Type = char;
|
||||
};
|
||||
template<>
|
||||
struct MakeSigned<unsigned short> {
|
||||
using Type = short;
|
||||
};
|
||||
template<>
|
||||
struct MakeSigned<unsigned int> {
|
||||
using Type = int;
|
||||
};
|
||||
template<>
|
||||
struct MakeSigned<unsigned long> {
|
||||
using Type = long;
|
||||
};
|
||||
template<>
|
||||
struct MakeSigned<unsigned long long> {
|
||||
using Type = long long;
|
||||
};
|
||||
template<>
|
||||
struct MakeSigned<char> {
|
||||
using Type = signed char;
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct IsVoid : IsSame<void, typename RemoveCV<T>::Type> {
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct IsConst : FalseType {
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct IsConst<const T> : TrueType {
|
||||
};
|
||||
|
||||
template<typename T, typename U = T>
|
||||
constexpr T exchange(T& slot, U&& value)
|
||||
{
|
||||
|
@ -460,183 +122,14 @@ constexpr T exchange(T& slot, U&& value)
|
|||
return old_value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct IsEnum : public IntegralConstant<bool, __is_enum(T)> {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct IsUnion : public IntegralConstant<bool, __is_union(T)> {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct IsClass : public IntegralConstant<bool, __is_class(T)> {
|
||||
};
|
||||
|
||||
template<typename Base, typename Derived>
|
||||
struct IsBaseOf : public IntegralConstant<bool, __is_base_of(Base, Derived)> {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
constexpr bool is_trivial()
|
||||
{
|
||||
return __is_trivial(T);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool is_trivially_copyable()
|
||||
{
|
||||
return __is_trivially_copyable(T);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct __IsIntegral : FalseType {
|
||||
};
|
||||
template<>
|
||||
struct __IsIntegral<bool> : TrueType {
|
||||
};
|
||||
template<>
|
||||
struct __IsIntegral<unsigned char> : TrueType {
|
||||
};
|
||||
template<>
|
||||
struct __IsIntegral<char8_t> : TrueType {
|
||||
};
|
||||
template<>
|
||||
struct __IsIntegral<char16_t> : TrueType {
|
||||
};
|
||||
template<>
|
||||
struct __IsIntegral<char32_t> : TrueType {
|
||||
};
|
||||
template<>
|
||||
struct __IsIntegral<unsigned short> : TrueType {
|
||||
};
|
||||
template<>
|
||||
struct __IsIntegral<unsigned int> : TrueType {
|
||||
};
|
||||
template<>
|
||||
struct __IsIntegral<unsigned long> : TrueType {
|
||||
};
|
||||
template<>
|
||||
struct __IsIntegral<unsigned long long> : TrueType {
|
||||
};
|
||||
template<typename T>
|
||||
using IsIntegral = __IsIntegral<typename MakeUnsigned<typename RemoveCV<T>::Type>::Type>;
|
||||
|
||||
template<typename T>
|
||||
struct __IsFloatingPoint : FalseType {
|
||||
};
|
||||
template<>
|
||||
struct __IsFloatingPoint<float> : TrueType {
|
||||
};
|
||||
template<>
|
||||
struct __IsFloatingPoint<double> : TrueType {
|
||||
};
|
||||
template<>
|
||||
struct __IsFloatingPoint<long double> : TrueType {
|
||||
};
|
||||
template<typename T>
|
||||
using IsFloatingPoint = __IsFloatingPoint<typename RemoveCV<T>::Type>;
|
||||
|
||||
template<typename ReferenceType, typename T>
|
||||
using CopyConst =
|
||||
typename Conditional<IsConst<ReferenceType>::value, typename AddConst<T>::Type, typename RemoveConst<T>::Type>::Type;
|
||||
|
||||
template<typename... Ts>
|
||||
using Void = void;
|
||||
|
||||
template<typename... _Ignored>
|
||||
constexpr auto DependentFalse = false;
|
||||
|
||||
template<typename T>
|
||||
using IsSigned = IsSame<T, typename MakeSigned<T>::Type>;
|
||||
|
||||
template<typename T>
|
||||
using IsUnsigned = IsSame<T, typename MakeUnsigned<T>::Type>;
|
||||
|
||||
template<typename T>
|
||||
using IsArithmetic = IntegralConstant<bool, IsIntegral<T>::value || IsFloatingPoint<T>::value>;
|
||||
|
||||
template<typename T>
|
||||
using IsFundamental = IntegralConstant<bool, IsArithmetic<T>::value || IsVoid<T>::value || IsNullPointer<T>::value>;
|
||||
|
||||
template<typename T, T... Ts>
|
||||
struct IntegerSequence {
|
||||
using Type = T;
|
||||
static constexpr unsigned size() noexcept { return sizeof...(Ts); };
|
||||
};
|
||||
|
||||
template<unsigned... Indices>
|
||||
using IndexSequence = IntegerSequence<unsigned, Indices...>;
|
||||
|
||||
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>());
|
||||
|
||||
template<unsigned N>
|
||||
using MakeIndexSequence = MakeIntegerSequence<unsigned, N>;
|
||||
|
||||
template<typename T>
|
||||
struct IdentityType {
|
||||
using Type = T;
|
||||
};
|
||||
|
||||
template<class T, bool = IsEnum<T>::value>
|
||||
struct __UnderlyingType {
|
||||
using Type = __underlying_type(T);
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct __UnderlyingType<T, false> {
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct UnderlyingType : __UnderlyingType<T> {
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
using AK::AddConst;
|
||||
using AK::array_size;
|
||||
using AK::ceil_div;
|
||||
using AK::clamp;
|
||||
using AK::Conditional;
|
||||
using AK::declval;
|
||||
using AK::DependentFalse;
|
||||
using AK::exchange;
|
||||
using AK::forward;
|
||||
using AK::IdentityType;
|
||||
using AK::IndexSequence;
|
||||
using AK::IntegerSequence;
|
||||
using AK::is_trivial;
|
||||
using AK::is_trivially_copyable;
|
||||
using AK::IsArithmetic;
|
||||
using AK::IsBaseOf;
|
||||
using AK::IsClass;
|
||||
using AK::IsConst;
|
||||
using AK::IsEnum;
|
||||
using AK::IsFloatingPoint;
|
||||
using AK::IsFundamental;
|
||||
using AK::IsIntegral;
|
||||
using AK::IsNullPointer;
|
||||
using AK::IsSame;
|
||||
using AK::IsSigned;
|
||||
using AK::IsUnion;
|
||||
using AK::IsUnsigned;
|
||||
using AK::IsVoid;
|
||||
using AK::MakeIndexSequence;
|
||||
using AK::MakeIntegerSequence;
|
||||
using AK::MakeSigned;
|
||||
using AK::MakeUnsigned;
|
||||
using AK::max;
|
||||
using AK::min;
|
||||
using AK::RemoveConst;
|
||||
using AK::swap;
|
||||
using AK::UnderlyingType;
|
||||
using AK::Void;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue