diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/newtype/impl/type_traits_extensions.hpp | 184 | ||||
| -rw-r--r-- | include/newtype/new_type.hpp | 120 |
2 files changed, 302 insertions, 2 deletions
diff --git a/include/newtype/impl/type_traits_extensions.hpp b/include/newtype/impl/type_traits_extensions.hpp index f7dafef..121e2c0 100644 --- a/include/newtype/impl/type_traits_extensions.hpp +++ b/include/newtype/impl/type_traits_extensions.hpp @@ -629,7 +629,7 @@ namespace nt::impl auto constexpr has_rbegin_v = has_rbegin<T>::value; } // namespace iterable_rbegin - inline namespace iterable_rbegin + inline namespace iterable_crbegin { template<typename T, typename = void> struct has_free_crbegin : std::false_type @@ -666,7 +666,187 @@ namespace nt::impl template<typename T> auto constexpr has_crbegin_v = has_crbegin<T>::value; - } // namespace iterable_rbegin + } // namespace iterable_crbegin + + inline namespace iterable_end + { + template<typename T, typename = void> + struct has_free_end : std::false_type + { + }; + + template<typename T> + struct has_free_end<T, std::void_t<decltype(end(std::declval<T &>()))>> + : std::is_same<typename T::iterator, std::remove_cvref_t<decltype(end(std::declval<T &>()))>> + { + }; + + template<typename T> + struct has_free_end<T const, std::void_t<decltype(end(std::declval<T const &>()))>> + : std::is_same<typename T::const_iterator, std::remove_cvref_t<decltype(end(std::declval<T const &>()))>> + { + }; + + template<typename T> + auto constexpr has_free_end_v = has_free_end<T>::value; + + template<typename T, typename = void> + struct has_member_end : std::false_type + { + }; + + template<typename T> + struct has_member_end<T, std::void_t<decltype(std::declval<T &>().end())>> + : std::is_same<typename T::iterator, std::remove_cvref_t<decltype(std::declval<T &>().end())>> + { + }; + + template<typename T> + struct has_member_end<T const, std::void_t<decltype(std::declval<T const &>().end())>> + : std::is_same<typename T::const_iterator, std::remove_cvref_t<decltype(std::declval<T const &>().end())>> + { + }; + + template<typename T> + auto constexpr has_member_end_v = has_member_end<T>::value; + + template<typename T> + struct has_end : std::disjunction<has_free_end<T>, has_member_end<T>> + { + }; + + template<typename T> + auto constexpr has_end_v = has_end<T>::value; + } // namespace iterable_end + + inline namespace iterable_cend + { + template<typename T, typename = void> + struct has_free_cend : std::false_type + { + }; + + template<typename T> + struct has_free_cend<T, std::void_t<decltype(cend(std::declval<T const &>()))>> + : std::is_same<typename T::const_iterator, std::remove_cvref_t<decltype(cend(std::declval<T const &>()))>> + { + }; + + template<typename T> + auto constexpr has_free_cend_v = has_free_cend<T>::value; + + template<typename T, typename = void> + struct has_member_cend : std::false_type + { + }; + + template<typename T> + struct has_member_cend<T, std::void_t<decltype(std::declval<T const &>().cend())>> + : std::is_same<typename T::const_iterator, decltype(std::declval<T const &>().cend())> + { + }; + + template<typename T> + auto constexpr has_member_cend_v = has_member_cend<T>::value; + + template<typename T> + struct has_cend : std::disjunction<has_free_cend<T>, has_member_cend<T>> + { + }; + + template<typename T> + auto constexpr has_cend_v = has_cend<T>::value; + } // namespace iterable_cend + + inline namespace iterable_rend + { + template<typename T, typename = void> + struct has_free_rend : std::false_type + { + }; + + template<typename T> + struct has_free_rend<T, std::void_t<decltype(rend(std::declval<T &>()))>> + : std::is_same<typename T::reverse_iterator, std::remove_cvref_t<decltype(end(std::declval<T &>()))>> + { + }; + + template<typename T> + struct has_free_rend<T const, std::void_t<decltype(rend(std::declval<T const &>()))>> + : std::is_same<typename T::const_reverse_iterator, std::remove_cvref_t<decltype(rend(std::declval<T const &>()))>> + { + }; + + template<typename T> + auto constexpr has_free_rend_v = has_free_rend<T>::value; + + template<typename T, typename = void> + struct has_member_rend : std::false_type + { + }; + + template<typename T> + struct has_member_rend<T, std::void_t<decltype(std::declval<T &>().rend())>> + : std::is_same<typename T::reverse_iterator, std::remove_cvref_t<decltype(std::declval<T &>().rend())>> + { + }; + + template<typename T> + struct has_member_rend<T const, std::void_t<decltype(std::declval<T const &>().rend())>> + : std::is_same<typename T::const_reverse_iterator, std::remove_cvref_t<decltype(std::declval<T const &>().rend())>> + { + }; + + template<typename T> + auto constexpr has_member_rend_v = has_member_rend<T>::value; + + template<typename T> + struct has_rend : std::disjunction<has_free_rend<T>, has_member_rend<T>> + { + }; + + template<typename T> + auto constexpr has_rend_v = has_rend<T>::value; + } // namespace iterable_rend + + inline namespace iterable_crend + { + template<typename T, typename = void> + struct has_free_crend : std::false_type + { + }; + + template<typename T> + struct has_free_crend<T, std::void_t<decltype(crend(std::declval<T const &>()))>> + : std::is_same<typename T::const_reverse_iterator, std::remove_cvref_t<decltype(crend(std::declval<T const &>()))>> + { + }; + + template<typename T> + auto constexpr has_free_crend_v = has_free_crend<T>::value; + + template<typename T, typename = void> + struct has_member_crend : std::false_type + { + }; + + template<typename T> + struct has_member_crend<T, std::void_t<decltype(std::declval<T const &>().crend())>> + : std::is_same<typename T::const_reverse_iterator, std::remove_cvref_t<decltype(std::declval<T const &>().crend())>> + { + }; + + template<typename T> + auto constexpr has_member_crend_v = has_member_crend<T>::value; + + template<typename T> + struct has_crend : std::disjunction<has_free_crend<T>, has_member_crend<T>> + { + }; + + template<typename T> + auto constexpr has_crend_v = has_crend<T>::value; + } // namespace iterable_crend } // namespace nt::impl diff --git a/include/newtype/new_type.hpp b/include/newtype/new_type.hpp index 36a3927..66ff332 100644 --- a/include/newtype/new_type.hpp +++ b/include/newtype/new_type.hpp @@ -88,6 +88,36 @@ namespace nt -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_crbegin_v<BaseTypeT const>, typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_reverse_iterator>; + template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV> + auto constexpr friend end(new_type<BaseTypeT, TagTypeT, DerivationClauseV> & obj) + -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_end_v<BaseTypeT>, + typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::iterator>; + + template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV> + auto constexpr friend end(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj) + -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_end_v<BaseTypeT const>, + typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_iterator>; + + template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV> + auto constexpr friend cend(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj) + -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_cend_v<BaseTypeT const>, + typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_iterator>; + + template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV> + auto constexpr friend rend(new_type<BaseTypeT, TagTypeT, DerivationClauseV> & obj) + -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_rend_v<BaseTypeT>, + typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::reverse_iterator>; + + template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV> + auto constexpr friend rend(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj) + -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_rend_v<BaseTypeT const>, + typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_reverse_iterator>; + + template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV> + auto constexpr friend crend(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj) + -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_crend_v<BaseTypeT const>, + typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_reverse_iterator>; + using super = impl::new_type_move_assignment<BaseType, TagType>; public: @@ -176,6 +206,48 @@ namespace nt { return this->m_value.crbegin(); } + + template<typename NewType = new_type, std::enable_if_t<NewType::derivation_clause(nt::Iterable)> * = nullptr> + auto constexpr end() + -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_end_v<BaseType>, typename NewType::iterator> + { + return this->m_value.end(); + } + + template<typename NewType = new_type> + auto constexpr end() const -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_end_v<BaseType const>, + typename NewType::const_iterator> + { + return this->m_value.end(); + } + + template<typename NewType = new_type> + auto constexpr cend() const -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_cend_v<BaseType const>, + typename NewType::const_iterator> + { + return this->m_value.cend(); + } + + template<typename NewType = new_type, std::enable_if_t<NewType::derivation_clause(nt::Iterable)> * = nullptr> + auto constexpr rend() + -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_rend_v<BaseType>, typename NewType::reverse_iterator> + { + return this->m_value.rend(); + } + + template<typename NewType = new_type> + auto constexpr rend() const -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_rend_v<BaseType const>, + typename NewType::const_reverse_iterator> + { + return this->m_value.rend(); + } + + template<typename NewType = new_type> + auto constexpr crend() const -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_crend_v<BaseType const>, + typename NewType::const_reverse_iterator> + { + return this->m_value.crend(); + } }; template<typename BaseType, typename TagType, auto DerivationClause> @@ -410,6 +482,54 @@ namespace nt return crbegin(obj.m_value); } + template<typename BaseType, typename TagType, auto DerivationClause> + auto constexpr end(new_type<BaseType, TagType, DerivationClause> & obj) + -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_end_v<BaseType>, + typename new_type<BaseType, TagType, DerivationClause>::iterator> + { + return end(obj.m_value); + } + + template<typename BaseType, typename TagType, auto DerivationClause> + auto constexpr end(new_type<BaseType, TagType, DerivationClause> const & obj) + -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_end_v<BaseType const>, + typename new_type<BaseType, TagType, DerivationClause>::const_iterator> + { + return end(obj.m_value); + } + + template<typename BaseType, typename TagType, auto DerivationClause> + auto constexpr cend(new_type<BaseType, TagType, DerivationClause> const & obj) + -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_cend_v<BaseType const>, + typename new_type<BaseType, TagType, DerivationClause>::const_iterator> + { + return cend(obj.m_value); + } + + template<typename BaseType, typename TagType, auto DerivationClause> + auto constexpr rend(new_type<BaseType, TagType, DerivationClause> & obj) + -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_rend_v<BaseType>, + typename new_type<BaseType, TagType, DerivationClause>::reverse_iterator> + { + return rend(obj.m_value); + } + + template<typename BaseType, typename TagType, auto DerivationClause> + auto constexpr rend(new_type<BaseType, TagType, DerivationClause> const & obj) + -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_rend_v<BaseType const>, + typename new_type<BaseType, TagType, DerivationClause>::const_reverse_iterator> + { + return rend(obj.m_value); + } + + template<typename BaseType, typename TagType, auto DerivationClause> + auto constexpr crend(new_type<BaseType, TagType, DerivationClause> const & obj) + -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_crend_v<BaseType const>, + typename new_type<BaseType, TagType, DerivationClause>::const_reverse_iterator> + { + return crend(obj.m_value); + } + } // namespace nt namespace std |
