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.
---
libstdc++-v3/include/bits/refwrap.h | 34 +++++++++++++++
libstdc++-v3/include/bits/version.def | 8 ++++
libstdc++-v3/include/bits/version.h | 10 +++++
libstdc++-v3/include/std/functional | 1 +
.../20_util/reference_wrapper/p2655r3.cc | 43 +++++++++++++++++++
5 files changed, 96 insertions(+)
create mode 100644 libstdc++-v3/testsuite/20_util/reference_wrapper/p2655r3.cc
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<typename _Tp>
+ constexpr bool __is_ref_wrapper = false;
+
+ template<typename _Tp>
+ constexpr bool __is_ref_wrapper<reference_wrapper<_Tp>> = true;
+
+ template<typename _Rp, typename _Tp, typename _RQual, typename _TQual>
+ concept __ref_wrap_common_reference_exists_with = __is_ref_wrapper<_Rp>
+ && requires { typename common_reference_t<typename _Rp::type&, _TQual>;
}
+ && convertible_to<_RQual, common_reference_t<typename _Rp::type&,
_TQual>>;
+ } // namespace __detail
+
+ template<typename _Rp, typename _Tp,
+ template<typename> class _RQual, template<typename> 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<typename _Rp::type&, _TQual<_Tp>>; };
+
+ template<typename _Tp, typename _Rp,
+ template<typename> class _TQual, template<typename> 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<typename _Rp::type&, _TQual<_Tp>>; };
+#endif
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
diff --git a/libstdc++-v3/include/bits/version.def
b/libstdc++-v3/include/bits/version.def
index e2b064e09b1e..9f4e46e37260 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -1801,6 +1801,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 4581519d3a7d..e7af12bf629c 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -2011,6 +2011,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 8ad73b343bda..6f7f2f627a2a 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 <bits/version.h>
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..a240971f2e24
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/reference_wrapper/p2655r3.cc
@@ -0,0 +1,43 @@
+// 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 <functional>
+
+#if __cpp_lib_common_reference_wrapper != 202302L
+# error "Feature-test macro __cpp_lib_common_reference_wrapper has wrong value
in <functional>"
+#endif
+
+using std::is_same_v;
+using std::common_reference_t;
+using std::reference_wrapper;
+
+static_assert( is_same_v<common_reference_t<const reference_wrapper<int>&,
int&>, int&> );
+static_assert( is_same_v<common_reference_t<int&, const
reference_wrapper<int>&>, int&> );
+
+static_assert( is_same_v<common_reference_t<reference_wrapper<int>, int&>,
+ common_reference_t<int&, int&>> );
+static_assert( is_same_v<common_reference_t<reference_wrapper<int>, const
int&>,
+ common_reference_t<int&, const int&>> );
+static_assert( is_same_v<common_reference_t<reference_wrapper<const int>,
int&>,
+ common_reference_t<const int&, int&>> );
+
+static_assert( is_same_v<common_reference_t<int&, reference_wrapper<int>>,
+ common_reference_t<int&, int&>> );
+static_assert( is_same_v<common_reference_t<const int&,
reference_wrapper<int>>,
+ common_reference_t<int&, const int&>> );
+static_assert( is_same_v<common_reference_t<int&, reference_wrapper<const
int>>,
+ common_reference_t<const int&, int&>> );
+
+static_assert( is_same_v<common_reference_t<reference_wrapper<int>&,
reference_wrapper<int>&>,
+ reference_wrapper<int>&> );
+
+static_assert( is_same_v<common_reference_t<reference_wrapper<char>,
+ reference_wrapper<int>>,
+ int> );
+static_assert(
is_same_v<common_reference_t<reference_wrapper<reference_wrapper<int>>,
+ reference_wrapper<int>>,
+ reference_wrapper<int>> );
+static_assert( is_same_v<common_reference_t<reference_wrapper<int>,
+
reference_wrapper<reference_wrapper<int>>>,
+ reference_wrapper<int>> );
--
2.51.0.491.g4b71b29477