[libcxx-commits] [PATCH] D107721: [libc++][spaceship] Implement std::pair::operator<=>
Kent Ross via Phabricator via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Sep 12 18:42:54 PDT 2021
mumbleskates added inline comments.
================
Comment at: libcxx/include/utility:107
+ synth-three-way-result<T2> >
+ operator<=>(const pair<T1,T2>&, const pair<T1,T2>&); // C++20
----------------
Quuxplusone wrote:
> Nit: I think `// C++20` is indented by 4 too many spaces.
> I'd also cuddle the angle-brackets `>>` on line 106.
> Nit: I think `// C++20` is indented by 4 too many spaces.
It's aligned perfectly with the other comparison operators above it for me. There are no tabs in this file, and dedenting it by 4 doesn't line it up with anything so I'm not sure what you're seeing.
> I'd also cuddle the angle-brackets `>>` on line 106.
Done.
================
Comment at: libcxx/test/std/utilities/utility/pairs/pairs.spec/three_way_comparison.pass.cpp:47-55
+ // Pairs of int (strongly ordered) and double (partially ordered) should compare with partial ordering.
+ assert((std::make_pair(1, 1.0) <=> std::make_pair(1, 2.0)) < 0);
+ assert((std::make_pair(2, 1.0) <=> std::make_pair(1, 1.0)) > 0);
+ assert((std::make_pair(std::numeric_limits<double>::quiet_NaN(), 1)
+ <=> std::make_pair(std::numeric_limits<double>::quiet_NaN(), 2))
+ == std::partial_ordering::unordered);
+ auto same = std::make_pair(0, 0.0) <=> std::make_pair(0, 0.0);
----------------
Quuxplusone wrote:
> How about:
> ```
> using P = std::pair<int, double>;
> using nan = std::numeric_limits<double>::quiet_NaN();
> ASSERT_SAME_TYPE(decltype(P() <=> P()), std::partial_ordering);
> assert((P(1, 1.0) <=> P(1, 2.0)) == std::partial_ordering::less);
> assert((P(1, 1.0) <=> P(1, 1.0)) == std::partial_ordering::equivalent);
> assert((P(1, -0.0) <=> P(1, 0.0)) == std::partial_ordering::equivalent);
> assert((P(1, 2.0) <=> P(1, 1.0)) == std::partial_ordering::greater);
> assert((P(1, nan) <=> P(2, nan)) == std::partial_ordering::less); // because 1 < 2
> assert((P(2, nan) <=> P(1, nan)) == std::partial_ordering::greater); // because 2 > 1
> assert((P(1, nan) <=> P(1, nan)) == std::partial_ordering::unordered);
> assert((P(1, nan) <=> P(1, 1.0)) == std::partial_ordering::unordered);
> ```
>
> And then finally I think we should have a SFINAE test, basically like this (IIUC):
> ```
> template<class T> concept HasEqual = requires(T t) { t == t; };
> template<class T> concept HasLess = requires(T t) { t < t; };
> template<class T> concept HasSpaceship = requires(T t) { t <=> t; };
>
> struct NoCompare {};
> static_assert(HasEqual<std::pair<int, NoCompare>>);
> static_assert(!HasLess<std::pair<int, NoCompare>>);
> static_assert(!HasSpaceship<std::pair<int, NoCompare>>);
> ```
> This SFINAE behavior is a bit bizarre, but it's Standard-conforming IIUC: `(p == p)` is well-formed, it's just going to hard-error if you actually evaluate it.
> `assert((P(1, nan) <=> P(1, 1.0)) == std::partial_ordering::unordered);`
This cannot be evaluated constexpr by GCC, and needs its own non-constexpr-only function. As this is annoying and doesn't particularly add any information that we don't already get by comparing `NaN <=> NaN` to get `unordered`, I've been leaving these cases out. (GCC rules that `A @ B` can't be evaluated constexpr if only one of the operands is NaN; there are similar rules for inf.)
> This SFINAE behavior is a bit bizarre, but it's Standard-conforming IIUC: (p == p) is well-formed, it's just going to hard-error if you actually evaluate it.
Would it be better to define `operator==` in `NoCompare` to make this less strange? How about this, which achieves the same end but is less weird:
```
struct NoRelative {
constexpr bool operator==(const NoRelative&) const = default;
};
static_assert(HasEqual<std::pair<int, NoRelative>>);
static_assert(!HasLess<std::pair<int, NoRelative>>);
static_assert(!HasSpaceship<std::pair<int, NoRelative>>);
```
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D107721/new/
https://reviews.llvm.org/D107721
More information about the libcxx-commits
mailing list