aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@gmail.com>2019-12-29 16:37:11 +0100
committerFelix Morgner <felix.morgner@gmail.com>2019-12-29 16:37:11 +0100
commit993b49d9b0aba3a9e60ee2bc86aa72b5ee69d063 (patch)
treeadff3291e1ecb8222a404f671600c590528288fc
parenta8d181abe5a64def14b0f90f6149a67cca354a3a (diff)
downloadnewtype-993b49d9b0aba3a9e60ee2bc86aa72b5ee69d063.tar.xz
newtype-993b49d9b0aba3a9e60ee2bc86aa72b5ee69d063.zip
new_type: extract type_traits extensions
-rw-r--r--include/newtype/impl/type_traits_extensions.hpp518
-rw-r--r--include/newtype/new_type.hpp98
2 files changed, 565 insertions, 51 deletions
diff --git a/include/newtype/impl/type_traits_extensions.hpp b/include/newtype/impl/type_traits_extensions.hpp
new file mode 100644
index 0000000..ae0c7d5
--- /dev/null
+++ b/include/newtype/impl/type_traits_extensions.hpp
@@ -0,0 +1,518 @@
+#ifndef NEWTYPE_IMPL_TYPE_TRAITS_EXTENSIONS_HPP
+#define NEWTYPE_IMPL_TYPE_TRAITS_EXTENSIONS_HPP
+
+#include <iosfwd>
+#include <type_traits>
+
+namespace nt::impl
+{
+
+ inline namespace equality_comparable
+ {
+
+ /**
+ * @brief A trait to test if a given type is comparable using operator==
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the base case for non-equals-comparable T
+ */
+ template<typename T, typename = void>
+ struct is_equality_comparable : std::false_type
+ {
+ };
+
+ /**
+ * @brief A trait to test if a given type is comparable using operator==
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the case for equals-comparable T
+ */
+ template<typename T>
+ struct is_equality_comparable<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 comparable using operator==
+ *
+ * @tparam T The type to test
+ */
+ template<typename T>
+ auto constexpr is_equality_comparable_v = is_equality_comparable<T>::value;
+
+ /**
+ * @brief A trait to test if a given type is noexcept comparable using operator==
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the base case for non-noexcept equals-comparable or non-equals-comparable T
+ */
+ template<typename T, typename = void>
+ struct is_nothrow_equality_comparable : std::false_type
+ {
+ };
+
+ /**
+ * @brief A trait to test if a given type is noexcept comparable using operator==
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the case for equals-comparable T detemining if T is noexcept comparable using operator==
+ */
+ template<typename T>
+ struct is_nothrow_equality_comparable<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 comparable using operator==
+ *
+ * @tparam T The type to test
+ */
+ template<typename T>
+ auto constexpr is_nothrow_equality_comparable_v = is_nothrow_equality_comparable<T>::value;
+
+ /**
+ * @brief A trait to test if a given type is comparable using operator!=
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the base case for non-not-equals-comparable T
+ */
+ template<typename T, typename = void>
+ struct is_inequality_comparable : std::false_type
+ {
+ };
+
+ /**
+ * @brief A trait to test if a given type is comparable using operator!=
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the case for not-equals-comparable T
+ */
+ template<typename T>
+ struct is_inequality_comparable<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 comparable using operator!=
+ *
+ * @tparam T The type to test
+ */
+ template<typename T>
+ auto constexpr is_inequality_comparable_v = is_inequality_comparable<T>::value;
+
+ /**
+ * @brief A trait to test if a given type is noexcept comparable using operator!=
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the base case for non-noexcept not-equals-comparable or non-not-equals-comparable T
+ */
+ template<typename T, typename = void>
+ struct is_nothrow_inequality_comparable : std::false_type
+ {
+ };
+
+ /**
+ * @brief A trait to test if a given type is noexcept comparable using operator==
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the case for equals-comparable T detemining if T is noexcept comparable using operator!=
+ */
+ template<typename T>
+ struct is_nothrow_inequality_comparable<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 comparable using operator!=
+ *
+ * @tparam T The type to test
+ */
+ template<typename T>
+ auto constexpr is_nothrow_inequality_comparable_v = is_nothrow_inequality_comparable<T>::value;
+
+ } // namespace equality_comparable
+
+ inline namespace relationally_comparable
+ {
+
+ /**
+ * @brief A trait to test if a given type is comparable using operator<
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the base case for non-less-than-comparable T
+ */
+ template<typename T, typename = void>
+ struct is_less_than_comparable : std::false_type
+ {
+ };
+
+ /**
+ * @brief A trait to test if a given type is comparable using operator<
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the case for less-than-comparable T
+ */
+ template<typename T>
+ struct is_less_than_comparable<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 comparable using operator<
+ *
+ * @tparam T The type to test
+ */
+ template<typename T>
+ auto constexpr is_less_than_comparable_v = is_less_than_comparable<T>::value;
+
+ /**
+ * @brief A trait to test if a given type is noexcept comparable using operator<
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the base case for non-noexcept less-than-comparable or non-less-than-comparable T
+ */
+ template<typename T, typename = void>
+ struct is_nothrow_less_than_comparable : std::false_type
+ {
+ };
+
+ /**
+ * @brief A trait to test if a given type is noexcept comparable using operator<
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the case for less-than-comparable T detemining if T is noexcept comparable using operator<
+ */
+ template<typename T>
+ struct is_nothrow_less_than_comparable<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 comparable using operator<
+ *
+ * @tparam T The type to test
+ */
+ template<typename T>
+ auto constexpr is_nothrow_less_than_comparable_v = is_nothrow_less_than_comparable<T>::value;
+
+ /**
+ * @brief A trait to test if a given type is comparable using operator>
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the base case for non-greater-than-comparable T
+ */
+ template<typename T, typename = void>
+ struct is_greater_than_comparable : std::false_type
+ {
+ };
+
+ /**
+ * @brief A trait to test if a given type is comparable using operator>
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the case for greater-than-comparable T
+ */
+ template<typename T>
+ struct is_greater_than_comparable<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 comparable using operator>
+ *
+ * @tparam T The type to test
+ */
+ template<typename T>
+ auto constexpr is_greater_than_comparable_v = is_greater_than_comparable<T>::value;
+
+ /**
+ * @brief A trait to test if a given type is noexcept comparable using operator>
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the base case for non-noexcept greater-than-comparable or non-greater-than-comparable T
+ */
+ template<typename T, typename = void>
+ struct is_nothrow_greater_than_comparable : std::false_type
+ {
+ };
+
+ /**
+ * @brief A trait to test if a given type is noexcept comparable using operator>
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the case for greater-than-comparable T detemining if T is noexcept comparable using operator>
+ */
+ template<typename T>
+ struct is_nothrow_greater_than_comparable<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 comparable using operator>
+ *
+ * @tparam T The type to test
+ */
+ template<typename T>
+ auto constexpr is_nothrow_greater_than_comparable_v = is_nothrow_greater_than_comparable<T>::value;
+
+ /**
+ * @brief A trait to test if a given type is comparable using operator<=
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the base case for non-less-than-or-equal-to-comparable T
+ */
+ template<typename T, typename = void>
+ struct is_less_than_equal_to_comparable : std::false_type
+ {
+ };
+
+ /**
+ * @brief A trait to test if a given type is comparable using operator<=
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the case for less-than-or-equal-to-comparable T
+ */
+ template<typename T>
+ struct is_less_than_equal_to_comparable<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 comparable using operator<=
+ *
+ * @tparam T The type to test
+ */
+ template<typename T>
+ auto constexpr is_less_than_equal_to_comparable_v = is_less_than_equal_to_comparable<T>::value;
+
+ /**
+ * @brief A trait to test if a given type is noexcept comparable using operator<=
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the base case for non-noexcept less-than-or-equal-to-comparable or non-less-than-or-equal-to-comparable T
+ */
+ template<typename T, typename = void>
+ struct is_nothrow_less_than_equal_to_comparable : std::false_type
+ {
+ };
+
+ /**
+ * @brief A trait to test if a given type is noexcept comparable using operator<=
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the case for less-than-or-equal-to-comparable T detemining if T is noexcept comparable using operator<=
+ */
+ template<typename T>
+ struct is_nothrow_less_than_equal_to_comparable<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 comparable using operator<=
+ *
+ * @tparam T The type to test
+ */
+ template<typename T>
+ auto constexpr is_nothrow_less_than_equal_to_comparable_v = is_nothrow_less_than_equal_to_comparable<T>::value;
+
+ /**
+ * @brief A trait to test if a given type is comparable using operator>=
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the base case for non-greater-than-or-equal-to-comparable T
+ */
+ template<typename T, typename = void>
+ struct is_greater_than_equal_to_comparable : std::false_type
+ {
+ };
+
+ /**
+ * @brief A trait to test if a given type is comparable using operator>=
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the case for greater-than-or-equal-to-comparable T
+ */
+ template<typename T>
+ struct is_greater_than_equal_to_comparable<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 comparable using operator>=
+ *
+ * @tparam T The type to test
+ */
+ template<typename T>
+ auto constexpr is_greater_than_equal_to_comparable_v = is_greater_than_equal_to_comparable<T>::value;
+
+ /**
+ * @brief A trait to test if a given type is noexcept comparable using operator>=
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the base case for non-noexcept greater-than-or-equal-to-comparable or
+ * non-greater-than-or-equal-to-comparable T
+ */
+ template<typename T, typename = void>
+ struct is_nothrow_greater_than_equal_to_comparable : std::false_type
+ {
+ };
+
+ /**
+ * @brief A trait to test if a given type is noexcept comparable using operator>=
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the case for greater-than-or-equal-to-comparable T detemining if T is noexcept comparable using
+ * operator>=
+ */
+ template<typename T>
+ struct is_nothrow_greater_than_equal_to_comparable<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 comparable using operator>=
+ *
+ * @tparam T The type to test
+ */
+ template<typename T>
+ auto constexpr is_nothrow_greater_than_equal_to_comparable_v = is_nothrow_greater_than_equal_to_comparable<T>::value;
+ } // namespace relationally_comparable
+
+ inline namespace iostreamable
+ {
+
+ /**
+ * @brief A trait to test if a given type is output streamable
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the base case for non-output-streamable T
+ */
+ template<typename StreamType, typename T, typename = void>
+ struct is_output_streamable : std::false_type
+ {
+ };
+
+ /**
+ * @brief A trait to test if a given type is output streamable
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the case for output-streamable T
+ */
+ template<typename StreamType, typename T>
+ struct is_output_streamable<StreamType, T, std::void_t<decltype(std::declval<StreamType &>() << std::declval<T const &>())>>
+ : std::true_type
+ {
+ };
+
+ /**
+ * @brief A variable template to test if a given type is output streamable
+ *
+ * @tparam T The type to test
+ */
+ template<typename StreamType, typename T>
+ auto constexpr is_output_streamable_v = is_output_streamable<StreamType, T>::value;
+
+ /**
+ * @brief A trait to test if a given type is noexcept output streamable
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the base case for non-noexcept output-streamable or non-output-streamable T
+ */
+ template<typename StreamType, typename T, typename = void>
+ struct is_nothrow_output_streamable : std::false_type
+ {
+ };
+
+ /**
+ * @brief A trait to test if a given type is noexcept output streamable
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the case for output-streamable T detemining if T is noexcept output-streamable
+ */
+ template<typename StreamType, typename T>
+ struct is_nothrow_output_streamable<StreamType, T, std::void_t<decltype(std::declval<StreamType &>() << std::declval<T const &>())>>
+ : std::bool_constant<noexcept(std::declval<StreamType &>() << std::declval<T const &>())>
+ {
+ };
+
+ /**
+ * @brief A variable template to test if a given type is noexcept output streamable
+ *
+ * @tparam T The type to test
+ */
+ template<typename StreamType, typename T>
+ auto constexpr is_nothrow_output_streamable_v = is_nothrow_output_streamable<StreamType, T>::value;
+
+ /**
+ * @brief A trait to test if a given type is input streamable
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the base case for non-input-streamable T
+ */
+ template<typename StreamType, typename T, typename = void>
+ struct is_input_streamable : 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 input-streamable T
+ */
+ template<typename StreamType, typename T>
+ struct is_input_streamable<StreamType, T, std::void_t<decltype(std::declval<StreamType &>() >> std::declval<T &>())>> : std::true_type
+ {
+ };
+
+ /**
+ * @brief A variable template to test if a given type is input streamable
+ *
+ * @tparam T The type to test
+ */
+ template<typename StreamType, typename T>
+ auto constexpr is_input_streamable_v = is_input_streamable<StreamType, T>::value;
+
+ /**
+ * @brief A trait to test if a given type is noexcept input streamable
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the base case for non-noexcept input-streamable or non-input-streamable T
+ */
+ template<typename StreamType, typename T, typename = void>
+ struct is_nothrow_input_streamable : std::false_type
+ {
+ };
+
+ /**
+ * @brief A trait to test if a given type is noexcept input streamable
+ *
+ * @tparam T The type to test
+ * @note This specialization forms the case for input-streamable T detemining if T is noexcept input-streamable
+ */
+ template<typename StreamType, typename T>
+ struct is_nothrow_input_streamable<StreamType, T, std::void_t<decltype(std::declval<StreamType &>() >> std::declval<T &>())>>
+ : std::bool_constant<noexcept(std::declval<StreamType &>() >> std::declval<T &>())>
+ {
+ };
+
+ /**
+ * @brief A variable template to test if a given type is noexcept input streamable
+ *
+ * @tparam T The type to test
+ */
+ template<typename StreamType, typename T>
+ auto constexpr is_nothrow_input_streamable_v = is_nothrow_input_streamable<StreamType, T>::value;
+
+ } // namespace iostreamable
+
+} // namespace nt::impl
+
+#endif \ No newline at end of file
diff --git a/include/newtype/new_type.hpp b/include/newtype/new_type.hpp
index 7f73daa..85f0d40 100644
--- a/include/newtype/new_type.hpp
+++ b/include/newtype/new_type.hpp
@@ -4,6 +4,7 @@
#include "newtype/derivable.hpp"
#include "newtype/deriving.hpp"
#include "newtype/impl/new_type_storage.hpp"
+#include "newtype/impl/type_traits_extensions.hpp"
#include "newtype/type.hpp"
#include <istream>
@@ -30,10 +31,10 @@ namespace nt
static_assert(!std::is_void_v<std::remove_cv_t<BaseType>>, "The base type must not be possibly cv-qualified void");
template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV, typename CharType, typename StreamTraits>
- auto friend
- operator>>(std::basic_istream<CharType, StreamTraits> & input, new_type<BaseTypeT, TagTypeT, DerivationClauseV> & target) noexcept(
- noexcept(std::declval<std::basic_istream<CharType, StreamTraits> &>() >> std::declval<BaseTypeT &>()))
- -> std::enable_if_t<DerivationClauseV(nt::Read), std::basic_istream<CharType, StreamTraits>> &;
+ auto friend operator>>(std::basic_istream<CharType, StreamTraits> &, new_type<BaseTypeT, TagTypeT, DerivationClauseV> &) noexcept(
+ impl::is_nothrow_input_streamable_v<std::basic_istream<CharType, StreamTraits>, BaseTypeT>)
+ -> std::enable_if_t<DerivationClauseV(nt::Read) && impl::is_input_streamable_v<std::basic_istream<CharType, StreamTraits>, BaseTypeT>,
+ std::basic_istream<CharType, StreamTraits>> &;
using super = impl::new_type_move_assignment<BaseType, TagType>;
@@ -177,10 +178,10 @@ namespace nt
* @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,
- new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(noexcept(std::declval<BaseType const &>() ==
- std::declval<BaseType const &>()))
- -> bool
+ auto constexpr
+ operator==(new_type<BaseType, TagType, DerivationClause> const & lhs,
+ new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(impl::is_nothrow_equality_comparable_v<BaseType>)
+ -> std::enable_if_t<impl::is_equality_comparable_v<BaseType>, bool>
{
return lhs.decay() == rhs.decay();
}
@@ -193,10 +194,10 @@ namespace nt
* @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,
- new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(noexcept(std::declval<BaseType const &>() !=
- std::declval<BaseType const &>()))
- -> bool
+ auto constexpr
+ operator!=(new_type<BaseType, TagType, DerivationClause> const & lhs,
+ new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(impl::is_nothrow_inequality_comparable_v<BaseType>)
+ -> std::enable_if_t<impl::is_inequality_comparable_v<BaseType>, bool>
{
return lhs.decay() != rhs.decay();
}
@@ -204,50 +205,46 @@ namespace nt
/**
* @brief Check if one nt::new_type object is less-than an other
*
- * @note This operator is only avalaible if the the derivation clause of this nt::new_type does contains nt::Relational. Otherwise is is
- * defined as deleted.
+ * @note This operator is only avalaible if the the derivation clause of this nt::new_type does contains nt::Relational and the base type is
+ * less-than comparable. Otherwise is is defined as deleted.
* @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,
- new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(noexcept(std::declval<BaseType const &>() <
- std::declval<BaseType const &>()))
- -> std::enable_if_t<DerivationClause(nt::Relational), bool>
+ auto constexpr
+ operator<(new_type<BaseType, TagType, DerivationClause> const & lhs,
+ new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(impl::is_nothrow_less_than_comparable_v<BaseType>)
+ -> std::enable_if_t<DerivationClause(nt::Relational) && impl::is_less_than_comparable_v<BaseType>, bool>
{
return lhs.decay() < rhs.decay();
}
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(noexcept(std::declval<BaseType const &>() <
- std::declval<BaseType const &>()))
- -> std::enable_if_t<!DerivationClause(nt::Relational), bool> = delete;
+ auto constexpr operator<(new_type<BaseType, TagType, DerivationClause> const &, new_type<BaseType, TagType, DerivationClause> const &)
+ -> std::enable_if_t<!DerivationClause(nt::Relational) || !impl::is_less_than_comparable_v<BaseType>, bool> = delete;
/**
* Check if one nt::new_type object is greater-than an other
*
- * @note This operator is only avalaible if the the derivation clause of this nt::new_type does contains nt::Relational. Otherwise is is
- * defined as deleted.
+ * @note This operator is only avalaible if the the derivation clause of this nt::new_type does contains nt::Relational and the base type is
+ * greater-than comparable. Otherwise is is defined as deleted.
* @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,
- new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(noexcept(std::declval<BaseType const &>() >
- std::declval<BaseType const &>()))
- -> std::enable_if_t<DerivationClause(nt::Relational), bool>
+ auto constexpr
+ operator>(new_type<BaseType, TagType, DerivationClause> const & lhs,
+ new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(impl::is_nothrow_greater_than_comparable_v<BaseType>)
+ -> std::enable_if_t<DerivationClause(nt::Relational) && impl::is_greater_than_comparable_v<BaseType>, bool>
{
return lhs.decay() > rhs.decay();
}
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(noexcept(std::declval<BaseType const &>() >
- std::declval<BaseType const &>()))
- -> std::enable_if_t<!DerivationClause(nt::Relational), bool> = delete;
+ auto constexpr operator>(new_type<BaseType, TagType, DerivationClause> const &, new_type<BaseType, TagType, DerivationClause> const &)
+ -> std::enable_if_t<!DerivationClause(nt::Relational) || !impl::is_greater_than_comparable_v<BaseType>, bool> = delete;
/**
* Check if one nt::new_type object is less-than or equal-to an other
@@ -258,19 +255,17 @@ namespace nt
* @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,
- new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(noexcept(std::declval<BaseType const &>() <=
- std::declval<BaseType const &>()))
- -> std::enable_if_t<DerivationClause(nt::Relational), bool>
+ auto constexpr
+ operator<=(new_type<BaseType, TagType, DerivationClause> const & lhs,
+ new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(impl::is_nothrow_less_than_equal_to_comparable_v<BaseType>)
+ -> std::enable_if_t<DerivationClause(nt::Relational) && impl::is_less_than_equal_to_comparable_v<BaseType>, bool>
{
return lhs.decay() <= rhs.decay();
}
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(noexcept(std::declval<BaseType const &>() <=
- std::declval<BaseType const &>()))
- -> std::enable_if_t<!DerivationClause(nt::Relational), bool> = delete;
+ auto constexpr operator<=(new_type<BaseType, TagType, DerivationClause> const &, new_type<BaseType, TagType, DerivationClause> const &)
+ -> std::enable_if_t<!DerivationClause(nt::Relational) || !impl::is_less_than_equal_to_comparable_v<BaseType>, bool> = delete;
/**
* Check if one nt::new_type object is greater-than or equal-to an other
@@ -281,19 +276,18 @@ namespace nt
* @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,
- new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(noexcept(std::declval<BaseType const &>() >=
- std::declval<BaseType const &>()))
- -> std::enable_if_t<DerivationClause(nt::Relational), bool>
+ auto constexpr
+ operator>=(new_type<BaseType, TagType, DerivationClause> const & lhs,
+ new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(impl::is_nothrow_greater_than_equal_to_comparable_v<BaseType>)
+ -> std::enable_if_t<DerivationClause(nt::Relational) && impl::is_greater_than_equal_to_comparable_v<BaseType>, bool>
{
return lhs.decay() >= rhs.decay();
}
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(noexcept(std::declval<BaseType const &>() >=
- std::declval<BaseType const &>()))
- -> std::enable_if_t<!DerivationClause(nt::Relational), bool> = delete;
+ new_type<BaseType, TagType, DerivationClause> const & rhs)
+ -> std::enable_if_t<!DerivationClause(nt::Relational) || !impl::is_greater_than_equal_to_comparable_v<BaseType>, bool> = delete;
/**
* @brief Write the contained base type object to a standard output stream
@@ -305,8 +299,9 @@ namespace nt
*/
template<typename BaseType, typename TagType, auto DerivationClause, typename CharType, typename StreamTraits>
auto operator<<(std::basic_ostream<CharType, StreamTraits> & output, new_type<BaseType, TagType, DerivationClause> const & source) noexcept(
- noexcept(std::declval<std::basic_ostream<CharType, StreamTraits> &>() << std::declval<BaseType const &>()))
- -> std::enable_if_t<DerivationClause(nt::Show), std::basic_ostream<CharType, StreamTraits>> &
+ impl::is_nothrow_output_streamable_v<std::basic_ostream<CharType, StreamTraits>, BaseType>)
+ -> std::enable_if_t<DerivationClause(nt::Show) && impl::is_output_streamable_v<std::basic_ostream<CharType, StreamTraits>, BaseType>,
+ std::basic_ostream<CharType, StreamTraits>> &
{
return output << source.decay();
}
@@ -321,8 +316,9 @@ namespace nt
*/
template<typename BaseType, typename TagType, auto DerivationClause, typename CharType, typename StreamTraits>
auto operator>>(std::basic_istream<CharType, StreamTraits> & input, new_type<BaseType, TagType, DerivationClause> & target) noexcept(
- noexcept(std::declval<std::basic_istream<CharType, StreamTraits> &>() >> std::declval<BaseType &>()))
- -> std::enable_if_t<DerivationClause(nt::Read), std::basic_istream<CharType, StreamTraits>> &
+ impl::is_nothrow_input_streamable_v<std::basic_istream<CharType, StreamTraits>, BaseType>)
+ -> std::enable_if_t<DerivationClause(nt::Read) && impl::is_input_streamable_v<std::basic_istream<CharType, StreamTraits>, BaseType>,
+ std::basic_istream<CharType, StreamTraits>> &
{
return input >> target.m_value;
}