From 9927206e62ac74b1c01feec4141a09777eb18cbd Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Wed, 4 Oct 2023 09:42:23 +0800 Subject: [PATCH] implement threeway comparison --- include/semver.hpp | 16 ++++++++++++++++ test/test.cpp | 27 +++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/include/semver.hpp b/include/semver.hpp index 5f1d9d6..459f8df 100644 --- a/include/semver.hpp +++ b/include/semver.hpp @@ -76,6 +76,11 @@ # pragma clang diagnostic ignored "-Wmissing-braces" // Ignore warning: suggest braces around initialization of subobject 'return {first, std::errc::invalid_argument};'. #endif +#if __cpp_impl_three_way_comparison >= 201907L +#include +#endif + + namespace semver { enum struct prerelease : std::uint8_t { @@ -482,6 +487,17 @@ struct version { return lhs.compare(rhs) <= 0; } +#if __cpp_impl_three_way_comparison >= 201907L +[[nodiscard]] constexpr std::strong_ordering operator<=>(const version& lhs, const version& rhs) { + int compare = lhs.compare(rhs); + if ( compare == 0 ) + return std::strong_ordering::equal; + if ( compare > 0 ) + return std::strong_ordering::greater; + return std::strong_ordering::less; +} +#endif + [[nodiscard]] constexpr version operator""_version(const char* str, std::size_t length) { return version{std::string_view{str, length}}; } diff --git a/test/test.cpp b/test/test.cpp index fb0172f..a898c3e 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -406,6 +406,33 @@ TEST_CASE("operators") { } } +#if __cpp_impl_three_way_comparison >= 201907L + SECTION("operator <=>") { + constexpr version v1{1, 2, 3, prerelease::rc, 4}; + constexpr version v2{1, 2, 3}; + constexpr version v3{1, 2, 3}; + REQUIRE(v1 <=> v1 == std::strong_ordering::equal); + REQUIRE(v2 <=> v3 == std::strong_ordering::equal); + + auto validate_threeway_compare = [] (auto v1, auto v2) { + if (v1 < v2) + REQUIRE(v1 <=> v2 == std::strong_ordering::less); + else if (v1 > v2) + REQUIRE(v1 <=> v2 == std::strong_ordering::greater); + else if (v1 == v2) + REQUIRE(v1 <=> v2 == std::strong_ordering::equal); + }; + + for (std::size_t i = 1; i < versions.size(); ++i) { + for (std::size_t j = 1; j < i; ++j) { + version v = versions[i - j]; + validate_threeway_compare(versions[i - j], versions[i]); + validate_threeway_compare(v, versions[i - j]); + } + } + } +#endif + SECTION("operator _version") { constexpr version v = "1.2.3-rc.4"_version; static_assert(v == version{1, 2, 3, prerelease::rc, 4});