mirror of git://gcc.gnu.org/git/gcc.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 <tkaminsk@redhat.com> Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com> Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
This commit is contained in:
parent
a9fd651fbb
commit
d1ac432c5a
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <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>> );
|
||||
|
||||
struct A { };
|
||||
struct B { operator A&() const; };
|
||||
|
||||
template<typename T, typename U>
|
||||
concept has_common_reference = requires {
|
||||
typename std::common_reference_t<T, U>;
|
||||
};
|
||||
|
||||
static_assert( is_same_v<common_reference_t<reference_wrapper<A>, const B&>, A&> );
|
||||
// reference_wrapper<const B> is not convertible to A&, as it would require two user
|
||||
// defined conversions.
|
||||
static_assert( !has_common_reference<A, reference_wrapper<const B>> );
|
||||
static_assert( !has_common_reference<reference_wrapper<A>, reference_wrapper<const B>> );
|
||||
|
||||
struct D1 : A {};
|
||||
struct D2 : A {};
|
||||
|
||||
template<template<class> typename Qual1, template<class> typename Qual2>
|
||||
struct std::basic_common_reference<D1, D2, Qual1, Qual2>
|
||||
: std::common_reference<Qual1<A>, Qual2<A>>
|
||||
{ };
|
||||
|
||||
template<template<class> typename Qual1, template<class> typename Qual2>
|
||||
struct std::basic_common_reference<D2, D1, Qual1, Qual2>
|
||||
: std::common_reference<Qual1<A>, Qual2<A>>
|
||||
{ };
|
||||
|
||||
static_assert( is_same_v<common_reference_t<D1&, D2&>, A&> );
|
||||
static_assert( is_same_v<common_reference_t<reference_wrapper<D1>, D2&>, A&> );
|
||||
static_assert( is_same_v<common_reference_t<D1&, reference_wrapper<D2>>, A&> );
|
||||
static_assert( !has_common_reference<reference_wrapper<D1>, reference_wrapper<D2>> );
|
||||
Loading…
Reference in New Issue