aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.vscode/c_cpp_properties.json7
-rw-r--r--source/lib/include/newtype/concepts.hpp516
-rw-r--r--source/lib/include/newtype/derivation_clause.hpp6
-rw-r--r--source/lib/include/newtype/impl/type_traits_extensions.hpp853
-rw-r--r--source/lib/include/newtype/newtype.hpp425
-rw-r--r--source/tests/CMakeLists.txt1
-rw-r--r--source/tests/src/arithmetic.cpp33
-rw-r--r--source/tests/src/equality_comparison.cpp15
-rw-r--r--source/tests/src/hash.cpp20
-rw-r--r--source/tests/src/io_operators.cpp2
-rw-r--r--source/tests/src/iterable.cpp577
-rw-r--r--source/tests/src/relational_operators.cpp198
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>