File indexing completed on 2025-09-18 09:26:51
0001
0002
0003
0004 #ifndef QTTYPETRAITS_H
0005 #define QTTYPETRAITS_H
0006
0007 #include <QtCore/qtconfigmacros.h>
0008 #include <QtCore/qtdeprecationmarkers.h>
0009
0010 #if defined(__cpp_lib_three_way_comparison) && defined(__cpp_lib_concepts)
0011 #include <compare>
0012 #include <concepts>
0013 #endif
0014 #include <optional>
0015 #include <tuple>
0016 #include <type_traits>
0017 #include <utility>
0018 #include <variant>
0019
0020 #if 0
0021 #pragma qt_class(QtTypeTraits)
0022 #pragma qt_sync_stop_processing
0023 #endif
0024
0025 QT_BEGIN_NAMESPACE
0026
0027
0028 template <typename Enum>
0029 constexpr std::underlying_type_t<Enum> qToUnderlying(Enum e) noexcept
0030 {
0031 return static_cast<std::underlying_type_t<Enum>>(e);
0032 }
0033
0034 #ifndef QT_NO_QASCONST
0035 #if QT_DEPRECATED_SINCE(6, 6)
0036
0037
0038 template <typename T>
0039 QT_DEPRECATED_VERSION_X_6_6("Use std::as_const() instead.")
0040 constexpr typename std::add_const<T>::type &qAsConst(T &t) noexcept { return t; }
0041
0042 template <typename T>
0043 void qAsConst(const T &&) = delete;
0044
0045 #endif
0046 #endif
0047
0048 #ifndef QT_NO_QEXCHANGE
0049
0050
0051 template <typename T, typename U = T>
0052 constexpr T qExchange(T &t, U &&newValue)
0053 noexcept(std::conjunction_v<std::is_nothrow_move_constructible<T>,
0054 std::is_nothrow_assignable<T &, U>>)
0055 {
0056 T old = std::move(t);
0057 t = std::forward<U>(newValue);
0058 return old;
0059 }
0060
0061 #endif
0062
0063 namespace QtPrivate {
0064
0065
0066 template <typename T> struct type_dependent_false : std::false_type {};
0067 template <auto T> struct value_dependent_false : std::false_type {};
0068
0069
0070
0071 template <typename T> struct is_standard_or_extended_integer_type_helper : std::is_integral<T> {};
0072
0073
0074 #define QSEIT_EXCLUDE(X) \
0075 template <> struct is_standard_or_extended_integer_type_helper<X> : std::false_type {}
0076 QSEIT_EXCLUDE(bool);
0077 QSEIT_EXCLUDE(char);
0078 #ifdef __cpp_char8_t
0079 QSEIT_EXCLUDE(char8_t);
0080 #endif
0081 QSEIT_EXCLUDE(char16_t);
0082 QSEIT_EXCLUDE(char32_t);
0083 QSEIT_EXCLUDE(wchar_t);
0084 #undef QSEIT_EXCLUDE
0085 template <typename T>
0086 struct is_standard_or_extended_integer_type : is_standard_or_extended_integer_type_helper<std::remove_cv_t<T>> {};
0087 template <typename T>
0088 constexpr bool is_standard_or_extended_integer_type_v = is_standard_or_extended_integer_type<T>::value;
0089 }
0090
0091 namespace QTypeTraits {
0092
0093 namespace detail {
0094 template<typename T, typename U,
0095 typename = std::enable_if_t<std::is_arithmetic_v<T> && std::is_arithmetic_v<U> &&
0096 std::is_floating_point_v<T> == std::is_floating_point_v<U> &&
0097 std::is_signed_v<T> == std::is_signed_v<U> &&
0098 !std::is_same_v<T, bool> && !std::is_same_v<U, bool> &&
0099 !std::is_same_v<T, char> && !std::is_same_v<U, char>>>
0100 struct Promoted
0101 {
0102 using type = decltype(T() + U());
0103 };
0104 }
0105
0106 template <typename T, typename U>
0107 using Promoted = typename detail::Promoted<T, U>::type;
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122 namespace detail {
0123
0124
0125
0126 template <typename, typename = void>
0127 struct is_container : std::false_type {};
0128 template <typename T>
0129 struct is_container<T, std::void_t<
0130 typename T::value_type,
0131 std::is_convertible<decltype(std::declval<T>().begin() != std::declval<T>().end()), bool>
0132 >> : std::true_type {};
0133
0134
0135
0136 QT_WARNING_PUSH
0137 QT_WARNING_DISABLE_FLOAT_COMPARE
0138 template <typename, typename = void>
0139 struct has_operator_equal : std::false_type {};
0140 template <typename T>
0141 struct has_operator_equal<T, std::void_t<decltype(bool(std::declval<const T&>() == std::declval<const T&>()))>>
0142 : std::true_type {};
0143 QT_WARNING_POP
0144
0145
0146 template<typename T, bool = is_container<T>::value>
0147 struct expand_operator_equal_container;
0148 template<typename T>
0149 struct expand_operator_equal_tuple;
0150
0151
0152 template<typename T>
0153 using expand_operator_equal = expand_operator_equal_container<T>;
0154
0155
0156 template<typename T, bool>
0157 struct expand_operator_equal_container : expand_operator_equal_tuple<T> {};
0158
0159 template<typename T>
0160 struct expand_operator_equal_container<T, true> :
0161 std::conjunction<
0162 std::disjunction<
0163 std::is_same<T, typename T::value_type>,
0164 expand_operator_equal<typename T::value_type>
0165 >, expand_operator_equal_tuple<T>> {};
0166
0167
0168 template<typename ...T>
0169 using expand_operator_equal_recursive = std::conjunction<expand_operator_equal<T>...>;
0170
0171 template<typename T>
0172 struct expand_operator_equal_tuple : has_operator_equal<T> {};
0173 template<typename T>
0174 struct expand_operator_equal_tuple<std::optional<T>> : expand_operator_equal_recursive<T> {};
0175 template<typename T1, typename T2>
0176 struct expand_operator_equal_tuple<std::pair<T1, T2>> : expand_operator_equal_recursive<T1, T2> {};
0177 template<typename ...T>
0178 struct expand_operator_equal_tuple<std::tuple<T...>> : expand_operator_equal_recursive<T...> {};
0179 template<typename ...T>
0180 struct expand_operator_equal_tuple<std::variant<T...>> : expand_operator_equal_recursive<T...> {};
0181
0182
0183 template <typename, typename = void>
0184 struct has_operator_less_than : std::false_type{};
0185 template <typename T>
0186 struct has_operator_less_than<T, std::void_t<decltype(bool(std::declval<const T&>() < std::declval<const T&>()))>>
0187 : std::true_type{};
0188
0189 template<typename T, bool = is_container<T>::value>
0190 struct expand_operator_less_than_container;
0191 template<typename T>
0192 struct expand_operator_less_than_tuple;
0193
0194 template<typename T>
0195 using expand_operator_less_than = expand_operator_less_than_container<T>;
0196
0197 template<typename T, bool>
0198 struct expand_operator_less_than_container : expand_operator_less_than_tuple<T> {};
0199 template<typename T>
0200 struct expand_operator_less_than_container<T, true> :
0201 std::conjunction<
0202 std::disjunction<
0203 std::is_same<T, typename T::value_type>,
0204 expand_operator_less_than<typename T::value_type>
0205 >, expand_operator_less_than_tuple<T>
0206 > {};
0207
0208 template<typename ...T>
0209 using expand_operator_less_than_recursive = std::conjunction<expand_operator_less_than<T>...>;
0210
0211 template<typename T>
0212 struct expand_operator_less_than_tuple : has_operator_less_than<T> {};
0213 template<typename T>
0214 struct expand_operator_less_than_tuple<std::optional<T>> : expand_operator_less_than_recursive<T> {};
0215 template<typename T1, typename T2>
0216 struct expand_operator_less_than_tuple<std::pair<T1, T2>> : expand_operator_less_than_recursive<T1, T2> {};
0217 template<typename ...T>
0218 struct expand_operator_less_than_tuple<std::tuple<T...>> : expand_operator_less_than_recursive<T...> {};
0219 template<typename ...T>
0220 struct expand_operator_less_than_tuple<std::variant<T...>> : expand_operator_less_than_recursive<T...> {};
0221
0222 }
0223
0224 template<typename T, typename = void>
0225 struct is_dereferenceable : std::false_type {};
0226
0227 template<typename T>
0228 struct is_dereferenceable<T, std::void_t<decltype(std::declval<T>().operator->())> >
0229 : std::true_type {};
0230
0231 template <typename T>
0232 inline constexpr bool is_dereferenceable_v = is_dereferenceable<T>::value;
0233
0234 template<typename T>
0235 struct has_operator_equal : detail::expand_operator_equal<T> {};
0236 template<typename T>
0237 inline constexpr bool has_operator_equal_v = has_operator_equal<T>::value;
0238
0239 template <typename Container, typename T>
0240 using has_operator_equal_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_operator_equal<T>>;
0241
0242 template<typename T>
0243 struct has_operator_less_than : detail::expand_operator_less_than<T> {};
0244 template<typename T>
0245 inline constexpr bool has_operator_less_than_v = has_operator_less_than<T>::value;
0246
0247 template <typename Container, typename T>
0248 using has_operator_less_than_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_operator_less_than<T>>;
0249
0250 template <typename ...T>
0251 using compare_eq_result = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_equal<T>...>, bool>;
0252
0253 template <typename Container, typename ...T>
0254 using compare_eq_result_container = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_equal_container<Container, T>...>, bool>;
0255
0256 template <typename ...T>
0257 using compare_lt_result = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_less_than<T>...>, bool>;
0258
0259 template <typename Container, typename ...T>
0260 using compare_lt_result_container = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_less_than_container<Container, T>...>, bool>;
0261
0262 template<typename T>
0263 struct has_operator_compare_three_way : std::false_type {};
0264 template <typename T, typename U>
0265 struct has_operator_compare_three_way_with : std::false_type {};
0266 #if defined(__cpp_lib_three_way_comparison) && defined(__cpp_lib_concepts)
0267 template<std::three_way_comparable T>
0268 struct has_operator_compare_three_way<T> : std::true_type {};
0269 template <typename T, typename U>
0270 requires std::three_way_comparable_with<T, U>
0271 struct has_operator_compare_three_way_with<T, U> : std::true_type {};
0272 #endif
0273 template<typename T>
0274 constexpr inline bool has_operator_compare_three_way_v = has_operator_compare_three_way<T>::value;
0275 template<typename T, typename U>
0276 constexpr inline bool has_operator_compare_three_way_with_v = has_operator_compare_three_way_with<T, U>::value;
0277
0278
0279
0280
0281
0282
0283
0284 namespace detail {
0285
0286 template<typename T>
0287 const T &const_reference();
0288 template<typename T>
0289 T &reference();
0290
0291 }
0292
0293 template <typename Stream, typename, typename = void>
0294 struct has_ostream_operator : std::false_type {};
0295 template <typename Stream, typename T>
0296 struct has_ostream_operator<Stream, T, std::void_t<decltype(detail::reference<Stream>() << detail::const_reference<T>())>>
0297 : std::true_type {};
0298 template <typename Stream, typename T>
0299 inline constexpr bool has_ostream_operator_v = has_ostream_operator<Stream, T>::value;
0300
0301 template <typename Stream, typename Container, typename T>
0302 using has_ostream_operator_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_ostream_operator<Stream, T>>;
0303
0304 template <typename Stream, typename, typename = void>
0305 struct has_istream_operator : std::false_type {};
0306 template <typename Stream, typename T>
0307 struct has_istream_operator<Stream, T, std::void_t<decltype(detail::reference<Stream>() >> detail::reference<T>())>>
0308 : std::true_type {};
0309 template <typename Stream, typename T>
0310 inline constexpr bool has_istream_operator_v = has_istream_operator<Stream, T>::value;
0311 template <typename Stream, typename Container, typename T>
0312 using has_istream_operator_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_istream_operator<Stream, T>>;
0313
0314 template <typename Stream, typename T>
0315 inline constexpr bool has_stream_operator_v = has_ostream_operator_v<Stream, T> && has_istream_operator_v<Stream, T>;
0316
0317 }
0318
0319 QT_END_NAMESPACE
0320
0321 #endif