coord/comparator: convert to use std::weak_ordering

This allows more flexibility in some client code (eg, calling this to
sort compound objects like region).
This commit is contained in:
Danny Robson 2020-10-21 14:03:08 +10:00
parent b0ac349f70
commit 5a7613d3f3
2 changed files with 24 additions and 31 deletions

View File

@ -10,48 +10,42 @@
#include "base.hpp" #include "base.hpp"
#include <compare>
#include <cstddef> #include <cstddef>
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
namespace cruft::coord { namespace cruft::coord {
/// A StrictWeakOrder over coordinate types.
template <typename CoordT = void>
struct ordering;
/// A StrictWeakOrder over coordinate types. /// A StrictWeakOrder over coordinate types.
/// ///
/// The comparison operates across successive elements of the two /// The comparison operates across successive elements of the two
/// coordinates. /// coordinates.
template <typename CoordT> template <typename CoordT>
struct ordering { std::weak_ordering
bool operator() ( element_ordering (
CoordT const &a, CoordT const &a,
CoordT const &b CoordT const &b
) const noexcept { ) noexcept {
for (std::size_t i = 0; i < CoordT::elements; ++i) { for (std::size_t i = 0; i < CoordT::elements; ++i)
if (a[i] < b[i]) if (auto cmp = a[i] <=> b[i]; cmp != 0)
return true; return cmp;
else if (a[i] > b[i])
return false;
}
return false; return std::weak_ordering::equivalent;
} }
};
/// A StrictWeakOrder over coordinate types. /// A StrictWeakOrder over coordinate types.
/// ///
/// Deduction is deferred until the function is called, in the same way /// Deduction is deferred until the function is called, in the same way
/// that std::less<> operates. /// that std::less<> operates.
template <> template <typename = void>
struct ordering<void> { struct ordering {
template <typename CoordT> template <typename CoordT>
bool operator() (CoordT const &a, CoordT const &b) const noexcept bool
operator() (CoordT const &a, CoordT const &b) const noexcept
{ {
return ordering<CoordT> {} (a, b); return element_ordering<CoordT> (a, b) < 0;
} }
}; };
} }

View File

@ -132,19 +132,18 @@ main (void)
struct { struct {
cruft::point2i a; cruft::point2i a;
cruft::point2i b; cruft::point2i b;
bool expected; std::weak_ordering expected;
char const *message; char const *message;
} const TESTS[] { } const TESTS[] {
{ { 0, 0 }, { 0, 0 }, false, "equal zeroes" }, { { 0, 0 }, { 0, 0 }, std::weak_ordering::equivalent, "equal zeroes" },
{ { 1, 0 }, { 0, 0 }, false, "a, leading high" }, { { 1, 0 }, { 0, 0 }, std::weak_ordering::greater, "a, leading high" },
{ { 0, 1 }, { 0, 0 }, false, "a, trailing high" }, { { 0, 1 }, { 0, 0 }, std::weak_ordering::greater, "a, trailing high" },
{ { 0, 0 }, { 1, 0 }, true, "b, leading high" }, { { 0, 0 }, { 1, 0 }, std::weak_ordering::less, "b, leading high" },
{ { 0, 0 }, { 0, 1 }, true, "b, trailing high" }, { { 0, 0 }, { 0, 1 }, std::weak_ordering::less, "b, trailing high" },
}; };
cruft::coord::ordering<cruft::point2i> const comp;
for (auto const &t: TESTS) for (auto const &t: TESTS)
tap.expect (comp (t.a, t.b) == t.expected, "ordering; %!", t.message); tap.expect (cruft::coord::element_ordering (t.a, t.b) == t.expected, "ordering; %!", t.message);
} }
return tap.status (); return tap.status ();