I’d like to use a defaulted three-way comparison operator in a recursive data structure, like this:
struct MyStruct {
int i;
std::vector<MyStruct> v;
std::partial_ordering operator<=>(const MyStruct &a) const = default;
};
// Fails: can't infer comparison result type
static_assert(std::same_as<std::compare_three_way_result_t<MyStruct>,
std::partial_ordering>);
Unfortunately, there seems to be a circular dependency, because the defaulted <=>
operator depends on the comparison categories of integer comparison and std::vector, while the vector comparison category depends on the comparison category if its value_type
, namely MyStruct
. The fact that I’ve explicitly declared the comparison type to be std::partial_ordering
doesn’t seem to help, even though it should. In particular, it does work if I implement the function by hand:
struct MyStruct {
int i;
std::vector<MyStruct> v;
std::partial_ordering operator<=>(const MyStruct &other) const {
if (auto r = i <=> other.i; r != 0)
return r;
return v <=> other.v;
}
};
// OK
static_assert(std::same_as<std::compare_three_way_result_t<MyStruct>,
std::partial_ordering>);
My questions:
-
Is there any way to short-circuit this problem? The spec prohibits overloading std::compare_three_way_result, but is there some other way to affect
vector
orstd::lexicographical_compare_three_way
? -
Is there any way, using concepts or requires clauses, to detect an incomplete type? As an alternative, I could design my own vector-like container class that just defaults to
std::partial_ordering
when the type is incomplete.