Date: Tue, 26 Jan 2021 22:35:32 +0100
Hi,
I noticed a discrepancy for between std::compare_three_way_result and
std::three_way_comparable. The standard defines them as follows:
template<class T, class U = T>
using compare_three_way_result_t = decltype(
std::declval<const std::remove_reference_t<T>&>() <=>
std::declval<const std::remove_reference_t<U>&>()
);
[1] and
template<class T, class Cat = partial_ordering>
concept three_way_comparable =
weakly-equality-comparable-with<T, T> &&
partially-ordered-with<T, T> &&
requires(const remove_reference_t<T>& a, const
remove_reference_t<T>& b) {
{ a <=> b } -> compares-as<Cat>;
};
[2] where
template<class T, class U>
concept weakly-equality-comparable-with = // exposition only
requires(const remove_reference_t<T>& t,
const remove_reference_t<U>& u) {
{ t == u } -> boolean-testable;
{ t != u } -> boolean-testable;
{ u == t } -> boolean-testable;
{ u != t } -> boolean-testable;
};
[3] Now, if you write a class like this
struct foo {
std::strong_ordering operator<=>(const foo&) {
// Some non-defaulted implementation
}
};
it holds
static_assert(std::is_same_v<std::compare_three_way_result_t<foo,foo>,
std::strong_ordering>>);
static_assert(!std::three_way_comparable<foo>);
This comes from the fact, that paper P1185 [4] disallows obtaining
operator== from operator<=>. I concur with the reasoning in that paper,
but the discrepancy between compare_three_way_result and
three_way_comparable seems counter-intuitive to me. It also has effects
such as:
foo{} <=> foo{}; // is fine
std::optional<foo>{} <=> std::optional<foo>{} // ill-formed
since operator<=> for optional<T> requires three_way_comparable<T>.
Is there a reason for this behavior that I am not aware of? If not, I
would propose that compare_three_way_result_t<T,U> should require
three_way_comparable_with<T,U> to fix this.
Best Wishes,
Nicholas
Links for the above:
[1] http://eel.is/c++draft/cmp#result
[2] http://eel.is/c++draft/cmp#concept:three_way_comparable
[3]
http://eel.is/c++draft/concept.equalitycomparable#concept:weakly-equality-comparable-with
[4] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1185r2.html
I noticed a discrepancy for between std::compare_three_way_result and
std::three_way_comparable. The standard defines them as follows:
template<class T, class U = T>
using compare_three_way_result_t = decltype(
std::declval<const std::remove_reference_t<T>&>() <=>
std::declval<const std::remove_reference_t<U>&>()
);
[1] and
template<class T, class Cat = partial_ordering>
concept three_way_comparable =
weakly-equality-comparable-with<T, T> &&
partially-ordered-with<T, T> &&
requires(const remove_reference_t<T>& a, const
remove_reference_t<T>& b) {
{ a <=> b } -> compares-as<Cat>;
};
[2] where
template<class T, class U>
concept weakly-equality-comparable-with = // exposition only
requires(const remove_reference_t<T>& t,
const remove_reference_t<U>& u) {
{ t == u } -> boolean-testable;
{ t != u } -> boolean-testable;
{ u == t } -> boolean-testable;
{ u != t } -> boolean-testable;
};
[3] Now, if you write a class like this
struct foo {
std::strong_ordering operator<=>(const foo&) {
// Some non-defaulted implementation
}
};
it holds
static_assert(std::is_same_v<std::compare_three_way_result_t<foo,foo>,
std::strong_ordering>>);
static_assert(!std::three_way_comparable<foo>);
This comes from the fact, that paper P1185 [4] disallows obtaining
operator== from operator<=>. I concur with the reasoning in that paper,
but the discrepancy between compare_three_way_result and
three_way_comparable seems counter-intuitive to me. It also has effects
such as:
foo{} <=> foo{}; // is fine
std::optional<foo>{} <=> std::optional<foo>{} // ill-formed
since operator<=> for optional<T> requires three_way_comparable<T>.
Is there a reason for this behavior that I am not aware of? If not, I
would propose that compare_three_way_result_t<T,U> should require
three_way_comparable_with<T,U> to fix this.
Best Wishes,
Nicholas
Links for the above:
[1] http://eel.is/c++draft/cmp#result
[2] http://eel.is/c++draft/cmp#concept:three_way_comparable
[3]
http://eel.is/c++draft/concept.equalitycomparable#concept:weakly-equality-comparable-with
[4] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1185r2.html
Received on 2021-01-26 15:35:37