aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.vscode/c_cpp_properties.json4
-rw-r--r--include/newtype/impl/type_traits_extensions.hpp61
-rw-r--r--include/newtype/new_type.hpp18
-rw-r--r--test/src/arithmetic_suite.cpp37
4 files changed, 118 insertions, 2 deletions
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
index 179e475..e71cdab 100644
--- a/.vscode/c_cpp_properties.json
+++ b/.vscode/c_cpp_properties.json
@@ -6,9 +6,9 @@
"${workspaceFolder}/**"
],
"defines": [],
- "compilerPath": "/usr/bin/clang",
+ "compilerPath": "/usr/bin/gcc",
"cppStandard": "c++20",
- "intelliSenseMode": "clang-x64",
+ "intelliSenseMode": "gcc-x64",
"configurationProvider": "go2sh.cmake-integration"
}
],
diff --git a/include/newtype/impl/type_traits_extensions.hpp b/include/newtype/impl/type_traits_extensions.hpp
index d6dbfd6..56824e2 100644
--- a/include/newtype/impl/type_traits_extensions.hpp
+++ b/include/newtype/impl/type_traits_extensions.hpp
@@ -577,6 +577,67 @@ namespace nt::impl
template<typename T>
auto constexpr is_nothrow_addable_v = is_nothrow_addable<T>::value;
+ /**
+ * @brief A trait to test if a given type is subtractable
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the base case for non-subtractable T
+ */
+ template<typename T, typename = void>
+ struct is_subtractable : std::false_type
+ {
+ };
+
+ /**
+ * @brief A trait to test if a given type is input streamable
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the case for subtractable T
+ */
+ template<typename T>
+ struct is_subtractable<T, std::void_t<decltype(std::declval<T const &>() + std::declval<T const &>())>> : std::true_type
+ {
+ };
+
+ /**
+ * @brief A variable template to test if a given type is subtractable
+ *
+ * @tparam T The type to test
+ */
+ template<typename T>
+ auto constexpr is_subtractable_v = is_subtractable<T>::value;
+
+ /**
+ * @brief A trait to test if a given type is noexcept subtractable
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the base case for non-noexcept subtractable or non-subtractable T
+ */
+ template<typename T, typename = void>
+ struct is_nothrow_subtractable : std::false_type
+ {
+ };
+
+ /**
+ * @brief A trait to test if a given type is noexcept subtractable
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the case for subtractable T detemining if T is noexcept subtractable
+ */
+ template<typename T>
+ struct is_nothrow_subtractable<T, std::void_t<decltype(std::declval<T const &>() + std::declval<T const &>())>>
+ : std::bool_constant<noexcept(std::declval<T const &>() + std::declval<T const &>())>
+ {
+ };
+
+ /**
+ * @brief A variable template to test if a given type is noexcept subtractable
+ *
+ * @tparam T The type to test
+ */
+ template<typename T>
+ auto constexpr is_nothrow_subtractable_v = is_nothrow_subtractable<T>::value;
+
} // namespace arithmetic
} // namespace nt::impl
diff --git a/include/newtype/new_type.hpp b/include/newtype/new_type.hpp
index 8228a94..bc8ecee 100644
--- a/include/newtype/new_type.hpp
+++ b/include/newtype/new_type.hpp
@@ -346,6 +346,24 @@ namespace nt
return {lhs.decay() + rhs.decay()};
}
+ /**
+ * @brief Subtract two instances of the same nt::new_type
+ *
+ * @note This operator is only available if the derivation clause of the passed in nt::new_type objects contains nt::Arithmetic and the base
+ * type is subtractable.
+ * @param lhs The left-hand side of the subtraction
+ * @param rhs The right-hand side of the subtraction
+ * @return a new instance of the same nt::new_type
+ */
+ template<typename BaseType, typename TagType, auto DerivationClause>
+ auto constexpr
+ operator-(new_type<BaseType, TagType, DerivationClause> const & lhs, new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(
+ impl::is_nothrow_subtractable_v<BaseType> && std::is_nothrow_copy_constructible_v<BaseType>)
+ -> std::enable_if_t<DerivationClause(nt::Arithmetic) && impl::is_subtractable_v<BaseType>, new_type<BaseType, TagType, DerivationClause>>
+ {
+ return {lhs.decay() - rhs.decay()};
+ }
+
} // namespace nt
#endif
diff --git a/test/src/arithmetic_suite.cpp b/test/src/arithmetic_suite.cpp
index 4541125..57c06e8 100644
--- a/test/src/arithmetic_suite.cpp
+++ b/test/src/arithmetic_suite.cpp
@@ -40,6 +40,37 @@ inline namespace addition_tests
} // namespace addition_tests
+inline namespace subtraction_tests
+{
+
+ auto a_new__type_not_deriving_arithmetic_is_not_subtractable_with_instances_of_itself() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag>;
+ ASSERT(!(nt::impl::is_subtractable_v<type_alias>));
+ }
+
+ auto a_new__type_deriving_arithmetic_is_subtractable_with_instances_of_itself() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag, deriving(nt::Arithmetic)>;
+ ASSERT(nt::impl::is_subtractable_v<type_alias>);
+ }
+
+ auto subtraction_of_two_instances_of_a_new__type_deriving_arithmetic_produces_an_instance_of_the_same_new__type() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag, deriving(nt::Arithmetic)>;
+ ASSERT((std::is_same_v<type_alias, decltype(std::declval<type_alias const &>() + std::declval<type_alias const &>())>));
+ }
+
+ auto subtraction_of_two_instances_of_a_new__type_deriving_arithmetic_produces_the_correct_value_with_respect_to_the_base_type() -> void
+ {
+ using type_alias = nt::new_type<int, struct tag, deriving(nt::Arithmetic)>;
+ auto lhs = type_alias{24};
+ auto rhs = type_alias{18};
+ ASSERT_EQUAL(24 - 18, (lhs - rhs).decay());
+ }
+
+} // namespace subtraction_tests
+
auto arithmetic_suite() -> std::pair<cute::suite, std::string>
{
return {{
@@ -48,6 +79,12 @@ auto arithmetic_suite() -> std::pair<cute::suite, std::string>
KAWAII(a_new__type_deriving_arithmetic_is_addable_with_instances_of_itself),
KAWAII(addition_of_two_instances_of_a_new__type_deriving_arithmetic_produces_an_instance_of_the_same_new__type),
KAWAII(addition_of_two_instances_of_a_new__type_deriving_arithmetic_produces_the_correct_value_with_respect_to_the_base_type),
+
+ /// Subtraction Tests
+ KAWAII(a_new__type_not_deriving_arithmetic_is_not_subtractable_with_instances_of_itself),
+ KAWAII(a_new__type_deriving_arithmetic_is_subtractable_with_instances_of_itself),
+ KAWAII(subtraction_of_two_instances_of_a_new__type_deriving_arithmetic_produces_an_instance_of_the_same_new__type),
+ KAWAII(subtraction_of_two_instances_of_a_new__type_deriving_arithmetic_produces_the_correct_value_with_respect_to_the_base_type),
},
"Arithmetic Operators Tests"};
} \ No newline at end of file