From 0f2c94a59de9837a1eee7b849d309088c4be8154 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 9 Jun 2023 20:45:11 +0200 Subject: new_type: implement basic spaceship support --- source/lib/include/newtype/newtype.hpp | 22 +++++++++++++- source/tests/CMakeLists.txt | 17 +++++------ source/tests/src/threeway_comparison.cpp | 52 ++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 10 deletions(-) create mode 100644 source/tests/src/threeway_comparison.cpp diff --git a/source/lib/include/newtype/newtype.hpp b/source/lib/include/newtype/newtype.hpp index 8e7729b..3654afd 100644 --- a/source/lib/include/newtype/newtype.hpp +++ b/source/lib/include/newtype/newtype.hpp @@ -747,6 +747,7 @@ namespace nt auto constexpr Read = derivable{}; auto constexpr Relational = derivable{}; auto constexpr Show = derivable{}; + auto constexpr ThreewayCompare = derivable{}; } // namespace derivables @@ -767,6 +768,9 @@ namespace nt template concept derives = requires(DerivationClause clause) { requires DerivationClause::template derives::value; }; + template + concept doesnt_derive = !derives; + template auto constexpr deriving(derivable... features) noexcept -> derivation_clause { @@ -780,6 +784,8 @@ namespace nt { static_assert(!std::is_reference_v, "The base type must not be a reference type"); static_assert(!std::is_void_v>, "The base type must not be possibly cv-qualified void"); + static_assert(!derives, + "Cannot derive both nt::Relational and nt::ThreewayCompare at the same time."); template + template auto DerivationClause> auto constexpr operator==(new_type const & lhs, new_type const & rhs) noexcept(nt::concepts::nothrow_equality_comparable) -> bool @@ -993,6 +999,13 @@ namespace nt return lhs.decay() == rhs.decay(); } + template auto DerivationClause> + auto constexpr operator==(new_type const & lhs, + new_type const & rhs) -> bool + { + return lhs.decay() == rhs.decay(); + } + template auto DerivationClause> auto constexpr operator==(new_type const & lhs, BaseType const & rhs) noexcept(nt::concepts::nothrow_equality_comparable) -> bool @@ -1008,6 +1021,13 @@ namespace nt return lhs == rhs.decay(); } + template auto DerivationClause> + auto constexpr operator<=>(new_type const & lhs, + new_type const & rhs) + { + return lhs.decay() <=> rhs.decay(); + } + template auto constexpr operator!=(new_type const & lhs, diff --git a/source/tests/CMakeLists.txt b/source/tests/CMakeLists.txt index ce6b707..47b8331 100644 --- a/source/tests/CMakeLists.txt +++ b/source/tests/CMakeLists.txt @@ -6,16 +6,15 @@ find_package("Catch2" "3.1" include("CTest") include("Catch") +file(GLOB SOURCES + RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" + CONFIGURE_DEPENDS + "src/*.cpp" +) + + add_executable("${PROJECT_NAME}_tests" - "src/arithmetic.cpp" - "src/constructors.cpp" - "src/conversion.cpp" - "src/derivation_clause.cpp" - "src/equality_comparison.cpp" - "src/hash.cpp" - "src/io_operators.cpp" - "src/iterable.cpp" - "src/relational_operators.cpp" + ${SOURCES} ) target_link_libraries("${PROJECT_NAME}_tests" diff --git a/source/tests/src/threeway_comparison.cpp b/source/tests/src/threeway_comparison.cpp new file mode 100644 index 0000000..ddca7f3 --- /dev/null +++ b/source/tests/src/threeway_comparison.cpp @@ -0,0 +1,52 @@ +#include "newtype/newtype.hpp" + +#include +#include + +#include +#include +#include + +TEMPLATE_TEST_CASE("Scenario: Three-way Comparison", "[comparison]", int, std::string, std::vector) +{ + GIVEN("A new_type over a <=> comparable base type deriving nt::ThreewayCompare") + { + using type_alias = nt::new_type; + static_assert(std::three_way_comparable); + + THEN("it is equality-comparable") + { + STATIC_REQUIRE(std::equality_comparable); + } + + THEN("it is inequality-comparable") + { + STATIC_REQUIRE(nt::concepts::inequality_comparable); + } + + THEN("it is three-way comparable") + { + STATIC_REQUIRE(std::three_way_comparable); + } + + THEN("it is less-than comparable") + { + STATIC_REQUIRE(nt::concepts::less_than_comparable); + } + + THEN("it is less-than-equal comparable") + { + STATIC_REQUIRE(nt::concepts::greater_than_equal_comparable); + } + + THEN("it is greater-than comparable") + { + STATIC_REQUIRE(nt::concepts::less_than_comparable); + } + + THEN("it is greater-than-equal comparable") + { + STATIC_REQUIRE(nt::concepts::greater_than_equal_comparable); + } + } +} \ No newline at end of file -- cgit v1.2.3