diff options
| -rw-r--r-- | source/lib/include/newtype/newtype.hpp | 22 | ||||
| -rw-r--r-- | source/tests/CMakeLists.txt | 17 | ||||
| -rw-r--r-- | source/tests/src/threeway_comparison.cpp | 52 |
3 files changed, 81 insertions, 10 deletions
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<struct read_tag>{}; auto constexpr Relational = derivable<struct relational_tag>{}; auto constexpr Show = derivable<struct show_tag>{}; + auto constexpr ThreewayCompare = derivable<struct threeway_compare_tag>{}; } // namespace derivables @@ -767,6 +768,9 @@ namespace nt template<typename DerivationClause, auto... Features> concept derives = requires(DerivationClause clause) { requires DerivationClause::template derives<Features...>::value; }; + template<typename DerivationClause, auto... Features> + concept doesnt_derive = !derives<DerivationClause, Features...>; + template<typename... DerivableTags> auto constexpr deriving(derivable<DerivableTags>... features) noexcept -> derivation_clause<DerivableTags...> { @@ -780,6 +784,8 @@ namespace nt { static_assert(!std::is_reference_v<BaseType>, "The base type must not be a reference type"); static_assert(!std::is_void_v<std::remove_cv_t<BaseType>>, "The base type must not be possibly cv-qualified void"); + static_assert(!derives<decltype(DerivationClause), nt::Relational, nt::ThreewayCompare>, + "Cannot derive both nt::Relational and nt::ThreewayCompare at the same time."); template<typename CharType, typename StreamTraits, @@ -985,7 +991,7 @@ namespace nt } }; - template<nt::concepts::equality_comparable BaseType, typename TagType, auto DerivationClause> + template<nt::concepts::equality_comparable BaseType, typename TagType, doesnt_derive<nt::ThreewayCompare> auto DerivationClause> auto constexpr operator==(new_type<BaseType, TagType, DerivationClause> const & lhs, new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(nt::concepts::nothrow_equality_comparable<BaseType>) -> bool @@ -993,6 +999,13 @@ namespace nt return lhs.decay() == rhs.decay(); } + template<std::three_way_comparable BaseType, typename TagType, derives<nt::ThreewayCompare> auto DerivationClause> + auto constexpr operator==(new_type<BaseType, TagType, DerivationClause> const & lhs, + new_type<BaseType, TagType, DerivationClause> const & rhs) -> bool + { + return lhs.decay() == rhs.decay(); + } + template<nt::concepts::equality_comparable BaseType, typename TagType, nt::derives<nt::EqBase> auto DerivationClause> auto constexpr operator==(new_type<BaseType, TagType, DerivationClause> const & lhs, BaseType const & rhs) noexcept(nt::concepts::nothrow_equality_comparable<BaseType>) -> bool @@ -1008,6 +1021,13 @@ namespace nt return lhs == rhs.decay(); } + template<std::three_way_comparable BaseType, typename TagType, nt::derives<nt::ThreewayCompare> auto DerivationClause> + auto constexpr operator<=>(new_type<BaseType, TagType, DerivationClause> const & lhs, + new_type<BaseType, TagType, DerivationClause> const & rhs) + { + return lhs.decay() <=> rhs.decay(); + } + template<nt::concepts::inequality_comparable BaseType, typename TagType, auto DerivationClause> auto constexpr operator!=(new_type<BaseType, TagType, DerivationClause> 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 <catch2/catch_template_test_macros.hpp> +#include <catch2/catch_test_macros.hpp> + +#include <compare> +#include <string> +#include <vector> + +TEMPLATE_TEST_CASE("Scenario: Three-way Comparison", "[comparison]", int, std::string, std::vector<double>) +{ + GIVEN("A new_type over a <=> comparable base type deriving nt::ThreewayCompare") + { + using type_alias = nt::new_type<TestType, struct tag, deriving(nt::ThreewayCompare)>; + static_assert(std::three_way_comparable<TestType>); + + THEN("it is equality-comparable") + { + STATIC_REQUIRE(std::equality_comparable<type_alias>); + } + + THEN("it is inequality-comparable") + { + STATIC_REQUIRE(nt::concepts::inequality_comparable<type_alias>); + } + + THEN("it is three-way comparable") + { + STATIC_REQUIRE(std::three_way_comparable<type_alias>); + } + + THEN("it is less-than comparable") + { + STATIC_REQUIRE(nt::concepts::less_than_comparable<type_alias>); + } + + THEN("it is less-than-equal comparable") + { + STATIC_REQUIRE(nt::concepts::greater_than_equal_comparable<type_alias>); + } + + THEN("it is greater-than comparable") + { + STATIC_REQUIRE(nt::concepts::less_than_comparable<type_alias>); + } + + THEN("it is greater-than-equal comparable") + { + STATIC_REQUIRE(nt::concepts::greater_than_equal_comparable<type_alias>); + } + } +}
\ No newline at end of file |
