From 440d47cae6431de3332ac934b6056a970cc1a0d7 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 26 Feb 2025 11:24:59 +0100 Subject: build: remove conan --- lib/CMakeLists.txt | 16 + lib/include/newtype/newtype.hpp | 753 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 769 insertions(+) create mode 100644 lib/CMakeLists.txt create mode 100644 lib/include/newtype/newtype.hpp (limited to 'lib') diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt new file mode 100644 index 0000000..0219803 --- /dev/null +++ b/lib/CMakeLists.txt @@ -0,0 +1,16 @@ +add_library("${PROJECT_NAME}" INTERFACE) + +target_include_directories("${PROJECT_NAME}" INTERFACE + "$" + "$" +) + +target_compile_features("${PROJECT_NAME}" INTERFACE + "cxx_std_20" +) + +install(DIRECTORY "include/" + TYPE INCLUDE +) + +add_library("${PROJECT_NAME}::${PROJECT_NAME}" ALIAS "${PROJECT_NAME}") diff --git a/lib/include/newtype/newtype.hpp b/lib/include/newtype/newtype.hpp new file mode 100644 index 0000000..fecaf2c --- /dev/null +++ b/lib/include/newtype/newtype.hpp @@ -0,0 +1,753 @@ +#ifndef NEWTYPE_NEWTYPE_HPP +#define NEWTYPE_NEWTYPE_HPP + +#include +#include +#include +#include +#include +#include +#include + +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 + { + inline namespace storage + { + template + struct new_type_storage + { + T m_value; + }; + } // namespace storage + + inline namespace member_types + { + + template> + struct new_type_iterator : new_type_storage + { + }; + + template + struct new_type_iterator> : new_type_storage + { + using iterator = typename T::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; \ + }; + + 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 + { + }; + + } // namespace member_types + + } // namespace impl + + 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; \ + }; + + 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 + { + + template + concept nothrow_three_way_comparable = requires(SubjectType lhs, SubjectType rhs) { + requires std::three_way_comparable; + { + lhs <=> rhs + } noexcept; + }; + + template + concept equality_comparable = requires(SubjectType lhs, SubjectType rhs) { + { + lhs == rhs + } -> std::convertible_to; + }; + + template + concept nothrow_equality_comparable = requires(SubjectType lhs, SubjectType rhs) { + requires equality_comparable; + { + lhs == rhs + } noexcept; + }; + + template + concept inequality_comparable = requires(SubjectType lhs, SubjectType rhs) { + { + lhs != rhs + } -> std::convertible_to; + }; + + template + concept nothrow_inequality_comparable = requires(SubjectType lhs, SubjectType rhs) { + requires inequality_comparable; + { + lhs != rhs + } noexcept; + }; + + template + concept less_than_comparable = requires(SubjectType lhs, SubjectType rhs) { + { + lhs < rhs + } -> std::convertible_to; + }; + + template + concept nothrow_less_than_comparable = requires(SubjectType lhs, SubjectType rhs) { + requires less_than_comparable; + { + lhs < rhs + } noexcept; + }; + + template + concept less_than_equal_comparable = requires(SubjectType lhs, SubjectType rhs) { + { + 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; + }; + + template + concept greater_than_comparable = requires(SubjectType lhs, SubjectType rhs) { + { + lhs > rhs + } -> std::convertible_to; + }; + + template + concept nothrow_greater_than_comparable = requires(SubjectType lhs, SubjectType rhs) { + requires greater_than_comparable; + { + lhs > rhs + } noexcept; + }; + + template + concept greater_than_equal_comparable = requires(SubjectType lhs, SubjectType rhs) { + { + 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; + }; + + } // namespace comparability + + inline namespace iostreamable + { + + template + concept input_streamable = requires(SubjectType subject) { + { + std::declval &>() >> subject + } -> std::same_as &>; + }; + + template + concept nothrow_input_streamable = requires(SubjectType subject) { + requires input_streamable; + { + std::declval &>() >> subject + } noexcept; + }; + + template + concept output_streamable = requires(SubjectType subject) { + { + std::declval &>() << subject + } -> std::same_as &>; + }; + + template + concept nothrow_output_streamable = requires(SubjectType subject) { + requires output_streamable; + { + std::declval &>() << subject + } noexcept; + }; + + } // namespace iostreamable + + inline namespace iterable + { + + template + concept free_begin = requires(SubjectType & subject) { + typename SubjectType::iterator; + { + begin(subject) + } -> std::same_as; + }; + + template + concept const_free_begin = requires(SubjectType const & subject) { + typename SubjectType::const_iterator; + { + begin(subject) + } -> std::same_as; + }; + + template + concept member_begin = requires(SubjectType & subject) { + typename SubjectType::iterator; + { + subject.begin() + } -> std::same_as; + }; + + template + concept const_member_begin = requires(SubjectType const & subject) { + typename SubjectType::const_iterator; + { + subject.begin() + } -> std::same_as; + }; + + template + concept beginnable = free_begin || member_begin; + + template + concept const_beginnable = const_free_begin || const_member_begin; + + template + concept free_cbegin = requires(SubjectType const & subject) { + typename SubjectType::const_iterator; + { + cbegin(subject) + } -> std::same_as; + }; + + template + concept member_cbegin = requires(SubjectType const & subject) { + typename SubjectType::const_iterator; + { + subject.cbegin() + } -> std::same_as; + }; + + template + concept cbeginnable = free_cbegin || member_cbegin; + + template + concept free_rbegin = requires(SubjectType & subject) { + typename SubjectType::reverse_iterator; + { + rbegin(subject) + } -> std::same_as; + }; + + template + concept const_free_rbegin = requires(SubjectType const & subject) { + typename SubjectType::const_reverse_iterator; + { + rbegin(subject) + } -> std::same_as; + }; + + template + concept member_rbegin = requires(SubjectType & subject) { + typename SubjectType::reverse_iterator; + { + subject.rbegin() + } -> std::same_as; + }; + + template + concept const_member_rbegin = requires(SubjectType const & subject) { + typename SubjectType::const_reverse_iterator; + { + subject.rbegin() + } -> std::same_as; + }; + + template + concept rbeginnable = free_rbegin || member_rbegin; + + template + concept const_rbeginnable = const_free_rbegin || const_member_rbegin; + + template + concept free_crbegin = requires(SubjectType const & subject) { + typename SubjectType::const_reverse_iterator; + { + crbegin(subject) + } -> std::same_as; + }; + + template + concept member_crbegin = requires(SubjectType const & subject) { + typename SubjectType::const_reverse_iterator; + { + subject.crbegin() + } -> std::same_as; + }; + + template + concept crbeginnable = free_crbegin || member_crbegin; + + template + concept free_end = requires(SubjectType & subject) { + typename SubjectType::iterator; + { + end(subject) + } -> std::same_as; + }; + + template + concept const_free_end = requires(SubjectType const & subject) { + typename SubjectType::const_iterator; + { + end(subject) + } -> std::same_as; + }; + + template + concept member_end = requires(SubjectType & subject) { + typename SubjectType::iterator; + { + subject.end() + } -> std::same_as; + }; + + template + concept const_member_end = requires(SubjectType const & subject) { + typename SubjectType::const_iterator; + { + subject.end() + } -> std::same_as; + }; + + template + concept endable = free_end || member_end; + + template + concept const_endable = const_free_end || const_member_end; + + template + concept free_cend = requires(SubjectType const & subject) { + typename SubjectType::const_iterator; + { + cend(subject) + } -> std::same_as; + }; + + template + concept member_cend = requires(SubjectType const & subject) { + typename SubjectType::const_iterator; + { + subject.cend() + } -> std::same_as; + }; + + template + concept cendable = free_cend || member_cend; + + template + concept free_rend = requires(SubjectType & subject) { + typename SubjectType::reverse_iterator; + { + rend(subject) + } -> std::same_as; + }; + + template + concept const_free_rend = requires(SubjectType const & subject) { + typename SubjectType::const_reverse_iterator; + { + rend(subject) + } -> std::same_as; + }; + + template + concept member_rend = requires(SubjectType & subject) { + typename SubjectType::reverse_iterator; + { + subject.rend() + } -> std::same_as; + }; + + template + concept const_member_rend = requires(SubjectType const & subject) { + typename SubjectType::const_reverse_iterator; + { + subject.rend() + } -> std::same_as; + }; + + template + concept rendable = free_rend || member_rend; + + template + concept const_rendable = const_free_rend || const_member_rend; + + template + concept free_crend = requires(SubjectType const & subject) { + typename SubjectType::const_reverse_iterator; + { + crend(subject) + } -> std::same_as; + }; + + template + concept member_crend = requires(SubjectType const & subject) { + typename SubjectType::const_reverse_iterator; + { + subject.crend() + } -> std::same_as; + }; + + template + concept crendable = free_crend || member_crend; + } // namespace iterable + + inline namespace standard_extensions + { + + template + concept hashable = requires(SubjectType subject) { + { + std::hash{}(subject) + } -> std::convertible_to; + }; + + } + + } // namespace concepts + + template + struct derivable final + { + using tag_type = DerivableTag; + }; + + inline namespace derivables + { + + auto constexpr Arithmetic = derivable{}; + auto constexpr EqBase = derivable{}; + auto constexpr Hash = derivable{}; + auto constexpr ImplicitConversion = derivable{}; + auto constexpr Indirection = derivable{}; + auto constexpr Iterable = derivable{}; + auto constexpr Read = derivable{}; + auto constexpr Relational = derivable{}; + auto constexpr Show = derivable{}; + auto constexpr ThreewayCompare = derivable{}; + + } // namespace derivables + + template + struct derivation_clause + { + template + using derives_one = std::disjunction...>; + + template + using derives = std::conjunction...>; + + constexpr derivation_clause(derivable...) noexcept + { + } + }; + + template + concept derives = requires(DerivationClause clause) { requires DerivationClause::template derives::value; }; + + template + concept doesnt_derive = !derives; + + template + auto constexpr deriving(derivable... features) noexcept -> derivation_clause + { + return {features...}; + } + + template + class new_type : public impl::new_type_iterator_types> + { + static_assert(!std::is_reference_v, "The base type must not be a reference type"); + static_assert(!std::is_void_v>, "The base type must not be possibly cv-qualified void"); + static_assert(!derives, + "Cannot derive both nt::Relational and nt::ThreewayCompare at the same time."); + + using super = impl::new_type_iterator_types>; + + public: + using base_type = BaseType; + using tag_type = TagType; + using derivation_clause_type = decltype(DerivationClause); + + auto constexpr static derivation_clause = DerivationClause; + + constexpr new_type() noexcept(std::is_nothrow_default_constructible_v) + requires std::constructible_from + = default; + + constexpr new_type(new_type const &) noexcept(std::is_nothrow_copy_constructible_v) + requires std::copy_constructible + = default; + + constexpr new_type(new_type &&) noexcept(std::is_nothrow_move_constructible_v) + requires std::move_constructible + = default; + + constexpr new_type(BaseType const & base) noexcept(std::is_nothrow_copy_constructible_v) + requires std::copy_constructible + : super{base} + { + } + + constexpr new_type(BaseType && base) noexcept(std::is_nothrow_move_constructible_v) + requires std::move_constructible + : super{std::move(base)} + { + } + + auto constexpr operator=(new_type const &) noexcept(std::is_nothrow_copy_assignable_v) -> new_type & = default; + auto constexpr operator=(new_type &&) noexcept(std::is_nothrow_move_assignable_v) -> new_type & = default; + + auto constexpr decay() const noexcept(std::is_nothrow_copy_constructible_v) -> BaseType + { + return this->m_value; + } + + template + constexpr operator base_type() const noexcept(std::is_nothrow_copy_constructible_v) + requires(nt::derives) + { + return decay(); + } + + template + explicit constexpr operator base_type() const noexcept(std::is_nothrow_copy_constructible_v) + requires(nt::doesnt_derive) + { + return decay(); + } + + template BaseTypeT = BaseType> + auto friend operator>>(std::basic_istream & in, + new_type & obj) noexcept(nt::concepts::nothrow_input_streamable) + -> std::basic_istream & + requires nt::derives + { + return in >> obj.m_value; + } + + template BaseTypeT = BaseType> + auto friend operator<<(std::basic_ostream & out, + new_type const & obj) noexcept(nt::concepts::nothrow_output_streamable) + -> std::basic_ostream & + requires nt::derives + { + return out << obj.m_value; + } + + // THREE-WAY ORDER AND EQUAL + + auto constexpr operator<=>(new_type const & rhs) const noexcept(nt::concepts::nothrow_three_way_comparable) + requires(std::three_way_comparable && nt::derives) + { + return decay() <=> rhs.decay(); + } + + auto constexpr operator==(new_type const & rhs) const -> bool + requires(nt::concepts::equality_comparable && nt::derives) + { + return decay() == rhs.decay(); + } + + // NOT THREE-WAY EQUAL + + auto constexpr operator==(new_type const & rhs) const noexcept(nt::concepts::nothrow_equality_comparable) -> bool + requires(nt::concepts::equality_comparable && nt::doesnt_derive) + { + return decay() == rhs.decay(); + } + + // BASE EQUAL + + auto constexpr operator==(BaseType const & rhs) const noexcept(nt::concepts::nothrow_equality_comparable) -> bool + requires(nt::concepts::equality_comparable && nt::derives) + { + return decay() == rhs; + } + + // NOT THREE-WAY EQUAL + + auto constexpr operator!=(new_type const & rhs) const noexcept(nt::concepts::nothrow_inequality_comparable) -> bool + requires(nt::concepts::inequality_comparable && nt::doesnt_derive) + { + 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(); \ + } + + 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(); \ + } + +#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) + + 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 + + // template + // requires(nt::derives) + // auto constexpr operator->() noexcept -> BaseType * + // { + // return std::addressof(this->m_value); + // } + + // template + // requires(nt::derives) + // auto constexpr operator->() const noexcept -> BaseType const * + // { + // return std::addressof(this->m_value); + // } + }; + +} // namespace nt + +namespace std +{ + template auto DerivationClause> + struct hash> + { + auto constexpr operator()(nt::new_type const & object) const + { + return std::hash{}(object.decay()); + } + }; +} // namespace std + +#endif -- cgit v1.2.3