diff options
| -rw-r--r-- | libstdc++-v3/include/bits/refwrap.h | 34 | ||||
| -rw-r--r-- | libstdc++-v3/include/bits/version.def | 8 | ||||
| -rw-r--r-- | libstdc++-v3/include/bits/version.h | 10 | ||||
| -rw-r--r-- | libstdc++-v3/include/std/functional | 1 | ||||
| -rw-r--r-- | libstdc++-v3/testsuite/20_util/reference_wrapper/p2655r3.cc | 75 |
5 files changed, 128 insertions, 0 deletions
diff --git a/libstdc++-v3/include/bits/refwrap.h b/libstdc++-v3/include/bits/refwrap.h index 612715e..5d9f8c8 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 91c1ede..412b9ce 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -1830,6 +1830,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 = { v = 202302; diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index f5ddc86..2b96934 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 69a3910..74aa5fa 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 0000000..f2fafec --- /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 <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>> ); |
