From b55156bed4a56b2e9af46e0d17adc092ac16342e Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 8 Jun 2023 17:55:22 +0200 Subject: concepts: replace relational traits --- source/lib/include/newtype/concepts.hpp | 60 +++++++ .../newtype/impl/type_traits_extensions.hpp | 113 ------------ source/lib/include/newtype/newtype.hpp | 20 +-- source/tests/src/relational_operators.cpp | 198 ++++++++------------- 4 files changed, 141 insertions(+), 250 deletions(-) diff --git a/source/lib/include/newtype/concepts.hpp b/source/lib/include/newtype/concepts.hpp index 8f94a42..a50b2b3 100644 --- a/source/lib/include/newtype/concepts.hpp +++ b/source/lib/include/newtype/concepts.hpp @@ -42,6 +42,66 @@ namespace nt::concepts } noexcept; }; + template + concept less_than_comparable = requires(SubjectType lhs, SubjectType rhs) { + { + lhs < rhs + } -> std::convertible_to; + }; + + template + concept nothrow_less_than_comparable = requires(SubjectType lhs, SubjectType rhs) { + requires less_than_comparable; + { + lhs < rhs + } noexcept; + }; + + template + concept less_than_equal_comparable = requires(SubjectType lhs, SubjectType rhs) { + { + lhs <= rhs + } -> std::convertible_to; + }; + + template + concept nothrow_less_than_equal_comparable = requires(SubjectType lhs, SubjectType rhs) { + requires less_than_equal_comparable; + { + lhs <= rhs + } noexcept; + }; + + template + concept greater_than_comparable = requires(SubjectType lhs, SubjectType rhs) { + { + lhs > rhs + } -> std::convertible_to; + }; + + template + concept nothrow_greater_than_comparable = requires(SubjectType lhs, SubjectType rhs) { + requires greater_than_comparable; + { + lhs > rhs + } noexcept; + }; + + template + concept greater_than_equal_comparable = requires(SubjectType lhs, SubjectType rhs) { + { + lhs >= rhs + } -> std::convertible_to; + }; + + template + concept nothrow_greater_than_equal_comparable = requires(SubjectType lhs, SubjectType rhs) { + requires greater_than_equal_comparable; + { + lhs >= rhs + } noexcept; + }; + } // namespace comparability inline namespace iostreamable diff --git a/source/lib/include/newtype/impl/type_traits_extensions.hpp b/source/lib/include/newtype/impl/type_traits_extensions.hpp index 22834f2..c2caf51 100644 --- a/source/lib/include/newtype/impl/type_traits_extensions.hpp +++ b/source/lib/include/newtype/impl/type_traits_extensions.hpp @@ -11,119 +11,6 @@ namespace nt::impl { - inline namespace relationally_comparable - { - - template - struct is_less_than_comparable : std::false_type - { - }; - - template - struct is_less_than_comparable() < std::declval())>> : std::true_type - { - }; - - template - auto constexpr is_less_than_comparable_v = is_less_than_comparable::value; - - template - struct is_nothrow_less_than_comparable : std::false_type - { - }; - - template - struct is_nothrow_less_than_comparable() < std::declval())>> - : std::bool_constant() < std::declval())> - { - }; - - template - auto constexpr is_nothrow_less_than_comparable_v = is_nothrow_less_than_comparable::value; - - template - struct is_greater_than_comparable : std::false_type - { - }; - - template - struct is_greater_than_comparable() > std::declval())>> : std::true_type - { - }; - - template - auto constexpr is_greater_than_comparable_v = is_greater_than_comparable::value; - - template - struct is_nothrow_greater_than_comparable : std::false_type - { - }; - - template - struct is_nothrow_greater_than_comparable() > std::declval())>> - : std::bool_constant() > std::declval())> - { - }; - - template - auto constexpr is_nothrow_greater_than_comparable_v = is_nothrow_greater_than_comparable::value; - - template - struct is_less_than_equal_to_comparable : std::false_type - { - }; - - template - struct is_less_than_equal_to_comparable() <= std::declval())>> : std::true_type - { - }; - - template - auto constexpr is_less_than_equal_to_comparable_v = is_less_than_equal_to_comparable::value; - - template - struct is_nothrow_less_than_equal_to_comparable : std::false_type - { - }; - - template - struct is_nothrow_less_than_equal_to_comparable() <= std::declval())>> - : std::bool_constant() <= std::declval())> - { - }; - - template - auto constexpr is_nothrow_less_than_equal_to_comparable_v = is_nothrow_less_than_equal_to_comparable::value; - - template - struct is_greater_than_equal_to_comparable : std::false_type - { - }; - - template - struct is_greater_than_equal_to_comparable() >= std::declval())>> - : std::true_type - { - }; - - template - auto constexpr is_greater_than_equal_to_comparable_v = is_greater_than_equal_to_comparable::value; - - template - struct is_nothrow_greater_than_equal_to_comparable : std::false_type - { - }; - - template - struct is_nothrow_greater_than_equal_to_comparable() >= std::declval())>> - : std::bool_constant() >= std::declval())> - { - }; - - template - auto constexpr is_nothrow_greater_than_equal_to_comparable_v = is_nothrow_greater_than_equal_to_comparable::value; - } // namespace relationally_comparable - inline namespace arithmetic { diff --git a/source/lib/include/newtype/newtype.hpp b/source/lib/include/newtype/newtype.hpp index e40097d..44bd1b8 100644 --- a/source/lib/include/newtype/newtype.hpp +++ b/source/lib/include/newtype/newtype.hpp @@ -299,38 +299,34 @@ namespace nt return lhs != rhs.decay(); } - template + template auto DerivationClause> auto constexpr operator<(new_type const & lhs, - new_type const & rhs) noexcept(impl::is_nothrow_less_than_comparable_v) - -> std::enable_if_t, bool> + new_type const & rhs) noexcept(nt::concepts::nothrow_less_than_comparable) { return lhs.decay() < rhs.decay(); } - template + template auto DerivationClause> auto constexpr operator>(new_type const & lhs, - new_type const & rhs) noexcept(impl::is_nothrow_greater_than_comparable_v) - -> std::enable_if_t, bool> + new_type const & rhs) noexcept(nt::concepts::nothrow_greater_than_comparable) { return lhs.decay() > rhs.decay(); } - template + template auto DerivationClause> auto constexpr operator<=(new_type const & lhs, - new_type const & rhs) noexcept(impl::is_nothrow_less_than_equal_to_comparable_v) - -> std::enable_if_t, bool> + new_type const & rhs) noexcept(nt::concepts::nothrow_less_than_equal_comparable) { return lhs.decay() <= rhs.decay(); } - template + template auto DerivationClause> auto constexpr operator>=(new_type const & lhs, - new_type const & rhs) noexcept(impl::is_nothrow_greater_than_equal_to_comparable_v) - -> std::enable_if_t, bool> + new_type const & rhs) noexcept(nt::concepts::nothrow_greater_than_equal_comparable) { return lhs.decay() >= rhs.decay(); } diff --git a/source/tests/src/relational_operators.cpp b/source/tests/src/relational_operators.cpp index 95e1bd4..de6f7f3 100644 --- a/source/tests/src/relational_operators.cpp +++ b/source/tests/src/relational_operators.cpp @@ -9,190 +9,121 @@ #include #include -inline namespace traits_extensions -{ - - template - struct has_less_than : std::false_type - { - }; - - template - struct has_less_than() < std::declval())>> : std::true_type - { - }; - - template - auto constexpr has_less_than_v = has_less_than::value; - - template - auto constexpr has_nothrow_less_than_v = has_less_than_v && noexcept(std::declval() < std::declval()); - - template - struct has_greater_than : std::false_type - { - }; - - template - struct has_greater_than() > std::declval())>> : std::true_type - { - }; - - template - auto constexpr has_greater_than_v = has_greater_than::value; - - template - auto constexpr has_nothrow_greater_than_v = has_less_than_v && noexcept(std::declval() < std::declval()); - - template - struct has_less_than_equal_to : std::false_type - { - }; - - template - struct has_less_than_equal_to() <= std::declval())>> : std::true_type - { - }; - - template - auto constexpr has_less_than_equal_to_v = has_less_than_equal_to::value; - - template - auto constexpr has_nothrow_less_than_equal_to_v = has_less_than_v && noexcept(std::declval() < std::declval()); - - template - struct has_greater_than_equal_to : std::false_type - { - }; - - template - struct has_greater_than_equal_to() >= std::declval())>> : std::true_type - { - }; - - template - auto constexpr has_greater_than_equal_to_v = has_greater_than_equal_to::value; - - template - auto constexpr has_nothrow_greater_than_equal_to_v = has_less_than_v && noexcept(std::declval() < std::declval()); - -} // namespace traits_extensions - SCENARIO("Relational Operator Availability") { GIVEN("A new_type over a relationally comparable type not deriving nt::Relational") { using type_alias = nt::new_type; - static_assert(has_less_than_v); - static_assert(has_less_than_equal_to_v); - static_assert(has_greater_than_v); - static_assert(has_greater_than_equal_to_v); + static_assert(nt::concepts::less_than_comparable); + static_assert(nt::concepts::less_than_equal_comparable); + static_assert(nt::concepts::greater_than_comparable); + static_assert(nt::concepts::greater_than_equal_comparable); THEN("it does not have <") { - STATIC_REQUIRE_FALSE(has_less_than_v); + STATIC_REQUIRE_FALSE(nt::concepts::less_than_comparable); } THEN("it does not have <=") { - STATIC_REQUIRE_FALSE(has_less_than_equal_to_v); + STATIC_REQUIRE_FALSE(nt::concepts::less_than_equal_comparable); } THEN("it does not have >") { - STATIC_REQUIRE_FALSE(has_greater_than_v); + STATIC_REQUIRE_FALSE(nt::concepts::greater_than_comparable); } THEN("it does not have >=") { - STATIC_REQUIRE_FALSE(has_greater_than_equal_to_v); + STATIC_REQUIRE_FALSE(nt::concepts::greater_than_equal_comparable); } } GIVEN("A new_type over a relationally comparable type deriving nt::Relational") { using type_alias = nt::new_type; - static_assert(has_less_than_v); - static_assert(has_less_than_equal_to_v); - static_assert(has_greater_than_v); - static_assert(has_greater_than_equal_to_v); + static_assert(nt::concepts::less_than_comparable); + static_assert(nt::concepts::less_than_equal_comparable); + static_assert(nt::concepts::greater_than_comparable); + static_assert(nt::concepts::greater_than_equal_comparable); THEN("it does have <") { - STATIC_REQUIRE(has_less_than_v); + STATIC_REQUIRE(nt::concepts::less_than_comparable); } THEN("it does have <=") { - STATIC_REQUIRE(has_less_than_equal_to_v); + STATIC_REQUIRE(nt::concepts::less_than_equal_comparable); } THEN("it does have >") { - STATIC_REQUIRE(has_greater_than_v); + STATIC_REQUIRE(nt::concepts::greater_than_comparable); } THEN("it does have >=") { - STATIC_REQUIRE(has_greater_than_equal_to_v); + STATIC_REQUIRE(nt::concepts::greater_than_equal_comparable); } } GIVEN("A new_type over a type that is not relationally comparable not deriving nt::Relational") { using type_alias = nt::new_type; - static_assert(!has_less_than_v); - static_assert(!has_less_than_equal_to_v); - static_assert(!has_greater_than_v); - static_assert(!has_greater_than_equal_to_v); + static_assert(!nt::concepts::less_than_comparable); + static_assert(!nt::concepts::less_than_equal_comparable); + static_assert(!nt::concepts::greater_than_comparable); + static_assert(!nt::concepts::greater_than_equal_comparable); THEN("it does not have <") { - STATIC_REQUIRE_FALSE(has_less_than_v); + STATIC_REQUIRE_FALSE(nt::concepts::less_than_comparable); } THEN("it does not have <=") { - STATIC_REQUIRE_FALSE(has_less_than_equal_to_v); + STATIC_REQUIRE_FALSE(nt::concepts::less_than_equal_comparable); } THEN("it does not have >") { - STATIC_REQUIRE_FALSE(has_greater_than_v); + STATIC_REQUIRE_FALSE(nt::concepts::greater_than_comparable); } THEN("it does not have >=") { - STATIC_REQUIRE_FALSE(has_greater_than_equal_to_v); + STATIC_REQUIRE_FALSE(nt::concepts::greater_than_equal_comparable); } } GIVEN("A new_type over a type that is not relationally comparable deriving nt::Relational") { using type_alias = nt::new_type; - static_assert(!has_less_than_v); - static_assert(!has_less_than_equal_to_v); - static_assert(!has_greater_than_v); - static_assert(!has_greater_than_equal_to_v); + static_assert(!nt::concepts::less_than_comparable); + static_assert(!nt::concepts::less_than_equal_comparable); + static_assert(!nt::concepts::greater_than_comparable); + static_assert(!nt::concepts::greater_than_equal_comparable); THEN("it does not have <") { - STATIC_REQUIRE_FALSE(has_less_than_v); + STATIC_REQUIRE_FALSE(nt::concepts::less_than_comparable); } THEN("it does not have <=") { - STATIC_REQUIRE_FALSE(has_less_than_equal_to_v); + STATIC_REQUIRE_FALSE(nt::concepts::less_than_equal_comparable); } THEN("it does not have >") { - STATIC_REQUIRE_FALSE(has_greater_than_v); + STATIC_REQUIRE_FALSE(nt::concepts::greater_than_comparable); } THEN("it does not have >=") { - STATIC_REQUIRE_FALSE(has_greater_than_equal_to_v); + STATIC_REQUIRE_FALSE(nt::concepts::greater_than_equal_comparable); } } } @@ -202,10 +133,10 @@ SCENARIO("Relational Comparisons") GIVEN("A new_type over a relationally comparable type deriving nt::Relational") { using type_alias = nt::new_type; - static_assert(has_less_than_v); - static_assert(has_less_than_equal_to_v); - static_assert(has_greater_than_v); - static_assert(has_greater_than_equal_to_v); + static_assert(nt::concepts::less_than_comparable); + static_assert(nt::concepts::less_than_equal_comparable); + static_assert(nt::concepts::greater_than_comparable); + static_assert(nt::concepts::greater_than_equal_comparable); THEN("comparing two instances using < yields the same result as it does for the base type") { @@ -238,29 +169,29 @@ SCENARIO("Nothrow Relational Comparison") GIVEN("A new_type over a nothrow relationally comparable type deriving nt::Relational") { using type_alias = nt::new_type; - static_assert(has_nothrow_less_than_v); - static_assert(has_nothrow_less_than_equal_to_v); - static_assert(has_nothrow_greater_than_v); - static_assert(has_nothrow_greater_than_equal_to_v); + static_assert(nt::concepts::nothrow_less_than_comparable); + static_assert(nt::concepts::nothrow_less_than_equal_comparable); + static_assert(nt::concepts::nothrow_greater_than_comparable); + static_assert(nt::concepts::nothrow_greater_than_equal_comparable); THEN("it is nothrow-comparable using < ") { - STATIC_REQUIRE(has_nothrow_less_than_v); + STATIC_REQUIRE(nt::concepts::nothrow_less_than_comparable); } THEN("it is nothrow-comparable using <= ") { - STATIC_REQUIRE(has_nothrow_less_than_equal_to_v); + STATIC_REQUIRE(nt::concepts::nothrow_less_than_equal_comparable); } THEN("it is nothrow-comparable using > ") { - STATIC_REQUIRE(has_nothrow_greater_than_v); + STATIC_REQUIRE(nt::concepts::nothrow_greater_than_comparable); } THEN("it is nothrow-comparable using >= ") { - STATIC_REQUIRE(has_nothrow_greater_than_equal_to_v); + STATIC_REQUIRE(nt::concepts::nothrow_greater_than_equal_comparable); } } @@ -268,36 +199,53 @@ SCENARIO("Nothrow Relational Comparison") { struct strange_type { - auto constexpr operator<(strange_type const & other) const noexcept(false) -> bool; - auto constexpr operator>(strange_type const & other) const noexcept(false) -> bool; - auto constexpr operator<=(strange_type const & other) const noexcept(false) -> bool; - auto constexpr operator>=(strange_type const & other) const noexcept(false) -> bool; + auto constexpr operator<(strange_type const &) const noexcept(false) -> bool + { + return false; + } + auto constexpr operator>(strange_type const &) const noexcept(false) -> bool + { + return false; + } + auto constexpr operator<=(strange_type const &) const noexcept(false) -> bool + { + return false; + } + auto constexpr operator>=(strange_type const &) const noexcept(false) -> bool + { + return false; + } }; using type_alias = nt::new_type; - static_assert(has_less_than_v && !has_nothrow_less_than_v); - static_assert(has_less_than_equal_to_v && !has_nothrow_less_than_equal_to_v); - static_assert(has_greater_than_v && !has_nothrow_greater_than_v); - static_assert(has_greater_than_equal_to_v && !has_nothrow_greater_than_equal_to_v); + static_assert(nt::concepts::less_than_comparable && + !nt::concepts::nothrow_less_than_comparable); + static_assert(nt::concepts::less_than_equal_comparable && + !nt::concepts::nothrow_less_than_equal_comparable); + static_assert(nt::concepts::greater_than_comparable && + !nt::concepts::nothrow_greater_than_comparable); + static_assert(nt::concepts::greater_than_equal_comparable && + !nt::concepts::nothrow_greater_than_equal_comparable); THEN("it is not nothrow-comparable using < ") { - STATIC_REQUIRE(has_less_than_v && !has_nothrow_less_than_v); + STATIC_REQUIRE(nt::concepts::less_than_comparable && !nt::concepts::nothrow_less_than_comparable); } THEN("it is not nothrow-comparable using <= ") { - STATIC_REQUIRE(has_less_than_equal_to_v && !has_nothrow_less_than_equal_to_v); + STATIC_REQUIRE(nt::concepts::less_than_equal_comparable && !nt::concepts::nothrow_less_than_equal_comparable); } THEN("it is not nothrow-comparable using > ") { - STATIC_REQUIRE(has_greater_than_v && !has_nothrow_greater_than_v); + STATIC_REQUIRE(nt::concepts::greater_than_comparable && !nt::concepts::nothrow_greater_than_comparable); } THEN("it is not nothrow-comparable using >= ") { - STATIC_REQUIRE(has_greater_than_equal_to_v && !has_nothrow_greater_than_equal_to_v); + STATIC_REQUIRE(nt::concepts::greater_than_equal_comparable && + !nt::concepts::nothrow_greater_than_equal_comparable); } } } -- cgit v1.2.3