From 124d4f363a9d86b023aadec0eb0a3eb6fc1cbfdd Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 21 Dec 2023 18:40:57 +0100 Subject: new_type: reduce code cuplication --- source/lib/include/newtype/newtype.hpp | 558 +++++++-------------------------- 1 file changed, 108 insertions(+), 450 deletions(-) diff --git a/source/lib/include/newtype/newtype.hpp b/source/lib/include/newtype/newtype.hpp index 25c7313..fecaf2c 100644 --- a/source/lib/include/newtype/newtype.hpp +++ b/source/lib/include/newtype/newtype.hpp @@ -11,6 +11,23 @@ namespace nt { + inline namespace lib + { + constexpr struct + { + int const major; + int const minor; + int const patch; + + char const * const name; + } version{ + .major = 2, + .minor = 0, + .patch = 0, + .name = "Brynn", + }; + + } // namespace lib namespace impl { @@ -37,38 +54,21 @@ namespace nt using iterator = typename T::iterator; }; - template> - struct new_type_const_iterator : new_type_iterator - { - }; - - template - struct new_type_const_iterator> : new_type_iterator - { - using const_iterator = typename T::const_iterator; - }; - - template> - struct new_type_reverse_iterator : new_type_const_iterator - { - }; - - template - struct new_type_reverse_iterator> : new_type_const_iterator - { - using reverse_iterator = typename T::reverse_iterator; - }; - - template> - struct new_type_const_reverse_iterator : new_type_reverse_iterator - { - }; +#define NEWTYPE_MAKE_ITERATOR_BASE(NAME, BASE) \ + template> \ + struct new_type_##NAME : new_type_##BASE \ + { \ + }; \ + template \ + struct new_type_##NAME> : new_type_##BASE \ + { \ + using NAME = typename T::NAME; \ + }; - template - struct new_type_const_reverse_iterator> : new_type_reverse_iterator - { - using const_reverse_iterator = typename T::const_reverse_iterator; - }; + NEWTYPE_MAKE_ITERATOR_BASE(const_iterator, iterator) + NEWTYPE_MAKE_ITERATOR_BASE(reverse_iterator, const_iterator) + NEWTYPE_MAKE_ITERATOR_BASE(const_reverse_iterator, reverse_iterator) +#undef NEWTYPE_MAKE_ITERATOR_BASE template struct new_type_iterator_types : new_type_const_reverse_iterator @@ -79,90 +79,35 @@ namespace nt } // namespace impl - inline namespace lib - { - constexpr struct - { - int const major; - int const minor; - int const patch; - - char const * const name; - } version{ - .major = 2, - .minor = 0, - .patch = 0, - .name = "Brynn", - }; - - } // namespace lib - namespace concepts { inline namespace arithmetic { +#define NEWTYPE_MAKE_ARITHMETIC_CONCEPT(NAME, OPERATOR, REF) \ + template \ + concept NAME = requires(SubjectType lhs, SubjectType rhs) { \ + { \ + lhs OPERATOR rhs \ + } -> std::same_as; \ + }; \ + template \ + concept nothrow_##NAME = requires(SubjectType lhs, SubjectType rhs) { \ + requires NAME; \ + { \ + lhs OPERATOR rhs \ + } noexcept; \ + }; - template - concept addable = requires(SubjectType lhs, SubjectType rhs) { - { - lhs + rhs - } -> std::same_as; - }; - - template - concept nothrow_addable = requires(SubjectType lhs, SubjectType rhs) { - requires addable; - { - lhs + rhs - } noexcept; - }; - - template - concept divisible = requires(SubjectType lhs, SubjectType rhs) { - { - lhs / rhs - } -> std::same_as; - }; - - template - concept nothrow_divisible = requires(SubjectType lhs, SubjectType rhs) { - requires divisible; - { - lhs / rhs - } noexcept; - }; - - template - concept multipliable = requires(SubjectType lhs, SubjectType rhs) { - { - lhs * rhs - } -> std::same_as; - }; - - template - concept nothrow_multipliable = requires(SubjectType lhs, SubjectType rhs) { - requires multipliable; - { - lhs / rhs - } noexcept; - }; - - template - concept subtractable = requires(SubjectType lhs, SubjectType rhs) { - { - lhs - rhs - } -> std::same_as; - }; - - template - concept nothrow_subtractable = requires(SubjectType lhs, SubjectType rhs) { - requires subtractable; - { - lhs - rhs - } noexcept; - }; - + NEWTYPE_MAKE_ARITHMETIC_CONCEPT(addable, +, /*no-ref*/) + NEWTYPE_MAKE_ARITHMETIC_CONCEPT(divisible, /, /*no-ref*/) + NEWTYPE_MAKE_ARITHMETIC_CONCEPT(multipliable, *, /*no-ref*/) + NEWTYPE_MAKE_ARITHMETIC_CONCEPT(subtractable, -, /*no-ref*/) + NEWTYPE_MAKE_ARITHMETIC_CONCEPT(compound_addable, +=, &) + NEWTYPE_MAKE_ARITHMETIC_CONCEPT(compound_divisible, /=, &) + NEWTYPE_MAKE_ARITHMETIC_CONCEPT(compound_multipliable, *=, &) + NEWTYPE_MAKE_ARITHMETIC_CONCEPT(compound_subtractable, -=, &) +#undef NEWTYPE_MAKE_ARITHMETIC_CONCEPT } // namespace arithmetic inline namespace comparability @@ -268,69 +213,6 @@ namespace nt } // namespace comparability - inline namespace compound_arithmetic - { - template - concept compound_addable = requires(SubjectType & lhs, SubjectType const & rhs) { - { - lhs += rhs - } -> std::convertible_to; - }; - - template - concept nothrow_compound_addable = requires(SubjectType & lhs, SubjectType const & rhs) { - requires compound_addable; - { - lhs += rhs - } noexcept; - }; - - template - concept compound_divisible = requires(SubjectType & lhs, SubjectType const & rhs) { - { - lhs /= rhs - } -> std::convertible_to; - }; - - template - concept nothrow_compound_divisible = requires(SubjectType & lhs, SubjectType const & rhs) { - requires compound_divisible; - { - lhs /= rhs - } noexcept; - }; - - template - concept compound_multipliable = requires(SubjectType & lhs, SubjectType const & rhs) { - { - lhs *= rhs - } -> std::convertible_to; - }; - - template - concept nothrow_compound_multipliable = requires(SubjectType & lhs, SubjectType const & rhs) { - requires compound_multipliable; - { - lhs *= rhs - } noexcept; - }; - - template - concept compound_subtractable = requires(SubjectType & lhs, SubjectType const & rhs) { - { - lhs -= rhs - } -> std::convertible_to; - }; - - template - concept nothrow_compound_subtractable = requires(SubjectType & lhs, SubjectType const & rhs) { - requires compound_subtractable; - { - lhs -= rhs - } noexcept; - }; - } // namespace compound_arithmetic - inline namespace iostreamable { @@ -741,21 +623,6 @@ namespace nt return out << obj.m_value; } - /** - * @brief Check two instances of nt::new_type for equality. - * - * @param lhs The left-hand side of the comparison. - * @param rhs The right-hand side of the comparison. - * - * @note This overload is available iff. the underlying type is equality-comparable and this nt::new_type does not derive - * nt::ThreewayCompare. - * - * @return The value returned by the comparison of the underlying objects. - * - * @throws Any exception thrown by the comparison operator of the underlying objects of @ref lhs and @ref rhs. `noexcept` iff. - * new_type::base_type is nothrow equality-comparable. - */ - // THREE-WAY ORDER AND EQUAL auto constexpr operator<=>(new_type const & rhs) const noexcept(nt::concepts::nothrow_three_way_comparable) @@ -794,88 +661,63 @@ namespace nt return decay() != rhs.decay(); } - // NOT THREE-WAY ORDER - - auto constexpr operator<(new_type const & rhs) const noexcept(nt::concepts::nothrow_less_than_comparable) -> bool - requires(nt::concepts::less_than_comparable && // - nt::doesnt_derive && // - nt::derives) - { - return decay() < rhs.decay(); - } - - auto constexpr operator<=(new_type const & rhs) const noexcept(nt::concepts::nothrow_less_than_equal_comparable) -> bool - requires(nt::concepts::less_than_equal_comparable && // - nt::doesnt_derive && // - nt::derives) - { - return decay() <= rhs.decay(); - } - - auto constexpr operator>(new_type const & rhs) const noexcept(nt::concepts::nothrow_greater_than_comparable) -> bool - requires(nt::concepts::greater_than_comparable && // - nt::doesnt_derive && // - nt::derives) - { - return decay() > rhs.decay(); - } - - auto constexpr operator>=(new_type const & rhs) const noexcept(nt::concepts::nothrow_greater_than_equal_comparable) -> bool - requires(nt::concepts::greater_than_equal_comparable && // - nt::doesnt_derive && // - nt::derives) - { - return decay() >= rhs.decay(); - } - - // ARITHMETIC - - auto constexpr operator+(new_type const & rhs) const noexcept(nt::concepts::nothrow_addable) -> new_type - requires(nt::concepts::addable && nt::derives) - { - return {decay() + rhs.decay()}; - } - - auto constexpr operator+=(new_type const & rhs) const noexcept(nt::concepts::nothrow_compound_addable) - -> new_type & requires(nt::concepts::compound_addable && nt::derives) { - return this->m_value += rhs.decay(); - } - - auto constexpr - operator-(new_type const & rhs) const noexcept(nt::concepts::nothrow_subtractable) -> new_type - requires(nt::concepts::subtractable && nt::derives) - { - return {decay() - rhs.decay()}; - } - - auto constexpr operator-=(new_type const & rhs) const noexcept(nt::concepts::nothrow_compound_subtractable) - -> new_type & requires(nt::concepts::compound_subtractable && nt::derives) { - return this->m_value -= rhs.decay(); - } - - auto constexpr - operator*(new_type const & rhs) const noexcept(nt::concepts::nothrow_multipliable) -> new_type - requires(nt::concepts::multipliable && nt::derives) - { - return {decay() * rhs.decay()}; - } +#define NEWTYPE_MAKE_LOGICAL_OPERATOR(OPERATOR, CONCEPT) \ + 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) \ + { \ + return decay() OPERATOR rhs.decay(); \ + } - auto constexpr operator*=(new_type const & rhs) const noexcept(nt::concepts::nothrow_compound_multipliable) - -> new_type & requires(nt::concepts::compound_multipliable && nt::derives) { - return this->m_value *= rhs.decay(); - } + NEWTYPE_MAKE_LOGICAL_OPERATOR(<, less_than) + NEWTYPE_MAKE_LOGICAL_OPERATOR(<=, less_than_equal) + NEWTYPE_MAKE_LOGICAL_OPERATOR(>, greater_than) + NEWTYPE_MAKE_LOGICAL_OPERATOR(>=, greater_than_equal) +#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 \ + 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 & \ + requires(nt::concepts::compound_##CONCEPT && nt::derives) { \ + return this->m_value OPERATOR## = rhs.decay(), *this; \ + }; + + NEWTYPE_MAKE_ARITHMETIC_OPERATOR(+, addable) + NEWTYPE_MAKE_ARITHMETIC_OPERATOR(-, subtractable) + NEWTYPE_MAKE_ARITHMETIC_OPERATOR(*, multipliable) + NEWTYPE_MAKE_ARITHMETIC_OPERATOR(/, divisible) +#undef NEWTYPE_MAKE_ARITHMETIC_OPERATOR + +#define NEWTYPE_MAKE_ITERATOR_FACTORY_HELPER(NAME, QUALIFICATION, ITERATOR) \ + template \ + auto constexpr friend NAME(new_type QUALIFICATION & obj) -> new_type::ITERATOR \ + requires nt::derives \ + { \ + using std::NAME; \ + return NAME(obj.m_value); \ + } \ + template \ + auto constexpr NAME() QUALIFICATION->new_type::ITERATOR \ + requires nt::derives \ + { \ + return this->m_value.NAME(); \ + } - auto constexpr - operator/(new_type const & rhs) const noexcept(nt::concepts::nothrow_divisible) -> new_type - requires(nt::concepts::divisible && nt::derives) - { - return {decay() / rhs.decay()}; - } +#define NEWTYPE_MAKE_ITERATOR_FACTORY(NAME, ITERATOR) \ + NEWTYPE_MAKE_ITERATOR_FACTORY_HELPER(NAME, /*non-const*/, ITERATOR) \ + NEWTYPE_MAKE_ITERATOR_FACTORY_HELPER(NAME, const, const_##ITERATOR) \ + NEWTYPE_MAKE_ITERATOR_FACTORY_HELPER(c##NAME, const, const_##ITERATOR) - auto constexpr operator/=(new_type const & rhs) const noexcept(nt::concepts::nothrow_compound_divisible) - -> new_type & requires(nt::concepts::compound_divisible && nt::derives) { - return this->m_value /= rhs.decay(); - } + NEWTYPE_MAKE_ITERATOR_FACTORY(begin, iterator) + NEWTYPE_MAKE_ITERATOR_FACTORY(rbegin, reverse_iterator) + NEWTYPE_MAKE_ITERATOR_FACTORY(end, iterator) + NEWTYPE_MAKE_ITERATOR_FACTORY(rend, reverse_iterator) +#undef NEWTYPE_MAKE_ITERATOR_FACTORY +#undef NEWTYPE_MAKE_ITERATOR_FACTORY_HELPER // INDIRECTION @@ -892,190 +734,6 @@ namespace nt // { // return std::addressof(this->m_value); // } - - // FREE ITERATORS - - template - auto constexpr friend begin(new_type & obj) -> new_type::iterator - requires nt::derives - { - using std::begin; - return begin(obj.m_value); - } - - template - auto constexpr friend begin(new_type const & obj) -> new_type::const_iterator - requires nt::derives - { - using std::begin; - return begin(obj.m_value); - } - - template - auto constexpr friend cbegin(new_type const & obj) -> new_type::const_iterator - requires nt::derives - { - using std::cbegin; - return cbegin(obj.m_value); - } - - template - auto constexpr friend rbegin(new_type & obj) -> new_type::reverse_iterator - requires nt::derives - { - using std::rbegin; - return rbegin(obj.m_value); - } - - template - auto constexpr friend rbegin(new_type const & obj) -> new_type::const_reverse_iterator - requires nt::derives - { - using std::rbegin; - return rbegin(obj.m_value); - } - - template - auto constexpr friend crbegin(new_type const & obj) -> new_type::const_reverse_iterator - requires nt::derives - { - using std::crbegin; - return crbegin(obj.m_value); - } - - template - auto constexpr friend end(new_type & obj) -> new_type::iterator - requires nt::derives - { - using std::end; - return end(obj.m_value); - } - - template - auto constexpr friend end(new_type const & obj) -> new_type::const_iterator - requires nt::derives - { - using std::end; - return end(obj.m_value); - } - - template - auto constexpr friend cend(new_type const & obj) -> new_type::const_iterator - requires nt::derives - { - using std::cend; - return cend(obj.m_value); - } - - template - auto constexpr friend rend(new_type & obj) -> new_type::reverse_iterator - requires nt::derives - { - using std::rend; - return rend(obj.m_value); - } - - template - auto constexpr friend rend(new_type const & obj) -> new_type::const_reverse_iterator - requires nt::derives - { - using std::rend; - return rend(obj.m_value); - } - - template - auto constexpr friend crend(new_type const & obj) -> new_type::const_reverse_iterator - requires nt::derives - { - using std::crend; - return crend(obj.m_value); - } - - // MEMBER ITERATORS - - template - auto constexpr begin() -> new_type::iterator - requires nt::derives - { - return this->m_value.begin(); - } - - template - auto constexpr begin() const -> new_type::const_iterator - requires nt::derives - { - return this->m_value.begin(); - } - - template - auto constexpr cbegin() const -> new_type::const_iterator - requires nt::derives - { - return this->m_value.cbegin(); - } - - template - auto constexpr rbegin() -> new_type::reverse_iterator - requires nt::derives - { - return this->m_value.rbegin(); - } - - template - auto constexpr rbegin() const -> new_type::const_reverse_iterator - requires nt::derives - { - return this->m_value.rbegin(); - } - - template - auto constexpr crbegin() const -> new_type::const_reverse_iterator - requires nt::derives - { - return this->m_value.crbegin(); - } - - template - auto constexpr end() -> new_type::iterator - requires nt::derives - { - return this->m_value.end(); - } - - template - auto constexpr end() const -> new_type::const_iterator - requires nt::derives - { - return this->m_value.end(); - } - - template - auto constexpr cend() const -> new_type::const_iterator - requires nt::derives - { - return this->m_value.cend(); - } - - template - auto constexpr rend() -> new_type::reverse_iterator - requires nt::derives - { - return this->m_value.rend(); - } - - template - auto constexpr rend() const -> new_type::const_reverse_iterator - requires nt::derives - { - return this->m_value.rend(); - } - - template - auto constexpr crend() const -> new_type::const_reverse_iterator - requires nt::derives - { - return this->m_value.crend(); - } }; } // namespace nt -- cgit v1.2.3