From: Jonathan Wakely <jwakely@redhat.com>
To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org
Subject: Re: [PATCH 2/4] libstdc++: Add std::reference_wrapper comparison operators for C++26
Date: Mon, 15 Apr 2024 19:30:04 +0100 [thread overview]
Message-ID: <CACb0b4mLOOD72H9BDDO6dg9YFrpov4erEB3ZTFO9AVGyrvtSQQ@mail.gmail.com> (raw)
In-Reply-To: <20240410085039.267589-2-jwakely@redhat.com>
Pushed to trunk now.
On Wed, 10 Apr 2024 at 09:53, Jonathan Wakely <jwakely@redhat.com> wrote:
>
> Tested x86_64-linux.
>
> Since this only affects C++26 it seems OK for trunk now.
>
> -- >8 --
>
> This C++26 change was just approved in Tokyo, in P2944R3. It adds
> operator== and operator<=> overloads to std::reference_wrapper.
>
> The operator<=> overloads in the paper cause compilation errors for any
> type without <=> so they're implemented here with deduced return types
> and constrained by a requires clause.
>
> libstdc++-v3/ChangeLog:
>
> * include/bits/refwrap.h (reference_wrapper): Add comparison
> operators as proposed by P2944R3.
> * include/bits/version.def (reference_wrapper): Define.
> * include/bits/version.h: Regenerate.
> * include/std/functional: Enable feature test macro.
> * testsuite/20_util/reference_wrapper/compare.cc: New test.
> ---
> libstdc++-v3/include/bits/refwrap.h | 45 +++++++++
> libstdc++-v3/include/bits/version.def | 8 ++
> libstdc++-v3/include/bits/version.h | 10 ++
> libstdc++-v3/include/std/functional | 1 +
> .../20_util/reference_wrapper/compare.cc | 95 +++++++++++++++++++
> 5 files changed, 159 insertions(+)
> create mode 100644 libstdc++-v3/testsuite/20_util/reference_wrapper/compare.cc
>
> diff --git a/libstdc++-v3/include/bits/refwrap.h b/libstdc++-v3/include/bits/refwrap.h
> index 2d4338b718f..fd1cc2b63e6 100644
> --- a/libstdc++-v3/include/bits/refwrap.h
> +++ b/libstdc++-v3/include/bits/refwrap.h
> @@ -38,6 +38,10 @@
> #include <bits/invoke.h>
> #include <bits/stl_function.h> // for unary_function and binary_function
>
> +#if __glibcxx_reference_wrapper >= 202403L // >= C++26
> +# include <compare>
> +#endif
> +
> namespace std _GLIBCXX_VISIBILITY(default)
> {
> _GLIBCXX_BEGIN_NAMESPACE_VERSION
> @@ -358,6 +362,47 @@ _GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type)
> #endif
> return std::__invoke(get(), std::forward<_Args>(__args)...);
> }
> +
> +#if __glibcxx_reference_wrapper >= 202403L // >= C++26
> + // [refwrap.comparisons], comparisons
> + [[nodiscard]]
> + friend constexpr bool
> + operator==(reference_wrapper __x, reference_wrapper __y)
> + requires requires { { __x.get() == __y.get() } -> convertible_to<bool>; }
> + { return __x.get() == __y.get(); }
> +
> + [[nodiscard]]
> + friend constexpr bool
> + operator==(reference_wrapper __x, const _Tp& __y)
> + requires requires { { __x.get() == __y } -> convertible_to<bool>; }
> + { return __x.get() == __y; }
> +
> + [[nodiscard]]
> + friend constexpr bool
> + operator==(reference_wrapper __x, reference_wrapper<const _Tp> __y)
> + requires (!is_const_v<_Tp>)
> + && requires { { __x.get() == __y.get() } -> convertible_to<bool>; }
> + { return __x.get() == __y.get(); }
> +
> + [[nodiscard]]
> + friend constexpr auto
> + operator<=>(reference_wrapper __x, reference_wrapper<_Tp> __y)
> + requires requires { __detail::__synth3way(__x.get(), __y.get()); }
> + { return __detail::__synth3way(__x.get(), __y.get()); }
> +
> + [[nodiscard]]
> + friend constexpr auto
> + operator<=>(reference_wrapper __x, const _Tp& __y)
> + requires requires { __detail::__synth3way(__x.get(), __y); }
> + { return __detail::__synth3way(__x.get(), __y); }
> +
> + [[nodiscard]]
> + friend constexpr auto
> + operator<=>(reference_wrapper __x, reference_wrapper<const _Tp> __y)
> + requires (!is_const_v<_Tp>)
> + && requires { __detail::__synth3way(__x.get(), __y.get()); }
> + { return __detail::__synth3way(__x.get(), __y.get()); }
> +#endif
> };
>
> #if __cpp_deduction_guides
> diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def
> index 5ad44941bff..5c0477fb61e 100644
> --- a/libstdc++-v3/include/bits/version.def
> +++ b/libstdc++-v3/include/bits/version.def
> @@ -1760,6 +1760,14 @@ ftms = {
> };
> };
>
> +ftms = {
> + name = reference_wrapper;
> + values = {
> + v = 202403;
> + cxxmin = 26;
> + };
> +};
> +
> ftms = {
> name = saturation_arithmetic;
> values = {
> diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h
> index 460a3e0116a..65e708c73fb 100644
> --- a/libstdc++-v3/include/bits/version.h
> +++ b/libstdc++-v3/include/bits/version.h
> @@ -1963,6 +1963,16 @@
> #endif /* !defined(__cpp_lib_ratio) && defined(__glibcxx_want_ratio) */
> #undef __glibcxx_want_ratio
>
> +#if !defined(__cpp_lib_reference_wrapper)
> +# if (__cplusplus > 202302L)
> +# define __glibcxx_reference_wrapper 202403L
> +# if defined(__glibcxx_want_all) || defined(__glibcxx_want_reference_wrapper)
> +# define __cpp_lib_reference_wrapper 202403L
> +# endif
> +# endif
> +#endif /* !defined(__cpp_lib_reference_wrapper) && defined(__glibcxx_want_reference_wrapper) */
> +#undef __glibcxx_want_reference_wrapper
> +
> #if !defined(__cpp_lib_saturation_arithmetic)
> # if (__cplusplus > 202302L)
> # define __glibcxx_saturation_arithmetic 202311L
> diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
> index 766558b3ce0..99364286a72 100644
> --- a/libstdc++-v3/include/std/functional
> +++ b/libstdc++-v3/include/std/functional
> @@ -83,6 +83,7 @@
> #define __glibcxx_want_move_only_function
> #define __glibcxx_want_not_fn
> #define __glibcxx_want_ranges
> +#define __glibcxx_want_reference_wrapper
> #define __glibcxx_want_transparent_operators
> #include <bits/version.h>
>
> diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/compare.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/compare.cc
> new file mode 100644
> index 00000000000..039c9d26496
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/20_util/reference_wrapper/compare.cc
> @@ -0,0 +1,95 @@
> +// { dg-do compile { target c++26 } }
> +
> +
> +#include <functional>
> +
> +#ifndef __cpp_lib_reference_wrapper
> +# error "Feature-test macro for reference_wrapper missing"
> +#elif __cpp_lib_reference_wrapper != 202403
> +# error "Feature-test macro for reference_wrapper has wrong value"
> +#endif
> +
> +// P2944R3 Comparisons for reference_wrapper
> +
> +auto check(int i, std::reference_wrapper<int> r) -> bool {
> + return i == r;
> +}
> +
> +template <class T> using Ref = std::reference_wrapper<T>;
> +
> +template <class T>
> +concept ref_equality_comparable
> += requires (T a, T const ca, Ref<T> r, Ref<T const> cr) {
> + // the usual T is equality-comparable with itself
> + a == a;
> + a == ca;
> + ca == ca;
> +
> + // Ref<T> is equality-comparable with itself
> + r == r;
> + r == cr;
> + cr == cr;
> +
> + // T and Ref<T> are equality-comparable
> + a == r;
> + a == cr;
> + ca == r;
> + ca == cr;
> +};
> +
> +static_assert( ref_equality_comparable<int> );
> +
> +struct A {
> + auto operator==(A const&) const -> bool { return true; }
> +};
> +
> +struct B {
> + friend auto operator==(B const&, B const&) -> bool { return true; }
> +};
> +
> +template <class T>
> +struct C {
> + friend auto operator==(C const&, C const&) -> bool { return true; }
> +};
> +
> +template <class T>
> +struct D { };
> +template <class T>
> +auto operator==(D<T> const&, D<T> const&) -> bool { return true; }
> +
> +static_assert(ref_equality_comparable<int>);
> +static_assert(ref_equality_comparable<A>);
> +static_assert(ref_equality_comparable<B>);
> +static_assert(ref_equality_comparable<C<int>>);
> +static_assert(ref_equality_comparable<D<int>>);
> +#include <string_view>
> +static_assert(ref_equality_comparable<std::string_view>);
> +
> +template <typename T>
> +struct ValArray {
> + friend auto operator==(ValArray const&, ValArray const&) -> ValArray<bool> {
> + return {};
> + }
> +};
> +
> +void f(ValArray<int> v) {
> + // this is valid and has type ValArray<bool>
> + v == v;
> +
> + // this is also valid today and has the same type
> + std::ref(v) == std::ref(v);
> +}
> +
> +struct ComparesAsInt {
> + friend auto operator==(ComparesAsInt, ComparesAsInt) -> int;
> +};
> +
> +auto f(std::reference_wrapper<ComparesAsInt> a,
> + std::reference_wrapper<ComparesAsInt> b) {
> + // today: compiles and returns int
> + // proposed: compiles and returns bool
> + return a == b;
> +}
> +
> +ComparesAsInt& c();
> +static_assert( std::is_same_v<decltype(f(c(), c())), bool> );
> --
> 2.44.0
>
next prev parent reply other threads:[~2024-04-15 18:30 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-04-10 8:45 [PATCH 1/4] libstdc++: Heterogeneous std::pair comparisons [PR113386] Jonathan Wakely
2024-04-10 8:45 ` [PATCH 2/4] libstdc++: Add std::reference_wrapper comparison operators for C++26 Jonathan Wakely
2024-04-15 18:30 ` Jonathan Wakely [this message]
2024-04-10 8:45 ` [PATCH 3/4] libstdc++: Constrain equality ops for std::pair, std::tuple, std::variant Jonathan Wakely
2024-04-10 8:45 ` [PATCH 4/4] libstdc++: Simplify std::variant comparison operators Jonathan Wakely
2024-04-10 10:45 ` [PATCH 5/4] libstdc++: Rewrite std::variant comparisons without macros Jonathan Wakely
2024-05-07 13:45 ` [PATCH 4/4] libstdc++: Simplify std::variant comparison operators Jonathan Wakely
2024-04-15 18:29 ` [PATCH 1/4] libstdc++: Heterogeneous std::pair comparisons [PR113386] Jonathan Wakely
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CACb0b4mLOOD72H9BDDO6dg9YFrpov4erEB3ZTFO9AVGyrvtSQQ@mail.gmail.com \
--to=jwakely@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=libstdc++@gcc.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).