9 #include <QtCore/QLatin1String>
10 #include <QtCore/QHashFunctions>
11 #include <QtCore/QDebug>
12 #include <QtCore/QElapsedTimer>
15 #include <unordered_map>
18 #define DISABLE_MOVE(_ClassName) static_assert
19 (false, "Use Q_DISABLE_MOVE instead; Quotient enables it across all used versions of Qt");
21 #if __cpp_conditional_explicit >= 201806L
22 #define QUO_IMPLICIT explicit(false)
27 #define DECL_DEPRECATED_ENUMERATOR(Deprecated, Recommended)
28 Deprecated Q_DECL_ENUMERATOR_DEPRECATED_X("Use " #Recommended) = Recommended
44 #define SLICE(Object, ToType) ToType{static_cast<const ToType&>(Object)}
47 #if Quotient_VERSION_MAJOR == 0
&& Quotient_VERSION_MINOR < 10
57 template <
typename KeyT,
typename ValT>
59 [[deprecated(
"Use std::unordered_map directly")]] = std::unordered_map<KeyT, ValT, HashQ<KeyT>>;
61 constexpr auto operator"" _ls(
const char* s, std::size_t size)
63 return QLatin1String(s,
int(size));
66 template <
typename ArrayT>
67 class [[deprecated(
"Use std::ranges::subrange instead")]]
Range {
68 using iterator =
typename ArrayT::iterator;
69 using const_iterator =
typename ArrayT::const_iterator;
70 using size_type =
typename ArrayT::size_type;
73 constexpr Range(ArrayT& arr) : from(std::begin(arr)), to(std::end(arr)) {}
74 constexpr Range(iterator from, iterator to) : from(from), to(to) {}
76 constexpr size_type
size()
const
78 Q_ASSERT(std::distance(from, to) >= 0);
79 return size_type(std::distance(from, to));
81 constexpr bool empty()
const {
return from == to; }
82 constexpr const_iterator
begin()
const {
return from; }
83 constexpr const_iterator
end()
const {
return to; }
84 constexpr iterator
begin() {
return from; }
85 constexpr iterator
end() {
return to; }
94 concept Holds_NonConst_LValue_Ref = requires {
95 std::is_lvalue_reference_v<T>;
96 !std::is_const_v<std::remove_reference<T>>;
113 template <
typename T>
115 "Use the member function with the same name of the respective container")]]
asKeyValueRange {
138 template <
typename U>
139 asKeyValueRange(U&) -> asKeyValueRange<U&>;
141 template <
typename U>
142 asKeyValueRange(U&&) -> asKeyValueRange<U>;
151 template <
typename InputIt,
typename ForwardIt,
typename Pred>
152 inline std::pair<InputIt, ForwardIt> findFirstOf(InputIt first, InputIt last,
154 ForwardIt sLast, Pred pred)
156 for (; first != last; ++first)
157 for (
auto it = sFirst; it != sLast; ++it)
158 if (pred(*first, *it))
159 return { first, it };
161 return { last, sLast };
170 template <
typename ImplType,
typename TypeToDelete = ImplType>
171 using ImplPtr = std::unique_ptr<ImplType,
void (*)(TypeToDelete*)>;
191 template <
typename ImplType,
typename TypeToDelete = ImplType,
typename... ArgTs>
194 return ImplPtr<ImplType, TypeToDelete> {
195 new ImplType{std::forward<ArgTs>(args)...},
196 [](TypeToDelete* impl) {
delete impl; }
200 template <
typename ImplType,
typename TypeToDelete = ImplType>
203 return ImplPtr<ImplType, TypeToDelete> { from, [](TypeToDelete* impl) {
208 template <
typename ImplType,
typename TypeToDelete = ImplType>
211 return {
nullptr, [](TypeToDelete*) { } };
214 template <
typename T>
216 size_t (*destructor)(T*);
220 destructor(toDelete);
221 delete[]
reinterpret_cast<std::byte*>(toDelete);
229 template <
typename T>
242 template <
typename T>
243 inline auto makeCStruct(T* (*constructor)(
void*), size_t (*sizeFn)(),
246 return CStructPtr<T>{ constructor(
new std::byte[sizeFn()]), { destructor } };
254 template <
typename... FunctorTs>
255 struct Overloads : FunctorTs... {
256 using FunctorTs::operator()...;
259 template <
typename... FunctorTs>
260 Overloads(FunctorTs&&...) -> Overloads<FunctorTs...>;
310 inline QDebug formatJson(QDebug dbg) {
return dbg.noquote(); }
313 inline QDebug terse(QDebug dbg)
315 return dbg.verbosity(QDebug::MinimumVerbosity);
318 constexpr qint64 ProfilerMinNsecs =
319 #ifdef PROFILER_LOG_USECS
332 template <
typename FnT>
333 inline QDebug operator<<(QDebug dbg, FnT manipFn)
334 requires std::is_invocable_v<FnT, QDebug>
337 return std::invoke(manipFn, dbg);
340 inline QDebug operator<<(QDebug dbg, QElapsedTimer et)
343 dbg <<
static_cast<
double>(et.nsecsElapsed() / 1000) / 1000
359 template <
typename FnT>
360 inline auto lift(FnT&& fn,
auto&&... args)
362 if constexpr (std::is_void_v<std::invoke_result_t<FnT,
decltype(*args)...>>) {
363 if ((... &&
bool(args)))
364 std::invoke(std::forward<FnT>(fn), *args...);
366 return (... &&
bool(args))
367 ? std::optional(std::invoke(std::forward<FnT>(fn), *args...))
377 template <
typename T1,
typename T2>
378 requires std::is_assignable_v<T1&,
const T2&>
379 constexpr inline bool merge(T1& lhs,
const std::optional<T2>& rhs)
381 if (!rhs || lhs == *rhs)
393 template <
typename StructT>
394 constexpr inline size_t mergeStruct(StructT& lhs,
const StructT& rhs,
const auto... fields)
396 return ((... +
static_cast<size_t>(merge(lhs.*fields, rhs.*fields))));