Move qMin/qMax/qBound() to a separate qminmax.h header

Also replaced qMin() uses in qnumeric.h with QtPrivate::min().
Including qassert.h in qminmax.h leads to indirect include of qglobal.h
(through qcompilerdetection.h), which in turn leads to qMin() declaration
not being available at the point the compiler sees qFuzzyCompare()
definitions in qnumeric.h. This makes the headersclean build fail.

Task-number: QTBUG-99313
Change-Id: I824422698b06f94a4a62e2f19d4507c87f90334e
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Ivan Solovev 2022-07-06 16:49:35 +02:00 committed by Sona Kurazyan
parent fc3441101b
commit df1db826cb
6 changed files with 137 additions and 106 deletions

View File

@ -64,6 +64,7 @@ qt_internal_add_module(Core
global/qlibraryinfo.cpp global/qlibraryinfo.h global/qlibraryinfo_p.h
global/qlogging.cpp global/qlogging.h global/qlogging_p.h
global/qmalloc.cpp
global/qminmax.h
global/qnamespace.h # this header is specified on purpose so AUTOMOC processes it
global/qnativeinterface.h global/qnativeinterface_p.h
global/qnumeric.cpp global/qnumeric.h global/qnumeric_p.h

View File

@ -861,43 +861,6 @@ using namespace Qt::StringLiterals;
\snippet code/src_corelib_global_qglobal.cpp 12B
*/
/*! \fn template <typename T> const T &qMin(const T &a, const T &b)
\relates <QtGlobal>
Returns the minimum of \a a and \a b.
Example:
\snippet code/src_corelib_global_qglobal.cpp 13
\sa qMax(), qBound()
*/
/*! \fn template <typename T> const T &qMax(const T &a, const T &b)
\relates <QtGlobal>
Returns the maximum of \a a and \a b.
Example:
\snippet code/src_corelib_global_qglobal.cpp 14
\sa qMin(), qBound()
*/
/*! \fn template <typename T> const T &qBound(const T &min, const T &val, const T &max)
\relates <QtGlobal>
Returns \a val bounded by \a min and \a max. This is equivalent
to qMax(\a min, qMin(\a val, \a max)).
Example:
\snippet code/src_corelib_global_qglobal.cpp 15
\sa qMin(), qMax()
*/
/*!
\macro QT_VERSION_STR
\relates <QtGlobal>

View File

@ -446,73 +446,6 @@ typedef void (*QFunctionPointer)();
# define Q_UNIMPLEMENTED() qWarning("Unimplemented code.")
#endif
namespace QTypeTraits {
namespace detail {
template<typename T, typename U,
typename = std::enable_if_t<std::is_arithmetic_v<T> && std::is_arithmetic_v<U> &&
std::is_floating_point_v<T> == std::is_floating_point_v<U> &&
std::is_signed_v<T> == std::is_signed_v<U> &&
!std::is_same_v<T, bool> && !std::is_same_v<U, bool> &&
!std::is_same_v<T, char> && !std::is_same_v<U, char>>>
struct Promoted
{
using type = decltype(T() + U());
};
}
template <typename T, typename U>
using Promoted = typename detail::Promoted<T, U>::type;
}
template <typename T>
constexpr inline const T &qMin(const T &a, const T &b) { return (a < b) ? a : b; }
template <typename T>
constexpr inline const T &qMax(const T &a, const T &b) { return (a < b) ? b : a; }
template <typename T>
constexpr inline const T &qBound(const T &min, const T &val, const T &max)
{
Q_ASSERT(!(max < min));
return qMax(min, qMin(max, val));
}
template <typename T, typename U>
constexpr inline QTypeTraits::Promoted<T, U> qMin(const T &a, const U &b)
{
using P = QTypeTraits::Promoted<T, U>;
P _a = a;
P _b = b;
return (_a < _b) ? _a : _b;
}
template <typename T, typename U>
constexpr inline QTypeTraits::Promoted<T, U> qMax(const T &a, const U &b)
{
using P = QTypeTraits::Promoted<T, U>;
P _a = a;
P _b = b;
return (_a < _b) ? _b : _a;
}
template <typename T, typename U>
constexpr inline QTypeTraits::Promoted<T, U> qBound(const T &min, const U &val, const T &max)
{
Q_ASSERT(!(max < min));
return qMax(min, qMin(max, val));
}
template <typename T, typename U>
constexpr inline QTypeTraits::Promoted<T, U> qBound(const T &min, const T &val, const U &max)
{
using P = QTypeTraits::Promoted<T, U>;
Q_ASSERT(!(P(max) < P(min)));
return qMax(min, qMin(max, val));
}
template <typename T, typename U>
constexpr inline QTypeTraits::Promoted<T, U> qBound(const U &min, const T &val, const T &max)
{
using P = QTypeTraits::Promoted<T, U>;
Q_ASSERT(!(P(max) < P(min)));
return qMax(min, qMin(max, val));
}
/*
Compilers which follow outdated template instantiation rules
require a class to have a comparison operator to exist when
@ -704,6 +637,7 @@ QT_END_NAMESPACE
#include <QtCore/qenvironmentvariables.h>
#include <QtCore/qforeach.h>
#include <QtCore/qglobalstatic.h>
#include <QtCore/qminmax.h>
#include <QtCore/qnumeric.h>
#include <QtCore/qoverload.h>
#include <QtCore/qtdeprecationmarkers.h>

View File

@ -0,0 +1,88 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QMINMAX_H
#define QMINMAX_H
#if 0
#pragma qt_class(QtMinMax)
#pragma qt_sync_stop_processing
#endif
#include <QtCore/qassert.h>
#include <QtCore/qtconfigmacros.h>
#include <type_traits>
QT_BEGIN_NAMESPACE
namespace QTypeTraits {
namespace detail {
template<typename T, typename U,
typename = std::enable_if_t<std::is_arithmetic_v<T> && std::is_arithmetic_v<U> &&
std::is_floating_point_v<T> == std::is_floating_point_v<U> &&
std::is_signed_v<T> == std::is_signed_v<U> &&
!std::is_same_v<T, bool> && !std::is_same_v<U, bool> &&
!std::is_same_v<T, char> && !std::is_same_v<U, char>>>
struct Promoted
{
using type = decltype(T() + U());
};
}
template <typename T, typename U>
using Promoted = typename detail::Promoted<T, U>::type;
}
template <typename T>
constexpr inline const T &qMin(const T &a, const T &b) { return (a < b) ? a : b; }
template <typename T>
constexpr inline const T &qMax(const T &a, const T &b) { return (a < b) ? b : a; }
template <typename T>
constexpr inline const T &qBound(const T &min, const T &val, const T &max)
{
Q_ASSERT(!(max < min));
return qMax(min, qMin(max, val));
}
template <typename T, typename U>
constexpr inline QTypeTraits::Promoted<T, U> qMin(const T &a, const U &b)
{
using P = QTypeTraits::Promoted<T, U>;
P _a = a;
P _b = b;
return (_a < _b) ? _a : _b;
}
template <typename T, typename U>
constexpr inline QTypeTraits::Promoted<T, U> qMax(const T &a, const U &b)
{
using P = QTypeTraits::Promoted<T, U>;
P _a = a;
P _b = b;
return (_a < _b) ? _b : _a;
}
template <typename T, typename U>
constexpr inline QTypeTraits::Promoted<T, U> qBound(const T &min, const U &val, const T &max)
{
Q_ASSERT(!(max < min));
return qMax(min, qMin(max, val));
}
template <typename T, typename U>
constexpr inline QTypeTraits::Promoted<T, U> qBound(const T &min, const T &val, const U &max)
{
using P = QTypeTraits::Promoted<T, U>;
Q_ASSERT(!(P(max) < P(min)));
return qMax(min, qMin(max, val));
}
template <typename T, typename U>
constexpr inline QTypeTraits::Promoted<T, U> qBound(const U &min, const T &val, const T &max)
{
using P = QTypeTraits::Promoted<T, U>;
Q_ASSERT(!(P(max) < P(min)));
return qMax(min, qMin(max, val));
}
QT_END_NAMESPACE
#endif // QMINMAX_H

View File

@ -0,0 +1,39 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*! \fn template <typename T> const T &qMin(const T &a, const T &b)
\relates <QtMinMax>
Returns the minimum of \a a and \a b.
Example:
\snippet code/src_corelib_global_qglobal.cpp 13
\sa qMax(), qBound()
*/
/*! \fn template <typename T> const T &qMax(const T &a, const T &b)
\relates <QtMinMax>
Returns the maximum of \a a and \a b.
Example:
\snippet code/src_corelib_global_qglobal.cpp 14
\sa qMin(), qBound()
*/
/*! \fn template <typename T> const T &qBound(const T &min, const T &val, const T &max)
\relates <QtMinMax>
Returns \a val bounded by \a min and \a max. This is equivalent
to qMax(\a min, qMin(\a val, \a max)).
Example:
\snippet code/src_corelib_global_qglobal.cpp 15
\sa qMin(), qMax()
*/

View File

@ -9,6 +9,7 @@
#endif
#include <QtCore/qglobal.h>
#include <cmath>
#include <limits>
#include <type_traits>
@ -356,14 +357,19 @@ constexpr inline qint64 qRound64(float d)
{ return d >= 0.0f ? qint64(d + 0.5f) : qint64(d - 0.5f); }
#endif
namespace QtPrivate {
template <typename T>
constexpr inline const T &min(const T &a, const T &b) { return (a < b) ? a : b; }
}
[[nodiscard]] constexpr bool qFuzzyCompare(double p1, double p2)
{
return (qAbs(p1 - p2) * 1000000000000. <= qMin(qAbs(p1), qAbs(p2)));
return (qAbs(p1 - p2) * 1000000000000. <= QtPrivate::min(qAbs(p1), qAbs(p2)));
}
[[nodiscard]] constexpr bool qFuzzyCompare(float p1, float p2)
{
return (qAbs(p1 - p2) * 100000.f <= qMin(qAbs(p1), qAbs(p2)));
return (qAbs(p1 - p2) * 100000.f <= QtPrivate::min(qAbs(p1), qAbs(p2)));
}
[[nodiscard]] constexpr bool qFuzzyIsNull(double d)