This isn't properly tested so I'm not pushing it, but I'm sharing it now for comment.
-- >8 -- Inspired by https://github.com/llvm/llvm-project/issues/101614 this replaces the deduced return type of std::forward_like with a type trait to compute that type. libstdc++-v3/ChangeLog: * include/bits/move.h (__forward_like_impl): New metafunction to compute the return type of std::forward_like. (forward_like, __like_t): Use it. * testsuite/20_util/forward_like/2_neg.cc: Adjust expected errors. --- libstdc++-v3/include/bits/move.h | 45 +++++++++---------- .../testsuite/20_util/forward_like/2_neg.cc | 2 +- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/libstdc++-v3/include/bits/move.h b/libstdc++-v3/include/bits/move.h index bb200c95964..15b7cd07fce 100644 --- a/libstdc++-v3/include/bits/move.h +++ b/libstdc++-v3/include/bits/move.h @@ -88,31 +88,30 @@ _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 __forward_like_impl + { +#if _GLIBCXX_USE_BUILTIN_TRAIT(__remove_reference) + template<typename _Xp> using __remove_ref_t = __remove_reference(_Xp); +#else + template<typename _Xp> using __remove_ref_t = remove_reference_t<_Xp>; +#endif + template<typename _Xp, typename _Yp> + using _Copy_const = __conditional_t<is_const_v<_Xp>, const _Yp, _Yp>; + template<typename _Xp, typename _Yp> + using _Override_ref = __conditional_t<is_rvalue_reference_v<_Xp>, + __remove_ref_t<_Yp>&&, _Yp&>; + using type = _Override_ref<_Tp&&, _Copy_const<__remove_ref_t<_Tp>, + __remove_ref_t<_Up>>>; + }; template<typename _Tp, typename _Up> - using __like_t = decltype(std::forward_like<_Tp>(std::declval<_Up>())); + using __like_t = typename __forward_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 ff835af1915..f6e98420a9a 100644 --- a/libstdc++-v3/testsuite/20_util/forward_like/2_neg.cc +++ b/libstdc++-v3/testsuite/20_util/forward_like/2_neg.cc @@ -7,4 +7,4 @@ auto x1 = std::forward_like<void>(1); // { dg-error "here" } auto x2 = std::forward_like<void()const>(1); // { dg-error "here" } // { dg-error "forming reference to qualified function" "" { target *-*-* } 0 } -// { dg-prune-output "inconsistent deduction for auto return type" } // PR111484 +// { dg-prune-output "no matching function" } -- 2.45.2