From: Patrick Palka Date: Fri, 5 Dec 2025 18:43:40 +0000 (-0500) Subject: libstdc++: Implement rest of P2655R3 common_reference of reference_wrapper X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d1ac432c5a889a101e5a81ec349f76e55403c2f4;p=thirdparty%2Fgcc.git libstdc++: Implement rest of P2655R3 common_reference of reference_wrapper PR libstdc++/120446 libstdc++-v3/ChangeLog: * include/bits/refwrap.h (__detail::__is_ref_wrapper): Define as per P2655R3 for C++20. (__detail::__ref_wrap_common_reference_exists_with): Likewise. (basic_common_reference): Define partial specializations using the above as per P2655R3 for C++20. * include/bits/version.def (common_reference_wrapper): New. * include/bits/version.h: Regenerate. * include/std/functional (__glibcxx_want_common_reference_wrapper): Define. * testsuite/20_util/reference_wrapper/p2655r3.cc: New test. Co-authored-by: Tomasz Kamiński Reviewed-by: Tomasz Kamiński Reviewed-by: Jonathan Wakely --- diff --git a/libstdc++-v3/include/bits/refwrap.h b/libstdc++-v3/include/bits/refwrap.h index 612715e9b7bd..5d9f8c8f49f9 100644 --- a/libstdc++-v3/include/bits/refwrap.h +++ b/libstdc++-v3/include/bits/refwrap.h @@ -457,6 +457,40 @@ _GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type) /// @} +#if __glibcxx_common_reference_wrapper // C++ >= 20 + namespace __detail + { + template + constexpr bool __is_ref_wrapper = false; + + template + constexpr bool __is_ref_wrapper> = true; + + template + concept __ref_wrap_common_reference_exists_with = __is_ref_wrapper<_Rp> + && requires { typename common_reference_t; } + && convertible_to<_RQual, common_reference_t>; + } // namespace __detail + + template class _RQual, template class _TQual> + requires __detail::__ref_wrap_common_reference_exists_with<_Rp, _Tp, + _RQual<_Rp>, _TQual<_Tp>> + && (!__detail::__ref_wrap_common_reference_exists_with<_Tp, _Rp, + _TQual<_Tp>, _RQual<_Rp>>) + struct basic_common_reference<_Rp, _Tp, _RQual, _TQual> + { using type = common_reference_t>; }; + + template class _TQual, template class _RQual> + requires __detail::__ref_wrap_common_reference_exists_with<_Rp, _Tp, + _RQual<_Rp>, _TQual<_Tp>> + && (!__detail::__ref_wrap_common_reference_exists_with<_Tp, _Rp, + _TQual<_Tp>, _RQual<_Rp>>) + struct basic_common_reference<_Tp, _Rp, _TQual, _RQual> + { using type = common_reference_t>; }; +#endif + _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index 91c1edec4d60..412b9ce96f8a 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -1829,6 +1829,14 @@ ftms = { }; }; +ftms = { + name = common_reference_wrapper; + values = { + v = 202302; + cxxmin = 20; // We treat P2655R3 as a DR against C++20. + }; +}; + ftms = { name = formatters; values = { diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index f5ddc86f21a3..2b96934ca099 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -2040,6 +2040,16 @@ #endif /* !defined(__cpp_lib_common_reference) && defined(__glibcxx_want_common_reference) */ #undef __glibcxx_want_common_reference +#if !defined(__cpp_lib_common_reference_wrapper) +# if (__cplusplus >= 202002L) +# define __glibcxx_common_reference_wrapper 202302L +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_common_reference_wrapper) +# define __cpp_lib_common_reference_wrapper 202302L +# endif +# endif +#endif /* !defined(__cpp_lib_common_reference_wrapper) && defined(__glibcxx_want_common_reference_wrapper) */ +#undef __glibcxx_want_common_reference_wrapper + #if !defined(__cpp_lib_formatters) # if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED # define __glibcxx_formatters 202302L diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index 69a3910b0bd9..74aa5fa3e9a1 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -64,6 +64,7 @@ #define __glibcxx_want_not_fn #define __glibcxx_want_ranges #define __glibcxx_want_reference_wrapper +#define __glibcxx_want_common_reference_wrapper #define __glibcxx_want_transparent_operators #include diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/p2655r3.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/p2655r3.cc new file mode 100644 index 000000000000..f2fafec46660 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/reference_wrapper/p2655r3.cc @@ -0,0 +1,75 @@ +// P2655R3 - common_reference_t of reference_wrapper Should Be a Reference Type +// Implemented as a DR against C++20 +// { dg-do compile { target c++20 } } + +#include + +#if __cpp_lib_common_reference_wrapper != 202302L +# error "Feature-test macro __cpp_lib_common_reference_wrapper has wrong value in " +#endif + +using std::is_same_v; +using std::common_reference_t; +using std::reference_wrapper; + +static_assert( is_same_v&, int&>, int&> ); +static_assert( is_same_v&>, int&> ); + +static_assert( is_same_v, int&>, + common_reference_t> ); +static_assert( is_same_v, const int&>, + common_reference_t> ); +static_assert( is_same_v, int&>, + common_reference_t> ); + +static_assert( is_same_v>, + common_reference_t> ); +static_assert( is_same_v>, + common_reference_t> ); +static_assert( is_same_v>, + common_reference_t> ); + +static_assert( is_same_v&, reference_wrapper&>, + reference_wrapper&> ); + +static_assert( is_same_v, + reference_wrapper>, + int> ); +static_assert( is_same_v>, + reference_wrapper>, + reference_wrapper> ); +static_assert( is_same_v, + reference_wrapper>>, + reference_wrapper> ); + +struct A { }; +struct B { operator A&() const; }; + +template +concept has_common_reference = requires { + typename std::common_reference_t; +}; + +static_assert( is_same_v, const B&>, A&> ); +// reference_wrapper is not convertible to A&, as it would require two user +// defined conversions. +static_assert( !has_common_reference> ); +static_assert( !has_common_reference, reference_wrapper> ); + +struct D1 : A {}; +struct D2 : A {}; + +template typename Qual1, template typename Qual2> +struct std::basic_common_reference + : std::common_reference, Qual2> +{ }; + +template typename Qual1, template typename Qual2> +struct std::basic_common_reference + : std::common_reference, Qual2> +{ }; + +static_assert( is_same_v, A&> ); +static_assert( is_same_v, D2&>, A&> ); +static_assert( is_same_v>, A&> ); +static_assert( !has_common_reference, reference_wrapper> );