diff options
| -rw-r--r-- | source/lib/include/newtype/concepts.hpp | 16 | ||||
| -rw-r--r-- | source/lib/include/newtype/impl/type_traits_extensions.hpp | 27 | ||||
| -rw-r--r-- | source/lib/include/newtype/newtype.hpp | 20 |
3 files changed, 28 insertions, 35 deletions
diff --git a/source/lib/include/newtype/concepts.hpp b/source/lib/include/newtype/concepts.hpp index 6db528c..c053612 100644 --- a/source/lib/include/newtype/concepts.hpp +++ b/source/lib/include/newtype/concepts.hpp @@ -4,6 +4,7 @@ #include <concepts> #include <cstddef> #include <functional> +#include <iosfwd> namespace nt::concepts { @@ -38,6 +39,21 @@ namespace nt::concepts } noexcept; }; + 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> concept hashable = requires(SubjectType subject) { { diff --git a/source/lib/include/newtype/impl/type_traits_extensions.hpp b/source/lib/include/newtype/impl/type_traits_extensions.hpp index c4b9bee..7db8e66 100644 --- a/source/lib/include/newtype/impl/type_traits_extensions.hpp +++ b/source/lib/include/newtype/impl/type_traits_extensions.hpp @@ -155,33 +155,6 @@ namespace nt::impl 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 diff --git a/source/lib/include/newtype/newtype.hpp b/source/lib/include/newtype/newtype.hpp index 33863ac..acfd2f9 100644 --- a/source/lib/include/newtype/newtype.hpp +++ b/source/lib/include/newtype/newtype.hpp @@ -25,11 +25,13 @@ 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> auto constexpr friend @@ -342,11 +344,13 @@ namespace nt 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; } |
