From ab3587d2f66f3b238b139f741284b4b4c90902f0 Mon Sep 17 00:00:00 2001 From: Nana Sakisaka <1901813+saki7@users.noreply.github.com> Date: Fri, 23 May 2025 00:10:55 +0900 Subject: [PATCH] Correctly promote `partial | promote(partial)` --- include/yk/compare/comparator.hpp | 10 ++++++++-- test/compare.cpp | 20 +++++++++++++++++--- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/include/yk/compare/comparator.hpp b/include/yk/compare/comparator.hpp index e5e5e043..d866ee36 100644 --- a/include/yk/compare/comparator.hpp +++ b/include/yk/compare/comparator.hpp @@ -280,8 +280,14 @@ struct promote_comparator : comparator_interface { const auto res = std::invoke(comp1, x, y); if constexpr (std::same_as) { - if (res == From::equivalent) return std::invoke(comp2, x, y); - return res; + if constexpr (std::same_as) { + if (res == From::equivalent || res == From::unordered) return std::invoke(comp2, x, y); + return res; + + } else { + if (res == From::equivalent) return std::invoke(comp2, x, y); + return res; + } } else { if (res == From::less) return To::less; diff --git a/test/compare.cpp b/test/compare.cpp index 45b98444..32f24f49 100644 --- a/test/compare.cpp +++ b/test/compare.cpp @@ -434,17 +434,31 @@ BOOST_AUTO_TEST_CASE(ClosureTypeTraits) } } +struct PartialPartial +{ + double a, b; + std::partial_ordering operator<=>(const PartialPartial&) const noexcept = default; +}; + BOOST_AUTO_TEST_CASE(promotion) { using namespace yk::comparators; + constexpr double NaN = std::numeric_limits::quiet_NaN(); + // partial | promote(partial) { const auto partial_comparator = [](double a, double b) -> std::partial_ordering { return a <=> b; }; auto comp = partial_comparator | promote(partial_comparator); BOOST_TEST((comp(3.14, 1.41) == std::partial_ordering::greater)); - BOOST_TEST((comp(3.14, std::numeric_limits::quiet_NaN()) == std::partial_ordering::unordered)); + BOOST_TEST((comp(3.14, NaN) == std::partial_ordering::unordered)); + } + { + auto comp = extract(&PartialPartial::a) | promote(extract(&PartialPartial::b)); + BOOST_TEST((comp(PartialPartial{1.0, NaN}, PartialPartial{2.0, NaN}) == std::partial_ordering::less)); + BOOST_TEST(((PartialPartial{NaN, 1.0} <=> PartialPartial{NaN, 2.0}) == std::partial_ordering::unordered)); + BOOST_TEST((comp(PartialPartial{NaN, 1.0}, PartialPartial{NaN, 2.0}) == std::partial_ordering::less)); } // partial | promote(weak) @@ -454,7 +468,7 @@ BOOST_AUTO_TEST_CASE(promotion) auto comp = partial_comparator | promote(weak_comparator); BOOST_TEST((comp(3.14, 1.41) == std::weak_ordering::greater)); - BOOST_TEST((comp(3.14, std::numeric_limits::quiet_NaN()) == std::weak_ordering::less)); + BOOST_TEST((comp(3.14, NaN) == std::weak_ordering::less)); } // partial | promote(strong) @@ -464,7 +478,7 @@ BOOST_AUTO_TEST_CASE(promotion) auto comp = partial_comparator | promote(strong_comparator); BOOST_TEST((comp(3.14, 1.41) == std::strong_ordering::greater)); - BOOST_TEST((comp(3.14, std::numeric_limits::quiet_NaN()) == std::strong_ordering::less)); + BOOST_TEST((comp(3.14, NaN) == std::strong_ordering::less)); } // weak | promote(weak)