summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-04-07 14:31:49 +0200
committerAndreas Kling <kling@serenityos.org>2020-04-07 15:56:19 +0200
commitf8942411ac68245edb8086186ccb45b91874e56b (patch)
tree2df3cea62e11543b289fba50d2cd4c7c727ed578
parente54cc055ac62bbb74986baca509511fffe3aa84e (diff)
downloadserenity-f8942411ac68245edb8086186ccb45b91874e56b.zip
AK: Add forward() overload that refuses to forward lvalue as rvalue
This matches what other forward() implementations do.
-rw-r--r--AK/StdLibExtras.h47
1 files changed, 35 insertions, 12 deletions
diff --git a/AK/StdLibExtras.h b/AK/StdLibExtras.h
index c68f3c93e2..e0fba83309 100644
--- a/AK/StdLibExtras.h
+++ b/AK/StdLibExtras.h
@@ -81,17 +81,6 @@ inline T&& move(T& arg)
# pragma clang diagnostic pop
#endif
-template<typename T>
-struct Identity {
- typedef T Type;
-};
-
-template<class T>
-inline constexpr T&& forward(typename Identity<T>::Type& param)
-{
- return static_cast<T&&>(param);
-}
-
template<typename T, typename U>
inline T exchange(T& a, U&& b)
{
@@ -151,6 +140,14 @@ typedef IntegralConstant<bool, false> FalseType;
typedef IntegralConstant<bool, true> TrueType;
template<class T>
+struct IsLvalueReference : FalseType {
+};
+
+template<class T>
+struct IsLvalueReference<T&> : TrueType {
+};
+
+template<class T>
struct __IsPointerHelper : FalseType {
};
@@ -293,11 +290,37 @@ struct Conditional<false, TrueType, FalseType> {
typedef FalseType Type;
};
+template<typename T>
+struct RemoveReference {
+ typedef T Type;
+};
+template<class T>
+struct RemoveReference<T&> {
+ typedef T Type;
+};
+template<class T>
+struct RemoveReference<T&&> {
+ typedef T Type;
+};
+
+template<class T>
+inline constexpr T&& forward(typename RemoveReference<T>::Type& param)
+{
+ return static_cast<T&&>(param);
+}
+
+template<class T>
+inline 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);
+}
+
}
-using AK::Conditional;
using AK::ceil_div;
using AK::clamp;
+using AK::Conditional;
using AK::exchange;
using AK::forward;
using AK::IsSame;