diff options
| author | Felix Morgner <felix.morgner@gmail.com> | 2023-06-09 11:34:56 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@gmail.com> | 2023-06-09 11:34:56 +0200 |
| commit | 7ce8f285efd6d3c036e54423881b85ab67c071bb (patch) | |
| tree | 2e65b52fc60dcceda80efc207839c23ffb80e1fa /source | |
| parent | c740152b77bbbc8112528931b158d5115b695cb0 (diff) | |
| parent | 306982e16c4191604840e33b20db9479de977bbb (diff) | |
| download | newtype-7ce8f285efd6d3c036e54423881b85ab67c071bb.tar.xz newtype-7ce8f285efd6d3c036e54423881b85ab67c071bb.zip | |
concepts: move from enable_if to concepts
Diffstat (limited to 'source')
| -rw-r--r-- | source/lib/include/newtype/concepts.hpp | 516 | ||||
| -rw-r--r-- | source/lib/include/newtype/derivation_clause.hpp | 6 | ||||
| -rw-r--r-- | source/lib/include/newtype/impl/type_traits_extensions.hpp | 853 | ||||
| -rw-r--r-- | source/lib/include/newtype/newtype.hpp | 425 | ||||
| -rw-r--r-- | source/tests/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | source/tests/src/arithmetic.cpp | 33 | ||||
| -rw-r--r-- | source/tests/src/equality_comparison.cpp | 15 | ||||
| -rw-r--r-- | source/tests/src/hash.cpp | 20 | ||||
| -rw-r--r-- | source/tests/src/io_operators.cpp | 2 | ||||
| -rw-r--r-- | source/tests/src/iterable.cpp | 577 | ||||
| -rw-r--r-- | source/tests/src/relational_operators.cpp | 198 |
11 files changed, 1109 insertions, 1537 deletions
diff --git a/source/lib/include/newtype/concepts.hpp b/source/lib/include/newtype/concepts.hpp new file mode 100644 index 0000000..88313b9 --- /dev/null +++ b/source/lib/include/newtype/concepts.hpp @@ -0,0 +1,516 @@ +#ifndef NEWTYPE_CONCEPTS_HPP +#define NEWTYPE_CONCEPTS_HPP + +#include <concepts> +#include <cstddef> +#include <functional> +#include <iosfwd> + +namespace nt::concepts +{ + + inline namespace arithmetic + { + + template<typename SubjectType> + concept addable = requires(SubjectType lhs, SubjectType rhs) { + { + lhs + rhs + } -> std::same_as<SubjectType>; + }; + + template<typename SubjectType> + concept nothrow_addable = requires(SubjectType lhs, SubjectType rhs) { + requires addable<SubjectType>; + { + lhs + rhs + } noexcept; + }; + + template<typename SubjectType> + concept divisible = requires(SubjectType lhs, SubjectType rhs) { + { + lhs / rhs + } -> std::same_as<SubjectType>; + }; + + template<typename SubjectType> + concept nothrow_divisible = requires(SubjectType lhs, SubjectType rhs) { + requires divisible<SubjectType>; + { + lhs / rhs + } noexcept; + }; + + template<typename SubjectType> + concept multipliable = requires(SubjectType lhs, SubjectType rhs) { + { + lhs * rhs + } -> std::same_as<SubjectType>; + }; + + template<typename SubjectType> + concept nothrow_multipliable = requires(SubjectType lhs, SubjectType rhs) { + requires multipliable<SubjectType>; + { + lhs / rhs + } noexcept; + }; + + template<typename SubjectType> + concept subtractable = requires(SubjectType lhs, SubjectType rhs) { + { + lhs - rhs + } -> std::same_as<SubjectType>; + }; + + template<typename SubjectType> + concept nothrow_subtractable = requires(SubjectType lhs, SubjectType rhs) { + requires subtractable<SubjectType>; + { + lhs - rhs + } noexcept; + }; + + } // namespace arithmetic + + inline namespace comparability + { + + template<typename SubjectType> + concept equality_comparable = requires(SubjectType lhs, SubjectType rhs) { + { + lhs == rhs + } -> std::convertible_to<bool>; + }; + + template<typename SubjectType> + concept nothrow_equality_comparable = requires(SubjectType lhs, SubjectType rhs) { + requires equality_comparable<SubjectType>; + { + lhs == rhs + } noexcept; + }; + + template<typename SubjectType> + concept inequality_comparable = requires(SubjectType lhs, SubjectType rhs) { + { + lhs != rhs + } -> std::convertible_to<bool>; + }; + + template<typename SubjectType> + concept nothrow_inequality_comparable = requires(SubjectType lhs, SubjectType rhs) { + requires inequality_comparable<SubjectType>; + { + lhs != rhs + } noexcept; + }; + + template<typename SubjectType> + concept less_than_comparable = requires(SubjectType lhs, SubjectType rhs) { + { + lhs < rhs + } -> std::convertible_to<bool>; + }; + + template<typename SubjectType> + concept nothrow_less_than_comparable = requires(SubjectType lhs, SubjectType rhs) { + requires less_than_comparable<SubjectType>; + { + lhs < rhs + } noexcept; + }; + + template<typename SubjectType> + concept less_than_equal_comparable = requires(SubjectType lhs, SubjectType rhs) { + { + lhs <= rhs + } -> std::convertible_to<bool>; + }; + + template<typename SubjectType> + concept nothrow_less_than_equal_comparable = requires(SubjectType lhs, SubjectType rhs) { + requires less_than_equal_comparable<SubjectType>; + { + lhs <= rhs + } noexcept; + }; + + template<typename SubjectType> + concept greater_than_comparable = requires(SubjectType lhs, SubjectType rhs) { + { + lhs > rhs + } -> std::convertible_to<bool>; + }; + + template<typename SubjectType> + concept nothrow_greater_than_comparable = requires(SubjectType lhs, SubjectType rhs) { + requires greater_than_comparable<SubjectType>; + { + lhs > rhs + } noexcept; + }; + + template<typename SubjectType> + concept greater_than_equal_comparable = requires(SubjectType lhs, SubjectType rhs) { + { + lhs >= rhs + } -> std::convertible_to<bool>; + }; + + template<typename SubjectType> + concept nothrow_greater_than_equal_comparable = requires(SubjectType lhs, SubjectType rhs) { + requires greater_than_equal_comparable<SubjectType>; + { + lhs >= rhs + } noexcept; + }; + + } // namespace comparability + + inline namespace compound_arithmetic + { + template<typename SubjectType> + concept compound_addable = requires(SubjectType & lhs, SubjectType const & rhs) { + { + lhs += rhs + } -> std::convertible_to<SubjectType &>; + }; + + template<typename SubjectType> + concept nothrow_compound_addable = requires(SubjectType & lhs, SubjectType const & rhs) { + requires compound_addable<SubjectType>; + { + lhs += rhs + } noexcept; + }; + + template<typename SubjectType> + concept compound_divisible = requires(SubjectType & lhs, SubjectType const & rhs) { + { + lhs /= rhs + } -> std::convertible_to<SubjectType &>; + }; + + template<typename SubjectType> + concept nothrow_compound_divisible = requires(SubjectType & lhs, SubjectType const & rhs) { + requires compound_divisible<SubjectType>; + { + lhs /= rhs + } noexcept; + }; + + template<typename SubjectType> + concept compound_multipliable = requires(SubjectType & lhs, SubjectType const & rhs) { + { + lhs *= rhs + } -> std::convertible_to<SubjectType &>; + }; + + template<typename SubjectType> + concept nothrow_compound_multipliable = requires(SubjectType & lhs, SubjectType const & rhs) { + requires compound_multipliable<SubjectType>; + { + lhs *= rhs + } noexcept; + }; + + template<typename SubjectType> + concept compound_subtractable = requires(SubjectType & lhs, SubjectType const & rhs) { + { + lhs -= rhs + } -> std::convertible_to<SubjectType &>; + }; + + template<typename SubjectType> + concept nothrow_compound_subtractable = requires(SubjectType & lhs, SubjectType const & rhs) { + requires compound_subtractable<SubjectType>; + { + lhs -= rhs + } noexcept; + }; + } // namespace compound_arithmetic + + inline namespace iostreamable + { + + template<typename SubjectType, typename CharType, typename StreamTraits> + concept input_streamable = requires(SubjectType subject) { + { + std::declval<std::basic_istream<CharType, StreamTraits> &>() >> subject + } -> std::same_as<std::basic_istream<CharType, StreamTraits> &>; + }; + + template<typename SubjectType, typename CharType, typename StreamTraits> + concept nothrow_input_streamable = requires(SubjectType subject) { + requires input_streamable<SubjectType, CharType, StreamTraits>; + { + std::declval<std::basic_istream<CharType, StreamTraits> &>() >> subject + } noexcept; + }; + + template<typename SubjectType, typename CharType, typename StreamTraits> + concept output_streamable = requires(SubjectType subject) { + { + std::declval<std::basic_ostream<CharType, StreamTraits> &>() << subject + } -> std::same_as<std::basic_ostream<CharType, StreamTraits> &>; + }; + + template<typename SubjectType, typename CharType, typename StreamTraits> + concept nothrow_output_streamable = requires(SubjectType subject) { + requires output_streamable<SubjectType, CharType, StreamTraits>; + { + std::declval<std::basic_ostream<CharType, StreamTraits> &>() << subject + } noexcept; + }; + + } // namespace iostreamable + + inline namespace iterable + { + + template<typename SubjectType> + concept free_begin = requires(SubjectType & subject) { + typename SubjectType::iterator; + { + begin(subject) + } -> std::same_as<typename SubjectType::iterator>; + }; + + template<typename SubjectType> + concept const_free_begin = requires(SubjectType const & subject) { + typename SubjectType::const_iterator; + { + begin(subject) + } -> std::same_as<typename SubjectType::const_iterator>; + }; + + template<typename SubjectType> + concept member_begin = requires(SubjectType & subject) { + typename SubjectType::iterator; + { + subject.begin() + } -> std::same_as<typename SubjectType::iterator>; + }; + + template<typename SubjectType> + concept const_member_begin = requires(SubjectType const & subject) { + typename SubjectType::const_iterator; + { + subject.begin() + } -> std::same_as<typename SubjectType::const_iterator>; + }; + + template<typename SubjectType> + concept beginnable = free_begin<SubjectType> || member_begin<SubjectType>; + + template<typename SubjectType> + concept const_beginnable = const_free_begin<SubjectType> || const_member_begin<SubjectType>; + + template<typename SubjectType> + concept free_cbegin = requires(SubjectType const & subject) { + typename SubjectType::const_iterator; + { + cbegin(subject) + } -> std::same_as<typename SubjectType::const_iterator>; + }; + + template<typename SubjectType> + concept member_cbegin = requires(SubjectType const & subject) { + typename SubjectType::const_iterator; + { + subject.cbegin() + } -> std::same_as<typename SubjectType::const_iterator>; + }; + + template<typename SubjectType> + concept cbeginnable = free_cbegin<SubjectType> || member_cbegin<SubjectType>; + + template<typename SubjectType> + concept free_rbegin = requires(SubjectType & subject) { + typename SubjectType::reverse_iterator; + { + rbegin(subject) + } -> std::same_as<typename SubjectType::reverse_iterator>; + }; + + template<typename SubjectType> + concept const_free_rbegin = requires(SubjectType const & subject) { + typename SubjectType::const_reverse_iterator; + { + rbegin(subject) + } -> std::same_as<typename SubjectType::const_reverse_iterator>; + }; + + template<typename SubjectType> + concept member_rbegin = requires(SubjectType & subject) { + typename SubjectType::reverse_iterator; + { + subject.rbegin() + } -> std::same_as<typename SubjectType::reverse_iterator>; + }; + + template<typename SubjectType> + concept const_member_rbegin = requires(SubjectType const & subject) { + typename SubjectType::const_reverse_iterator; + { + subject.rbegin() + } -> std::same_as<typename SubjectType::const_reverse_iterator>; + }; + + template<typename SubjectType> + concept rbeginnable = free_rbegin<SubjectType> || member_rbegin<SubjectType>; + + template<typename SubjectType> + concept const_rbeginnable = const_free_rbegin<SubjectType> || const_member_rbegin<SubjectType>; + + template<typename SubjectType> + concept free_crbegin = requires(SubjectType const & subject) { + typename SubjectType::const_reverse_iterator; + { + crbegin(subject) + } -> std::same_as<typename SubjectType::const_reverse_iterator>; + }; + + template<typename SubjectType> + concept member_crbegin = requires(SubjectType const & subject) { + typename SubjectType::const_reverse_iterator; + { + subject.crbegin() + } -> std::same_as<typename SubjectType::const_reverse_iterator>; + }; + + template<typename SubjectType> + concept crbeginnable = free_crbegin<SubjectType> || member_crbegin<SubjectType>; + + template<typename SubjectType> + concept free_end = requires(SubjectType & subject) { + typename SubjectType::iterator; + { + end(subject) + } -> std::same_as<typename SubjectType::iterator>; + }; + + template<typename SubjectType> + concept const_free_end = requires(SubjectType const & subject) { + typename SubjectType::const_iterator; + { + end(subject) + } -> std::same_as<typename SubjectType::const_iterator>; + }; + + template<typename SubjectType> + concept member_end = requires(SubjectType & subject) { + typename SubjectType::iterator; + { + subject.end() + } -> std::same_as<typename SubjectType::iterator>; + }; + + template<typename SubjectType> + concept const_member_end = requires(SubjectType const & subject) { + typename SubjectType::const_iterator; + { + subject.end() + } -> std::same_as<typename SubjectType::const_iterator>; + }; + + template<typename SubjectType> + concept endable = free_end<SubjectType> || member_end<SubjectType>; + + template<typename SubjectType> + concept const_endable = const_free_end<SubjectType> || const_member_end<SubjectType>; + + template<typename SubjectType> + concept free_cend = requires(SubjectType const & subject) { + typename SubjectType::const_iterator; + { + cend(subject) + } -> std::same_as<typename SubjectType::const_iterator>; + }; + + template<typename SubjectType> + concept member_cend = requires(SubjectType const & subject) { + typename SubjectType::const_iterator; + { + subject.cend() + } -> std::same_as<typename SubjectType::const_iterator>; + }; + + template<typename SubjectType> + concept cendable = free_cend<SubjectType> || member_cend<SubjectType>; + + template<typename SubjectType> + concept free_rend = requires(SubjectType & subject) { + typename SubjectType::reverse_iterator; + { + rend(subject) + } -> std::same_as<typename SubjectType::reverse_iterator>; + }; + + template<typename SubjectType> + concept const_free_rend = requires(SubjectType const & subject) { + typename SubjectType::const_reverse_iterator; + { + rend(subject) + } -> std::same_as<typename SubjectType::const_reverse_iterator>; + }; + + template<typename SubjectType> + concept member_rend = requires(SubjectType & subject) { + typename SubjectType::reverse_iterator; + { + subject.rend() + } -> std::same_as<typename SubjectType::reverse_iterator>; + }; + + template<typename SubjectType> + concept const_member_rend = requires(SubjectType const & subject) { + typename SubjectType::const_reverse_iterator; + { + subject.rend() + } -> std::same_as<typename SubjectType::const_reverse_iterator>; + }; + + template<typename SubjectType> + concept rendable = free_rend<SubjectType> || member_rend<SubjectType>; + + template<typename SubjectType> + concept const_rendable = const_free_rend<SubjectType> || const_member_rend<SubjectType>; + + template<typename SubjectType> + concept free_crend = requires(SubjectType const & subject) { + typename SubjectType::const_reverse_iterator; + { + crend(subject) + } -> std::same_as<typename SubjectType::const_reverse_iterator>; + }; + + template<typename SubjectType> + concept member_crend = requires(SubjectType const & subject) { + typename SubjectType::const_reverse_iterator; + { + subject.crend() + } -> std::same_as<typename SubjectType::const_reverse_iterator>; + }; + + template<typename SubjectType> + concept crendable = free_crend<SubjectType> || member_crend<SubjectType>; + } // namespace iterable + + inline namespace standard_extensions + { + + template<typename SubjectType> + concept hashable = requires(SubjectType subject) { + { + std::hash<SubjectType>{}(subject) + } -> std::convertible_to<std::size_t>; + }; + + } + +} // namespace nt::concepts + +#endif
\ No newline at end of file diff --git a/source/lib/include/newtype/derivation_clause.hpp b/source/lib/include/newtype/derivation_clause.hpp index 6de70e1..eb3e8f1 100644 --- a/source/lib/include/newtype/derivation_clause.hpp +++ b/source/lib/include/newtype/derivation_clause.hpp @@ -12,6 +12,9 @@ namespace nt template<typename... DerivableTags> struct derivation_clause { + template<auto... Needles> + using contains = std::disjunction<std::is_same<DerivableTags, typename decltype(Needles)::tag_type>...>; + constexpr derivation_clause(derivable<DerivableTags>...) noexcept { } @@ -65,6 +68,9 @@ namespace nt } }; + template<typename DerivationClause, auto... Features> + concept contains = requires(DerivationClause clause) { requires DerivationClause::template contains<Features...>::value; }; + } // namespace nt #endif
\ No newline at end of file diff --git a/source/lib/include/newtype/impl/type_traits_extensions.hpp b/source/lib/include/newtype/impl/type_traits_extensions.hpp deleted file mode 100644 index dc41649..0000000 --- a/source/lib/include/newtype/impl/type_traits_extensions.hpp +++ /dev/null @@ -1,853 +0,0 @@ -#ifndef NEWTYPE_IMPL_TYPE_TRAITS_EXTENSIONS_HPP -#define NEWTYPE_IMPL_TYPE_TRAITS_EXTENSIONS_HPP - -#include "newtype/version.hpp" - -#include <cstddef> -#include <functional> -#include <iosfwd> -#include <type_traits> - -namespace nt::impl -{ - - inline namespace equality_comparable - { - - template<typename T, typename = void> - struct is_equality_comparable : std::false_type - { - }; - - template<typename T> - struct is_equality_comparable<T, std::void_t<decltype(std::declval<T const &>() == std::declval<T const &>())>> : std::true_type - { - }; - - template<typename T> - auto constexpr is_equality_comparable_v = is_equality_comparable<T>::value; - - template<typename T, typename = void> - struct is_nothrow_equality_comparable : std::false_type - { - }; - - 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 &>())> - { - }; - - template<typename T> - auto constexpr is_nothrow_equality_comparable_v = is_nothrow_equality_comparable<T>::value; - - template<typename T, typename = void> - struct is_inequality_comparable : std::false_type - { - }; - - template<typename T> - struct is_inequality_comparable<T, std::void_t<decltype(std::declval<T const &>() != std::declval<T const &>())>> : std::true_type - { - }; - - template<typename T> - auto constexpr is_inequality_comparable_v = is_inequality_comparable<T>::value; - - template<typename T, typename = void> - struct is_nothrow_inequality_comparable : std::false_type - { - }; - - 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 &>())> - { - }; - - template<typename T> - auto constexpr is_nothrow_inequality_comparable_v = is_nothrow_inequality_comparable<T>::value; - - } // namespace equality_comparable - - inline namespace relationally_comparable - { - - template<typename T, typename = void> - struct is_less_than_comparable : std::false_type - { - }; - - template<typename T> - struct is_less_than_comparable<T, std::void_t<decltype(std::declval<T const &>() < std::declval<T const &>())>> : std::true_type - { - }; - - template<typename T> - auto constexpr is_less_than_comparable_v = is_less_than_comparable<T>::value; - - template<typename T, typename = void> - struct is_nothrow_less_than_comparable : std::false_type - { - }; - - 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 &>())> - { - }; - - template<typename T> - auto constexpr is_nothrow_less_than_comparable_v = is_nothrow_less_than_comparable<T>::value; - - template<typename T, typename = void> - struct is_greater_than_comparable : std::false_type - { - }; - - template<typename T> - struct is_greater_than_comparable<T, std::void_t<decltype(std::declval<T const &>() > std::declval<T const &>())>> : std::true_type - { - }; - - template<typename T> - auto constexpr is_greater_than_comparable_v = is_greater_than_comparable<T>::value; - - template<typename T, typename = void> - struct is_nothrow_greater_than_comparable : std::false_type - { - }; - - 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 &>())> - { - }; - - template<typename T> - auto constexpr is_nothrow_greater_than_comparable_v = is_nothrow_greater_than_comparable<T>::value; - - template<typename T, typename = void> - struct is_less_than_equal_to_comparable : std::false_type - { - }; - - 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 - { - }; - - template<typename T> - auto constexpr is_less_than_equal_to_comparable_v = is_less_than_equal_to_comparable<T>::value; - - template<typename T, typename = void> - struct is_nothrow_less_than_equal_to_comparable : std::false_type - { - }; - - 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 &>())> - { - }; - - template<typename T> - auto constexpr is_nothrow_less_than_equal_to_comparable_v = is_nothrow_less_than_equal_to_comparable<T>::value; - - template<typename T, typename = void> - struct is_greater_than_equal_to_comparable : std::false_type - { - }; - - 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 - { - }; - - template<typename T> - auto constexpr is_greater_than_equal_to_comparable_v = is_greater_than_equal_to_comparable<T>::value; - - template<typename T, typename = void> - struct is_nothrow_greater_than_equal_to_comparable : std::false_type - { - }; - - 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 &>())> - { - }; - - 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 - { - - template<typename StreamType, typename T, typename = void> - struct is_output_streamable : std::false_type - { - }; - - 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 - { - }; - - template<typename StreamType, typename T> - auto constexpr is_output_streamable_v = is_output_streamable<StreamType, T>::value; - - template<typename StreamType, typename T, typename = void> - struct is_nothrow_output_streamable : std::false_type - { - }; - - 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 &>())> - { - }; - - template<typename StreamType, typename T> - auto constexpr is_nothrow_output_streamable_v = is_nothrow_output_streamable<StreamType, T>::value; - - template<typename StreamType, typename T, typename = void> - struct is_input_streamable : std::false_type - { - }; - - template<typename StreamType, typename T> - struct is_input_streamable<StreamType, T, std::void_t<decltype(std::declval<StreamType &>() >> std::declval<T &>())>> : std::true_type - { - }; - - template<typename StreamType, typename T> - auto constexpr is_input_streamable_v = is_input_streamable<StreamType, T>::value; - - template<typename StreamType, typename T, typename = void> - struct is_nothrow_input_streamable : std::false_type - { - }; - - 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 &>())> - { - }; - - template<typename StreamType, typename T> - auto constexpr is_nothrow_input_streamable_v = is_nothrow_input_streamable<StreamType, T>::value; - - } // namespace iostreamable - - inline namespace arithmetic - { - - template<typename T, typename = void> - struct is_addable : std::false_type - { - }; - - template<typename T> - struct is_addable<T, std::void_t<decltype(std::declval<T const &>() + std::declval<T const &>())>> : std::true_type - { - }; - - template<typename T> - auto constexpr is_addable_v = is_addable<T>::value; - - template<typename T, typename = void> - struct is_nothrow_addable : std::false_type - { - }; - - template<typename T> - struct is_nothrow_addable<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 &>())> - { - }; - - template<typename T> - auto constexpr is_nothrow_addable_v = is_nothrow_addable<T>::value; - - template<typename T, typename = void> - struct is_subtractable : std::false_type - { - }; - - template<typename T> - struct is_subtractable<T, std::void_t<decltype(std::declval<T const &>() - std::declval<T const &>())>> : std::true_type - { - }; - - template<typename T> - auto constexpr is_subtractable_v = is_subtractable<T>::value; - - template<typename T, typename = void> - struct is_nothrow_subtractable : std::false_type - { - }; - - template<typename T> - struct is_nothrow_subtractable<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 &>())> - { - }; - - template<typename T> - auto constexpr is_nothrow_subtractable_v = is_nothrow_subtractable<T>::value; - - template<typename T, typename = void> - struct is_multipliable : std::false_type - { - }; - - template<typename T> - struct is_multipliable<T, std::void_t<decltype(std::declval<T const &>() * std::declval<T const &>())>> : std::true_type - { - }; - - template<typename T> - auto constexpr is_multipliable_v = is_multipliable<T>::value; - - template<typename T, typename = void> - struct is_nothrow_multipliable : std::false_type - { - }; - - template<typename T> - struct is_nothrow_multipliable<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 &>())> - { - }; - - template<typename T> - auto constexpr is_nothrow_multipliable_v = is_nothrow_multipliable<T>::value; - - template<typename T, typename = void> - struct is_dividable : std::false_type - { - }; - - template<typename T> - struct is_dividable<T, std::void_t<decltype(std::declval<T const &>() / std::declval<T const &>())>> : std::true_type - { - }; - - template<typename T> - auto constexpr is_dividable_v = is_dividable<T>::value; - - template<typename T, typename = void> - struct is_nothrow_dividable : std::false_type - { - }; - - template<typename T> - struct is_nothrow_dividable<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 &>())> - { - }; - - template<typename T> - auto constexpr is_nothrow_dividable_v = is_nothrow_dividable<T>::value; - - } // namespace arithmetic - - inline namespace compound_arithmetic - { - - template<typename T, typename = void> - struct is_add_assignable : std::false_type - { - }; - - template<typename T> - struct is_add_assignable<T, std::void_t<decltype(std::declval<T &>() += std::declval<T const &>())>> : std::true_type - { - }; - - template<typename T> - auto constexpr is_add_assignable_v = is_add_assignable<T>::value; - - template<typename T, typename = void> - struct is_nothrow_add_assignable : std::false_type - { - }; - - template<typename T> - struct is_nothrow_add_assignable<T, std::void_t<decltype(std::declval<T &>() += std::declval<T const &>())>> - : std::bool_constant<noexcept(std::declval<T &>() += std::declval<T const &>())> - { - }; - - template<typename T> - auto constexpr is_nothrow_add_assignable_v = is_nothrow_add_assignable<T>::value; - - template<typename T, typename = void> - struct is_subtract_assignable : std::false_type - { - }; - - template<typename T> - struct is_subtract_assignable<T, std::void_t<decltype(std::declval<T &>() -= std::declval<T const &>())>> : std::true_type - { - }; - - template<typename T> - auto constexpr is_subtract_assignable_v = is_subtract_assignable<T>::value; - - template<typename T, typename = void> - struct is_nothrow_subtract_assignable : std::false_type - { - }; - - template<typename T> - struct is_nothrow_subtract_assignable<T, std::void_t<decltype(std::declval<T &>() -= std::declval<T const &>())>> - : std::bool_constant<noexcept(std::declval<T &>() -= std::declval<T const &>())> - { - }; - - template<typename T> - auto constexpr is_nothrow_subtract_assignable_v = is_nothrow_subtract_assignable<T>::value; - - template<typename T, typename = void> - struct is_multiply_assignable : std::false_type - { - }; - - template<typename T> - struct is_multiply_assignable<T, std::void_t<decltype(std::declval<T &>() *= std::declval<T const &>())>> : std::true_type - { - }; - - template<typename T> - auto constexpr is_multiply_assignable_v = is_multiply_assignable<T>::value; - - template<typename T, typename = void> - struct is_nothrow_multiply_assignable : std::false_type - { - }; - - template<typename T> - struct is_nothrow_multiply_assignable<T, std::void_t<decltype(std::declval<T &>() *= std::declval<T const &>())>> - : std::bool_constant<noexcept(std::declval<T &>() *= std::declval<T const &>())> - { - }; - - template<typename T> - auto constexpr is_nothrow_multiply_assignable_v = is_nothrow_multiply_assignable<T>::value; - - template<typename T, typename = void> - struct is_divide_assignable : std::false_type - { - }; - - template<typename T> - struct is_divide_assignable<T, std::void_t<decltype(std::declval<T &>() /= std::declval<T const &>())>> : std::true_type - { - }; - - template<typename T> - auto constexpr is_divide_assignable_v = is_divide_assignable<T>::value; - - template<typename T, typename = void> - struct is_nothrow_divide_assignable : std::false_type - { - }; - - template<typename T> - struct is_nothrow_divide_assignable<T, std::void_t<decltype(std::declval<T &>() /= std::declval<T const &>())>> - : std::bool_constant<noexcept(std::declval<T &>() /= std::declval<T const &>())> - { - }; - - template<typename T> - auto constexpr is_nothrow_divide_assignable_v = is_nothrow_divide_assignable<T>::value; - - } // namespace compound_arithmetic - - inline namespace std_support - { - - template<typename T, typename = void> - struct is_hashable : std::false_type - { - }; - - template<typename T> - struct is_hashable<T, std::void_t<decltype(std::declval<std::hash<T> const &>()(std::declval<T const &>()))>> - : std::is_same<std::size_t, decltype(std::declval<std::hash<T> const &>()(std::declval<T const &>()))> - { - }; - - template<typename T> - auto constexpr is_hashable_v = is_hashable<T>::value; - - } // namespace std_support - - inline namespace iterable_begin - { - template<typename T, typename = void> - struct has_free_begin : std::false_type - { - }; - - template<typename T> - struct has_free_begin<T, std::void_t<decltype(begin(std::declval<T &>()))>> - : std::is_same<typename T::iterator, std::remove_cvref_t<decltype(begin(std::declval<T &>()))>> - { - }; - - template<typename T> - struct has_free_begin<T const, std::void_t<decltype(begin(std::declval<T const &>()))>> - : std::is_same<typename T::const_iterator, std::remove_cvref_t<decltype(begin(std::declval<T const &>()))>> - { - }; - - template<typename T> - auto constexpr has_free_begin_v = has_free_begin<T>::value; - - template<typename T, typename = void> - struct has_member_begin : std::false_type - { - }; - - template<typename T> - struct has_member_begin<T, std::void_t<decltype(std::declval<T &>().begin())>> - : std::is_same<typename T::iterator, std::remove_cvref_t<decltype(std::declval<T &>().begin())>> - { - }; - - template<typename T> - struct has_member_begin<T const, std::void_t<decltype(std::declval<T const &>().begin())>> - : std::is_same<typename T::const_iterator, std::remove_cvref_t<decltype(std::declval<T const &>().begin())>> - { - }; - - template<typename T> - auto constexpr has_member_begin_v = has_member_begin<T>::value; - - template<typename T> - struct has_begin : std::disjunction<has_free_begin<T>, has_member_begin<T>> - { - }; - - template<typename T> - auto constexpr has_begin_v = has_begin<T>::value; - } // namespace iterable_begin - - inline namespace iterable_cbegin - { - template<typename T, typename = void> - struct has_free_cbegin : std::false_type - { - }; - - template<typename T> - struct has_free_cbegin<T, std::void_t<decltype(cbegin(std::declval<T const &>()))>> - : std::is_same<typename T::const_iterator, std::remove_cvref_t<decltype(cbegin(std::declval<T const &>()))>> - { - }; - - template<typename T> - auto constexpr has_free_cbegin_v = has_free_cbegin<T>::value; - - template<typename T, typename = void> - struct has_member_cbegin : std::false_type - { - }; - - template<typename T> - struct has_member_cbegin<T, std::void_t<decltype(std::declval<T const &>().cbegin())>> - : std::is_same<typename T::const_iterator, decltype(std::declval<T const &>().cbegin())> - { - }; - - template<typename T> - auto constexpr has_member_cbegin_v = has_member_cbegin<T>::value; - - template<typename T> - struct has_cbegin : std::disjunction<has_free_cbegin<T>, has_member_cbegin<T>> - { - }; - - template<typename T> - auto constexpr has_cbegin_v = has_cbegin<T>::value; - } // namespace iterable_cbegin - - inline namespace iterable_rbegin - { - template<typename T, typename = void> - struct has_free_rbegin : std::false_type - { - }; - - template<typename T> - struct has_free_rbegin<T, std::void_t<decltype(rbegin(std::declval<T &>()))>> - : std::is_same<typename T::reverse_iterator, std::remove_cvref_t<decltype(rbegin(std::declval<T &>()))>> - { - }; - - template<typename T> - struct has_free_rbegin<T const, std::void_t<decltype(rbegin(std::declval<T const &>()))>> - : std::is_same<typename T::const_reverse_iterator, std::remove_cvref_t<decltype(rbegin(std::declval<T const &>()))>> - { - }; - - template<typename T> - auto constexpr has_free_rbegin_v = has_free_rbegin<T>::value; - - template<typename T, typename = void> - struct has_member_rbegin : std::false_type - { - }; - - template<typename T> - struct has_member_rbegin<T, std::void_t<decltype(std::declval<T &>().rbegin())>> - : std::is_same<typename T::reverse_iterator, std::remove_cvref_t<decltype(std::declval<T &>().rbegin())>> - { - }; - - template<typename T> - struct has_member_rbegin<T const, std::void_t<decltype(std::declval<T const &>().rbegin())>> - : std::is_same<typename T::const_reverse_iterator, std::remove_cvref_t<decltype(std::declval<T const &>().rbegin())>> - { - }; - - template<typename T> - auto constexpr has_member_rbegin_v = has_member_rbegin<T>::value; - - template<typename T> - struct has_rbegin : std::disjunction<has_free_rbegin<T>, has_member_rbegin<T>> - { - }; - - template<typename T> - auto constexpr has_rbegin_v = has_rbegin<T>::value; - } // namespace iterable_rbegin - - inline namespace iterable_crbegin - { - template<typename T, typename = void> - struct has_free_crbegin : std::false_type - { - }; - - template<typename T> - struct has_free_crbegin<T, std::void_t<decltype(crbegin(std::declval<T const &>()))>> - : std::is_same<typename T::const_reverse_iterator, std::remove_cvref_t<decltype(crbegin(std::declval<T const &>()))>> - { - }; - - template<typename T> - auto constexpr has_free_crbegin_v = has_free_crbegin<T>::value; - - template<typename T, typename = void> - struct has_member_crbegin : std::false_type - { - }; - - template<typename T> - struct has_member_crbegin<T, std::void_t<decltype(std::declval<T const &>().crbegin())>> - : std::is_same<typename T::const_reverse_iterator, std::remove_cvref_t<decltype(std::declval<T const &>().crbegin())>> - { - }; - - template<typename T> - auto constexpr has_member_crbegin_v = has_member_crbegin<T>::value; - - template<typename T> - struct has_crbegin : std::disjunction<has_free_crbegin<T>, has_member_crbegin<T>> - { - }; - - template<typename T> - auto constexpr has_crbegin_v = has_crbegin<T>::value; - } // 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(rend(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 - -#endif
\ No newline at end of file diff --git a/source/lib/include/newtype/newtype.hpp b/source/lib/include/newtype/newtype.hpp index 2e71553..824a3da 100644 --- a/source/lib/include/newtype/newtype.hpp +++ b/source/lib/include/newtype/newtype.hpp @@ -1,11 +1,11 @@ #ifndef NEWTYPE_NEWTYPE_HPP #define NEWTYPE_NEWTYPE_HPP +#include "newtype/concepts.hpp" #include "newtype/derivable.hpp" #include "newtype/deriving.hpp" #include "newtype/impl/new_type_iterator_types.hpp" #include "newtype/impl/new_type_storage.hpp" -#include "newtype/impl/type_traits_extensions.hpp" #include "newtype/version.hpp" #include <functional> @@ -24,99 +24,85 @@ namespace nt static_assert(!std::is_reference_v<BaseType>, "The base type must not be a reference type"); 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> + template<typename CharType, + typename StreamTraits, + nt::concepts::input_streamable<CharType, StreamTraits> BaseTypeT, + typename TagTypeT, + nt::contains<nt::Read> auto DerivationClauseV> 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>> &; + nt::concepts::nothrow_input_streamable<BaseTypeT, CharType, StreamTraits>) -> std::basic_istream<CharType, StreamTraits> &; - template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV> + template<nt::concepts::compound_addable BaseTypeT, typename TagTypeT, nt::contains<nt::Arithmetic> auto DerivationClauseV> auto constexpr friend operator+=(new_type<BaseTypeT, TagTypeT, DerivationClauseV> & lhs, - new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & rhs) noexcept(impl::is_nothrow_add_assignable_v<BaseTypeT>) - -> std::enable_if_t<DerivationClauseV(nt::Arithmetic) && impl::is_add_assignable_v<BaseTypeT>, - new_type<BaseTypeT, TagTypeT, DerivationClauseV> &>; + new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & rhs) noexcept(nt::concepts::nothrow_compound_addable<BaseTypeT>) + -> new_type<BaseTypeT, TagTypeT, DerivationClauseV> &; - template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV> + template<nt::concepts::compound_subtractable BaseTypeT, typename TagTypeT, nt::contains<nt::Arithmetic> auto DerivationClauseV> auto constexpr friend operator-=(new_type<BaseTypeT, TagTypeT, DerivationClauseV> & lhs, - new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & rhs) noexcept(impl::is_nothrow_subtract_assignable_v<BaseTypeT>) - -> std::enable_if_t<DerivationClauseV(nt::Arithmetic) && impl::is_subtract_assignable_v<BaseTypeT>, - new_type<BaseTypeT, TagTypeT, DerivationClauseV> &>; + new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & rhs) noexcept(nt::concepts::nothrow_compound_subtractable<BaseTypeT>) + -> new_type<BaseTypeT, TagTypeT, DerivationClauseV> &; - template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV> + template<nt::concepts::compound_multipliable BaseTypeT, typename TagTypeT, nt::contains<nt::Arithmetic> auto DerivationClauseV> auto constexpr friend operator*=(new_type<BaseTypeT, TagTypeT, DerivationClauseV> & lhs, - new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & rhs) noexcept(impl::is_nothrow_multiply_assignable_v<BaseTypeT>) - -> std::enable_if_t<DerivationClauseV(nt::Arithmetic) && impl::is_multiply_assignable_v<BaseTypeT>, - new_type<BaseTypeT, TagTypeT, DerivationClauseV> &>; + new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & rhs) noexcept(nt::concepts::nothrow_compound_multipliable<BaseTypeT>) + -> new_type<BaseTypeT, TagTypeT, DerivationClauseV> &; - template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV> + template<nt::concepts::compound_divisible BaseTypeT, typename TagTypeT, nt::contains<nt::Arithmetic> auto DerivationClauseV> auto constexpr friend operator/=(new_type<BaseTypeT, TagTypeT, DerivationClauseV> & lhs, - new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & rhs) noexcept(impl::is_nothrow_divide_assignable_v<BaseTypeT>) - -> std::enable_if_t<DerivationClauseV(nt::Arithmetic) && impl::is_divide_assignable_v<BaseTypeT>, - new_type<BaseTypeT, TagTypeT, DerivationClauseV> &>; - - template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV> - auto constexpr friend begin(new_type<BaseTypeT, TagTypeT, DerivationClauseV> & obj) - -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_begin_v<BaseTypeT>, - typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::iterator>; - - template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV> - auto constexpr friend begin(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj) - -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_begin_v<BaseTypeT const>, - typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_iterator>; - - template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV> - auto constexpr friend cbegin(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj) - -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_cbegin_v<BaseTypeT const>, - typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_iterator>; - - template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV> - auto constexpr friend rbegin(new_type<BaseTypeT, TagTypeT, DerivationClauseV> & obj) - -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_rbegin_v<BaseTypeT>, - typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::reverse_iterator>; - - template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV> - auto constexpr friend rbegin(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj) - -> std::enable_if_t<DerivationClauseV(nt::Iterable) && impl::has_free_rbegin_v<BaseTypeT const>, - typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_reverse_iterator>; - - template<typename BaseTypeT, typename TagTypeT, auto DerivationClauseV> - auto constexpr friend crbegin(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj) - -> 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>; + new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & rhs) noexcept(nt::concepts::nothrow_compound_divisible<BaseTypeT>) + -> new_type<BaseTypeT, TagTypeT, DerivationClauseV> &; + + template<nt::concepts::free_begin BaseTypeT, typename TagTypeT, nt::contains<nt::Iterable> auto DerivationClauseV> + auto constexpr friend begin(new_type<BaseTypeT, TagTypeT, DerivationClauseV> & obj) -> + typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::iterator; + + template<nt::concepts::const_free_begin BaseTypeT, typename TagTypeT, nt::contains<nt::Iterable> auto DerivationClauseV> + auto constexpr friend begin(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj) -> + typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_iterator; + + template<nt::concepts::free_cbegin BaseTypeT, typename TagTypeT, nt::contains<nt::Iterable> auto DerivationClauseV> + auto constexpr friend cbegin(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj) -> + typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_iterator; + + template<nt::concepts::free_rbegin BaseTypeT, typename TagTypeT, nt::contains<nt::Iterable> auto DerivationClauseV> + auto constexpr friend rbegin(new_type<BaseTypeT, TagTypeT, DerivationClauseV> & obj) -> + typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::reverse_iterator; + + template<nt::concepts::const_free_rbegin BaseTypeT, typename TagTypeT, nt::contains<nt::Iterable> auto DerivationClauseV> + auto constexpr friend rbegin(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj) -> + typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_reverse_iterator; + + template<nt::concepts::free_crbegin BaseTypeT, typename TagTypeT, nt::contains<nt::Iterable> auto DerivationClauseV> + auto constexpr friend crbegin(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj) -> + typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_reverse_iterator; + + template<nt::concepts::free_end BaseTypeT, typename TagTypeT, nt::contains<nt::Iterable> auto DerivationClauseV> + auto constexpr friend end(new_type<BaseTypeT, TagTypeT, DerivationClauseV> & obj) -> + typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::iterator; + + template<nt::concepts::const_free_end BaseTypeT, typename TagTypeT, nt::contains<nt::Iterable> auto DerivationClauseV> + auto constexpr friend end(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj) -> + typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_iterator; + + template<nt::concepts::free_cend BaseTypeT, typename TagTypeT, nt::contains<nt::Iterable> auto DerivationClauseV> + auto constexpr friend cend(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj) -> + typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_iterator; + + template<nt::concepts::free_rend BaseTypeT, typename TagTypeT, nt::contains<nt::Iterable> auto DerivationClauseV> + auto constexpr friend rend(new_type<BaseTypeT, TagTypeT, DerivationClauseV> & obj) -> + typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::reverse_iterator; + + template<nt::concepts::const_free_rend BaseTypeT, typename TagTypeT, nt::contains<nt::Iterable> auto DerivationClauseV> + auto constexpr friend rend(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj) -> + typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_reverse_iterator; + + template<nt::concepts::free_crend BaseTypeT, typename TagTypeT, nt::contains<nt::Iterable> auto DerivationClauseV> + auto constexpr friend crend(new_type<BaseTypeT, TagTypeT, DerivationClauseV> const & obj) -> + typename new_type<BaseTypeT, TagTypeT, DerivationClauseV>::const_reverse_iterator; using super = impl::new_type_move_assignment<BaseType, TagType>; @@ -165,367 +151,333 @@ namespace nt return std::addressof(this->m_value); } - template<typename NewType = new_type, std::enable_if_t<NewType::derivation_clause(nt::Iterable)> * = nullptr> - auto constexpr begin() - -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_begin_v<BaseType>, typename NewType::iterator> + template<nt::concepts::member_begin BaseTypeT = BaseType, nt::contains<nt::Iterable> auto DerivationClauseV = DerivationClause> + auto constexpr begin() -> typename new_type<BaseTypeT, TagType, DerivationClauseV>::iterator { return this->m_value.begin(); } - template<typename NewType = new_type> - auto constexpr begin() const -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_begin_v<BaseType const>, - typename NewType::const_iterator> + template<nt::concepts::const_member_begin BaseTypeT = BaseType, nt::contains<nt::Iterable> auto DerivationClauseV = DerivationClause> + auto constexpr begin() const -> typename new_type<BaseTypeT, TagType, DerivationClauseV>::const_iterator { return this->m_value.begin(); } - template<typename NewType = new_type> - auto constexpr cbegin() const -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_cbegin_v<BaseType const>, - typename NewType::const_iterator> + template<nt::concepts::member_cbegin BaseTypeT = BaseType, nt::contains<nt::Iterable> auto DerivationClauseV = DerivationClause> + auto constexpr cbegin() const -> typename new_type<BaseTypeT, TagType, DerivationClauseV>::const_iterator { return this->m_value.cbegin(); } - template<typename NewType = new_type, std::enable_if_t<NewType::derivation_clause(nt::Iterable)> * = nullptr> - auto constexpr rbegin() - -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_rbegin_v<BaseType>, typename NewType::reverse_iterator> + template<nt::concepts::member_cbegin BaseTypeT = BaseType, nt::contains<nt::Iterable> auto DerivationClauseV = DerivationClause> + auto constexpr rbegin() -> typename new_type<BaseTypeT, TagType, DerivationClauseV>::reverse_iterator { return this->m_value.rbegin(); } - template<typename NewType = new_type> - auto constexpr rbegin() const -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_rbegin_v<BaseType const>, - typename NewType::const_reverse_iterator> + template<nt::concepts::member_cbegin BaseTypeT = BaseType, nt::contains<nt::Iterable> auto DerivationClauseV = DerivationClause> + auto constexpr rbegin() const -> typename new_type<BaseTypeT, TagType, DerivationClauseV>::const_reverse_iterator { return this->m_value.rbegin(); } - template<typename NewType = new_type> - auto constexpr crbegin() const -> std::enable_if_t<NewType::derivation_clause(nt::Iterable) && impl::has_member_crbegin_v<BaseType const>, - typename NewType::const_reverse_iterator> + template<nt::concepts::member_crbegin BaseTypeT = BaseType, nt::contains<nt::Iterable> auto DerivationClauseV = DerivationClause> + auto constexpr crbegin() const -> typename new_type<BaseTypeT, TagType, DerivationClauseV>::const_reverse_iterator { 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> + template<nt::concepts::member_end BaseTypeT = BaseType, nt::contains<nt::Iterable> auto DerivationClauseV = DerivationClause> + auto constexpr end() -> typename new_type<BaseTypeT, TagType, DerivationClauseV>::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> + template<nt::concepts::const_member_end BaseTypeT = BaseType, nt::contains<nt::Iterable> auto DerivationClauseV = DerivationClause> + auto constexpr end() const -> typename new_type<BaseTypeT, TagType, DerivationClauseV>::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> + template<nt::concepts::member_cend BaseTypeT = BaseType, nt::contains<nt::Iterable> auto DerivationClauseV = DerivationClause> + auto constexpr cend() const -> typename new_type<BaseTypeT, TagType, DerivationClauseV>::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> + template<nt::concepts::member_rend BaseTypeT = BaseType, nt::contains<nt::Iterable> auto DerivationClauseV = DerivationClause> + auto constexpr rend() -> typename new_type<BaseTypeT, TagType, DerivationClauseV>::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> + template<nt::concepts::const_member_rend BaseTypeT = BaseType, nt::contains<nt::Iterable> auto DerivationClauseV = DerivationClause> + auto constexpr rend() const -> typename new_type<BaseTypeT, TagType, DerivationClauseV>::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> + template<nt::concepts::const_member_rend BaseTypeT = BaseType, nt::contains<nt::Iterable> auto DerivationClauseV = DerivationClause> + auto constexpr crend() const -> typename new_type<BaseTypeT, TagType, DerivationClauseV>::const_reverse_iterator { return this->m_value.crend(); } }; - template<typename BaseType, typename TagType, auto DerivationClause> + template<nt::concepts::equality_comparable BaseType, typename TagType, auto DerivationClause> 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> + new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(nt::concepts::nothrow_equality_comparable<BaseType>) -> bool { return lhs.decay() == rhs.decay(); } - template<typename BaseType, typename TagType, auto DerivationClause> + template<nt::concepts::equality_comparable BaseType, typename TagType, nt::contains<nt::EqBase> auto DerivationClause> auto constexpr operator==(new_type<BaseType, TagType, DerivationClause> const & lhs, - BaseType const & rhs) noexcept(impl::is_nothrow_equality_comparable_v<BaseType>) - -> std::enable_if_t<DerivationClause(nt::EqBase) && impl::is_equality_comparable_v<BaseType>, bool> + BaseType const & rhs) noexcept(nt::concepts::nothrow_equality_comparable<BaseType>) -> bool { return lhs.decay() == rhs; } - template<typename BaseType, typename TagType, auto DerivationClause> + template<nt::concepts::equality_comparable BaseType, typename TagType, nt::contains<nt::EqBase> auto DerivationClause> auto constexpr operator==(BaseType const & lhs, - new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(impl::is_nothrow_equality_comparable_v<BaseType>) - -> std::enable_if_t<DerivationClause(nt::EqBase) && impl::is_equality_comparable_v<BaseType>, bool> + new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(nt::concepts::nothrow_equality_comparable<BaseType>) -> bool { return lhs == rhs.decay(); } - template<typename BaseType, typename TagType, auto DerivationClause> + template<nt::concepts::inequality_comparable BaseType, typename TagType, auto DerivationClause> 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> + new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(nt::concepts::nothrow_inequality_comparable<BaseType>) -> bool { return lhs.decay() != rhs.decay(); } - template<typename BaseType, typename TagType, auto DerivationClause> + template<nt::concepts::inequality_comparable BaseType, typename TagType, nt::contains<nt::EqBase> auto DerivationClause> auto constexpr operator!=(new_type<BaseType, TagType, DerivationClause> const & lhs, - BaseType const & rhs) noexcept(impl::is_nothrow_inequality_comparable_v<BaseType>) - -> std::enable_if_t<DerivationClause(nt::EqBase) && impl::is_inequality_comparable_v<BaseType>, bool> + BaseType const & rhs) noexcept(nt::concepts::nothrow_inequality_comparable<BaseType>) -> bool { return lhs.decay() != rhs; } - template<typename BaseType, typename TagType, auto DerivationClause> + template<nt::concepts::inequality_comparable BaseType, typename TagType, nt::contains<nt::EqBase> auto DerivationClause> auto constexpr operator!=(BaseType const & lhs, - new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(impl::is_nothrow_inequality_comparable_v<BaseType>) - -> std::enable_if_t<DerivationClause(nt::EqBase) && impl::is_inequality_comparable_v<BaseType>, bool> + new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(nt::concepts::nothrow_inequality_comparable<BaseType>) -> bool { return lhs != rhs.decay(); } - template<typename BaseType, typename TagType, auto DerivationClause> + template<nt::concepts::less_than_comparable BaseType, typename TagType, nt::contains<nt::Relational> auto DerivationClause> 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> + new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(nt::concepts::nothrow_less_than_comparable<BaseType>) { return lhs.decay() < rhs.decay(); } - template<typename BaseType, typename TagType, auto DerivationClause> + template<nt::concepts::greater_than_comparable BaseType, typename TagType, nt::contains<nt::Relational> auto DerivationClause> 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> + new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(nt::concepts::nothrow_greater_than_comparable<BaseType>) { return lhs.decay() > rhs.decay(); } - template<typename BaseType, typename TagType, auto DerivationClause> + template<nt::concepts::less_than_equal_comparable BaseType, typename TagType, nt::contains<nt::Relational> auto DerivationClause> 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> + new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(nt::concepts::nothrow_less_than_equal_comparable<BaseType>) { return lhs.decay() <= rhs.decay(); } - template<typename BaseType, typename TagType, auto DerivationClause> + template<nt::concepts::greater_than_equal_comparable BaseType, typename TagType, nt::contains<nt::Relational> auto DerivationClause> 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> + new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(nt::concepts::nothrow_greater_than_equal_comparable<BaseType>) { return lhs.decay() >= rhs.decay(); } - template<typename BaseType, typename TagType, auto DerivationClause, typename CharType, typename StreamTraits> + template<typename CharType, + typename StreamTraits, + nt::concepts::output_streamable<CharType, StreamTraits> BaseType, + typename TagType, + nt::contains<nt::Show> auto DerivationClause> auto operator<<(std::basic_ostream<CharType, StreamTraits> & output, new_type<BaseType, TagType, DerivationClause> const & source) noexcept( - 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>> & + nt::concepts::nothrow_output_streamable<BaseType, CharType, StreamTraits>) -> std::basic_ostream<CharType, StreamTraits> & { return output << source.decay(); } - template<typename BaseType, typename TagType, auto DerivationClause, typename CharType, typename StreamTraits> + template<typename CharType, + typename StreamTraits, + nt::concepts::input_streamable<CharType, StreamTraits> BaseType, + typename TagType, + nt::contains<nt::Read> auto DerivationClause> auto operator>>(std::basic_istream<CharType, StreamTraits> & input, new_type<BaseType, TagType, DerivationClause> & target) noexcept( - 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>> & + nt::concepts::nothrow_input_streamable<BaseType, CharType, StreamTraits>) -> std::basic_istream<CharType, StreamTraits> & { return input >> target.m_value; } - template<typename BaseType, typename TagType, auto DerivationClause> + template<nt::concepts::addable BaseType, typename TagType, nt::contains<nt::Arithmetic> auto DerivationClause> auto constexpr operator+(new_type<BaseType, TagType, DerivationClause> const & lhs, new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept( - impl::is_nothrow_addable_v<BaseType> && std::is_nothrow_copy_constructible_v<BaseType>) - -> std::enable_if_t<DerivationClause(nt::Arithmetic) && impl::is_addable_v<BaseType>, new_type<BaseType, TagType, DerivationClause>> + nt::concepts::nothrow_addable<BaseType> && std::is_nothrow_copy_constructible_v<BaseType>) + -> new_type<BaseType, TagType, DerivationClause> { return {lhs.decay() + rhs.decay()}; } - template<typename BaseType, typename TagType, auto DerivationClause> - auto constexpr operator+=(new_type<BaseType, TagType, DerivationClause> & lhs, - new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(impl::is_nothrow_add_assignable_v<BaseType>) - -> std::enable_if_t<DerivationClause(nt::Arithmetic) && impl::is_add_assignable_v<BaseType>, - new_type<BaseType, TagType, DerivationClause> &> + template<nt::concepts::compound_addable BaseType, typename TagType, nt::contains<nt::Arithmetic> auto DerivationClause> + auto constexpr + operator+=(new_type<BaseType, TagType, DerivationClause> & lhs, + new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(nt::concepts::nothrow_compound_addable<BaseType>) + -> new_type<BaseType, TagType, DerivationClause> & { lhs.m_value += rhs.m_value; return lhs; } - template<typename BaseType, typename TagType, auto DerivationClause> + template<nt::concepts::subtractable BaseType, typename TagType, nt::contains<nt::Arithmetic> auto DerivationClause> auto constexpr operator-(new_type<BaseType, TagType, DerivationClause> const & lhs, new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept( - impl::is_nothrow_subtractable_v<BaseType> && std::is_nothrow_copy_constructible_v<BaseType>) - -> std::enable_if_t<DerivationClause(nt::Arithmetic) && impl::is_subtractable_v<BaseType>, new_type<BaseType, TagType, DerivationClause>> + nt::concepts::nothrow_subtractable<BaseType> && std::is_nothrow_copy_constructible_v<BaseType>) + -> new_type<BaseType, TagType, DerivationClause> { return {lhs.decay() - rhs.decay()}; } - template<typename BaseType, typename TagType, auto DerivationClause> + template<nt::concepts::compound_subtractable BaseType, typename TagType, nt::contains<nt::Arithmetic> auto DerivationClause> auto constexpr operator-=(new_type<BaseType, TagType, DerivationClause> & lhs, - new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(impl::is_nothrow_subtract_assignable_v<BaseType>) - -> std::enable_if_t<DerivationClause(nt::Arithmetic) && impl::is_subtract_assignable_v<BaseType>, - new_type<BaseType, TagType, DerivationClause> &> + new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(nt::concepts::nothrow_compound_subtractable<BaseType>) + -> new_type<BaseType, TagType, DerivationClause> & { lhs.m_value -= rhs.m_value; return lhs; } - template<typename BaseType, typename TagType, auto DerivationClause> + template<nt::concepts::multipliable BaseType, typename TagType, nt::contains<nt::Arithmetic> auto DerivationClause> auto constexpr operator*(new_type<BaseType, TagType, DerivationClause> const & lhs, new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept( - impl::is_nothrow_multipliable_v<BaseType> && std::is_nothrow_copy_constructible_v<BaseType>) - -> std::enable_if_t<DerivationClause(nt::Arithmetic) && impl::is_multipliable_v<BaseType>, new_type<BaseType, TagType, DerivationClause>> + nt::concepts::nothrow_multipliable<BaseType> && std::is_nothrow_copy_constructible_v<BaseType>) + -> new_type<BaseType, TagType, DerivationClause> { return {lhs.decay() * rhs.decay()}; } - template<typename BaseType, typename TagType, auto DerivationClause> + template<nt::concepts::compound_multipliable BaseType, typename TagType, nt::contains<nt::Arithmetic> auto DerivationClause> auto constexpr operator*=(new_type<BaseType, TagType, DerivationClause> & lhs, - new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(impl::is_nothrow_multiply_assignable_v<BaseType>) - -> std::enable_if_t<DerivationClause(nt::Arithmetic) && impl::is_multiply_assignable_v<BaseType>, - new_type<BaseType, TagType, DerivationClause> &> + new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(nt::concepts::nothrow_compound_multipliable<BaseType>) + -> new_type<BaseType, TagType, DerivationClause> & { lhs.m_value *= rhs.m_value; return lhs; } - template<typename BaseType, typename TagType, auto DerivationClause> + template<nt::concepts::divisible BaseType, typename TagType, nt::contains<nt::Arithmetic> auto DerivationClause> auto constexpr operator/(new_type<BaseType, TagType, DerivationClause> const & lhs, new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept( - impl::is_nothrow_dividable_v<BaseType> && std::is_nothrow_copy_constructible_v<BaseType>) - -> std::enable_if_t<DerivationClause(nt::Arithmetic) && impl::is_dividable_v<BaseType>, new_type<BaseType, TagType, DerivationClause>> + nt::concepts::nothrow_divisible<BaseType> && std::is_nothrow_copy_constructible_v<BaseType>) + -> new_type<BaseType, TagType, DerivationClause> { return {lhs.decay() / rhs.decay()}; } - template<typename BaseType, typename TagType, auto DerivationClause> - auto constexpr operator/=(new_type<BaseType, TagType, DerivationClause> & lhs, - new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(impl::is_nothrow_divide_assignable_v<BaseType>) - -> std::enable_if_t<DerivationClause(nt::Arithmetic) && impl::is_divide_assignable_v<BaseType>, - new_type<BaseType, TagType, DerivationClause> &> + template<nt::concepts::compound_divisible BaseType, typename TagType, nt::contains<nt::Arithmetic> auto DerivationClause> + auto constexpr + operator/=(new_type<BaseType, TagType, DerivationClause> & lhs, + new_type<BaseType, TagType, DerivationClause> const & rhs) noexcept(nt::concepts::nothrow_compound_divisible<BaseType>) + -> new_type<BaseType, TagType, DerivationClause> & { lhs.m_value /= rhs.m_value; return lhs; } - template<typename BaseType, typename TagType, auto DerivationClause> - auto constexpr begin(new_type<BaseType, TagType, DerivationClause> & obj) - -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_begin_v<BaseType>, - typename new_type<BaseType, TagType, DerivationClause>::iterator> + template<nt::concepts::free_begin BaseType, typename TagType, nt::contains<nt::Iterable> auto DerivationClause> + auto constexpr begin(new_type<BaseType, TagType, DerivationClause> & obj) -> typename new_type<BaseType, TagType, DerivationClause>::iterator { return begin(obj.m_value); } - template<typename BaseType, typename TagType, auto DerivationClause> - auto constexpr begin(new_type<BaseType, TagType, DerivationClause> const & obj) - -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_begin_v<BaseType const>, - typename new_type<BaseType, TagType, DerivationClause>::const_iterator> + template<nt::concepts::const_free_begin BaseType, typename TagType, nt::contains<nt::Iterable> auto DerivationClause> + auto constexpr begin(new_type<BaseType, TagType, DerivationClause> const & obj) -> + typename new_type<BaseType, TagType, DerivationClause>::const_iterator { return begin(obj.m_value); } - template<typename BaseType, typename TagType, auto DerivationClause> - auto constexpr cbegin(new_type<BaseType, TagType, DerivationClause> const & obj) - -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_cbegin_v<BaseType const>, - typename new_type<BaseType, TagType, DerivationClause>::const_iterator> + template<nt::concepts::free_cbegin BaseType, typename TagType, nt::contains<nt::Iterable> auto DerivationClause> + auto constexpr cbegin(new_type<BaseType, TagType, DerivationClause> const & obj) -> + typename new_type<BaseType, TagType, DerivationClause>::const_iterator { return cbegin(obj.m_value); } - template<typename BaseType, typename TagType, auto DerivationClause> - auto constexpr rbegin(new_type<BaseType, TagType, DerivationClause> & obj) - -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_rbegin_v<BaseType>, - typename new_type<BaseType, TagType, DerivationClause>::reverse_iterator> + template<nt::concepts::free_rbegin BaseType, typename TagType, nt::contains<nt::Iterable> auto DerivationClause> + auto constexpr rbegin(new_type<BaseType, TagType, DerivationClause> & obj) -> + typename new_type<BaseType, TagType, DerivationClause>::reverse_iterator { return rbegin(obj.m_value); } - template<typename BaseType, typename TagType, auto DerivationClause> - auto constexpr rbegin(new_type<BaseType, TagType, DerivationClause> const & obj) - -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_rbegin_v<BaseType const>, - typename new_type<BaseType, TagType, DerivationClause>::const_reverse_iterator> + template<nt::concepts::const_free_rbegin BaseType, typename TagType, nt::contains<nt::Iterable> auto DerivationClause> + auto constexpr rbegin(new_type<BaseType, TagType, DerivationClause> const & obj) -> + typename new_type<BaseType, TagType, DerivationClause>::const_reverse_iterator { return rbegin(obj.m_value); } - template<typename BaseType, typename TagType, auto DerivationClause> - auto constexpr crbegin(new_type<BaseType, TagType, DerivationClause> const & obj) - -> std::enable_if_t<DerivationClause(nt::Iterable) && impl::has_free_crbegin_v<BaseType const>, - typename new_type<BaseType, TagType, DerivationClause>::const_reverse_iterator> + template<nt::concepts::free_crbegin BaseType, typename TagType, nt::contains<nt::Iterable> auto DerivationClause> + auto constexpr crbegin(new_type<BaseType, TagType, DerivationClause> const & obj) -> + typename new_type<BaseType, TagType, DerivationClause>::const_reverse_iterator { 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> + template<nt::concepts::free_end BaseType, typename TagType, nt::contains<nt::Iterable> auto DerivationClause> + auto constexpr end(new_type<BaseType, TagType, DerivationClause> & obj) -> 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> + template<nt::concepts::const_free_end BaseType, typename TagType, nt::contains<nt::Iterable> auto DerivationClause> + auto constexpr end(new_type<BaseType, TagType, DerivationClause> const & obj) -> + 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> + template<nt::concepts::free_cend BaseType, typename TagType, nt::contains<nt::Iterable> auto DerivationClause> + auto constexpr cend(new_type<BaseType, TagType, DerivationClause> const & obj) -> + 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> + template<nt::concepts::free_rend BaseType, typename TagType, nt::contains<nt::Iterable> auto DerivationClause> + auto constexpr rend(new_type<BaseType, TagType, DerivationClause> & obj) -> + 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> + template<nt::concepts::const_free_rend BaseType, typename TagType, nt::contains<nt::Iterable> auto DerivationClause> + auto constexpr rend(new_type<BaseType, TagType, DerivationClause> const & obj) -> + 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> + template<nt::concepts::free_crend BaseType, typename TagType, nt::contains<nt::Iterable> auto DerivationClause> + auto constexpr crend(new_type<BaseType, TagType, DerivationClause> const & obj) -> + typename new_type<BaseType, TagType, DerivationClause>::const_reverse_iterator { return crend(obj.m_value); } @@ -534,13 +486,10 @@ namespace nt namespace std { - template<typename BaseType, typename TagType, auto DerivationClause> + template<nt::concepts::hashable BaseType, typename TagType, nt::contains<nt::Hash> auto DerivationClause> struct hash<nt::new_type<BaseType, TagType, DerivationClause>> { - template<typename BaseTypeT = BaseType> - auto constexpr operator()(nt::new_type<BaseType, TagType, DerivationClause> const & object, - std::enable_if_t<DerivationClause(nt::Hash) && nt::impl::is_hashable_v<BaseTypeT>> * = nullptr) const - -> std::size_t + auto constexpr operator()(nt::new_type<BaseType, TagType, DerivationClause> const & object) const { return std::hash<BaseType>{}(object.decay()); } diff --git a/source/tests/CMakeLists.txt b/source/tests/CMakeLists.txt index 4fa1cdc..ce6b707 100644 --- a/source/tests/CMakeLists.txt +++ b/source/tests/CMakeLists.txt @@ -28,6 +28,7 @@ target_compile_options("${PROJECT_NAME}_tests" PRIVATE "$<$<CXX_COMPILER_ID:GNU,Clang>:-Wextra>" "$<$<CXX_COMPILER_ID:GNU,Clang>:-Werror>" "$<$<CXX_COMPILER_ID:GNU,Clang>:-pedantic-errors>" + "$<$<CXX_COMPILER_ID:GNU>:-fconcepts-diagnostics-depth=5>" ) catch_discover_tests("${PROJECT_NAME}_tests") diff --git a/source/tests/src/arithmetic.cpp b/source/tests/src/arithmetic.cpp index 09b0c4a..8161f0c 100644 --- a/source/tests/src/arithmetic.cpp +++ b/source/tests/src/arithmetic.cpp @@ -1,6 +1,5 @@ #include "newtype/derivable.hpp" #include "newtype/deriving.hpp" -#include "newtype/impl/type_traits_extensions.hpp" #include "newtype/newtype.hpp" #include <catch2/catch_test_macros.hpp> @@ -23,7 +22,7 @@ SCENARIO("Addition", "[arithmetic]") THEN("it is not addable") { - STATIC_REQUIRE(!nt::impl::is_addable_v<type_alias>); + STATIC_REQUIRE(!nt::concepts::addable<type_alias>); } } @@ -33,7 +32,7 @@ SCENARIO("Addition", "[arithmetic]") THEN("it is addable") { - STATIC_REQUIRE(nt::impl::is_addable_v<type_alias>); + STATIC_REQUIRE(nt::concepts::addable<type_alias>); } } @@ -43,7 +42,7 @@ SCENARIO("Addition", "[arithmetic]") THEN("it is not addable") { - STATIC_REQUIRE(!nt::impl::is_addable_v<addable_type> == nt::impl::is_addable_v<type_alias>); + STATIC_REQUIRE(!nt::concepts::addable<addable_type> == nt::concepts::addable<type_alias>); } } @@ -53,7 +52,7 @@ SCENARIO("Addition", "[arithmetic]") THEN("it is addable") { - STATIC_REQUIRE(nt::impl::is_addable_v<addable_type> == nt::impl::is_addable_v<type_alias>); + STATIC_REQUIRE(nt::concepts::addable<addable_type> == nt::concepts::addable<type_alias>); } } @@ -96,7 +95,7 @@ SCENARIO("Subtraction", "[arithmetic]") THEN("it is not subtractable") { - STATIC_REQUIRE(!nt::impl::is_subtractable_v<type_alias>); + STATIC_REQUIRE(!nt::concepts::subtractable<type_alias>); } } @@ -106,7 +105,7 @@ SCENARIO("Subtraction", "[arithmetic]") THEN("it is subtractable") { - STATIC_REQUIRE(nt::impl::is_subtractable_v<type_alias>); + STATIC_REQUIRE(nt::concepts::subtractable<type_alias>); } } @@ -116,7 +115,7 @@ SCENARIO("Subtraction", "[arithmetic]") THEN("it is not addable") { - STATIC_REQUIRE(!nt::impl::is_subtractable_v<type_alias>); + STATIC_REQUIRE(!nt::concepts::subtractable<type_alias>); } } @@ -126,7 +125,7 @@ SCENARIO("Subtraction", "[arithmetic]") THEN("it is subtractable") { - STATIC_REQUIRE(nt::impl::is_subtractable_v<type_alias>); + STATIC_REQUIRE(nt::concepts::subtractable<type_alias>); } } @@ -169,7 +168,7 @@ SCENARIO("Multiplication", "[arithmetic]") THEN("it is not multipliable") { - STATIC_REQUIRE(!nt::impl::is_multipliable_v<type_alias>); + STATIC_REQUIRE(!nt::concepts::multipliable<type_alias>); } } @@ -179,7 +178,7 @@ SCENARIO("Multiplication", "[arithmetic]") THEN("it is multipliable") { - STATIC_REQUIRE(nt::impl::is_multipliable_v<type_alias>); + STATIC_REQUIRE(nt::concepts::multipliable<type_alias>); } } @@ -189,7 +188,7 @@ SCENARIO("Multiplication", "[arithmetic]") THEN("it is not multipliable") { - STATIC_REQUIRE(!nt::impl::is_multipliable_v<type_alias>); + STATIC_REQUIRE(!nt::concepts::multipliable<type_alias>); } } @@ -199,7 +198,7 @@ SCENARIO("Multiplication", "[arithmetic]") THEN("it is multipliable") { - STATIC_REQUIRE(nt::impl::is_multipliable_v<type_alias>); + STATIC_REQUIRE(nt::concepts::multipliable<type_alias>); } } @@ -242,7 +241,7 @@ SCENARIO("Division", "[arithmetic]") THEN("it is not divisible") { - STATIC_REQUIRE(!nt::impl::is_dividable_v<type_alias>); + STATIC_REQUIRE(!nt::concepts::divisible<type_alias>); } } @@ -252,7 +251,7 @@ SCENARIO("Division", "[arithmetic]") THEN("it is divisible") { - STATIC_REQUIRE(nt::impl::is_dividable_v<type_alias>); + STATIC_REQUIRE(nt::concepts::divisible<type_alias>); } } @@ -262,7 +261,7 @@ SCENARIO("Division", "[arithmetic]") THEN("it is not divisible") { - STATIC_REQUIRE(!nt::impl::is_dividable_v<type_alias>); + STATIC_REQUIRE(!nt::concepts::divisible<type_alias>); } } @@ -272,7 +271,7 @@ SCENARIO("Division", "[arithmetic]") THEN("it is divisible") { - STATIC_REQUIRE(nt::impl::is_dividable_v<type_alias>); + STATIC_REQUIRE(nt::concepts::divisible<type_alias>); } } diff --git a/source/tests/src/equality_comparison.cpp b/source/tests/src/equality_comparison.cpp index d857d9b..0876dc2 100644 --- a/source/tests/src/equality_comparison.cpp +++ b/source/tests/src/equality_comparison.cpp @@ -1,3 +1,4 @@ +#include "newtype/concepts.hpp" #include "newtype/derivable.hpp" #include "newtype/deriving.hpp" #include "newtype/newtype.hpp" @@ -64,17 +65,17 @@ SCENARIO("Equality Comparison", "[compare]") { using type_alias = nt::new_type<int, struct tag>; - static_assert(noexcept(std::declval<type_alias::base_type>() == std::declval<type_alias::base_type>())); - static_assert(noexcept(std::declval<type_alias::base_type>() != std::declval<type_alias::base_type>())); + static_assert(nt::concepts::nothrow_equality_comparable<type_alias::base_type>); + static_assert(nt::concepts::nothrow_inequality_comparable<type_alias::base_type>); THEN("it is nothrow-equality-comparable") { - STATIC_REQUIRE(noexcept(std::declval<type_alias>() == std::declval<type_alias>())); + STATIC_REQUIRE(nt::concepts::nothrow_equality_comparable<type_alias>); } THEN("it is nothrow-inequality-comparable") { - STATIC_REQUIRE(noexcept(std::declval<type_alias>() != std::declval<type_alias>())); + STATIC_REQUIRE(nt::concepts::nothrow_inequality_comparable<type_alias>); } } @@ -88,12 +89,12 @@ SCENARIO("Equality Comparison", "[compare]") using type_alias = nt::new_type<not_nothrow_comparable, struct tag>; - static_assert(!noexcept(std::declval<type_alias::base_type>() == std::declval<type_alias::base_type>())); - static_assert(!noexcept(std::declval<type_alias::base_type>() != std::declval<type_alias::base_type>())); + static_assert(!nt::concepts::nothrow_equality_comparable<type_alias::base_type>); + static_assert(!nt::concepts::nothrow_inequality_comparable<type_alias::base_type>); THEN("it is not nothrow-equality-comparable") { - STATIC_REQUIRE_FALSE(noexcept(std::declval<type_alias>() == std::declval<type_alias>())); + STATIC_REQUIRE_FALSE(nt::concepts::nothrow_equality_comparable<type_alias>); } THEN("it is not nothrow-inequality-comparable") diff --git a/source/tests/src/hash.cpp b/source/tests/src/hash.cpp index e3f624f..9bf6862 100644 --- a/source/tests/src/hash.cpp +++ b/source/tests/src/hash.cpp @@ -1,31 +1,35 @@ +#include "newtype/concepts.hpp" #include "newtype/derivable.hpp" #include "newtype/deriving.hpp" -#include "newtype/impl/type_traits_extensions.hpp" #include "newtype/newtype.hpp" +#include <catch2/catch_template_test_macros.hpp> #include <catch2/catch_test_macros.hpp> +#include <string> #include <unordered_map> -SCENARIO("Hash", "[hash]") +TEMPLATE_TEST_CASE("Hash", "[hash]", std::string, int) { GIVEN("A new_type not deriving nt::Hash") { - using type_alias = nt::new_type<int, struct tag>; + using type_alias = nt::new_type<TestType, struct tag>; + static_assert(nt::concepts::hashable<typename type_alias::base_type>); THEN("it is not hashable") { - STATIC_REQUIRE_FALSE(nt::impl::is_hashable_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::hashable<type_alias>); } } GIVEN("A new_type over a hashable type deriving nt::Hash") { - using type_alias = nt::new_type<int, struct tag, deriving(nt::Hash)>; + using type_alias = nt::new_type<TestType, struct tag, deriving(nt::Hash)>; + static_assert(nt::concepts::hashable<typename type_alias::base_type>); THEN("it is hashable") { - STATIC_REQUIRE(nt::impl::is_hashable_v<type_alias>); + STATIC_REQUIRE(nt::concepts::hashable<type_alias>); } } @@ -35,16 +39,18 @@ SCENARIO("Hash", "[hash]") { }; using type_alias = nt::new_type<non_hashable, struct tag, deriving(nt::Hash)>; + static_assert(!nt::concepts::hashable<typename type_alias::base_type>); THEN("it is not hashable") { - STATIC_REQUIRE_FALSE(nt::impl::is_hashable_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::hashable<type_alias>); } } GIVEN("A hashable new_type") { using type_alias = nt::new_type<int, struct tag, deriving(nt::Hash)>; + static_assert(nt::concepts::hashable<typename type_alias::base_type>); THEN("it can be used a the key in an unordered_map") { diff --git a/source/tests/src/io_operators.cpp b/source/tests/src/io_operators.cpp index 23be171..2be41eb 100644 --- a/source/tests/src/io_operators.cpp +++ b/source/tests/src/io_operators.cpp @@ -83,7 +83,7 @@ SCENARIO("Stream Output") using type_alias = nt::new_type<int, struct tag, deriving(nt::Show)>; static_assert(has_stream_output_v<type_alias::base_type>); - THEN("it has the stream input operator") + THEN("it has the stream output operator") { STATIC_REQUIRE(has_stream_output_v<type_alias>); } diff --git a/source/tests/src/iterable.cpp b/source/tests/src/iterable.cpp index 265dc8c..bc862cc 100644 --- a/source/tests/src/iterable.cpp +++ b/source/tests/src/iterable.cpp @@ -1,6 +1,5 @@ #include "newtype/derivable.hpp" #include "newtype/deriving.hpp" -#include "newtype/impl/type_traits_extensions.hpp" #include "newtype/newtype.hpp" #include <catch2/catch_test_macros.hpp> @@ -63,308 +62,308 @@ SCENARIO("Iterators", "[iterators]") GIVEN("A new_type over a non-iterable base type not deriving nt::Iterable") { using type_alias = nt::new_type<int, struct tag>; - static_assert(!nt::impl::has_begin_v<type_alias::base_type>); - static_assert(!nt::impl::has_begin_v<type_alias::base_type const>); - static_assert(!nt::impl::has_cbegin_v<type_alias::base_type>); - static_assert(!nt::impl::has_rbegin_v<type_alias::base_type>); - static_assert(!nt::impl::has_rbegin_v<type_alias::base_type const>); - static_assert(!nt::impl::has_crbegin_v<type_alias::base_type>); - static_assert(!nt::impl::has_end_v<type_alias::base_type>); - static_assert(!nt::impl::has_end_v<type_alias::base_type const>); - static_assert(!nt::impl::has_cend_v<type_alias::base_type>); - static_assert(!nt::impl::has_rend_v<type_alias::base_type>); - static_assert(!nt::impl::has_rend_v<type_alias::base_type const>); - static_assert(!nt::impl::has_crend_v<type_alias::base_type>); + static_assert(!nt::concepts::beginnable<type_alias::base_type>); + static_assert(!nt::concepts::beginnable<type_alias::base_type const>); + static_assert(!nt::concepts::cbeginnable<type_alias::base_type>); + static_assert(!nt::concepts::rbeginnable<type_alias::base_type>); + static_assert(!nt::concepts::rbeginnable<type_alias::base_type const>); + static_assert(!nt::concepts::crbeginnable<type_alias::base_type>); + static_assert(!nt::concepts::endable<type_alias::base_type>); + static_assert(!nt::concepts::endable<type_alias::base_type const>); + static_assert(!nt::concepts::cendable<type_alias::base_type>); + static_assert(!nt::concepts::rendable<type_alias::base_type>); + static_assert(!nt::concepts::rendable<type_alias::base_type const>); + static_assert(!nt::concepts::crendable<type_alias::base_type>); THEN("it has no begin") { - STATIC_REQUIRE_FALSE(nt::impl::has_begin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::beginnable<type_alias>); } THEN("it has no constant begin") { - STATIC_REQUIRE_FALSE(nt::impl::has_begin_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::beginnable<type_alias const>); } THEN("it has no cbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_cbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::cbeginnable<type_alias>); } THEN("it has no rbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_rbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::rbeginnable<type_alias>); } THEN("it has no constant rbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_rbegin_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::rbeginnable<type_alias const>); } THEN("it has no crbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_crbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::crbeginnable<type_alias>); } THEN("it has no end") { - STATIC_REQUIRE_FALSE(nt::impl::has_end_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::endable<type_alias>); } THEN("it has no constant end") { - STATIC_REQUIRE_FALSE(nt::impl::has_end_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::endable<type_alias const>); } THEN("it has no cend") { - STATIC_REQUIRE_FALSE(nt::impl::has_cend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::cendable<type_alias>); } THEN("it has no rend") { - STATIC_REQUIRE_FALSE(nt::impl::has_rend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::rendable<type_alias>); } THEN("it has no constant rend") { - STATIC_REQUIRE_FALSE(nt::impl::has_rend_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::rendable<type_alias const>); } THEN("it has no crend") { - STATIC_REQUIRE_FALSE(nt::impl::has_crend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::crendable<type_alias>); } } GIVEN("A new_type over a non-iterable base type deriving nt::Iterable") { using type_alias = nt::new_type<int, struct tag, deriving(nt::Iterable)>; - static_assert(!nt::impl::has_begin_v<type_alias::base_type>); - static_assert(!nt::impl::has_begin_v<type_alias::base_type const>); - static_assert(!nt::impl::has_cbegin_v<type_alias::base_type>); - static_assert(!nt::impl::has_rbegin_v<type_alias::base_type>); - static_assert(!nt::impl::has_rbegin_v<type_alias::base_type const>); - static_assert(!nt::impl::has_crbegin_v<type_alias::base_type>); - static_assert(!nt::impl::has_end_v<type_alias::base_type>); - static_assert(!nt::impl::has_end_v<type_alias::base_type const>); - static_assert(!nt::impl::has_cend_v<type_alias::base_type>); - static_assert(!nt::impl::has_rend_v<type_alias::base_type>); - static_assert(!nt::impl::has_rend_v<type_alias::base_type const>); - static_assert(!nt::impl::has_crend_v<type_alias::base_type>); + static_assert(!nt::concepts::beginnable<type_alias::base_type>); + static_assert(!nt::concepts::beginnable<type_alias::base_type const>); + static_assert(!nt::concepts::cbeginnable<type_alias::base_type>); + static_assert(!nt::concepts::rbeginnable<type_alias::base_type>); + static_assert(!nt::concepts::rbeginnable<type_alias::base_type const>); + static_assert(!nt::concepts::crbeginnable<type_alias::base_type>); + static_assert(!nt::concepts::endable<type_alias::base_type>); + static_assert(!nt::concepts::endable<type_alias::base_type const>); + static_assert(!nt::concepts::cendable<type_alias::base_type>); + static_assert(!nt::concepts::rendable<type_alias::base_type>); + static_assert(!nt::concepts::rendable<type_alias::base_type const>); + static_assert(!nt::concepts::crendable<type_alias::base_type>); THEN("it has no begin") { - STATIC_REQUIRE_FALSE(nt::impl::has_begin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::beginnable<type_alias>); } THEN("it has no constant begin") { - STATIC_REQUIRE_FALSE(nt::impl::has_begin_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::beginnable<type_alias const>); } THEN("it has no cbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_cbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::cbeginnable<type_alias>); } THEN("it has no rbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_rbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::rbeginnable<type_alias>); } THEN("it has no constant rbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_rbegin_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::rbeginnable<type_alias const>); } THEN("it has no crbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_crbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::crbeginnable<type_alias>); } THEN("it has no end") { - STATIC_REQUIRE_FALSE(nt::impl::has_end_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::endable<type_alias>); } THEN("it has no constant end") { - STATIC_REQUIRE_FALSE(nt::impl::has_end_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::endable<type_alias const>); } THEN("it has no cend") { - STATIC_REQUIRE_FALSE(nt::impl::has_cend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::cendable<type_alias>); } THEN("it has no rend") { - STATIC_REQUIRE_FALSE(nt::impl::has_rend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::rendable<type_alias>); } THEN("it has no constant rend") { - STATIC_REQUIRE_FALSE(nt::impl::has_rend_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::rendable<type_alias const>); } THEN("it has no crend") { - STATIC_REQUIRE_FALSE(nt::impl::has_crend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::crendable<type_alias>); } } GIVEN("A new_type over an iterable base type not deriving nt::Iterable") { using type_alias = nt::new_type<std::array<int, 1>, struct tag>; - static_assert(nt::impl::has_begin_v<type_alias::base_type>); - static_assert(nt::impl::has_begin_v<type_alias::base_type const>); - static_assert(nt::impl::has_cbegin_v<type_alias::base_type>); - static_assert(nt::impl::has_rbegin_v<type_alias::base_type>); - static_assert(nt::impl::has_rbegin_v<type_alias::base_type const>); - static_assert(nt::impl::has_crbegin_v<type_alias::base_type>); - static_assert(nt::impl::has_end_v<type_alias::base_type>); - static_assert(nt::impl::has_end_v<type_alias::base_type const>); - static_assert(nt::impl::has_cend_v<type_alias::base_type>); - static_assert(nt::impl::has_rend_v<type_alias::base_type>); - static_assert(nt::impl::has_rend_v<type_alias::base_type const>); - static_assert(nt::impl::has_crend_v<type_alias::base_type>); + static_assert(nt::concepts::beginnable<type_alias::base_type>); + static_assert(nt::concepts::const_beginnable<type_alias::base_type>); + static_assert(nt::concepts::cbeginnable<type_alias::base_type>); + static_assert(nt::concepts::rbeginnable<type_alias::base_type>); + static_assert(nt::concepts::const_rbeginnable<type_alias::base_type>); + static_assert(nt::concepts::crbeginnable<type_alias::base_type>); + static_assert(nt::concepts::endable<type_alias::base_type>); + static_assert(nt::concepts::const_endable<type_alias::base_type>); + static_assert(nt::concepts::cendable<type_alias::base_type>); + static_assert(nt::concepts::rendable<type_alias::base_type>); + static_assert(nt::concepts::const_rendable<type_alias::base_type>); + static_assert(nt::concepts::crendable<type_alias::base_type>); THEN("it has no begin") { - STATIC_REQUIRE_FALSE(nt::impl::has_begin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::beginnable<type_alias>); } THEN("it has no constant begin") { - STATIC_REQUIRE_FALSE(nt::impl::has_begin_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::beginnable<type_alias const>); } THEN("it has no cbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_cbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::cbeginnable<type_alias>); } THEN("it has no rbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_rbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::rbeginnable<type_alias>); } THEN("it has no constant rbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_rbegin_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::rbeginnable<type_alias const>); } THEN("it has no crbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_crbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::crbeginnable<type_alias>); } THEN("it has no end") { - STATIC_REQUIRE_FALSE(nt::impl::has_end_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::endable<type_alias>); } THEN("it has no constant end") { - STATIC_REQUIRE_FALSE(nt::impl::has_end_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::endable<type_alias const>); } THEN("it has no cend") { - STATIC_REQUIRE_FALSE(nt::impl::has_cend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::cendable<type_alias>); } THEN("it has no rend") { - STATIC_REQUIRE_FALSE(nt::impl::has_rend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::rendable<type_alias>); } THEN("it has no constant rend") { - STATIC_REQUIRE_FALSE(nt::impl::has_rend_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::rendable<type_alias const>); } THEN("it has no crend") { - STATIC_REQUIRE_FALSE(nt::impl::has_crend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::crendable<type_alias>); } } GIVEN("A new_type over an iterable base type deriving nt::Iterable") { using type_alias = nt::new_type<std::array<int, 1>, struct tag, deriving(nt::Iterable)>; - static_assert(nt::impl::has_begin_v<type_alias::base_type>); - static_assert(nt::impl::has_begin_v<type_alias::base_type const>); - static_assert(nt::impl::has_cbegin_v<type_alias::base_type>); - static_assert(nt::impl::has_rbegin_v<type_alias::base_type>); - static_assert(nt::impl::has_rbegin_v<type_alias::base_type const>); - static_assert(nt::impl::has_crbegin_v<type_alias::base_type>); - static_assert(nt::impl::has_end_v<type_alias::base_type>); - static_assert(nt::impl::has_end_v<type_alias::base_type const>); - static_assert(nt::impl::has_cend_v<type_alias::base_type>); - static_assert(nt::impl::has_rend_v<type_alias::base_type>); - static_assert(nt::impl::has_rend_v<type_alias::base_type const>); - static_assert(nt::impl::has_crend_v<type_alias::base_type>); + static_assert(nt::concepts::beginnable<type_alias::base_type>); + static_assert(nt::concepts::const_beginnable<type_alias::base_type>); + static_assert(nt::concepts::cbeginnable<type_alias::base_type>); + static_assert(nt::concepts::rbeginnable<type_alias::base_type>); + static_assert(nt::concepts::const_rbeginnable<type_alias::base_type>); + static_assert(nt::concepts::crbeginnable<type_alias::base_type>); + static_assert(nt::concepts::endable<type_alias::base_type>); + static_assert(nt::concepts::const_endable<type_alias::base_type>); + static_assert(nt::concepts::cendable<type_alias::base_type>); + static_assert(nt::concepts::rendable<type_alias::base_type>); + static_assert(nt::concepts::const_rendable<type_alias::base_type>); + static_assert(nt::concepts::crendable<type_alias::base_type>); THEN("it has begin") { - STATIC_REQUIRE(nt::impl::has_begin_v<type_alias>); + STATIC_REQUIRE(nt::concepts::beginnable<type_alias>); } THEN("it has constant begin") { - STATIC_REQUIRE(nt::impl::has_begin_v<type_alias const>); + STATIC_REQUIRE(nt::concepts::const_beginnable<type_alias>); } THEN("it has cbegin") { - STATIC_REQUIRE(nt::impl::has_cbegin_v<type_alias>); + STATIC_REQUIRE(nt::concepts::cbeginnable<type_alias>); } THEN("it has rbegin") { - STATIC_REQUIRE(nt::impl::has_rbegin_v<type_alias>); + STATIC_REQUIRE(nt::concepts::rbeginnable<type_alias>); } THEN("it has constant rbegin") { - STATIC_REQUIRE(nt::impl::has_rbegin_v<type_alias const>); + STATIC_REQUIRE(nt::concepts::const_rbeginnable<type_alias>); } THEN("it has crbegin") { - STATIC_REQUIRE(nt::impl::has_crbegin_v<type_alias>); + STATIC_REQUIRE(nt::concepts::crbeginnable<type_alias>); } THEN("it has end") { - STATIC_REQUIRE(nt::impl::has_end_v<type_alias>); + STATIC_REQUIRE(nt::concepts::endable<type_alias>); } THEN("it has constant end") { - STATIC_REQUIRE(nt::impl::has_end_v<type_alias const>); + STATIC_REQUIRE(nt::concepts::const_endable<type_alias>); } THEN("it has cend") { - STATIC_REQUIRE(nt::impl::has_cend_v<type_alias>); + STATIC_REQUIRE(nt::concepts::cendable<type_alias>); } THEN("it has rend") { - STATIC_REQUIRE(nt::impl::has_rend_v<type_alias>); + STATIC_REQUIRE(nt::concepts::rendable<type_alias>); } THEN("it has constant rend") { - STATIC_REQUIRE(nt::impl::has_rend_v<type_alias const>); + STATIC_REQUIRE(nt::concepts::const_rendable<type_alias>); } THEN("it has crend") { - STATIC_REQUIRE(nt::impl::has_crend_v<type_alias>); + STATIC_REQUIRE(nt::concepts::crendable<type_alias>); } } } @@ -374,308 +373,308 @@ SCENARIO("Iterators (member)", "[iterators]") GIVEN("A new_type over a non-iterable base type not deriving nt::Iterable") { using type_alias = nt::new_type<int, struct tag>; - static_assert(!nt::impl::has_member_begin_v<type_alias::base_type>); - static_assert(!nt::impl::has_member_begin_v<type_alias::base_type const>); - static_assert(!nt::impl::has_member_cbegin_v<type_alias::base_type>); - static_assert(!nt::impl::has_member_rbegin_v<type_alias::base_type>); - static_assert(!nt::impl::has_member_rbegin_v<type_alias::base_type const>); - static_assert(!nt::impl::has_member_crbegin_v<type_alias::base_type>); - static_assert(!nt::impl::has_member_end_v<type_alias::base_type>); - static_assert(!nt::impl::has_member_end_v<type_alias::base_type const>); - static_assert(!nt::impl::has_member_cend_v<type_alias::base_type>); - static_assert(!nt::impl::has_member_rend_v<type_alias::base_type>); - static_assert(!nt::impl::has_member_rend_v<type_alias::base_type const>); - static_assert(!nt::impl::has_member_crend_v<type_alias::base_type>); + static_assert(!nt::concepts::member_begin<type_alias::base_type>); + static_assert(!nt::concepts::const_member_begin<type_alias::base_type>); + static_assert(!nt::concepts::member_cbegin<type_alias::base_type>); + static_assert(!nt::concepts::member_rbegin<type_alias::base_type>); + static_assert(!nt::concepts::const_member_rbegin<type_alias::base_type>); + static_assert(!nt::concepts::member_crbegin<type_alias::base_type>); + static_assert(!nt::concepts::member_end<type_alias::base_type>); + static_assert(!nt::concepts::const_member_end<type_alias::base_type>); + static_assert(!nt::concepts::member_cend<type_alias::base_type>); + static_assert(!nt::concepts::member_rend<type_alias::base_type>); + static_assert(!nt::concepts::const_member_rend<type_alias::base_type>); + static_assert(!nt::concepts::member_crend<type_alias::base_type>); THEN("it has no member begin") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_begin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::member_begin<type_alias>); } THEN("it has no member constant begin") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_begin_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::member_begin<type_alias const>); } THEN("it has no member cbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_cbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::member_cbegin<type_alias>); } THEN("it has no member rbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_rbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::member_rbegin<type_alias>); } THEN("it has no member constant rbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_rbegin_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::member_rbegin<type_alias const>); } THEN("it has no member crbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_crbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::member_crbegin<type_alias>); } THEN("it has no member end") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_end_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::member_end<type_alias>); } THEN("it has no member constant end") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_end_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::member_end<type_alias const>); } THEN("it has no member cend") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_cend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::member_cend<type_alias>); } THEN("it has no member rend") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_rend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::member_rend<type_alias>); } THEN("it has no member constant rend") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_rend_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::member_rend<type_alias const>); } THEN("it has no member crend") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_crend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::member_crend<type_alias>); } } GIVEN("A new_type over a non-iterable base type deriving nt::Iterable") { using type_alias = nt::new_type<int, struct tag, deriving(nt::Iterable)>; - static_assert(!nt::impl::has_member_begin_v<type_alias::base_type>); - static_assert(!nt::impl::has_member_begin_v<type_alias::base_type const>); - static_assert(!nt::impl::has_member_cbegin_v<type_alias::base_type>); - static_assert(!nt::impl::has_member_rbegin_v<type_alias::base_type>); - static_assert(!nt::impl::has_member_rbegin_v<type_alias::base_type const>); - static_assert(!nt::impl::has_member_crbegin_v<type_alias::base_type>); - static_assert(!nt::impl::has_member_end_v<type_alias::base_type>); - static_assert(!nt::impl::has_member_end_v<type_alias::base_type const>); - static_assert(!nt::impl::has_member_cend_v<type_alias::base_type>); - static_assert(!nt::impl::has_member_rend_v<type_alias::base_type>); - static_assert(!nt::impl::has_member_rend_v<type_alias::base_type const>); - static_assert(!nt::impl::has_member_crend_v<type_alias::base_type>); + static_assert(!nt::concepts::member_begin<type_alias::base_type>); + static_assert(!nt::concepts::const_member_begin<type_alias::base_type>); + static_assert(!nt::concepts::member_cbegin<type_alias::base_type>); + static_assert(!nt::concepts::member_rbegin<type_alias::base_type>); + static_assert(!nt::concepts::const_member_rbegin<type_alias::base_type>); + static_assert(!nt::concepts::member_crbegin<type_alias::base_type>); + static_assert(!nt::concepts::member_end<type_alias::base_type>); + static_assert(!nt::concepts::const_member_end<type_alias::base_type>); + static_assert(!nt::concepts::member_cend<type_alias::base_type>); + static_assert(!nt::concepts::member_rend<type_alias::base_type>); + static_assert(!nt::concepts::const_member_rend<type_alias::base_type>); + static_assert(!nt::concepts::member_crend<type_alias::base_type>); THEN("it has no member begin") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_begin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::member_begin<type_alias>); } THEN("it has no member constant begin") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_begin_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::member_begin<type_alias const>); } THEN("it has no member cbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_cbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::member_cbegin<type_alias>); } THEN("it has no member rbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_rbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::member_rbegin<type_alias>); } THEN("it has no member constant rbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_rbegin_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::member_rbegin<type_alias const>); } THEN("it has no member crbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_crbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::member_crbegin<type_alias>); } THEN("it has no member end") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_end_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::member_end<type_alias>); } THEN("it has no member constant end") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_end_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::member_end<type_alias const>); } THEN("it has no member cend") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_cend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::member_cend<type_alias>); } THEN("it has no member rend") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_rend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::member_rend<type_alias>); } THEN("it has no member constant rend") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_rend_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::member_rend<type_alias const>); } THEN("it has no member crend") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_crend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::member_crend<type_alias>); } } GIVEN("A new_type over an iterable base type not deriving nt::Iterable") { using type_alias = nt::new_type<std::array<int, 1>, struct tag>; - static_assert(nt::impl::has_member_begin_v<type_alias::base_type>); - static_assert(nt::impl::has_member_begin_v<type_alias::base_type const>); - static_assert(nt::impl::has_member_cbegin_v<type_alias::base_type>); - static_assert(nt::impl::has_member_rbegin_v<type_alias::base_type>); - static_assert(nt::impl::has_member_rbegin_v<type_alias::base_type const>); - static_assert(nt::impl::has_member_crbegin_v<type_alias::base_type>); - static_assert(nt::impl::has_member_end_v<type_alias::base_type>); - static_assert(nt::impl::has_member_end_v<type_alias::base_type const>); - static_assert(nt::impl::has_member_cend_v<type_alias::base_type>); - static_assert(nt::impl::has_member_rend_v<type_alias::base_type>); - static_assert(nt::impl::has_member_rend_v<type_alias::base_type const>); - static_assert(nt::impl::has_member_crend_v<type_alias::base_type>); + static_assert(nt::concepts::member_begin<type_alias::base_type>); + static_assert(nt::concepts::const_member_begin<type_alias::base_type>); + static_assert(nt::concepts::member_cbegin<type_alias::base_type>); + static_assert(nt::concepts::member_rbegin<type_alias::base_type>); + static_assert(nt::concepts::const_member_rbegin<type_alias::base_type>); + static_assert(nt::concepts::member_crbegin<type_alias::base_type>); + static_assert(nt::concepts::member_end<type_alias::base_type>); + static_assert(nt::concepts::const_member_end<type_alias::base_type>); + static_assert(nt::concepts::member_cend<type_alias::base_type>); + static_assert(nt::concepts::member_rend<type_alias::base_type>); + static_assert(nt::concepts::const_member_rend<type_alias::base_type>); + static_assert(nt::concepts::member_crend<type_alias::base_type>); THEN("it has no member begin") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_begin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::member_begin<type_alias>); } THEN("it has no member constant begin") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_begin_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::member_begin<type_alias const>); } THEN("it has no member cbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_cbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::member_cbegin<type_alias>); } THEN("it has no member rbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_rbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::member_rbegin<type_alias>); } THEN("it has no member constant rbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_rbegin_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::member_rbegin<type_alias const>); } THEN("it has no member crbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_crbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::member_crbegin<type_alias>); } THEN("it has no member end") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_end_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::member_end<type_alias>); } THEN("it has no member constant end") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_end_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::member_end<type_alias const>); } THEN("it has no member cend") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_cend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::member_cend<type_alias>); } THEN("it has no member rend") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_rend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::member_rend<type_alias>); } THEN("it has no member constant rend") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_rend_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::member_rend<type_alias const>); } THEN("it has no member crend") { - STATIC_REQUIRE_FALSE(nt::impl::has_member_crend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::member_crend<type_alias>); } } GIVEN("A new_type over an iterable base type deriving nt::Iterable") { using type_alias = nt::new_type<std::array<int, 1>, struct tag, deriving(nt::Iterable)>; - static_assert(nt::impl::has_member_begin_v<type_alias::base_type>); - static_assert(nt::impl::has_member_begin_v<type_alias::base_type const>); - static_assert(nt::impl::has_member_cbegin_v<type_alias::base_type>); - static_assert(nt::impl::has_member_rbegin_v<type_alias::base_type>); - static_assert(nt::impl::has_member_rbegin_v<type_alias::base_type const>); - static_assert(nt::impl::has_member_crbegin_v<type_alias::base_type>); - static_assert(nt::impl::has_member_end_v<type_alias::base_type>); - static_assert(nt::impl::has_member_end_v<type_alias::base_type const>); - static_assert(nt::impl::has_member_cend_v<type_alias::base_type>); - static_assert(nt::impl::has_member_rend_v<type_alias::base_type>); - static_assert(nt::impl::has_member_rend_v<type_alias::base_type const>); - static_assert(nt::impl::has_member_crend_v<type_alias::base_type>); + static_assert(nt::concepts::member_begin<type_alias::base_type>); + static_assert(nt::concepts::const_member_begin<type_alias::base_type>); + static_assert(nt::concepts::member_cbegin<type_alias::base_type>); + static_assert(nt::concepts::member_rbegin<type_alias::base_type>); + static_assert(nt::concepts::const_member_rbegin<type_alias::base_type>); + static_assert(nt::concepts::member_crbegin<type_alias::base_type>); + static_assert(nt::concepts::member_end<type_alias::base_type>); + static_assert(nt::concepts::const_member_end<type_alias::base_type>); + static_assert(nt::concepts::member_cend<type_alias::base_type>); + static_assert(nt::concepts::member_rend<type_alias::base_type>); + static_assert(nt::concepts::const_member_rend<type_alias::base_type>); + static_assert(nt::concepts::member_crend<type_alias::base_type>); THEN("it has member begin") { - STATIC_REQUIRE(nt::impl::has_member_begin_v<type_alias>); + STATIC_REQUIRE(nt::concepts::member_begin<type_alias>); } THEN("it has member constant begin") { - STATIC_REQUIRE(nt::impl::has_member_begin_v<type_alias const>); + STATIC_REQUIRE(nt::concepts::const_member_begin<type_alias>); } THEN("it has member cbegin") { - STATIC_REQUIRE(nt::impl::has_member_cbegin_v<type_alias>); + STATIC_REQUIRE(nt::concepts::member_cbegin<type_alias>); } THEN("it has member rbegin") { - STATIC_REQUIRE(nt::impl::has_member_rbegin_v<type_alias>); + STATIC_REQUIRE(nt::concepts::member_rbegin<type_alias>); } THEN("it has member constant rbegin") { - STATIC_REQUIRE(nt::impl::has_member_rbegin_v<type_alias const>); + STATIC_REQUIRE(nt::concepts::const_member_rbegin<type_alias>); } THEN("it has member crbegin") { - STATIC_REQUIRE(nt::impl::has_member_crbegin_v<type_alias>); + STATIC_REQUIRE(nt::concepts::member_crbegin<type_alias>); } THEN("it has member end") { - STATIC_REQUIRE(nt::impl::has_member_end_v<type_alias>); + STATIC_REQUIRE(nt::concepts::member_end<type_alias>); } THEN("it has member constant end") { - STATIC_REQUIRE(nt::impl::has_member_end_v<type_alias const>); + STATIC_REQUIRE(nt::concepts::const_member_end<type_alias>); } THEN("it has member cend") { - STATIC_REQUIRE(nt::impl::has_member_cend_v<type_alias>); + STATIC_REQUIRE(nt::concepts::member_cend<type_alias>); } THEN("it has member rend") { - STATIC_REQUIRE(nt::impl::has_member_rend_v<type_alias>); + STATIC_REQUIRE(nt::concepts::member_rend<type_alias>); } THEN("it has member constant rend") { - STATIC_REQUIRE(nt::impl::has_member_rend_v<type_alias const>); + STATIC_REQUIRE(nt::concepts::const_member_rend<type_alias>); } THEN("it has member crend") { - STATIC_REQUIRE(nt::impl::has_member_crend_v<type_alias>); + STATIC_REQUIRE(nt::concepts::member_crend<type_alias>); } } } @@ -685,308 +684,308 @@ SCENARIO("Iterators (free)", "[iterators]") GIVEN("A new_type over a non-iterable base type not deriving nt::Iterable") { using type_alias = nt::new_type<int, struct tag>; - static_assert(!nt::impl::has_free_begin_v<type_alias::base_type>); - static_assert(!nt::impl::has_free_begin_v<type_alias::base_type const>); - static_assert(!nt::impl::has_free_cbegin_v<type_alias::base_type>); - static_assert(!nt::impl::has_free_rbegin_v<type_alias::base_type>); - static_assert(!nt::impl::has_free_rbegin_v<type_alias::base_type const>); - static_assert(!nt::impl::has_free_crbegin_v<type_alias::base_type>); - static_assert(!nt::impl::has_free_end_v<type_alias::base_type>); - static_assert(!nt::impl::has_free_end_v<type_alias::base_type const>); - static_assert(!nt::impl::has_free_cend_v<type_alias::base_type>); - static_assert(!nt::impl::has_free_rend_v<type_alias::base_type>); - static_assert(!nt::impl::has_free_rend_v<type_alias::base_type const>); - static_assert(!nt::impl::has_free_crend_v<type_alias::base_type>); + static_assert(!nt::concepts::free_begin<type_alias::base_type>); + static_assert(!nt::concepts::const_free_begin<type_alias::base_type>); + static_assert(!nt::concepts::free_cbegin<type_alias::base_type>); + static_assert(!nt::concepts::free_rbegin<type_alias::base_type>); + static_assert(!nt::concepts::const_free_rbegin<type_alias::base_type>); + static_assert(!nt::concepts::free_crbegin<type_alias::base_type>); + static_assert(!nt::concepts::free_end<type_alias::base_type>); + static_assert(!nt::concepts::const_free_end<type_alias::base_type>); + static_assert(!nt::concepts::free_cend<type_alias::base_type>); + static_assert(!nt::concepts::free_rend<type_alias::base_type>); + static_assert(!nt::concepts::const_free_rend<type_alias::base_type>); + static_assert(!nt::concepts::free_crend<type_alias::base_type>); THEN("it has no free begin") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_begin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::free_begin<type_alias>); } THEN("it has no free constant begin") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_begin_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::const_free_begin<type_alias>); } THEN("it has no free cbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_cbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::free_cbegin<type_alias>); } THEN("it has no free rbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_rbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::free_rbegin<type_alias>); } THEN("it has no free constant rbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_rbegin_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::const_free_rbegin<type_alias>); } THEN("it has no free crbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_crbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::free_crbegin<type_alias>); } THEN("it has no free end") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_end_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::free_end<type_alias>); } THEN("it has no free constant end") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_end_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::const_free_end<type_alias>); } THEN("it has no free cend") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_cend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::free_cend<type_alias>); } THEN("it has no free rend") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_rend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::free_rend<type_alias>); } THEN("it has no free constant rend") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_rend_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::const_free_rend<type_alias>); } THEN("it has no free crend") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_crend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::free_crend<type_alias>); } } GIVEN("A new_type over a non-iterable base type deriving nt::Iterable") { using type_alias = nt::new_type<int, struct tag, deriving(nt::Iterable)>; - static_assert(!nt::impl::has_free_begin_v<type_alias::base_type>); - static_assert(!nt::impl::has_free_begin_v<type_alias::base_type const>); - static_assert(!nt::impl::has_free_cbegin_v<type_alias::base_type>); - static_assert(!nt::impl::has_free_rbegin_v<type_alias::base_type>); - static_assert(!nt::impl::has_free_rbegin_v<type_alias::base_type const>); - static_assert(!nt::impl::has_free_crbegin_v<type_alias::base_type>); - static_assert(!nt::impl::has_free_end_v<type_alias::base_type>); - static_assert(!nt::impl::has_free_end_v<type_alias::base_type const>); - static_assert(!nt::impl::has_free_cend_v<type_alias::base_type>); - static_assert(!nt::impl::has_free_rend_v<type_alias::base_type>); - static_assert(!nt::impl::has_free_rend_v<type_alias::base_type const>); - static_assert(!nt::impl::has_free_crend_v<type_alias::base_type>); + static_assert(!nt::concepts::free_begin<type_alias::base_type>); + static_assert(!nt::concepts::const_free_begin<type_alias::base_type>); + static_assert(!nt::concepts::free_cbegin<type_alias::base_type>); + static_assert(!nt::concepts::free_rbegin<type_alias::base_type>); + static_assert(!nt::concepts::const_free_rbegin<type_alias::base_type>); + static_assert(!nt::concepts::free_crbegin<type_alias::base_type>); + static_assert(!nt::concepts::free_end<type_alias::base_type>); + static_assert(!nt::concepts::const_free_end<type_alias::base_type>); + static_assert(!nt::concepts::free_cend<type_alias::base_type>); + static_assert(!nt::concepts::free_rend<type_alias::base_type>); + static_assert(!nt::concepts::const_free_rend<type_alias::base_type>); + static_assert(!nt::concepts::free_crend<type_alias::base_type>); THEN("it has no free begin") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_begin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::free_begin<type_alias>); } THEN("it has no free constant begin") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_begin_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::const_free_begin<type_alias>); } THEN("it has no free cbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_cbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::free_cbegin<type_alias>); } THEN("it has no free rbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_rbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::free_rbegin<type_alias>); } THEN("it has no free constant rbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_rbegin_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::const_free_rbegin<type_alias>); } THEN("it has no free crbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_crbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::free_crbegin<type_alias>); } THEN("it has no free end") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_end_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::free_end<type_alias>); } THEN("it has no free constant end") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_end_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::const_free_end<type_alias>); } THEN("it has no free cend") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_cend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::free_cend<type_alias>); } THEN("it has no free rend") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_rend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::free_rend<type_alias>); } THEN("it has no free constant rend") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_rend_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::const_free_rend<type_alias>); } THEN("it has no free crend") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_crend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::free_crend<type_alias>); } } GIVEN("A new_type over an iterable base type not deriving nt::Iterable") { using type_alias = nt::new_type<std::array<int, 1>, struct tag>; - static_assert(nt::impl::has_free_begin_v<type_alias::base_type>); - static_assert(nt::impl::has_free_begin_v<type_alias::base_type const>); - static_assert(nt::impl::has_free_cbegin_v<type_alias::base_type>); - static_assert(nt::impl::has_free_rbegin_v<type_alias::base_type>); - static_assert(nt::impl::has_free_rbegin_v<type_alias::base_type const>); - static_assert(nt::impl::has_free_crbegin_v<type_alias::base_type>); - static_assert(nt::impl::has_free_end_v<type_alias::base_type>); - static_assert(nt::impl::has_free_end_v<type_alias::base_type const>); - static_assert(nt::impl::has_free_cend_v<type_alias::base_type>); - static_assert(nt::impl::has_free_rend_v<type_alias::base_type>); - static_assert(nt::impl::has_free_rend_v<type_alias::base_type const>); - static_assert(nt::impl::has_free_crend_v<type_alias::base_type>); + static_assert(nt::concepts::free_begin<type_alias::base_type>); + static_assert(nt::concepts::const_free_begin<type_alias::base_type>); + static_assert(nt::concepts::free_cbegin<type_alias::base_type>); + static_assert(nt::concepts::free_rbegin<type_alias::base_type>); + static_assert(nt::concepts::const_free_rbegin<type_alias::base_type>); + static_assert(nt::concepts::free_crbegin<type_alias::base_type>); + static_assert(nt::concepts::free_end<type_alias::base_type>); + static_assert(nt::concepts::const_free_end<type_alias::base_type>); + static_assert(nt::concepts::free_cend<type_alias::base_type>); + static_assert(nt::concepts::free_rend<type_alias::base_type>); + static_assert(nt::concepts::const_free_rend<type_alias::base_type>); + static_assert(nt::concepts::free_crend<type_alias::base_type>); THEN("it has no free begin") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_begin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::free_begin<type_alias>); } THEN("it has no free constant begin") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_begin_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::free_begin<type_alias const>); } THEN("it has no free cbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_cbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::free_cbegin<type_alias>); } THEN("it has no free rbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_rbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::free_rbegin<type_alias>); } THEN("it has no free constant rbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_rbegin_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::free_rbegin<type_alias const>); } THEN("it has no free crbegin") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_crbegin_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::free_crbegin<type_alias>); } THEN("it has no free end") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_end_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::free_end<type_alias>); } THEN("it has no free constant end") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_end_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::free_end<type_alias const>); } THEN("it has no free cend") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_cend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::free_cend<type_alias>); } THEN("it has no free rend") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_rend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::free_rend<type_alias>); } THEN("it has no free constant rend") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_rend_v<type_alias const>); + STATIC_REQUIRE_FALSE(nt::concepts::free_rend<type_alias const>); } THEN("it has no free crend") { - STATIC_REQUIRE_FALSE(nt::impl::has_free_crend_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::free_crend<type_alias>); } } GIVEN("A new_type over an iterable base type deriving nt::Iterable") { using type_alias = nt::new_type<std::array<int, 1>, struct tag, deriving(nt::Iterable)>; - static_assert(nt::impl::has_free_begin_v<type_alias::base_type>); - static_assert(nt::impl::has_free_begin_v<type_alias::base_type const>); - static_assert(nt::impl::has_free_cbegin_v<type_alias::base_type>); - static_assert(nt::impl::has_free_rbegin_v<type_alias::base_type>); - static_assert(nt::impl::has_free_rbegin_v<type_alias::base_type const>); - static_assert(nt::impl::has_free_crbegin_v<type_alias::base_type>); - static_assert(nt::impl::has_free_end_v<type_alias::base_type>); - static_assert(nt::impl::has_free_end_v<type_alias::base_type const>); - static_assert(nt::impl::has_free_cend_v<type_alias::base_type>); - static_assert(nt::impl::has_free_rend_v<type_alias::base_type>); - static_assert(nt::impl::has_free_rend_v<type_alias::base_type const>); - static_assert(nt::impl::has_free_crend_v<type_alias::base_type>); + static_assert(nt::concepts::free_begin<type_alias::base_type>); + static_assert(nt::concepts::const_free_begin<type_alias::base_type>); + static_assert(nt::concepts::free_cbegin<type_alias::base_type>); + static_assert(nt::concepts::free_rbegin<type_alias::base_type>); + static_assert(nt::concepts::const_free_rbegin<type_alias::base_type>); + static_assert(nt::concepts::free_crbegin<type_alias::base_type>); + static_assert(nt::concepts::free_end<type_alias::base_type>); + static_assert(nt::concepts::const_free_end<type_alias::base_type>); + static_assert(nt::concepts::free_cend<type_alias::base_type>); + static_assert(nt::concepts::free_rend<type_alias::base_type>); + static_assert(nt::concepts::const_free_rend<type_alias::base_type>); + static_assert(nt::concepts::free_crend<type_alias::base_type>); THEN("it has free begin") { - STATIC_REQUIRE(nt::impl::has_free_begin_v<type_alias>); + STATIC_REQUIRE(nt::concepts::free_begin<type_alias>); } THEN("it has free constant begin") { - STATIC_REQUIRE(nt::impl::has_free_begin_v<type_alias const>); + STATIC_REQUIRE(nt::concepts::const_free_begin<type_alias>); } THEN("it has free cbegin") { - STATIC_REQUIRE(nt::impl::has_free_cbegin_v<type_alias>); + STATIC_REQUIRE(nt::concepts::free_cbegin<type_alias>); } THEN("it has free rbegin") { - STATIC_REQUIRE(nt::impl::has_free_rbegin_v<type_alias>); + STATIC_REQUIRE(nt::concepts::free_rbegin<type_alias>); } THEN("it has free constant rbegin") { - STATIC_REQUIRE(nt::impl::has_free_rbegin_v<type_alias const>); + STATIC_REQUIRE(nt::concepts::const_free_rbegin<type_alias>); } THEN("it has free crbegin") { - STATIC_REQUIRE(nt::impl::has_free_crbegin_v<type_alias>); + STATIC_REQUIRE(nt::concepts::free_crbegin<type_alias>); } THEN("it has free end") { - STATIC_REQUIRE(nt::impl::has_free_end_v<type_alias>); + STATIC_REQUIRE(nt::concepts::free_end<type_alias>); } THEN("it has free constant end") { - STATIC_REQUIRE(nt::impl::has_free_end_v<type_alias const>); + STATIC_REQUIRE(nt::concepts::const_free_end<type_alias>); } THEN("it has free cend") { - STATIC_REQUIRE(nt::impl::has_free_cend_v<type_alias>); + STATIC_REQUIRE(nt::concepts::free_cend<type_alias>); } THEN("it has free rend") { - STATIC_REQUIRE(nt::impl::has_free_rend_v<type_alias>); + STATIC_REQUIRE(nt::concepts::free_rend<type_alias>); } THEN("it has free constant rend") { - STATIC_REQUIRE(nt::impl::has_free_rend_v<type_alias const>); + STATIC_REQUIRE(nt::concepts::const_free_rend<type_alias>); } THEN("it has free crend") { - STATIC_REQUIRE(nt::impl::has_free_crend_v<type_alias>); + STATIC_REQUIRE(nt::concepts::free_crend<type_alias>); } } } diff --git a/source/tests/src/relational_operators.cpp b/source/tests/src/relational_operators.cpp index 95e1bd4..de6f7f3 100644 --- a/source/tests/src/relational_operators.cpp +++ b/source/tests/src/relational_operators.cpp @@ -9,190 +9,121 @@ #include <type_traits> #include <utility> -inline namespace traits_extensions -{ - - template<typename T, typename = void> - struct has_less_than : std::false_type - { - }; - - template<typename T> - struct has_less_than<T, std::void_t<decltype(std::declval<T const &>() < std::declval<T const &>())>> : std::true_type - { - }; - - template<typename T> - auto constexpr has_less_than_v = has_less_than<T>::value; - - template<typename T> - auto constexpr has_nothrow_less_than_v = has_less_than_v<T> && noexcept(std::declval<T const &>() < std::declval<T const &>()); - - template<typename T, typename = void> - struct has_greater_than : std::false_type - { - }; - - template<typename T> - struct has_greater_than<T, std::void_t<decltype(std::declval<T const &>() > std::declval<T const &>())>> : std::true_type - { - }; - - template<typename T> - auto constexpr has_greater_than_v = has_greater_than<T>::value; - - template<typename T> - auto constexpr has_nothrow_greater_than_v = has_less_than_v<T> && noexcept(std::declval<T const &>() < std::declval<T const &>()); - - template<typename T, typename = void> - struct has_less_than_equal_to : std::false_type - { - }; - - template<typename T> - struct has_less_than_equal_to<T, std::void_t<decltype(std::declval<T const &>() <= std::declval<T const &>())>> : std::true_type - { - }; - - template<typename T> - auto constexpr has_less_than_equal_to_v = has_less_than_equal_to<T>::value; - - template<typename T> - auto constexpr has_nothrow_less_than_equal_to_v = has_less_than_v<T> && noexcept(std::declval<T const &>() < std::declval<T const &>()); - - template<typename T, typename = void> - struct has_greater_than_equal_to : std::false_type - { - }; - - template<typename T> - struct has_greater_than_equal_to<T, std::void_t<decltype(std::declval<T const &>() >= std::declval<T const &>())>> : std::true_type - { - }; - - template<typename T> - auto constexpr has_greater_than_equal_to_v = has_greater_than_equal_to<T>::value; - - template<typename T> - auto constexpr has_nothrow_greater_than_equal_to_v = has_less_than_v<T> && noexcept(std::declval<T const &>() < std::declval<T const &>()); - -} // namespace traits_extensions - SCENARIO("Relational Operator Availability") { GIVEN("A new_type over a relationally comparable type not deriving nt::Relational") { using type_alias = nt::new_type<int, struct tag>; - static_assert(has_less_than_v<type_alias::base_type>); - static_assert(has_less_than_equal_to_v<type_alias::base_type>); - static_assert(has_greater_than_v<type_alias::base_type>); - static_assert(has_greater_than_equal_to_v<type_alias::base_type>); + static_assert(nt::concepts::less_than_comparable<type_alias::base_type>); + static_assert(nt::concepts::less_than_equal_comparable<type_alias::base_type>); + static_assert(nt::concepts::greater_than_comparable<type_alias::base_type>); + static_assert(nt::concepts::greater_than_equal_comparable<type_alias::base_type>); THEN("it does not have <") { - STATIC_REQUIRE_FALSE(has_less_than_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::less_than_comparable<type_alias>); } THEN("it does not have <=") { - STATIC_REQUIRE_FALSE(has_less_than_equal_to_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::less_than_equal_comparable<type_alias>); } THEN("it does not have >") { - STATIC_REQUIRE_FALSE(has_greater_than_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::greater_than_comparable<type_alias>); } THEN("it does not have >=") { - STATIC_REQUIRE_FALSE(has_greater_than_equal_to_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::greater_than_equal_comparable<type_alias>); } } GIVEN("A new_type over a relationally comparable type deriving nt::Relational") { using type_alias = nt::new_type<int, struct tag, deriving(nt::Relational)>; - static_assert(has_less_than_v<type_alias::base_type>); - static_assert(has_less_than_equal_to_v<type_alias::base_type>); - static_assert(has_greater_than_v<type_alias::base_type>); - static_assert(has_greater_than_equal_to_v<type_alias::base_type>); + static_assert(nt::concepts::less_than_comparable<type_alias::base_type>); + static_assert(nt::concepts::less_than_equal_comparable<type_alias::base_type>); + static_assert(nt::concepts::greater_than_comparable<type_alias::base_type>); + static_assert(nt::concepts::greater_than_equal_comparable<type_alias::base_type>); THEN("it does have <") { - STATIC_REQUIRE(has_less_than_v<type_alias>); + STATIC_REQUIRE(nt::concepts::less_than_comparable<type_alias>); } THEN("it does have <=") { - STATIC_REQUIRE(has_less_than_equal_to_v<type_alias>); + STATIC_REQUIRE(nt::concepts::less_than_equal_comparable<type_alias>); } THEN("it does have >") { - STATIC_REQUIRE(has_greater_than_v<type_alias>); + STATIC_REQUIRE(nt::concepts::greater_than_comparable<type_alias>); } THEN("it does have >=") { - STATIC_REQUIRE(has_greater_than_equal_to_v<type_alias>); + STATIC_REQUIRE(nt::concepts::greater_than_equal_comparable<type_alias>); } } GIVEN("A new_type over a type that is not relationally comparable not deriving nt::Relational") { using type_alias = nt::new_type<std::istream, struct tag>; - static_assert(!has_less_than_v<type_alias::base_type>); - static_assert(!has_less_than_equal_to_v<type_alias::base_type>); - static_assert(!has_greater_than_v<type_alias::base_type>); - static_assert(!has_greater_than_equal_to_v<type_alias::base_type>); + static_assert(!nt::concepts::less_than_comparable<type_alias::base_type>); + static_assert(!nt::concepts::less_than_equal_comparable<type_alias::base_type>); + static_assert(!nt::concepts::greater_than_comparable<type_alias::base_type>); + static_assert(!nt::concepts::greater_than_equal_comparable<type_alias::base_type>); THEN("it does not have <") { - STATIC_REQUIRE_FALSE(has_less_than_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::less_than_comparable<type_alias>); } THEN("it does not have <=") { - STATIC_REQUIRE_FALSE(has_less_than_equal_to_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::less_than_equal_comparable<type_alias>); } THEN("it does not have >") { - STATIC_REQUIRE_FALSE(has_greater_than_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::greater_than_comparable<type_alias>); } THEN("it does not have >=") { - STATIC_REQUIRE_FALSE(has_greater_than_equal_to_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::greater_than_equal_comparable<type_alias>); } } GIVEN("A new_type over a type that is not relationally comparable deriving nt::Relational") { using type_alias = nt::new_type<std::istream, struct tag, deriving(nt::Relational)>; - static_assert(!has_less_than_v<type_alias::base_type>); - static_assert(!has_less_than_equal_to_v<type_alias::base_type>); - static_assert(!has_greater_than_v<type_alias::base_type>); - static_assert(!has_greater_than_equal_to_v<type_alias::base_type>); + static_assert(!nt::concepts::less_than_comparable<type_alias::base_type>); + static_assert(!nt::concepts::less_than_equal_comparable<type_alias::base_type>); + static_assert(!nt::concepts::greater_than_comparable<type_alias::base_type>); + static_assert(!nt::concepts::greater_than_equal_comparable<type_alias::base_type>); THEN("it does not have <") { - STATIC_REQUIRE_FALSE(has_less_than_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::less_than_comparable<type_alias>); } THEN("it does not have <=") { - STATIC_REQUIRE_FALSE(has_less_than_equal_to_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::less_than_equal_comparable<type_alias>); } THEN("it does not have >") { - STATIC_REQUIRE_FALSE(has_greater_than_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::greater_than_comparable<type_alias>); } THEN("it does not have >=") { - STATIC_REQUIRE_FALSE(has_greater_than_equal_to_v<type_alias>); + STATIC_REQUIRE_FALSE(nt::concepts::greater_than_equal_comparable<type_alias>); } } } @@ -202,10 +133,10 @@ SCENARIO("Relational Comparisons") GIVEN("A new_type over a relationally comparable type deriving nt::Relational") { using type_alias = nt::new_type<int, struct tag, deriving(nt::Relational)>; - static_assert(has_less_than_v<type_alias::base_type>); - static_assert(has_less_than_equal_to_v<type_alias::base_type>); - static_assert(has_greater_than_v<type_alias::base_type>); - static_assert(has_greater_than_equal_to_v<type_alias::base_type>); + static_assert(nt::concepts::less_than_comparable<type_alias::base_type>); + static_assert(nt::concepts::less_than_equal_comparable<type_alias::base_type>); + static_assert(nt::concepts::greater_than_comparable<type_alias::base_type>); + static_assert(nt::concepts::greater_than_equal_comparable<type_alias::base_type>); THEN("comparing two instances using < yields the same result as it does for the base type") { @@ -238,29 +169,29 @@ SCENARIO("Nothrow Relational Comparison") GIVEN("A new_type over a nothrow relationally comparable type deriving nt::Relational") { using type_alias = nt::new_type<int, struct tag, deriving(nt::Relational)>; - static_assert(has_nothrow_less_than_v<type_alias::base_type>); - static_assert(has_nothrow_less_than_equal_to_v<type_alias::base_type>); - static_assert(has_nothrow_greater_than_v<type_alias::base_type>); - static_assert(has_nothrow_greater_than_equal_to_v<type_alias::base_type>); + static_assert(nt::concepts::nothrow_less_than_comparable<type_alias::base_type>); + static_assert(nt::concepts::nothrow_less_than_equal_comparable<type_alias::base_type>); + static_assert(nt::concepts::nothrow_greater_than_comparable<type_alias::base_type>); + static_assert(nt::concepts::nothrow_greater_than_equal_comparable<type_alias::base_type>); THEN("it is nothrow-comparable using < ") { - STATIC_REQUIRE(has_nothrow_less_than_v<type_alias>); + STATIC_REQUIRE(nt::concepts::nothrow_less_than_comparable<type_alias>); } THEN("it is nothrow-comparable using <= ") { - STATIC_REQUIRE(has_nothrow_less_than_equal_to_v<type_alias>); + STATIC_REQUIRE(nt::concepts::nothrow_less_than_equal_comparable<type_alias>); } THEN("it is nothrow-comparable using > ") { - STATIC_REQUIRE(has_nothrow_greater_than_v<type_alias>); + STATIC_REQUIRE(nt::concepts::nothrow_greater_than_comparable<type_alias>); } THEN("it is nothrow-comparable using >= ") { - STATIC_REQUIRE(has_nothrow_greater_than_equal_to_v<type_alias>); + STATIC_REQUIRE(nt::concepts::nothrow_greater_than_equal_comparable<type_alias>); } } @@ -268,36 +199,53 @@ SCENARIO("Nothrow Relational Comparison") { struct strange_type { - auto constexpr operator<(strange_type const & other) const noexcept(false) -> bool; - auto constexpr operator>(strange_type const & other) const noexcept(false) -> bool; - auto constexpr operator<=(strange_type const & other) const noexcept(false) -> bool; - auto constexpr operator>=(strange_type const & other) const noexcept(false) -> bool; + auto constexpr operator<(strange_type const &) const noexcept(false) -> bool + { + return false; + } + auto constexpr operator>(strange_type const &) const noexcept(false) -> bool + { + return false; + } + auto constexpr operator<=(strange_type const &) const noexcept(false) -> bool + { + return false; + } + auto constexpr operator>=(strange_type const &) const noexcept(false) -> bool + { + return false; + } }; using type_alias = nt::new_type<strange_type, struct tag, deriving(nt::Relational)>; - static_assert(has_less_than_v<type_alias::base_type> && !has_nothrow_less_than_v<type_alias::base_type>); - static_assert(has_less_than_equal_to_v<type_alias::base_type> && !has_nothrow_less_than_equal_to_v<type_alias::base_type>); - static_assert(has_greater_than_v<type_alias::base_type> && !has_nothrow_greater_than_v<type_alias::base_type>); - static_assert(has_greater_than_equal_to_v<type_alias::base_type> && !has_nothrow_greater_than_equal_to_v<type_alias::base_type>); + static_assert(nt::concepts::less_than_comparable<type_alias::base_type> && + !nt::concepts::nothrow_less_than_comparable<type_alias::base_type>); + static_assert(nt::concepts::less_than_equal_comparable<type_alias::base_type> && + !nt::concepts::nothrow_less_than_equal_comparable<type_alias::base_type>); + static_assert(nt::concepts::greater_than_comparable<type_alias::base_type> && + !nt::concepts::nothrow_greater_than_comparable<type_alias::base_type>); + static_assert(nt::concepts::greater_than_equal_comparable<type_alias::base_type> && + !nt::concepts::nothrow_greater_than_equal_comparable<type_alias::base_type>); THEN("it is not nothrow-comparable using < ") { - STATIC_REQUIRE(has_less_than_v<type_alias> && !has_nothrow_less_than_v<type_alias>); + STATIC_REQUIRE(nt::concepts::less_than_comparable<type_alias> && !nt::concepts::nothrow_less_than_comparable<type_alias>); } THEN("it is not nothrow-comparable using <= ") { - STATIC_REQUIRE(has_less_than_equal_to_v<type_alias> && !has_nothrow_less_than_equal_to_v<type_alias>); + STATIC_REQUIRE(nt::concepts::less_than_equal_comparable<type_alias> && !nt::concepts::nothrow_less_than_equal_comparable<type_alias>); } THEN("it is not nothrow-comparable using > ") { - STATIC_REQUIRE(has_greater_than_v<type_alias> && !has_nothrow_greater_than_v<type_alias>); + STATIC_REQUIRE(nt::concepts::greater_than_comparable<type_alias> && !nt::concepts::nothrow_greater_than_comparable<type_alias>); } THEN("it is not nothrow-comparable using >= ") { - STATIC_REQUIRE(has_greater_than_equal_to_v<type_alias> && !has_nothrow_greater_than_equal_to_v<type_alias>); + STATIC_REQUIRE(nt::concepts::greater_than_equal_comparable<type_alias> && + !nt::concepts::nothrow_greater_than_equal_comparable<type_alias>); } } } |
