diff options
| -rw-r--r-- | .vscode/c_cpp_properties.json | 7 | ||||
| -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 |
12 files changed, 1113 insertions, 1540 deletions
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index d1852ca..eeb9f71 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -3,13 +3,14 @@ { "name": "Linux", "includePath": [ - "${workspaceFolder}/**" + "${workspaceFolder}/source/lib/include" ], "defines": [], - "compilerPath": "/usr/bin/gcc", + "compilerPath": "/usr/bin/g++", "cppStandard": "c++20", "intelliSenseMode": "gcc-x64", - "configurationProvider": "ms-vscode.cmake-tools" + "configurationProvider": "ms-vscode.cmake-tools", + "compileCommands": "${workspaceFolder}/build/compile_commands.json" } ], "version": 4 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> |
