summaryrefslogtreecommitdiff
path: root/AK
diff options
context:
space:
mode:
Diffstat (limited to 'AK')
-rw-r--r--AK/Function.h50
-rw-r--r--AK/StdLibExtraDetails.h7
-rw-r--r--AK/StdLibExtras.h4
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;