瀏覽代碼

AK: Add forward() overload that refuses to forward lvalue as rvalue

This matches what other forward() implementations do.
Andreas Kling 5 年之前
父節點
當前提交
f8942411ac
共有 1 個文件被更改,包括 35 次插入12 次删除
  1. 35 12
      AK/StdLibExtras.h

+ 35 - 12
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)
 {
@@ -150,6 +139,14 @@ struct IntegralConstant {
 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;