aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@gmail.com>2020-01-02 22:38:18 +0100
committerFelix Morgner <felix.morgner@gmail.com>2020-01-02 22:39:49 +0100
commitb196e2c10ed8823c681623dfd7bc09b0eb3ad1d2 (patch)
tree68a0670dba2ac95f71189383ce202e08345d9373
parent6998183b580b60ac72f79b3ebc4f206fa35937ac (diff)
downloadnewtype-b196e2c10ed8823c681623dfd7bc09b0eb3ad1d2.tar.xz
newtype-b196e2c10ed8823c681623dfd7bc09b0eb3ad1d2.zip
new_type: implement support for base comparison
-rw-r--r--doc/src/index.rst54
-rw-r--r--include/newtype/new_type.hpp62
-rw-r--r--test/src/equality_comparison_suite.cpp63
3 files changed, 166 insertions, 13 deletions
diff --git a/doc/src/index.rst b/doc/src/index.rst
index 3ef593d..0a92d90 100644
--- a/doc/src/index.rst
+++ b/doc/src/index.rst
@@ -181,6 +181,30 @@ Equality Comparison Operators
.. cpp:function:: template<typename BaseType, \
typename TagType, \
auto DerivationClause> \
+ constexpr bool operator==(new_type<BaseType, TagType, DerivationClause> const &,\
+ BaseType const &)
+
+ **noexcept specification:** This comparison operator shall be noexcept iff. :cpp:type:`new_type<BaseType, TagType, DerivationClause>::base_type` is nothrow equals-comparable.
+
+ **enablement:** This operator shall be available iff. a) :cpp:type:`new_type<BaseType, TagType, DerivationClause>::base_type` supports comparison using the operator :literal:`==` and b) the derivation clause contains :cpp:var:`EqBase`
+
+ .. versionadded:: 1.0.0
+
+.. cpp:function:: template<typename BaseType, \
+ typename TagType, \
+ auto DerivationClause> \
+ constexpr bool operator==(BaseType const &,\
+ new_type<BaseType, TagType, DerivationClause> const &)
+
+ **noexcept specification:** This comparison operator shall be noexcept iff. :cpp:type:`new_type<BaseType, TagType, DerivationClause>::base_type` is nothrow equals-comparable.
+
+ **enablement:** This operator shall be available iff. a) :cpp:type:`new_type<BaseType, TagType, DerivationClause>::base_type` supports comparison using the operator :literal:`==` and b) the derivation clause contains :cpp:var:`EqBase`
+
+ .. versionadded:: 1.0.0
+
+.. cpp:function:: template<typename BaseType, \
+ typename TagType, \
+ auto DerivationClause> \
constexpr bool operator!=(new_type<BaseType, TagType, DerivationClause> const &,\
new_type<BaseType, TagType, DerivationClause> const &)
@@ -190,6 +214,30 @@ Equality Comparison Operators
.. versionadded:: 1.0.0
+.. cpp:function:: template<typename BaseType, \
+ typename TagType, \
+ auto DerivationClause> \
+ constexpr bool operator!=(new_type<BaseType, TagType, DerivationClause> const &,\
+ BaseType const &)
+
+ **noexcept specification:** This comparison operator shall be noexcept iff. :cpp:type:`new_type<BaseType, TagType, DerivationClause>::base_type` is nothrow equals-comparable.
+
+ **enablement:** This operator shall be available iff. a) :cpp:type:`new_type<BaseType, TagType, DerivationClause>::base_type` supports comparison using the operator :literal:`!=` and b) the derivation clause contains :cpp:var:`EqBase`
+
+ .. versionadded:: 1.0.0
+
+.. cpp:function:: template<typename BaseType, \
+ typename TagType, \
+ auto DerivationClause> \
+ constexpr bool operator!=(BaseType const &,\
+ new_type<BaseType, TagType, DerivationClause> const &)
+
+ **noexcept specification:** This comparison operator shall be noexcept iff. :cpp:type:`new_type<BaseType, TagType, DerivationClause>::base_type` is nothrow equals-comparable.
+
+ **enablement:** This operator shall be available iff. a) :cpp:type:`new_type<BaseType, TagType, DerivationClause>::base_type` supports comparison using the operator :literal:`!=` and b) the derivation clause contains :cpp:var:`EqBase`
+
+ .. versionadded:: 1.0.0
+
Relational Comparison Operators
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -355,8 +403,8 @@ This header defines the alias template :cpp:type:`derivable` as well as the set
Alias template :cpp:type:`derivable`
------------------------------------
-.. cpp:type:: template<typename NameTag> \
- derivable = type<NameTag>
+.. cpp:struct:: template<typename NameTag> \
+ derivable
.. versionadded:: 1.0.0
@@ -373,7 +421,7 @@ Standard derivation tags
.. cpp:var:: auto constexpr EqBase = derivable<struct eq_base_tag>{}
- This tag enables the derivation of "Equality comparison with base type" operators :literal:`==` and :literal:`!=`
+ This tag enables the derivation of "Equality comparison with base type" operators :cpp:func:`template\<typename BaseType, typename TagType, auto DerivationClause> constexpr bool nt::operator==(BaseType const &, new_type<BaseType, TagType, DerivationClause> const &)`, :cpp:func:`template\<typename BaseType, typename TagType, auto DerivationClause> constexpr bool nt::operator==(new_type<BaseType, TagType, DerivationClause> const &, BaseType const &)` :cpp:func:`template\<typename BaseType, typename TagType, auto DerivationClause> constexpr bool nt::operator!=(BaseType const &, new_type<BaseType, TagType, DerivationClause> const &)`, and :cpp:func:`template\<typename BaseType, typename TagType, auto DerivationClause> constexpr bool nt::operator!=(new_type<BaseType, TagType, DerivationClause> const &, BaseType const &)`
By virtue of its nature, deriving this feature compromises the strength of the given :cpp:class:`new_type`.
.. versionadded:: 1.0.0
diff --git a/include/newtype/new_type.hpp b/include/newtype/new_type.hpp
index d22732a..b599c45 100644
--- a/include/newtype/new_type.hpp
+++ b/include/newtype/new_type.hpp
@@ -229,6 +229,37 @@ namespace nt
}
/**
+ * @brief Compare an instance of a given nt::new_type with an object of its base type
+ *
+ * @throw This comparison operator throws any exception thrown by the base type comparison operator. It it noexcept iff. the base type
+ * comparison operator is noexcept.
+ * @return true iff. the base type comparison operator returns true, false otherwise.
+ */
+ template<typename BaseType, typename TagType, auto DerivationClause>
+ auto constexpr operator==(new_type<BaseType, TagType, DerivationClause> const & lhs,
+ BaseType const & rhs) noexcept(impl::is_nothrow_equality_comparable_v<BaseType>)
+ -> std::enable_if_t<DerivationClause(nt::EqBase) && impl::is_equality_comparable_v<BaseType>, bool>
+ {
+ return lhs.decay() == rhs;
+ }
+
+ /**
+ * @brief Compare an instance of the base type with an instance of a given nt::new_type
+ *
+ * @throw This comparison operator throws any exception thrown by the base type comparison operator. It it noexcept iff. the base type
+ * comparison operator is noexcept.
+ * @return true iff. the base type comparison operator returns true, false otherwise.
+ */
+ template<typename BaseType, typename TagType, auto DerivationClause>
+ auto constexpr
+ operator==(BaseType const & lhs,
+ new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(impl::is_nothrow_equality_comparable_v<BaseType>)
+ -> std::enable_if_t<DerivationClause(nt::EqBase) && impl::is_equality_comparable_v<BaseType>, bool>
+ {
+ return lhs == rhs.decay();
+ }
+
+ /**
* @brief Compare two objects for non-equality
*
* @throw This comparison operator throws any exception thrown by the base type comparison operator. It it noexcept iff. the base type
@@ -244,6 +275,37 @@ namespace nt
return lhs.decay() != rhs.decay();
}
+ /**
+ * @brief Compare an instance of a given nt::new_type with an object of its base type
+ *
+ * @throw This comparison operator throws any exception thrown by the base type comparison operator. It it noexcept iff. the base type
+ * comparison operator is noexcept.
+ * @return true iff. the base type comparison operator returns true, false otherwise.
+ */
+ template<typename BaseType, typename TagType, auto DerivationClause>
+ auto constexpr operator!=(new_type<BaseType, TagType, DerivationClause> const & lhs,
+ BaseType const & rhs) noexcept(impl::is_nothrow_inequality_comparable_v<BaseType>)
+ -> std::enable_if_t<DerivationClause(nt::EqBase) && impl::is_inequality_comparable_v<BaseType>, bool>
+ {
+ return lhs.decay() != rhs;
+ }
+
+ /**
+ * @brief Compare an instance of the base type with an instance of a given nt::new_type
+ *
+ * @throw This comparison operator throws any exception thrown by the base type comparison operator. It it noexcept iff. the base type
+ * comparison operator is noexcept.
+ * @return true iff. the base type comparison operator returns true, false otherwise.
+ */
+ template<typename BaseType, typename TagType, auto DerivationClause>
+ auto constexpr
+ operator!=(BaseType const & lhs,
+ new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(impl::is_nothrow_inequality_comparable_v<BaseType>)
+ -> std::enable_if_t<DerivationClause(nt::EqBase) && impl::is_inequality_comparable_v<BaseType>, bool>
+ {
+ return lhs != rhs.decay();
+ }
+
/// @section Relational operators
/**
diff --git a/test/src/equality_comparison_suite.cpp b/test/src/equality_comparison_suite.cpp
index 64c7521..0789ae8 100644
--- a/test/src/equality_comparison_suite.cpp
+++ b/test/src/equality_comparison_suite.cpp
@@ -16,7 +16,7 @@ inline namespace basic_equality_comparsion_tests
auto two_instances_of_the_same_new__type_with_the_same_value_compare_equal() -> void
{
- using type_alias = nt::new_type<int, struct eq_test_tag_1>;
+ using type_alias = nt::new_type<int, struct tag>;
auto constexpr lhs = type_alias{42};
auto constexpr rhs = type_alias{42};
@@ -26,7 +26,7 @@ inline namespace basic_equality_comparsion_tests
auto two_instances_of_the_same_new__type_with_the_same_value_do_not_compare_not_equal() -> void
{
- using type_alias = nt::new_type<int, struct eq_test_tag_1>;
+ using type_alias = nt::new_type<int, struct tag>;
auto constexpr lhs = type_alias{42};
auto constexpr rhs = type_alias{42};
@@ -36,7 +36,7 @@ inline namespace basic_equality_comparsion_tests
auto two_instances_of_the_same_new__type_with_differing_values_do_compare_not_equal() -> void
{
- using type_alias = nt::new_type<int, struct eq_test_tag_1>;
+ using type_alias = nt::new_type<int, struct tag>;
auto constexpr lhs = type_alias{42};
auto constexpr rhs = type_alias{43};
@@ -46,7 +46,7 @@ inline namespace basic_equality_comparsion_tests
auto two_instances_of_the_same_new__type_with_differing_values_do_not_compare_equal() -> void
{
- using type_alias = nt::new_type<int, struct eq_test_tag_1>;
+ using type_alias = nt::new_type<int, struct tag>;
auto constexpr lhs = type_alias{42};
auto constexpr rhs = type_alias{43};
@@ -61,7 +61,7 @@ inline namespace equality_comparsion_noexcept_tests
auto equality_comparison_on_a_new__type_is_noexcept_if_the_base_type_is_noexcept_comparable() -> void
{
- using type_alias = nt::new_type<int, struct eq_test_tag_2>;
+ using type_alias = nt::new_type<int, struct tag>;
static_assert(noexcept(std::declval<int &>() == std::declval<int &>()), "Sanity Check");
ASSERT(noexcept(std::declval<type_alias &>() == std::declval<type_alias &>()));
}
@@ -76,14 +76,14 @@ inline namespace equality_comparsion_noexcept_tests
}
};
- using type_alias = nt::new_type<strange_type, struct eq_test_tag_3>;
+ using type_alias = nt::new_type<strange_type, struct tag>;
static_assert(!noexcept(std::declval<strange_type &>() == std::declval<strange_type &>()), "Sanity Check");
ASSERT(!noexcept(std::declval<type_alias &>() == std::declval<type_alias &>()));
}
auto inequality_comparison_on_a_new__type_is_noexcept_if_the_base_type_is_noexcept_comparable() -> void
{
- using type_alias = nt::new_type<int, struct eq_test_tag_4>;
+ using type_alias = nt::new_type<int, struct tag>;
static_assert(noexcept(std::declval<int &>() != std::declval<int &>()), "Sanity Check");
ASSERT(noexcept(std::declval<type_alias &>() != std::declval<type_alias &>()));
}
@@ -98,7 +98,7 @@ inline namespace equality_comparsion_noexcept_tests
}
};
- using type_alias = nt::new_type<strange_type, struct eq_test_tag_5>;
+ using type_alias = nt::new_type<strange_type, struct tag>;
static_assert(!noexcept(std::declval<strange_type &>() != std::declval<strange_type &>()), "Sanity Check");
ASSERT(!noexcept(std::declval<type_alias &>() != std::declval<type_alias &>()));
}
@@ -110,18 +110,55 @@ inline namespace equality_comparison_return_type_tests
auto equality_comparsion_of_two_new__type_instances_returns_bool() -> void
{
- using type_alias = nt::new_type<int, struct eq_test_tag_6>;
+ using type_alias = nt::new_type<int, struct tag>;
ASSERT((std::is_same_v<bool, decltype(std::declval<type_alias &>() == std::declval<type_alias &>())>));
}
auto inequality_comparsion_of_two_new__type_instances_returns_bool() -> void
{
- using type_alias = nt::new_type<int, struct eq_test_tag_7>;
+ using type_alias = nt::new_type<int, struct tag>;
ASSERT((std::is_same_v<bool, decltype(std::declval<type_alias &>() != std::declval<type_alias &>())>));
}
} // namespace equality_comparison_return_type_tests
+inline namespace base_type_equality_comparison_tests
+{
+
+ auto an_instance_of_a_new__type_compares_equal_to_an_instance_of_its_base_type_with_the_same_value() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag, deriving(nt::EqBase)>;
+ auto lhs = type_alias{42};
+ auto rhs = 42;
+ ASSERT_EQUAL(lhs, rhs);
+ }
+
+ auto an_instance_of_the_base_type_of_a_new__type_compares_equal_to_an_instance_of_the_new__type_with_the_same_value() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag, deriving(nt::EqBase)>;
+ auto lhs = 42;
+ auto rhs = type_alias{42};
+ ASSERT_EQUAL(lhs, rhs);
+ }
+
+ auto an_instance_of_a_new__type_compares_not_equal_to_an_instance_of_its_base_type_with_a_differing_value() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag, deriving(nt::EqBase)>;
+ auto lhs = type_alias{42};
+ auto rhs = 43;
+ ASSERT(lhs != rhs);
+ }
+
+ auto an_instance_of_the_base_type_of_a_new__type_compares_not_equal_to_an_instance_of_the_new__type_with_a_differing_value() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag, deriving(nt::EqBase)>;
+ auto lhs = 43;
+ auto rhs = type_alias{42};
+ ASSERT(lhs != rhs);
+ }
+
+} // namespace base_type_equality_comparison_tests
+
auto equality_comparison_suite() -> std::pair<cute::suite, std::string>
{
return {{
@@ -140,6 +177,12 @@ auto equality_comparison_suite() -> std::pair<cute::suite, std::string>
// Equality Comparison Return Type Tests
KAWAII(equality_comparsion_of_two_new__type_instances_returns_bool),
KAWAII(inequality_comparsion_of_two_new__type_instances_returns_bool),
+
+ // Base-type Equality Comparison Tests
+ KAWAII(an_instance_of_a_new__type_compares_equal_to_an_instance_of_its_base_type_with_the_same_value),
+ KAWAII(an_instance_of_the_base_type_of_a_new__type_compares_equal_to_an_instance_of_the_new__type_with_the_same_value),
+ KAWAII(an_instance_of_a_new__type_compares_not_equal_to_an_instance_of_its_base_type_with_a_differing_value),
+ KAWAII(an_instance_of_the_base_type_of_a_new__type_compares_not_equal_to_an_instance_of_the_new__type_with_a_differing_value),
},
"Equality Comparison Tests"};
} \ No newline at end of file