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 <compare>
#include <cstddef>
///////////////////////////////////////////////////////////////////////////////
namespace cruft::coord {
/// A StrictWeakOrder over coordinate types.
template <typename CoordT = void>
struct ordering;
/// A StrictWeakOrder over coordinate types.
///
/// The comparison operates across successive elements of the two
/// coordinates.
template <typename CoordT>
struct ordering {
bool operator() (
CoordT const &a,
CoordT const &b
) const noexcept {
for (std::size_t i = 0; i < CoordT::elements; ++i) {
if (a[i] < b[i])
return true;
else if (a[i] > b[i])
return false;
}
std::weak_ordering
element_ordering (
CoordT const &a,
CoordT const &b
) noexcept {
for (std::size_t i = 0; i < CoordT::elements; ++i)
if (auto cmp = a[i] <=> b[i]; cmp != 0)
return cmp;
return false;
}
};
return std::weak_ordering::equivalent;
}
/// A StrictWeakOrder over coordinate types.
///
/// Deduction is deferred until the function is called, in the same way
/// that std::less<> operates.
template <>
struct ordering<void> {
template <typename = void>
struct ordering {
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 {
cruft::point2i a;
cruft::point2i b;
bool expected;
std::weak_ordering expected;
char const *message;
} const TESTS[] {
{ { 0, 0 }, { 0, 0 }, false, "equal zeroes" },
{ { 1, 0 }, { 0, 0 }, false, "a, leading high" },
{ { 0, 1 }, { 0, 0 }, false, "a, trailing high" },
{ { 0, 0 }, { 1, 0 }, true, "b, leading high" },
{ { 0, 0 }, { 0, 1 }, true, "b, trailing high" },
{ { 0, 0 }, { 0, 0 }, std::weak_ordering::equivalent, "equal zeroes" },
{ { 1, 0 }, { 0, 0 }, std::weak_ordering::greater, "a, leading high" },
{ { 0, 1 }, { 0, 0 }, std::weak_ordering::greater, "a, trailing high" },
{ { 0, 0 }, { 1, 0 }, std::weak_ordering::less, "b, leading high" },
{ { 0, 0 }, { 0, 1 }, std::weak_ordering::less, "b, trailing high" },
};
cruft::coord::ordering<cruft::point2i> const comp;
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 ();