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