diff options
Diffstat (limited to 'AK')
-rw-r--r-- | AK/Function.h | 50 | ||||
-rw-r--r-- | AK/StdLibExtraDetails.h | 7 | ||||
-rw-r--r-- | AK/StdLibExtras.h | 4 |
3 files changed, 34 insertions, 27 deletions
diff --git a/AK/Function.h b/AK/Function.h index 06e3f3a75d..612a1906e8 100644 --- a/AK/Function.h +++ b/AK/Function.h @@ -39,26 +39,36 @@ namespace AK { template<typename> class Function; +template<typename F> +inline constexpr bool IsFunctionPointer = (IsPointer<F> && IsFunction<RemovePointer<F>>); + +// Not a function pointer, and not an lvalue reference. +template<typename F> +inline constexpr bool IsFunctionObject = (!IsFunctionPointer<F> && IsRvalueReference<F&&>); + template<typename Out, typename... In> class Function<Out(In...)> { AK_MAKE_NONCOPYABLE(Function); public: Function() = default; + Function(std::nullptr_t) + { + } ~Function() { clear(false); } - template<typename CallableType, class = typename EnableIf<!(IsPointer<CallableType> && IsFunction<RemovePointer<CallableType>>)&&IsRvalueReference<CallableType&&>>::Type> - Function(CallableType&& callable) + template<typename CallableType> + Function(CallableType&& callable) requires((IsFunctionObject<CallableType> && IsCallableWithArguments<CallableType, In...>)) { - init_with_callable(move(callable)); + init_with_callable(forward<CallableType>(callable)); } - template<typename FunctionType, class = typename EnableIf<IsPointer<FunctionType> && IsFunction<RemovePointer<FunctionType>>>::Type> - Function(FunctionType f) + template<typename FunctionType> + Function(FunctionType f) requires((IsFunctionPointer<FunctionType> && IsCallableWithArguments<RemovePointer<FunctionType>, In...>)) { init_with_callable(move(f)); } @@ -68,6 +78,7 @@ public: move_from(move(other)); } + // Note: Despite this method being const, a mutable lambda _may_ modify its own captures. Out operator()(In... in) const { auto* wrapper = callable_wrapper(); @@ -82,16 +93,16 @@ public: explicit operator bool() const { return !!callable_wrapper(); } - template<typename CallableType, class = typename EnableIf<!(IsPointer<CallableType> && IsFunction<RemovePointer<CallableType>>)&&IsRvalueReference<CallableType&&>>::Type> - Function& operator=(CallableType&& callable) + template<typename CallableType> + Function& operator=(CallableType&& callable) requires((IsFunctionObject<CallableType> && IsCallableWithArguments<CallableType, In...>)) { clear(); - init_with_callable(move(callable)); + init_with_callable(forward<CallableType>(callable)); return *this; } - template<typename FunctionType, class = typename EnableIf<IsPointer<FunctionType> && IsFunction<RemovePointer<FunctionType>>>::Type> - Function& operator=(FunctionType f) + template<typename FunctionType> + Function& operator=(FunctionType f) requires((IsFunctionPointer<FunctionType> && IsCallableWithArguments<RemovePointer<FunctionType>, In...>)) { clear(); if (f) @@ -118,7 +129,8 @@ private: class CallableWrapperBase { public: virtual ~CallableWrapperBase() = default; - virtual Out call(In...) const = 0; + // Note: This is not const to allow storing mutable lambdas. + virtual Out call(In...) = 0; virtual void destroy() = 0; virtual void init_and_swap(u8*, size_t) = 0; }; @@ -134,17 +146,9 @@ private: { } - Out call(In... in) const final override + Out call(In... in) final override { - if constexpr (requires { m_callable(forward<In>(in)...); }) { - return m_callable(forward<In>(in)...); - } else if constexpr (requires { m_callable(); }) { - return m_callable(); - } else if constexpr (IsVoid<Out>) { - return; - } else { - return {}; - } + return m_callable(forward<In>(in)...); } void destroy() final override @@ -208,10 +212,10 @@ private: VERIFY(m_call_nesting_level == 0); using WrapperType = CallableWrapper<Callable>; if constexpr (sizeof(WrapperType) > inline_capacity) { - *bit_cast<CallableWrapperBase**>(&m_storage) = new WrapperType(move(callable)); + *bit_cast<CallableWrapperBase**>(&m_storage) = new WrapperType(forward<Callable>(callable)); m_kind = FunctionKind::Outline; } else { - new (m_storage) WrapperType(move(callable)); + new (m_storage) WrapperType(forward<Callable>(callable)); m_kind = FunctionKind::Inline; } } diff --git a/AK/StdLibExtraDetails.h b/AK/StdLibExtraDetails.h index d0991b7a2a..8cf43ebbed 100644 --- a/AK/StdLibExtraDetails.h +++ b/AK/StdLibExtraDetails.h @@ -435,10 +435,16 @@ inline constexpr bool IsTrivial = __is_trivial(T); template<typename T> inline constexpr bool IsTriviallyCopyable = __is_trivially_copyable(T); +template<typename T> +auto declval() -> T; + +template<typename T, typename... Args> +inline constexpr bool IsCallableWithArguments = requires(T t) { t(declval<Args>()...); }; } using AK::Detail::AddConst; using AK::Detail::Conditional; using AK::Detail::CopyConst; +using AK::Detail::declval; using AK::Detail::DependentFalse; using AK::Detail::EnableIf; using AK::Detail::FalseType; @@ -447,6 +453,7 @@ using AK::Detail::IndexSequence; using AK::Detail::IntegerSequence; using AK::Detail::IsArithmetic; using AK::Detail::IsBaseOf; +using AK::Detail::IsCallableWithArguments; using AK::Detail::IsClass; using AK::Detail::IsConst; using AK::Detail::IsEnum; diff --git a/AK/StdLibExtras.h b/AK/StdLibExtras.h index 7a48da2ba1..19411fc4b6 100644 --- a/AK/StdLibExtras.h +++ b/AK/StdLibExtras.h @@ -39,9 +39,6 @@ struct _RawPtr { namespace AK { -template<typename T> -auto declval() -> T; - template<class T> constexpr T&& forward(RemoveReference<T>& param) { @@ -118,7 +115,6 @@ using RawPtr = typename Detail::_RawPtr<T>::Type; using AK::array_size; using AK::ceil_div; using AK::clamp; -using AK::declval; using AK::exchange; using AK::forward; using AK::max; |