1
0
mirror of https://github.com/SerenityOS/serenity synced 2024-07-05 22:10:24 +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:
AnotherTest 2021-04-10 18:29:06 +04:30 committed by Andreas Kling
parent d8d16dea95
commit a6e4482080
41 changed files with 650 additions and 662 deletions

View File

@ -53,13 +53,13 @@ static inline T atomic_exchange(volatile T* var, T desired, MemoryOrder order =
return __atomic_exchange_n(var, desired, order);
}
template<typename T, typename V = typename RemoveVolatile<T>::Type>
template<typename T, typename V = RemoveVolatile<T>>
static inline V* atomic_exchange(volatile T** var, V* desired, MemoryOrder order = memory_order_seq_cst) noexcept
{
return __atomic_exchange_n(var, desired, order);
}
template<typename T, typename V = typename RemoveVolatile<T>::Type>
template<typename T, typename V = RemoveVolatile<T>>
static inline V* atomic_exchange(volatile T** var, std::nullptr_t, MemoryOrder order = memory_order_seq_cst) noexcept
{
return __atomic_exchange_n(const_cast<V**>(var), nullptr, order);
@ -74,7 +74,7 @@ template<typename T>
return __atomic_compare_exchange_n(var, &expected, desired, false, order, order);
}
template<typename T, typename V = typename RemoveVolatile<T>::Type>
template<typename T, typename V = RemoveVolatile<T>>
[[nodiscard]] static inline bool atomic_compare_exchange_strong(volatile T** var, V*& expected, V* desired, MemoryOrder order = memory_order_seq_cst) noexcept
{
if (order == memory_order_acq_rel || order == memory_order_release)
@ -83,7 +83,7 @@ template<typename T, typename V = typename RemoveVolatile<T>::Type>
return __atomic_compare_exchange_n(var, &expected, desired, false, order, order);
}
template<typename T, typename V = typename RemoveVolatile<T>::Type>
template<typename T, typename V = RemoveVolatile<T>>
[[nodiscard]] static inline bool atomic_compare_exchange_strong(volatile T** var, V*& expected, std::nullptr_t, MemoryOrder order = memory_order_seq_cst) noexcept
{
if (order == memory_order_acq_rel || order == memory_order_release)
@ -128,7 +128,7 @@ static inline T atomic_load(volatile T* var, MemoryOrder order = memory_order_se
return __atomic_load_n(var, order);
}
template<typename T, typename V = typename RemoveVolatile<T>::Type>
template<typename T, typename V = RemoveVolatile<T>>
static inline V* atomic_load(volatile T** var, MemoryOrder order = memory_order_seq_cst) noexcept
{
return __atomic_load_n(const_cast<V**>(var), order);
@ -140,13 +140,13 @@ static inline void atomic_store(volatile T* var, T desired, MemoryOrder order =
__atomic_store_n(var, desired, order);
}
template<typename T, typename V = typename RemoveVolatile<T>::Type>
template<typename T, typename V = RemoveVolatile<T>>
static inline void atomic_store(volatile T** var, V* desired, MemoryOrder order = memory_order_seq_cst) noexcept
{
__atomic_store_n(var, desired, order);
}
template<typename T, typename V = typename RemoveVolatile<T>::Type>
template<typename T, typename V = RemoveVolatile<T>>
static inline void atomic_store(volatile T** var, std::nullptr_t, MemoryOrder order = memory_order_seq_cst) noexcept
{
__atomic_store_n(const_cast<V**>(var), nullptr, order);

View File

@ -41,7 +41,7 @@ template<typename StreamType, size_t Size = 4096, typename = void>
class Buffered;
template<typename StreamType, size_t Size>
class Buffered<StreamType, Size, typename EnableIf<IsBaseOf<InputStream, StreamType>::value>::Type> final : public InputStream {
class Buffered<StreamType, Size, typename EnableIf<IsBaseOf<InputStream, StreamType>>::Type> final : public InputStream {
AK_MAKE_NONCOPYABLE(Buffered);
public:
@ -137,7 +137,7 @@ private:
};
template<typename StreamType, size_t Size>
class Buffered<StreamType, Size, typename EnableIf<IsBaseOf<OutputStream, StreamType>::value>::Type> final : public OutputStream {
class Buffered<StreamType, Size, typename EnableIf<IsBaseOf<OutputStream, StreamType>>::Type> final : public OutputStream {
AK_MAKE_NONCOPYABLE(Buffered);
public:

View File

@ -237,6 +237,6 @@ private:
namespace AK {
template<typename... Args>
using CheckedFormatString = Format::Detail::CheckedFormatString<typename IdentityType<Args>::Type...>;
using CheckedFormatString = Format::Detail::CheckedFormatString<IdentityType<Args>...>;
}

View File

@ -33,19 +33,19 @@ namespace AK::Concepts {
#if defined(__cpp_concepts) && !defined(__COVERITY__)
template<typename T>
concept Integral = IsIntegral<T>::value;
concept Integral = IsIntegral<T>;
template<typename T>
concept FloatingPoint = IsFloatingPoint<T>::value;
concept FloatingPoint = IsFloatingPoint<T>;
template<typename T>
concept Arithmetic = IsArithmetic<T>::value;
concept Arithmetic = IsArithmetic<T>;
template<typename T>
concept Signed = IsSigned<T>::value;
concept Signed = IsSigned<T>;
template<typename T>
concept Unsigned = IsUnsigned<T>::value;
concept Unsigned = IsUnsigned<T>;
#endif

View File

@ -132,7 +132,7 @@ public:
template<typename U>
void prepend(U&& value)
{
static_assert(IsSame<T, U>::value);
static_assert(IsSame<T, U>);
auto* node = new Node(forward<U>(value));
if (!m_head) {
VERIFY(!m_tail);

View File

@ -44,35 +44,35 @@
\
[[nodiscard]] Prefix constexpr inline Enum operator|(Enum lhs, Enum rhs) \
{ \
using Type = UnderlyingType<Enum>::Type; \
using Type = UnderlyingType<Enum>; \
return static_cast<Enum>( \
static_cast<Type>(lhs) | static_cast<Type>(rhs)); \
} \
\
[[nodiscard]] Prefix constexpr inline Enum operator&(Enum lhs, Enum rhs) \
{ \
using Type = UnderlyingType<Enum>::Type; \
using Type = UnderlyingType<Enum>; \
return static_cast<Enum>( \
static_cast<Type>(lhs) & static_cast<Type>(rhs)); \
} \
\
[[nodiscard]] Prefix constexpr inline Enum operator^(Enum lhs, Enum rhs) \
{ \
using Type = UnderlyingType<Enum>::Type; \
using Type = UnderlyingType<Enum>; \
return static_cast<Enum>( \
static_cast<Type>(lhs) ^ static_cast<Type>(rhs)); \
} \
\
[[nodiscard]] Prefix constexpr inline Enum operator~(Enum rhs) \
{ \
using Type = UnderlyingType<Enum>::Type; \
using Type = UnderlyingType<Enum>; \
return static_cast<Enum>( \
~static_cast<Type>(rhs)); \
} \
\
Prefix constexpr inline Enum& operator|=(Enum& lhs, Enum rhs) \
{ \
using Type = UnderlyingType<Enum>::Type; \
using Type = UnderlyingType<Enum>; \
lhs = static_cast<Enum>( \
static_cast<Type>(lhs) | static_cast<Type>(rhs)); \
return lhs; \
@ -80,7 +80,7 @@
\
Prefix constexpr inline Enum& operator&=(Enum& lhs, Enum rhs) \
{ \
using Type = UnderlyingType<Enum>::Type; \
using Type = UnderlyingType<Enum>; \
lhs = static_cast<Enum>( \
static_cast<Type>(lhs) & static_cast<Type>(rhs)); \
return lhs; \
@ -88,7 +88,7 @@
\
Prefix constexpr inline Enum& operator^=(Enum& lhs, Enum rhs) \
{ \
using Type = UnderlyingType<Enum>::Type; \
using Type = UnderlyingType<Enum>; \
lhs = static_cast<Enum>( \
static_cast<Type>(lhs) ^ static_cast<Type>(rhs)); \
return lhs; \
@ -96,6 +96,6 @@
\
Prefix constexpr inline bool has_flag(Enum value, Enum mask) \
{ \
using Type = UnderlyingType<Enum>::Type; \
using Type = UnderlyingType<Enum>; \
return static_cast<Type>(value & mask) != 0; \
}

View File

@ -534,7 +534,7 @@ void Formatter<FormatString>::vformat(FormatBuilder& builder, StringView fmtstr,
}
template<typename T>
void Formatter<T, typename EnableIf<IsIntegral<T>::value>::Type>::format(FormatBuilder& builder, T value)
void Formatter<T, typename EnableIf<IsIntegral<T>>::Type>::format(FormatBuilder& builder, T value)
{
if (m_mode == Mode::Character) {
// FIXME: We just support ASCII for now, in the future maybe unicode?
@ -587,7 +587,7 @@ void Formatter<T, typename EnableIf<IsIntegral<T>::value>::Type>::format(FormatB
m_width = m_width.value_or(0);
if (IsSame<typename MakeUnsigned<T>::Type, T>::value)
if constexpr (IsSame<MakeUnsigned<T>, T>)
builder.put_u64(value, base, m_alternative_form, upper_case, m_zero_pad, m_align, m_width.value(), m_fill, m_sign_mode);
else
builder.put_i64(value, base, m_alternative_form, upper_case, m_zero_pad, m_align, m_width.value(), m_fill, m_sign_mode);

View File

@ -93,10 +93,10 @@ struct TypeErasedParameter {
template<typename T>
static Type get_type()
{
if (IsIntegral<T>::value)
return get_type_from_size(sizeof(T), IsUnsigned<T>::value);
return Type::Custom;
if constexpr (IsIntegral<T>)
return get_type_from_size(sizeof(T), IsUnsigned<T>);
else
return Type::Custom;
}
size_t to_size() const;
@ -269,7 +269,7 @@ struct StandardFormatter {
};
template<typename T>
struct Formatter<T, typename EnableIf<IsIntegral<T>::value>::Type> : StandardFormatter {
struct Formatter<T, typename EnableIf<IsIntegral<T>>::Type> : StandardFormatter {
Formatter() = default;
explicit Formatter(StandardFormatter formatter)
: StandardFormatter(formatter)
@ -416,11 +416,10 @@ void dmesgln(CheckedFormatString<Parameters...>&& fmt, const Parameters&... para
#endif
template<typename T, typename = void>
struct HasFormatter : TrueType {
};
inline constexpr bool HasFormatter = true;
template<typename T>
struct HasFormatter<T, typename Formatter<T>::__no_formatter_defined> : FalseType {
};
inline constexpr bool HasFormatter<T, typename Formatter<T>::__no_formatter_defined> = false;
template<typename T>
class FormatIfSupported {
@ -450,7 +449,7 @@ struct __FormatIfSupported<T, true> : Formatter<T> {
}
};
template<typename T>
struct Formatter<FormatIfSupported<T>> : __FormatIfSupported<T, HasFormatter<T>::value> {
struct Formatter<FormatIfSupported<T>> : __FormatIfSupported<T, HasFormatter<T>> {
};
// This is a helper class, the idea is that if you want to implement a formatter you can inherit

View File

@ -39,13 +39,13 @@ class Function<Out(In...)> {
public:
Function() = default;
template<typename CallableType, class = typename EnableIf<!(IsPointer<CallableType>::value && IsFunction<typename RemovePointer<CallableType>::Type>::value) && IsRvalueReference<CallableType&&>::value>::Type>
template<typename CallableType, class = typename EnableIf<!(IsPointer<CallableType> && IsFunction<RemovePointer<CallableType>>)&&IsRvalueReference<CallableType&&>>::Type>
Function(CallableType&& callable)
: m_callable_wrapper(make<CallableWrapper<CallableType>>(move(callable)))
{
}
template<typename FunctionType, class = typename EnableIf<IsPointer<FunctionType>::value && IsFunction<typename RemovePointer<FunctionType>::Type>::value>::Type>
template<typename FunctionType, class = typename EnableIf<IsPointer<FunctionType> && IsFunction<RemovePointer<FunctionType>>>::Type>
Function(FunctionType f)
: m_callable_wrapper(make<CallableWrapper<FunctionType>>(move(f)))
{
@ -59,14 +59,14 @@ public:
explicit operator bool() const { return !!m_callable_wrapper; }
template<typename CallableType, class = typename EnableIf<!(IsPointer<CallableType>::value && IsFunction<typename RemovePointer<CallableType>::Type>::value) && IsRvalueReference<CallableType&&>::value>::Type>
template<typename CallableType, class = typename EnableIf<!(IsPointer<CallableType> && IsFunction<RemovePointer<CallableType>>)&&IsRvalueReference<CallableType&&>>::Type>
Function& operator=(CallableType&& callable)
{
m_callable_wrapper = make<CallableWrapper<CallableType>>(move(callable));
return *this;
}
template<typename FunctionType, class = typename EnableIf<IsPointer<FunctionType>::value && IsFunction<typename RemovePointer<FunctionType>::Type>::value>::Type>
template<typename FunctionType, class = typename EnableIf<IsPointer<FunctionType> && IsFunction<RemovePointer<FunctionType>>>::Type>
Function& operator=(FunctionType f)
{
m_callable_wrapper = make<CallableWrapper<FunctionType>>(move(f));
@ -103,7 +103,7 @@ private:
return m_callable(forward<In>(in)...);
} else if constexpr (requires { m_callable(); }) {
return m_callable();
} else if constexpr (IsSame<void, Out>::value) {
} else if constexpr (IsVoid<Out>) {
return;
} else {
return {};

View File

@ -89,9 +89,9 @@ private:
static constexpr SimpleIterator begin(Container& container) { return { container, 0 }; }
static constexpr SimpleIterator end(Container& container)
{
using RawContainerType = typename RemoveCV<Container>::Type;
using RawContainerType = RemoveCV<Container>;
if constexpr (IsSame<StringView, RawContainerType>::value || IsSame<String, RawContainerType>::value)
if constexpr (IsSame<StringView, RawContainerType> || IsSame<String, RawContainerType>)
return { container, container.length() };
else
return { container, container.size() };

View File

@ -379,7 +379,7 @@ public:
ALWAYS_INLINE bool is_null() const { return PtrTraits::is_null(m_bits.load(AK::MemoryOrder::memory_order_relaxed)); }
template<typename U = T, typename EnableIf<IsSame<U, T>::value && !IsNullPointer<typename PtrTraits::NullType>::value>::Type* = nullptr>
template<typename U = T, typename EnableIf<IsSame<U, T> && !IsNullPointer<typename PtrTraits::NullType>>::Type* = nullptr>
typename PtrTraits::NullType null_value() const
{
// make sure we are holding a null value
@ -387,7 +387,7 @@ public:
VERIFY(PtrTraits::is_null(bits));
return PtrTraits::to_null_value(bits);
}
template<typename U = T, typename EnableIf<IsSame<U, T>::value && !IsNullPointer<typename PtrTraits::NullType>::value>::Type* = nullptr>
template<typename U = T, typename EnableIf<IsSame<U, T> && !IsNullPointer<typename PtrTraits::NullType>>::Type* = nullptr>
void set_null_value(typename PtrTraits::NullType value)
{
// make sure that new null value would be interpreted as a null value

View File

@ -167,16 +167,16 @@ public:
__builtin_memcpy(this->data() + offset, data, data_size);
}
ALWAYS_INLINE constexpr size_t copy_to(Span<typename RemoveConst<T>::Type> other) const
ALWAYS_INLINE constexpr size_t copy_to(Span<RemoveConst<T>> other) const
{
VERIFY(other.size() >= size());
return TypedTransfer<typename RemoveConst<T>::Type>::copy(other.data(), data(), size());
return TypedTransfer<RemoveConst<T>>::copy(other.data(), data(), size());
}
ALWAYS_INLINE constexpr size_t copy_trimmed_to(Span<typename RemoveConst<T>::Type> other) const
ALWAYS_INLINE constexpr size_t copy_trimmed_to(Span<RemoveConst<T>> other) const
{
const auto count = min(size(), other.size());
return TypedTransfer<typename RemoveConst<T>::Type>::copy(other.data(), data(), count);
return TypedTransfer<RemoveConst<T>>::copy(other.data(), data(), count);
}
ALWAYS_INLINE constexpr size_t fill(const T& value)

498
AK/StdLibExtraDetails.h Normal file
View File

@ -0,0 +1,498 @@
/*
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Ali Mohammad Pur <ali.mpfard@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
namespace AK::Detail {
template<bool B, class T = void>
struct EnableIf {
};
template<class T>
struct EnableIf<true, T> {
using Type = T;
};
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>
using AddConst = const T;
template<class T>
struct __RemoveConst {
using Type = T;
};
template<class T>
struct __RemoveConst<const T> {
using Type = T;
};
template<class T>
using RemoveConst = typename __RemoveConst<T>::Type;
template<class T>
struct __RemoveVolatile {
using Type = T;
};
template<class T>
struct __RemoveVolatile<volatile T> {
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>
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 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<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<bool condition, class TrueType, class FalseType>
using Conditional = typename __Conditional<condition, TrueType, FalseType>::Type;
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;
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>
using MakeUnsigned = typename __MakeUnsigned<T>::Type;
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 = char;
};
template<typename T>
using MakeSigned = typename __MakeSigned<T>::Type;
template<class T>
inline constexpr bool IsVoid = IsSame<void, RemoveCV<T>>;
template<class T>
inline constexpr bool IsConst = false;
template<class T>
inline constexpr bool IsConst<const T> = true;
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;
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<typename T>
using IdentityType = typename __IdentityType<T>::Type;
template<class T>
requires(IsEnum<T>) using UnderlyingType = __underlying_type(T);
template<typename T>
inline constexpr bool IsTrivial = __is_trivial(T);
template<typename T>
inline constexpr bool IsTriviallyCopyable = __is_trivially_copyable(T);
}
using AK::Detail::AddConst;
using AK::Detail::Conditional;
using AK::Detail::CopyConst;
using AK::Detail::DependentFalse;
using AK::Detail::EnableIf;
using AK::Detail::FalseType;
using AK::Detail::IdentityType;
using AK::Detail::IndexSequence;
using AK::Detail::IntegerSequence;
using AK::Detail::IsArithmetic;
using AK::Detail::IsBaseOf;
using AK::Detail::IsClass;
using AK::Detail::IsConst;
using AK::Detail::IsEnum;
using AK::Detail::IsFloatingPoint;
using AK::Detail::IsFunction;
using AK::Detail::IsFundamental;
using AK::Detail::IsIntegral;
using AK::Detail::IsLvalueReference;
using AK::Detail::IsNullPointer;
using AK::Detail::IsPointer;
using AK::Detail::IsRvalueReference;
using AK::Detail::IsSame;
using AK::Detail::IsSigned;
using AK::Detail::IsTrivial;
using AK::Detail::IsTriviallyCopyable;
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::RemovePointer;
using AK::Detail::RemoveReference;
using AK::Detail::RemoveVolatile;
using AK::Detail::TrueType;
using AK::Detail::UnderlyingType;
using AK::Detail::Void;

View File

@ -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;

View File

@ -148,13 +148,13 @@ InputStream& operator>>(InputStream& stream, Optional<T>& value)
}
template<typename Integral>
InputStream& operator>>(InputStream& stream, Integral& value) requires IsIntegral<Integral>::value
InputStream& operator>>(InputStream& stream, Integral& value) requires IsIntegral<Integral>
{
stream.read_or_error({ &value, sizeof(value) });
return stream;
}
template<typename Integral>
OutputStream& operator<<(OutputStream& stream, Integral value) requires IsIntegral<Integral>::value
OutputStream& operator<<(OutputStream& stream, Integral value) requires IsIntegral<Integral>
{
stream.write_or_error({ &value, sizeof(value) });
return stream;
@ -163,13 +163,13 @@ OutputStream& operator<<(OutputStream& stream, Integral value) requires IsIntegr
#ifndef KERNEL
template<typename FloatingPoint>
InputStream& operator>>(InputStream& stream, FloatingPoint& value) requires IsFloatingPoint<FloatingPoint>::value
InputStream& operator>>(InputStream& stream, FloatingPoint& value) requires IsFloatingPoint<FloatingPoint>
{
stream.read_or_error({ &value, sizeof(value) });
return stream;
}
template<typename FloatingPoint>
OutputStream& operator<<(OutputStream& stream, FloatingPoint value) requires IsFloatingPoint<FloatingPoint>::value
OutputStream& operator<<(OutputStream& stream, FloatingPoint value) requires IsFloatingPoint<FloatingPoint>
{
stream.write_or_error({ &value, sizeof(value) });
return stream;

View File

@ -276,7 +276,7 @@ public:
}
template<typename T>
static String number(T value) requires IsArithmetic<T>::value
static String number(T value) requires IsArithmetic<T>
{
return formatted("{}", value);
}

View File

@ -30,7 +30,7 @@
TEST_CASE(should_provide_underlying_type)
{
static_assert(IsSame<int, Badge<int>::Type>::value);
static_assert(IsSame<int, Badge<int>::Type>);
}
TEST_MAIN(Badge)

View File

@ -31,8 +31,8 @@
TEST_CASE(is_integral_works_properly)
{
EXPECT(!IsIntegral<const char*>::value);
EXPECT(IsIntegral<unsigned long>::value);
EXPECT(!IsIntegral<const char*>);
EXPECT(IsIntegral<unsigned long>);
}
TEST_CASE(format_string_literals)

View File

@ -46,14 +46,14 @@ TEST_CASE(TestIndexSequence)
{
constexpr auto integer_seq1 = IntegerSequence<int, 0, 1, 2, 3, 4> {};
constexpr auto integer_seq2 = MakeIntegerSequence<int, 5> {};
static_assert(IsSame<decltype(integer_seq1), decltype(integer_seq2)>::value, "");
static_assert(IsSame<decltype(integer_seq1), decltype(integer_seq2)>, "");
static_assert(integer_seq1.size() == 5, "");
static_assert(integer_seq2.size() == 5, "");
constexpr auto index_seq1 = IndexSequence<0, 1, 2> {};
constexpr auto index_seq2 = MakeIndexSequence<3> {};
static_assert(IsSame<decltype(index_seq1), decltype(index_seq2)>::value, "");
static_assert(IsSame<decltype(index_seq1), decltype(index_seq2)>, "");
verify_sequence(MakeIndexSequence<10> {}, std::initializer_list<unsigned> { 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U, 9U });
verify_sequence(MakeIntegerSequence<long, 16> {}, std::initializer_list<long> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 });
@ -62,9 +62,9 @@ TEST_CASE(TestIndexSequence)
TEST_CASE(TypeList)
{
using MyTypes = TypeList<int, bool, char>;
static_assert(IsSame<MyTypes::Type<0>, int>::value, "");
static_assert(IsSame<MyTypes::Type<1>, bool>::value, "");
static_assert(IsSame<MyTypes::Type<2>, char>::value, "");
static_assert(IsSame<MyTypes::Type<0>, int>, "");
static_assert(IsSame<MyTypes::Type<1>, bool>, "");
static_assert(IsSame<MyTypes::Type<2>, char>, "");
}
TEST_MAIN(IndexSequence);

View File

@ -49,7 +49,7 @@ TEST_CASE(span_works_with_constant_types)
static constexpr u8 buffer[4] { 1, 2, 3, 4 };
constexpr ReadonlyBytes bytes { buffer, 4 };
static_assert(IsConst<AK::RemoveReference<decltype(bytes[1])>::Type>::value);
static_assert(IsConst<RemoveReference<decltype(bytes[1])>>);
static_assert(bytes[2] == 3);
}

View File

@ -29,13 +29,13 @@
#include <AK/TypeList.h>
#define STATIC_EXPECT_EQ(lhs, rhs) \
static_assert(IsSame<lhs, rhs>::value, "");
static_assert(IsSame<lhs, rhs>, "");
#define STATIC_EXPECT_FALSE(Expression) \
static_assert(!Expression::value, "");
static_assert(!Expression, "");
#define STATIC_EXPECT_TRUE(Expression) \
static_assert(Expression::value, "");
static_assert(Expression, "");
#define EXPECT_TRAIT_TRUE(trait, ...) \
for_each_type<TypeList<__VA_ARGS__>>([]<typename T>(TypeWrapper<T>) { \
@ -49,7 +49,7 @@
#define EXPECT_EQ_WITH_TRAIT(trait, ListA, ListB) \
for_each_type_zipped<ListA, ListB>([]<typename A, typename B>(TypeWrapper<A>, TypeWrapper<B>) { \
STATIC_EXPECT_EQ(typename trait<A>::Type, B); \
STATIC_EXPECT_EQ(trait<A>, B); \
})
struct Empty {
@ -120,7 +120,7 @@ TEST_CASE(AddConst)
TEST_CASE(UnderlyingType)
{
using Type = UnderlyingType<Enummer>::Type;
using Type = UnderlyingType<Enummer>;
STATIC_EXPECT_EQ(Type, u8);
}

View File

@ -140,9 +140,9 @@ public:
return const_cast<Trie*>(this)->traverse_until_last_accessible_node(it, end);
}
Optional<MetadataType> metadata() const requires(!IsNullPointer<MetadataType>::value) { return m_metadata; }
void set_metadata(MetadataType metadata) requires(!IsNullPointer<MetadataType>::value) { m_metadata = move(metadata); }
const MetadataType& metadata_value() const requires(!IsNullPointer<MetadataType>::value) { return m_metadata.value(); }
Optional<MetadataType> metadata() const requires(!IsNullPointer<MetadataType>) { return m_metadata; }
void set_metadata(MetadataType metadata) requires(!IsNullPointer<MetadataType>) { m_metadata = move(metadata); }
const MetadataType& metadata_value() const requires(!IsNullPointer<MetadataType>) { return m_metadata.value(); }
const ValueType& value() const { return m_value; }
ValueType& value() { return m_value; }
@ -165,7 +165,7 @@ public:
template<typename It, typename ProvideMetadataFunction>
BaseType& insert(
It& it, const It& end, MetadataType metadata, ProvideMetadataFunction provide_missing_metadata) requires(!IsNullPointer<MetadataType>::value)
It& it, const It& end, MetadataType metadata, ProvideMetadataFunction provide_missing_metadata) requires(!IsNullPointer<MetadataType>)
{
Trie* last_root_node = &traverse_until_last_accessible_node(it, end);
for (; it != end; ++it)
@ -175,7 +175,7 @@ public:
}
template<typename It>
BaseType& insert(It& it, const It& end) requires(IsNullPointer<MetadataType>::value)
BaseType& insert(It& it, const It& end) requires(IsNullPointer<MetadataType>)
{
Trie* last_root_node = &traverse_until_last_accessible_node(it, end);
for (; it != end; ++it)
@ -185,14 +185,14 @@ public:
template<typename It, typename ProvideMetadataFunction>
BaseType& insert(
const It& begin, const It& end, MetadataType metadata, ProvideMetadataFunction provide_missing_metadata) requires(!IsNullPointer<MetadataType>::value)
const It& begin, const It& end, MetadataType metadata, ProvideMetadataFunction provide_missing_metadata) requires(!IsNullPointer<MetadataType>)
{
auto it = begin;
return insert(it, end, move(metadata), move(provide_missing_metadata));
}
template<typename It>
BaseType& insert(const It& begin, const It& end) requires(IsNullPointer<MetadataType>::value)
BaseType& insert(const It& begin, const It& end) requires(IsNullPointer<MetadataType>)
{
auto it = begin;
return insert(it, end);
@ -231,7 +231,7 @@ public:
using DetailTrie = Detail::Trie<BaseT, Trie<ValueType, MetadataT, ValueTraits>, ValueType, MetadataT, ValueTraits>;
using MetadataType = typename DetailTrie::MetadataType;
Trie(ValueType value, MetadataType metadata) requires(!IsVoid<MetadataType>::value && !IsNullPointer<MetadataType>::value)
Trie(ValueType value, MetadataType metadata) requires(!IsVoid<MetadataType> && !IsNullPointer<MetadataType>)
: DetailTrie(move(value), move(metadata))
{
}

View File

@ -50,7 +50,7 @@ ALWAYS_INLINE bool is(InputType* input)
template<typename OutputType, typename InputType>
ALWAYS_INLINE CopyConst<InputType, OutputType>* downcast(InputType* input)
{
static_assert(IsBaseOf<InputType, OutputType>::value);
static_assert(IsBaseOf<InputType, OutputType>);
VERIFY(!input || is<OutputType>(*input));
return static_cast<CopyConst<InputType, OutputType>*>(input);
}
@ -58,7 +58,7 @@ ALWAYS_INLINE CopyConst<InputType, OutputType>* downcast(InputType* input)
template<typename OutputType, typename InputType>
ALWAYS_INLINE CopyConst<InputType, OutputType>& downcast(InputType& input)
{
static_assert(IsBaseOf<InputType, OutputType>::value);
static_assert(IsBaseOf<InputType, OutputType>);
VERIFY(is<OutputType>(input));
return static_cast<CopyConst<InputType, OutputType>&>(input);
}

View File

@ -42,7 +42,7 @@ using i8 = __INT8_TYPE__;
#ifdef __serenity__
using size_t = __SIZE_TYPE__;
using ssize_t = MakeSigned<size_t>::Type;
using ssize_t = MakeSigned<size_t>;
using ptrdiff_t = __PTRDIFF_TYPE__;
@ -72,7 +72,7 @@ using __ptrdiff_t = __PTRDIFF_TYPE__;
#endif
using FlatPtr = Conditional<sizeof(void*) == 8, u64, u32>::Type;
using FlatPtr = Conditional<sizeof(void*) == 8, u64, u32>;
constexpr u64 KiB = 1024;
constexpr u64 MiB = KiB * KiB;

View File

@ -36,10 +36,10 @@ namespace AK {
// Once it supports C++20 concepts, we can remove this.
#if defined(__cpp_concepts) && !defined(__COVERITY__)
template<typename T>
concept PointerTypeName = IsPointer<T>::value;
concept PointerTypeName = IsPointer<T>;
template<PointerTypeName T>
#else
template<typename T, typename EnableIf<IsPointer<T>::value, int>::Type = 0>
template<typename T, typename EnableIf<IsPointer<T>, int>::Type = 0>
#endif
class Userspace {

View File

@ -38,26 +38,26 @@ class WeakPtr {
public:
WeakPtr() = default;
template<typename U, typename EnableIf<IsBaseOf<T, U>::value>::Type* = nullptr>
template<typename U, typename EnableIf<IsBaseOf<T, U>>::Type* = nullptr>
WeakPtr(const WeakPtr<U>& other)
: m_link(other.m_link)
{
}
template<typename U, typename EnableIf<IsBaseOf<T, U>::value>::Type* = nullptr>
template<typename U, typename EnableIf<IsBaseOf<T, U>>::Type* = nullptr>
WeakPtr(WeakPtr<U>&& other)
: m_link(other.take_link())
{
}
template<typename U, typename EnableIf<IsBaseOf<T, U>::value>::Type* = nullptr>
template<typename U, typename EnableIf<IsBaseOf<T, U>>::Type* = nullptr>
WeakPtr& operator=(WeakPtr<U>&& other)
{
m_link = other.take_link();
return *this;
}
template<typename U, typename EnableIf<IsBaseOf<T, U>::value>::Type* = nullptr>
template<typename U, typename EnableIf<IsBaseOf<T, U>>::Type* = nullptr>
WeakPtr& operator=(const WeakPtr<U>& other)
{
if ((const void*)this != (const void*)&other)
@ -71,20 +71,20 @@ public:
return *this;
}
template<typename U, typename EnableIf<IsBaseOf<T, U>::value>::Type* = nullptr>
template<typename U, typename EnableIf<IsBaseOf<T, U>>::Type* = nullptr>
WeakPtr(const U& object)
: m_link(object.template make_weak_ptr<U>().take_link())
{
}
template<typename U, typename EnableIf<IsBaseOf<T, U>::value>::Type* = nullptr>
template<typename U, typename EnableIf<IsBaseOf<T, U>>::Type* = nullptr>
WeakPtr(const U* object)
{
if (object)
m_link = object->template make_weak_ptr<U>().take_link();
}
template<typename U, typename EnableIf<IsBaseOf<T, U>::value>::Type* = nullptr>
template<typename U, typename EnableIf<IsBaseOf<T, U>>::Type* = nullptr>
WeakPtr(const RefPtr<U>& object)
{
object.do_while_locked([&](U* obj) {
@ -93,7 +93,7 @@ public:
});
}
template<typename U, typename EnableIf<IsBaseOf<T, U>::value>::Type* = nullptr>
template<typename U, typename EnableIf<IsBaseOf<T, U>>::Type* = nullptr>
WeakPtr(const NonnullRefPtr<U>& object)
{
object.do_while_locked([&](U* obj) {
@ -102,14 +102,14 @@ public:
});
}
template<typename U, typename EnableIf<IsBaseOf<T, U>::value>::Type* = nullptr>
template<typename U, typename EnableIf<IsBaseOf<T, U>>::Type* = nullptr>
WeakPtr& operator=(const U& object)
{
m_link = object.template make_weak_ptr<U>().take_link();
return *this;
}
template<typename U, typename EnableIf<IsBaseOf<T, U>::value>::Type* = nullptr>
template<typename U, typename EnableIf<IsBaseOf<T, U>>::Type* = nullptr>
WeakPtr& operator=(const U* object)
{
if (object)
@ -119,7 +119,7 @@ public:
return *this;
}
template<typename U, typename EnableIf<IsBaseOf<T, U>::value>::Type* = nullptr>
template<typename U, typename EnableIf<IsBaseOf<T, U>>::Type* = nullptr>
WeakPtr& operator=(const RefPtr<U>& object)
{
object.do_while_locked([&](U* obj) {
@ -131,7 +131,7 @@ public:
return *this;
}
template<typename U, typename EnableIf<IsBaseOf<T, U>::value>::Type* = nullptr>
template<typename U, typename EnableIf<IsBaseOf<T, U>>::Type* = nullptr>
WeakPtr& operator=(const NonnullRefPtr<U>& object)
{
object.do_while_locked([&](U* obj) {
@ -199,7 +199,7 @@ template<typename T>
template<typename U>
inline WeakPtr<U> Weakable<T>::make_weak_ptr() const
{
if constexpr (IsBaseOf<RefCountedBase, T>::value) {
if constexpr (IsBaseOf<RefCountedBase, T>) {
// Checking m_being_destroyed isn't sufficient when dealing with
// a RefCounted type.The reference count will drop to 0 before the
// destructor is invoked and revoke_weak_ptrs is called. So, try
@ -223,7 +223,7 @@ inline WeakPtr<U> Weakable<T>::make_weak_ptr() const
WeakPtr<U> weak_ptr(m_link);
if constexpr (IsBaseOf<RefCountedBase, T>::value) {
if constexpr (IsBaseOf<RefCountedBase, T>) {
// Now drop the reference we temporarily added
if (static_cast<const T*>(this)->unref()) {
// We just dropped the last reference, which should have called

View File

@ -49,7 +49,7 @@ class WeakLink : public RefCounted<WeakLink> {
friend class WeakPtr;
public:
template<typename T, typename PtrTraits = RefPtrTraits<T>, typename EnableIf<IsBaseOf<RefCountedBase, T>::value>::Type* = nullptr>
template<typename T, typename PtrTraits = RefPtrTraits<T>, typename EnableIf<IsBaseOf<RefCountedBase, T>>::Type* = nullptr>
RefPtr<T, PtrTraits> strong_ref() const
{
RefPtr<T, PtrTraits> ref;

View File

@ -77,28 +77,28 @@ const void* memmem(const void* haystack, size_t, const void* needle, size_t);
template<typename T>
[[nodiscard]] inline bool copy_from_user(T* dest, const T* src)
{
static_assert(is_trivially_copyable<T>());
static_assert(IsTriviallyCopyable<T>);
return copy_from_user(dest, src, sizeof(T));
}
template<typename T>
[[nodiscard]] inline bool copy_to_user(T* dest, const T* src)
{
static_assert(is_trivially_copyable<T>());
static_assert(IsTriviallyCopyable<T>);
return copy_to_user(dest, src, sizeof(T));
}
template<typename T>
[[nodiscard]] inline bool copy_from_user(T* dest, Userspace<const T*> src)
{
static_assert(is_trivially_copyable<T>());
static_assert(IsTriviallyCopyable<T>);
return copy_from_user(dest, src.unsafe_userspace_ptr(), sizeof(T));
}
template<typename T>
[[nodiscard]] inline bool copy_from_user(T* dest, Userspace<T*> src)
{
static_assert(is_trivially_copyable<T>());
static_assert(IsTriviallyCopyable<T>);
return copy_from_user(dest, src.unsafe_userspace_ptr(), sizeof(T));
}
@ -125,28 +125,28 @@ DEPRECATE_COPY_FROM_USER_TYPE(timeval, copy_time_from_user)
template<typename T>
[[nodiscard]] inline bool copy_to_user(Userspace<T*> dest, const T* src)
{
static_assert(is_trivially_copyable<T>());
static_assert(IsTriviallyCopyable<T>);
return copy_to_user(dest.unsafe_userspace_ptr(), src, sizeof(T));
}
template<typename T>
[[nodiscard]] inline bool copy_to_user(Userspace<T*> dest, const void* src, size_t size)
{
static_assert(is_trivially_copyable<T>());
static_assert(IsTriviallyCopyable<T>);
return copy_to_user(dest.unsafe_userspace_ptr(), src, size);
}
template<typename T>
[[nodiscard]] inline bool copy_from_user(void* dest, Userspace<const T*> src, size_t size)
{
static_assert(is_trivially_copyable<T>());
static_assert(IsTriviallyCopyable<T>);
return copy_from_user(dest, src.unsafe_userspace_ptr(), size);
}
template<typename T>
[[nodiscard]] inline bool copy_n_from_user(T* dest, const T* src, size_t count)
{
static_assert(is_trivially_copyable<T>());
static_assert(IsTriviallyCopyable<T>);
Checked size = sizeof(T);
size *= count;
if (size.has_overflow())
@ -157,7 +157,7 @@ template<typename T>
template<typename T>
[[nodiscard]] inline bool copy_n_to_user(T* dest, const T* src, size_t count)
{
static_assert(is_trivially_copyable<T>());
static_assert(IsTriviallyCopyable<T>);
Checked size = sizeof(T);
size *= count;
if (size.has_overflow())
@ -168,7 +168,7 @@ template<typename T>
template<typename T>
[[nodiscard]] inline bool copy_n_from_user(T* dest, Userspace<const T*> src, size_t count)
{
static_assert(is_trivially_copyable<T>());
static_assert(IsTriviallyCopyable<T>);
Checked size = sizeof(T);
size *= count;
if (size.has_overflow())
@ -179,7 +179,7 @@ template<typename T>
template<typename T>
[[nodiscard]] inline bool copy_n_to_user(Userspace<T*> dest, const T* src, size_t count)
{
static_assert(is_trivially_copyable<T>());
static_assert(IsTriviallyCopyable<T>);
Checked size = sizeof(T);
size *= count;
if (size.has_overflow())

View File

@ -277,19 +277,19 @@ struct ReadElement {
case Short:
return ReadElementConcrete<T, short, kind> {}(input_lexer, ap);
case Long:
if constexpr (IsSame<T, int>::value)
if constexpr (IsSame<T, int>)
return ReadElementConcrete<T, long, kind> {}(input_lexer, ap);
if constexpr (IsSame<T, unsigned>::value)
if constexpr (IsSame<T, unsigned>)
return ReadElementConcrete<T, unsigned, kind> {}(input_lexer, ap);
if constexpr (IsSame<T, float>::value)
if constexpr (IsSame<T, float>)
return ReadElementConcrete<int, double, kind> {}(input_lexer, ap);
return false;
case LongLong:
if constexpr (IsSame<T, int>::value)
if constexpr (IsSame<T, int>)
return ReadElementConcrete<long long, long long, kind> {}(input_lexer, ap);
if constexpr (IsSame<T, unsigned>::value)
if constexpr (IsSame<T, unsigned>)
return ReadElementConcrete<unsigned long long, unsigned long long, kind> {}(input_lexer, ap);
if constexpr (IsSame<T, float>::value)
if constexpr (IsSame<T, float>)
return ReadElementConcrete<long long, double, kind> {}(input_lexer, ap);
return false;
case IntMax:

View File

@ -68,7 +68,7 @@ public:
template<typename T>
T* data()
{
static_assert(IsVoid<T>::value || is_trivial<T>());
static_assert(IsVoid<T> || IsTrivial<T>);
if (!m_impl)
return nullptr;
return (T*)m_impl->data();
@ -77,7 +77,7 @@ public:
template<typename T>
const T* data() const
{
static_assert(IsVoid<T>::value || is_trivial<T>());
static_assert(IsVoid<T> || IsTrivial<T>);
if (!m_impl)
return nullptr;
return (const T*)m_impl->data();

View File

@ -90,13 +90,13 @@ public:
}
template<typename T, typename Callback>
void for_each_child_of_type(Callback callback) requires IsBaseOf<Object, T>::value;
void for_each_child_of_type(Callback callback) requires IsBaseOf<Object, T>;
template<typename T>
T* find_child_of_type_named(const String&) requires IsBaseOf<Object, T>::value;
T* find_child_of_type_named(const String&) requires IsBaseOf<Object, T>;
template<typename T>
T* find_descendant_of_type_named(const String&) requires IsBaseOf<Object, T>::value;
T* find_descendant_of_type_named(const String&) requires IsBaseOf<Object, T>;
bool is_ancestor_of(const Object&) const;
@ -187,7 +187,7 @@ struct AK::Formatter<Core::Object> : AK::Formatter<FormatString> {
namespace Core {
template<typename T, typename Callback>
inline void Object::for_each_child_of_type(Callback callback) requires IsBaseOf<Object, T>::value
inline void Object::for_each_child_of_type(Callback callback) requires IsBaseOf<Object, T>
{
for_each_child([&](auto& child) {
if (auto* child_as_t = dynamic_cast<T*>(&child); child_as_t)
@ -197,7 +197,7 @@ inline void Object::for_each_child_of_type(Callback callback) requires IsBaseOf<
}
template<typename T>
T* Object::find_child_of_type_named(const String& name) requires IsBaseOf<Object, T>::value
T* Object::find_child_of_type_named(const String& name) requires IsBaseOf<Object, T>
{
T* found_child = nullptr;
for_each_child_of_type<T>([&](auto& child) {
@ -212,7 +212,7 @@ T* Object::find_child_of_type_named(const String& name) requires IsBaseOf<Object
}
template<typename T>
T* Object::find_descendant_of_type_named(const String& name) requires IsBaseOf<Object, T>::value
T* Object::find_descendant_of_type_named(const String& name) requires IsBaseOf<Object, T>
{
auto* this_as_t = dynamic_cast<T*>(this);
if (this_as_t && this->name() == name)

View File

@ -37,13 +37,13 @@ class ItemListModel : public Model {
public:
static constexpr auto IsTwoDimensional = requires(Container data)
{
requires !IsVoid<ColumnNameListType>::value;
requires !IsVoid<ColumnNameListType>;
data.at(0).at(0);
data.at(0).size();
};
// Substitute 'void' for a dummy u8.
using ColumnNamesT = typename Conditional<IsVoid<ColumnNameListType>::value, u8, ColumnNameListType>::Type;
using ColumnNamesT = Conditional<IsVoid<ColumnNameListType>, u8, ColumnNameListType>;
static NonnullRefPtr<ItemListModel> create(const Container& data, const ColumnNamesT& column_names, const Optional<size_t>& row_count = {}) requires(IsTwoDimensional)
{

View File

@ -31,7 +31,7 @@
namespace Gfx {
template<size_t N, typename = typename AK::EnableIf<N % 2 == 1>::Type>
template<size_t N, typename = typename EnableIf<N % 2 == 1>::Type>
class SpatialGaussianBlurFilter : public GenericConvolutionFilter<N> {
public:
SpatialGaussianBlurFilter() { }

View File

@ -62,7 +62,7 @@ public:
auto* memory = allocate_cell(sizeof(T));
new (memory) T(forward<Args>(args)...);
auto* cell = static_cast<T*>(memory);
constexpr bool is_object = IsBaseOf<Object, T>::value;
constexpr bool is_object = IsBaseOf<Object, T>;
if constexpr (is_object)
static_cast<Object*>(cell)->disable_transitions();
cell->initialize(global_object);

View File

@ -101,7 +101,7 @@ public:
return Value((i32)data()[property_index]);
} else if constexpr (sizeof(T) == 4 || sizeof(T) == 8) {
auto value = data()[property_index];
if constexpr (IsFloatingPoint<T>::value) {
if constexpr (IsFloatingPoint<T>) {
return Value((double)value);
} else if constexpr (NumericLimits<T>::is_signed()) {
if (value > NumericLimits<i32>::max() || value < NumericLimits<i32>::min())

View File

@ -68,7 +68,7 @@ Result<T, ThreadError> Thread::join()
}
m_tid = 0;
if constexpr (IsVoid<T>::value)
if constexpr (IsVoid<T>)
return {};
else
return { static_cast<T>(thread_return) };

View File

@ -34,12 +34,10 @@
namespace Web::Bindings {
template<typename>
struct IsExceptionOr : AK::FalseType {
};
constexpr bool IsExceptionOr = false;
template<typename T>
struct IsExceptionOr<DOM::ExceptionOr<T>> : AK::TrueType {
};
constexpr bool IsExceptionOr<DOM::ExceptionOr<T>> = true;
template<typename T>
ALWAYS_INLINE bool throw_dom_exception(JS::VM& vm, JS::GlobalObject& global_object, DOM::ExceptionOr<T>& result)
@ -51,17 +49,17 @@ ALWAYS_INLINE bool throw_dom_exception(JS::VM& vm, JS::GlobalObject& global_obje
return false;
}
template<typename F, typename T = decltype(declval<F>()()), typename Ret = typename Conditional<!IsExceptionOr<T>::value && !IsVoid<T>::value, T, JS::Value>::Type>
template<typename F, typename T = decltype(declval<F>()()), typename Ret = Conditional<!IsExceptionOr<T> && !IsVoid<T>, T, JS::Value>>
Ret throw_dom_exception_if_needed(auto&& vm, auto&& global_object, F&& fn)
{
if constexpr (IsExceptionOr<T>::value) {
if constexpr (IsExceptionOr<T>) {
auto&& result = fn();
if (throw_dom_exception(vm, global_object, result))
return JS::Value();
if constexpr (requires(T v) { v.value(); })
return result.value();
return JS::Value();
} else if constexpr (IsVoid<T>::value) {
} else if constexpr (IsVoid<T>) {
fn();
return JS::js_undefined();
} else {
@ -72,7 +70,7 @@ Ret throw_dom_exception_if_needed(auto&& vm, auto&& global_object, F&& fn)
template<typename T>
bool should_return_empty(T&& value)
{
if constexpr (IsSame<JS::Value, T>::value)
if constexpr (IsSame<JS::Value, T>)
return value.is_empty();
return false;
}

View File

@ -39,7 +39,7 @@ class Performance final
, public Bindings::Wrappable {
public:
using WrapperType = Bindings::PerformanceWrapper;
using AllowOwnPtr = AK::TrueType;
using AllowOwnPtr = TrueType;
explicit Performance(DOM::Window&);
~Performance();

View File

@ -34,7 +34,7 @@ namespace Web::NavigationTiming {
class PerformanceTiming final : public Bindings::Wrappable {
public:
using WrapperType = Bindings::PerformanceTimingWrapper;
using AllowOwnPtr = AK::TrueType;
using AllowOwnPtr = TrueType;
explicit PerformanceTiming(DOM::Window&);
~PerformanceTiming();

View File

@ -49,7 +49,7 @@ public:
VERIFY(!m_in_removed_last_ref);
VERIFY(m_ref_count);
if (!--m_ref_count) {
if constexpr (IsBaseOf<DOM::Node, T>::value) {
if constexpr (IsBaseOf<DOM::Node, T>) {
m_in_removed_last_ref = true;
static_cast<T*>(this)->removed_last_ref();
} else {

View File

@ -47,7 +47,7 @@ template<typename T>
struct TypeTrivia {
static const size_t bits = sizeof(T) * 8;
static const T sign_bit = 1 << (bits - 1);
static const T mask = typename MakeUnsigned<T>::Type(-1);
static const T mask = MakeUnsigned<T>(-1);
};
template<typename T, typename U>