https://gcc.gnu.org/g:140aab25a4865433d987d73c57f4ddf11fdac1e2

commit r14-10654-g140aab25a4865433d987d73c57f4ddf11fdac1e2
Author: Patrick Palka <ppa...@redhat.com>
Date:   Sat Aug 3 09:05:05 2024 -0400

    libstdc++: use concrete return type for std::forward_like
    
    Inspired by https://github.com/llvm/llvm-project/issues/101614 this
    inverts the relationship between forward_like and __like_t so that
    forward_like is defined in terms of __like_t and with a concrete return
    type.  __like_t in turn is defined via partial specializations that
    pattern match on the const- and reference-ness of T.
    
    This turns out to be more SFINAE friendly and significantly cheaper
    to compile than the previous implementation.
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/move.h (__like_impl): New metafunction.
            (__like_t): Redefine in terms of __like_impl.
            (forward_like): Redefine in terms of __like_t.
            * testsuite/20_util/forward_like/2_neg.cc: Don't expect
            error outside the immediate context anymore.
    
    Reviewed-by: Jonathan Wakely <jwak...@redhat.com>
    (cherry picked from commit 8256d5c0097dff00f9bdf9ee0c9d53bd7cec2802)

Diff:
---
 libstdc++-v3/include/bits/move.h                   | 47 +++++++++++-----------
 .../testsuite/20_util/forward_like/2_neg.cc        |  6 +--
 2 files changed, 26 insertions(+), 27 deletions(-)

diff --git a/libstdc++-v3/include/bits/move.h b/libstdc++-v3/include/bits/move.h
index bb200c95964a..8397a01b6323 100644
--- a/libstdc++-v3/include/bits/move.h
+++ b/libstdc++-v3/include/bits/move.h
@@ -88,31 +88,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #if __glibcxx_forward_like // C++ >= 23
   template<typename _Tp, typename _Up>
-  [[nodiscard]]
-  constexpr decltype(auto)
-  forward_like(_Up&& __x) noexcept
-  {
-    constexpr bool __as_rval = is_rvalue_reference_v<_Tp&&>;
-
-    if constexpr (is_const_v<remove_reference_t<_Tp>>)
-      {
-       using _Up2 = remove_reference_t<_Up>;
-       if constexpr (__as_rval)
-         return static_cast<const _Up2&&>(__x);
-       else
-         return static_cast<const _Up2&>(__x);
-      }
-    else
-      {
-       if constexpr (__as_rval)
-         return static_cast<remove_reference_t<_Up>&&>(__x);
-       else
-         return static_cast<_Up&>(__x);
-      }
-  }
+  struct __like_impl; // _Tp must be a reference and _Up an lvalue reference
+
+  template<typename _Tp, typename _Up>
+  struct __like_impl<_Tp&, _Up&>
+  { using type = _Up&; };
+
+  template<typename _Tp, typename _Up>
+  struct __like_impl<const _Tp&, _Up&>
+  { using type = const _Up&; };
+
+  template<typename _Tp, typename _Up>
+  struct __like_impl<_Tp&&, _Up&>
+  { using type = _Up&&; };
+
+  template<typename _Tp, typename _Up>
+  struct __like_impl<const _Tp&&, _Up&>
+  { using type = const _Up&&; };
 
   template<typename _Tp, typename _Up>
-    using __like_t = decltype(std::forward_like<_Tp>(std::declval<_Up>()));
+    using __like_t = typename __like_impl<_Tp&&, _Up&>::type;
+
+  template<typename _Tp, typename _Up>
+  [[nodiscard]]
+  constexpr __like_t<_Tp, _Up>
+  forward_like(_Up&& __x) noexcept
+  { return static_cast<__like_t<_Tp, _Up>>(__x); }
 #endif
 
   /**
diff --git a/libstdc++-v3/testsuite/20_util/forward_like/2_neg.cc 
b/libstdc++-v3/testsuite/20_util/forward_like/2_neg.cc
index ff835af19151..5dafa419a7ea 100644
--- a/libstdc++-v3/testsuite/20_util/forward_like/2_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/forward_like/2_neg.cc
@@ -2,9 +2,7 @@
 
 #include <utility>
 
-auto x1 = std::forward_like<void>(1); // { dg-error "here" }
+auto x1 = std::forward_like<void>(1); // { dg-error "no match" }
 // { dg-error "forming reference to void" "" { target *-*-* } 0 }
-auto x2 = std::forward_like<void()const>(1); // { dg-error "here" }
+auto x2 = std::forward_like<void()const>(1); // { dg-error "no match" }
 // { dg-error "forming reference to qualified function" "" { target *-*-* } 0 }
-
-// { dg-prune-output "inconsistent deduction for auto return type" } // 
PR111484

Reply via email to