From 7ee8c79b48e6045ca87df5aadcde48b7f3f7733e Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 26 Feb 2025 12:24:57 +0100 Subject: lib: feature i/o stream functionality --- lib/include/newtype/newtype.hpp | 196 +++++++++++++--------------------------- 1 file changed, 64 insertions(+), 132 deletions(-) diff --git a/lib/include/newtype/newtype.hpp b/lib/include/newtype/newtype.hpp index fecaf2c..5a9b8ff 100644 --- a/lib/include/newtype/newtype.hpp +++ b/lib/include/newtype/newtype.hpp @@ -1,11 +1,17 @@ #ifndef NEWTYPE_NEWTYPE_HPP #define NEWTYPE_NEWTYPE_HPP +#if __has_include() && __has_include() +#define HAS_I_O_STREAM +#endif + #include #include #include +#ifdef HAS_I_O_STREAM #include #include +#endif #include #include @@ -87,16 +93,12 @@ namespace nt #define NEWTYPE_MAKE_ARITHMETIC_CONCEPT(NAME, OPERATOR, REF) \ template \ concept NAME = requires(SubjectType lhs, SubjectType rhs) { \ - { \ - lhs OPERATOR rhs \ - } -> std::same_as; \ + { lhs OPERATOR rhs } -> std::same_as; \ }; \ template \ concept nothrow_##NAME = requires(SubjectType lhs, SubjectType rhs) { \ requires NAME; \ - { \ - lhs OPERATOR rhs \ - } noexcept; \ + { lhs OPERATOR rhs } noexcept; \ }; NEWTYPE_MAKE_ARITHMETIC_CONCEPT(addable, +, /*no-ref*/) @@ -116,103 +118,78 @@ namespace nt template concept nothrow_three_way_comparable = requires(SubjectType lhs, SubjectType rhs) { requires std::three_way_comparable; - { - lhs <=> rhs - } noexcept; + { lhs <=> rhs } noexcept; }; template concept equality_comparable = requires(SubjectType lhs, SubjectType rhs) { - { - lhs == rhs - } -> std::convertible_to; + { lhs == rhs } -> std::convertible_to; }; template concept nothrow_equality_comparable = requires(SubjectType lhs, SubjectType rhs) { requires equality_comparable; - { - lhs == rhs - } noexcept; + { lhs == rhs } noexcept; }; template concept inequality_comparable = requires(SubjectType lhs, SubjectType rhs) { - { - lhs != rhs - } -> std::convertible_to; + { lhs != rhs } -> std::convertible_to; }; template concept nothrow_inequality_comparable = requires(SubjectType lhs, SubjectType rhs) { requires inequality_comparable; - { - lhs != rhs - } noexcept; + { lhs != rhs } noexcept; }; template concept less_than_comparable = requires(SubjectType lhs, SubjectType rhs) { - { - lhs < rhs - } -> std::convertible_to; + { lhs < rhs } -> std::convertible_to; }; template concept nothrow_less_than_comparable = requires(SubjectType lhs, SubjectType rhs) { requires less_than_comparable; - { - lhs < rhs - } noexcept; + { lhs < rhs } noexcept; }; template concept less_than_equal_comparable = requires(SubjectType lhs, SubjectType rhs) { - { - lhs <= rhs - } -> std::convertible_to; + { 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; + { lhs <= rhs } noexcept; }; template concept greater_than_comparable = requires(SubjectType lhs, SubjectType rhs) { - { - lhs > rhs - } -> std::convertible_to; + { lhs > rhs } -> std::convertible_to; }; template concept nothrow_greater_than_comparable = requires(SubjectType lhs, SubjectType rhs) { requires greater_than_comparable; - { - lhs > rhs - } noexcept; + { lhs > rhs } noexcept; }; template concept greater_than_equal_comparable = requires(SubjectType lhs, SubjectType rhs) { - { - lhs >= rhs - } -> std::convertible_to; + { 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; + { lhs >= rhs } noexcept; }; } // namespace comparability +#ifdef HAS_I_O_STREAM inline namespace iostreamable { @@ -226,9 +203,7 @@ namespace nt template concept nothrow_input_streamable = requires(SubjectType subject) { requires input_streamable; - { - std::declval &>() >> subject - } noexcept; + { std::declval &>() >> subject } noexcept; }; template @@ -241,12 +216,11 @@ namespace nt template concept nothrow_output_streamable = requires(SubjectType subject) { requires output_streamable; - { - std::declval &>() << subject - } noexcept; + { std::declval &>() << subject } noexcept; }; } // namespace iostreamable +#endif inline namespace iterable { @@ -254,33 +228,25 @@ namespace nt template concept free_begin = requires(SubjectType & subject) { typename SubjectType::iterator; - { - begin(subject) - } -> std::same_as; + { begin(subject) } -> std::same_as; }; template concept const_free_begin = requires(SubjectType const & subject) { typename SubjectType::const_iterator; - { - begin(subject) - } -> std::same_as; + { begin(subject) } -> std::same_as; }; template concept member_begin = requires(SubjectType & subject) { typename SubjectType::iterator; - { - subject.begin() - } -> std::same_as; + { subject.begin() } -> std::same_as; }; template concept const_member_begin = requires(SubjectType const & subject) { typename SubjectType::const_iterator; - { - subject.begin() - } -> std::same_as; + { subject.begin() } -> std::same_as; }; template @@ -292,17 +258,13 @@ namespace nt template concept free_cbegin = requires(SubjectType const & subject) { typename SubjectType::const_iterator; - { - cbegin(subject) - } -> std::same_as; + { cbegin(subject) } -> std::same_as; }; template concept member_cbegin = requires(SubjectType const & subject) { typename SubjectType::const_iterator; - { - subject.cbegin() - } -> std::same_as; + { subject.cbegin() } -> std::same_as; }; template @@ -311,33 +273,25 @@ namespace nt template concept free_rbegin = requires(SubjectType & subject) { typename SubjectType::reverse_iterator; - { - rbegin(subject) - } -> std::same_as; + { rbegin(subject) } -> std::same_as; }; template concept const_free_rbegin = requires(SubjectType const & subject) { typename SubjectType::const_reverse_iterator; - { - rbegin(subject) - } -> std::same_as; + { rbegin(subject) } -> std::same_as; }; template concept member_rbegin = requires(SubjectType & subject) { typename SubjectType::reverse_iterator; - { - subject.rbegin() - } -> std::same_as; + { subject.rbegin() } -> std::same_as; }; template concept const_member_rbegin = requires(SubjectType const & subject) { typename SubjectType::const_reverse_iterator; - { - subject.rbegin() - } -> std::same_as; + { subject.rbegin() } -> std::same_as; }; template @@ -349,17 +303,13 @@ namespace nt template concept free_crbegin = requires(SubjectType const & subject) { typename SubjectType::const_reverse_iterator; - { - crbegin(subject) - } -> std::same_as; + { crbegin(subject) } -> std::same_as; }; template concept member_crbegin = requires(SubjectType const & subject) { typename SubjectType::const_reverse_iterator; - { - subject.crbegin() - } -> std::same_as; + { subject.crbegin() } -> std::same_as; }; template @@ -368,33 +318,25 @@ namespace nt template concept free_end = requires(SubjectType & subject) { typename SubjectType::iterator; - { - end(subject) - } -> std::same_as; + { end(subject) } -> std::same_as; }; template concept const_free_end = requires(SubjectType const & subject) { typename SubjectType::const_iterator; - { - end(subject) - } -> std::same_as; + { end(subject) } -> std::same_as; }; template concept member_end = requires(SubjectType & subject) { typename SubjectType::iterator; - { - subject.end() - } -> std::same_as; + { subject.end() } -> std::same_as; }; template concept const_member_end = requires(SubjectType const & subject) { typename SubjectType::const_iterator; - { - subject.end() - } -> std::same_as; + { subject.end() } -> std::same_as; }; template @@ -406,17 +348,13 @@ namespace nt template concept free_cend = requires(SubjectType const & subject) { typename SubjectType::const_iterator; - { - cend(subject) - } -> std::same_as; + { cend(subject) } -> std::same_as; }; template concept member_cend = requires(SubjectType const & subject) { typename SubjectType::const_iterator; - { - subject.cend() - } -> std::same_as; + { subject.cend() } -> std::same_as; }; template @@ -425,33 +363,25 @@ namespace nt template concept free_rend = requires(SubjectType & subject) { typename SubjectType::reverse_iterator; - { - rend(subject) - } -> std::same_as; + { rend(subject) } -> std::same_as; }; template concept const_free_rend = requires(SubjectType const & subject) { typename SubjectType::const_reverse_iterator; - { - rend(subject) - } -> std::same_as; + { rend(subject) } -> std::same_as; }; template concept member_rend = requires(SubjectType & subject) { typename SubjectType::reverse_iterator; - { - subject.rend() - } -> std::same_as; + { subject.rend() } -> std::same_as; }; template concept const_member_rend = requires(SubjectType const & subject) { typename SubjectType::const_reverse_iterator; - { - subject.rend() - } -> std::same_as; + { subject.rend() } -> std::same_as; }; template @@ -463,17 +393,13 @@ namespace nt template concept free_crend = requires(SubjectType const & subject) { typename SubjectType::const_reverse_iterator; - { - crend(subject) - } -> std::same_as; + { crend(subject) } -> std::same_as; }; template concept member_crend = requires(SubjectType const & subject) { typename SubjectType::const_reverse_iterator; - { - subject.crend() - } -> std::same_as; + { subject.crend() } -> std::same_as; }; template @@ -485,12 +411,10 @@ namespace nt template concept hashable = requires(SubjectType subject) { - { - std::hash{}(subject) - } -> std::convertible_to; + { std::hash{}(subject) } -> std::convertible_to; }; - } + } // namespace standard_extensions } // namespace concepts @@ -509,9 +433,13 @@ namespace nt auto constexpr ImplicitConversion = derivable{}; auto constexpr Indirection = derivable{}; auto constexpr Iterable = derivable{}; +#ifdef HAS_I_O_STREAM auto constexpr Read = derivable{}; +#endif auto constexpr Relational = derivable{}; +#ifdef HAS_I_O_STREAM auto constexpr Show = derivable{}; +#endif auto constexpr ThreewayCompare = derivable{}; } // namespace derivables @@ -605,6 +533,7 @@ namespace nt return decay(); } +#ifdef HAS_I_O_STREAM template BaseTypeT = BaseType> auto friend operator>>(std::basic_istream & in, new_type & obj) noexcept(nt::concepts::nothrow_input_streamable) @@ -622,7 +551,7 @@ namespace nt { return out << obj.m_value; } - +#endif // THREE-WAY ORDER AND EQUAL auto constexpr operator<=>(new_type const & rhs) const noexcept(nt::concepts::nothrow_three_way_comparable) @@ -662,7 +591,8 @@ namespace nt } #define NEWTYPE_MAKE_LOGICAL_OPERATOR(OPERATOR, CONCEPT) \ - auto constexpr operator OPERATOR(new_type const & rhs) const noexcept(nt::concepts::nothrow_##CONCEPT##_comparable) -> bool \ + auto constexpr operator OPERATOR(new_type const & rhs) const noexcept(nt::concepts::nothrow_##CONCEPT##_comparable) \ + ->bool \ requires(nt::concepts::CONCEPT##_comparable && nt::doesnt_derive && \ nt::derives) \ { \ @@ -676,12 +606,13 @@ namespace nt #undef NEWTYPE_MAKE_LOGICAL_OPERATOR #define NEWTYPE_MAKE_ARITHMETIC_OPERATOR(OPERATOR, CONCEPT) \ - auto constexpr operator OPERATOR(new_type const & rhs) const noexcept(nt::concepts::nothrow_##CONCEPT) -> new_type \ + auto constexpr operator OPERATOR(new_type const & rhs) const noexcept(nt::concepts::nothrow_##CONCEPT) \ + ->new_type \ requires(nt::concepts::CONCEPT && nt::derives) \ { \ return {decay() OPERATOR rhs.decay()}; \ } \ - auto constexpr operator OPERATOR##=(new_type const & rhs) const noexcept(nt::concepts::nothrow_compound_##CONCEPT) -> new_type & \ + auto constexpr operator OPERATOR##=(new_type const & rhs) const noexcept(nt::concepts::nothrow_compound_##CONCEPT)->new_type & \ requires(nt::concepts::compound_##CONCEPT && nt::derives) { \ return this->m_value OPERATOR## = rhs.decay(), *this; \ }; @@ -694,7 +625,8 @@ namespace nt #define NEWTYPE_MAKE_ITERATOR_FACTORY_HELPER(NAME, QUALIFICATION, ITERATOR) \ template \ - auto constexpr friend NAME(new_type QUALIFICATION & obj) -> new_type::ITERATOR \ + auto constexpr friend NAME(new_type QUALIFICATION & obj) \ + ->new_type::ITERATOR \ requires nt::derives \ { \ using std::NAME; \ -- cgit v1.2.3