QObject::connect: allow to disable narrowing of the connection arguments

One of the good features of the new connection style is that
implicit conversion is performed for the connection arguments.

However, this is also a bad feature when it comes to the old
C remnants in the C++ language: for instance, doubles implicitly
convert to ints, possibly losing precision (and GCC/Clang do not
even warn about those under -Wall, only MSVC does) or even
triggering undefined behavior.

For this reason, when using braced initialization, C++11
disables narrowing conversions or floating/integral conversions.
Use this feature when checking the arguments of a PMF-style
signal/slot connection. Technically this makes the program
ill-formed, however GCC still accepts it (but at least
warns under -Wall).

Hence, add a way to disable these implicit conversions.
This is a opt-in and guarded by a macro, as it's a source
incompatible change.

[ChangeLog][QtCore][QObject] The
QT_NO_NARROWING_CONVERSIONS_IN_CONNECT macro has been added.
When using the new connection syntax (PMF-based) this macro
makes it illegal to narrow the arguments carried by the signal,
and/or to perform floating point to integral implicit
conversions on them. When the macro is defined,
depending on your compiler a QObject::connect() statement
triggering such conversions will now fail to compile.

Change-Id: Ie17eb3e66ce0cd780138e60d8bb7da815a4ada83
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Giuseppe D'Angelo 2016-06-07 12:30:28 +01:00
parent 65f5a7558a
commit c0637c0298
3 changed files with 569 additions and 0 deletions

View File

@ -4470,6 +4470,19 @@ QDebug operator<<(QDebug dbg, const QObject *o)
\sa QObject::objectName()
*/
/*!
\macro QT_NO_NARROWING_CONVERSIONS_IN_CONNECT
\relates QObject
\since 5.8
Defining this macro will disable narrowing and floating-point-to-integral
conversions between the arguments carried by a signal and the arguments
accepted by a slot, when the signal and the slot are connected using the
PMF-based syntax.
\sa QObject::connect
*/
/*!
\typedef QObjectList
\relates QObject

View File

@ -50,6 +50,8 @@
#pragma qt_sync_stop_processing
#endif
#include <type_traits>
QT_BEGIN_NAMESPACE
@ -193,6 +195,46 @@ namespace QtPrivate {
}
};
/*
Logic that checks if the underlying type of an enum is signed or not.
Needs an external, explicit check that E is indeed an enum. Works
around the fact that it's undefined behavior to instantiate
std::underlying_type on non-enums (cf. §20.13.7.6 [meta.trans.other]).
*/
template<typename E, typename Enable = void>
struct IsEnumUnderlyingTypeSigned : std::false_type
{
};
template<typename E>
struct IsEnumUnderlyingTypeSigned<E, typename std::enable_if<std::is_enum<E>::value>::type>
: std::integral_constant<bool, std::is_signed<typename std::underlying_type<E>::type>::value>
{
};
/*
Logic that checks if the argument of the slot does not narrow the
argument of the signal when used in list initialization. Cf. §8.5.4.7
[dcl.init.list] for the definition of narrowing.
For incomplete From/To types, there's no narrowing.
*/
template<typename From, typename To, typename Enable = void>
struct AreArgumentsNarrowedBase : std::false_type
{
};
template<typename From, typename To>
struct AreArgumentsNarrowedBase<From, To, typename std::enable_if<sizeof(From) && sizeof(To)>::type>
: std::integral_constant<bool,
(std::is_floating_point<From>::value && std::is_integral<To>::value) ||
(std::is_floating_point<From>::value && std::is_floating_point<To>::value && sizeof(From) > sizeof(To)) ||
((std::is_integral<From>::value || std::is_enum<From>::value) && std::is_floating_point<To>::value) ||
(std::is_integral<From>::value && std::is_integral<To>::value && (sizeof(From) > sizeof(To) || std::is_signed<From>::value != std::is_signed<To>::value)) ||
(std::is_enum<From>::value && std::is_integral<To>::value && (sizeof(From) > sizeof(To) || IsEnumUnderlyingTypeSigned<From>::value != std::is_signed<To>::value))
>
{
};
/*
Logic that check if the arguments of the slot matches the argument of the signal.
To be used like this:
@ -203,6 +245,10 @@ namespace QtPrivate {
static char test(...);
static const typename RemoveRef<A1>::Type &dummy();
enum { value = sizeof(test(dummy())) == sizeof(int) };
#ifdef QT_NO_NARROWING_CONVERSIONS_IN_CONNECT
struct AreArgumentsNarrowed : AreArgumentsNarrowedBase<typename RemoveRef<A1>::Type, typename RemoveRef<A2>::Type> {};
Q_STATIC_ASSERT_X(!AreArgumentsNarrowed::value, "Signal and slot arguments are not compatible (narrowing)");
#endif
};
template<typename A1, typename A2> struct AreArgumentsCompatible<A1, A2&> { enum { value = false }; };
template<typename A> struct AreArgumentsCompatible<A&, A&> { enum { value = true }; };

View File

@ -147,6 +147,7 @@ private slots:
void noDeclarativeParentChangedOnDestruction();
void deleteLaterInAboutToBlockHandler();
void mutableFunctor();
void checkArgumentsForNarrowing();
};
struct QObjectCreatedOnShutdown
@ -6670,6 +6671,515 @@ void tst_QObject::mutableFunctor()
QCOMPARE(functor.count, 0); // but the original object should have been copied at connect time
}
void tst_QObject::checkArgumentsForNarrowing()
{
enum UnscopedEnum {};
enum SignedUnscopedEnum { SignedUnscopedEnumV1 = -1, SignedUnscopedEnumV2 = 1 };
QVERIFY(sizeof(UnscopedEnum) <= sizeof(int));
QVERIFY(sizeof(SignedUnscopedEnum) <= sizeof(int));
// floating point to integral
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<float, bool>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<double, bool>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long double, bool>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<float, char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<double, char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long double, char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<float, short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<double, short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long double, short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<float, int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<double, int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long double, int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<float, long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<double, long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long double, long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<float, long long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<double, long long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long double, long long>::value));
// floating point to a smaller floating point
if (sizeof(double) > sizeof(float)) {
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<double, float>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long double, float>::value));
}
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<float, double>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<float, long double>::value));
if (sizeof(long double) > sizeof(double))
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long double, float>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<double, long double>::value));
// integral to floating point
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<bool, float>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<bool, double>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<bool, long double>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<char, float>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<char, double>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<char, long double>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<short, float>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<short, double>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<short, long double>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<int, float>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<int, double>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<int, long double>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long, float>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long, double>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long, long double>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long long, float>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long long, double>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long long, long double>::value));
// enum to floating point
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<UnscopedEnum, float>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<UnscopedEnum, double>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<UnscopedEnum, long double>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<SignedUnscopedEnum, float>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<SignedUnscopedEnum, double>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<SignedUnscopedEnum, long double>::value));
// integral to smaller integral
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<bool, bool>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<char, char>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<signed char, signed char>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<signed char, short>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<signed char, int>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<signed char, long>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<signed char, long long>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<unsigned char, unsigned char>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<unsigned char, unsigned short>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<unsigned char, unsigned int>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<unsigned char, unsigned long>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<unsigned char, unsigned long long>::value));
if (sizeof(bool) > sizeof(char))
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<bool, unsigned char>::value));
else
QVERIFY(!(QtPrivate::AreArgumentsNarrowedBase<bool, unsigned char>::value));
if (sizeof(bool) > sizeof(short))
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<bool, unsigned short>::value));
else
QVERIFY(!(QtPrivate::AreArgumentsNarrowedBase<bool, unsigned short>::value));
if (sizeof(bool) > sizeof(int))
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<bool, unsigned int>::value));
else
QVERIFY(!(QtPrivate::AreArgumentsNarrowedBase<bool, unsigned int>::value));
if (sizeof(bool) > sizeof(long))
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<bool, unsigned long>::value));
else
QVERIFY(!(QtPrivate::AreArgumentsNarrowedBase<bool, unsigned long>::value));
if (sizeof(bool) > sizeof(long long))
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<bool, unsigned long long>::value));
else
QVERIFY(!(QtPrivate::AreArgumentsNarrowedBase<bool, unsigned long long>::value));
if (sizeof(short) > sizeof(char)) {
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<short, char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<short, unsigned char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<short, signed char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned short, char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned short, unsigned char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned short, signed char>::value));
}
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<short, short>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<short, int>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<short, long>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<short, long long>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<unsigned short, unsigned short>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<unsigned short, unsigned int>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<unsigned short, unsigned long>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<unsigned short, unsigned long long>::value));
if (sizeof(int) > sizeof(short)) {
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<int, char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<int, unsigned char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<int, signed char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<int, short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<int, unsigned short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned int, char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned int, unsigned char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned int, signed char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned int, short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned int, unsigned short>::value));
}
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<int, int>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<int, long>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<int, long long>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<unsigned int, unsigned int>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<unsigned int, unsigned long>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<unsigned int, unsigned long long>::value));
if (sizeof(long) > sizeof(int)) {
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long, char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long, unsigned char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long, signed char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long, short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long, unsigned short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long, int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long, unsigned int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned long, char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned long, unsigned char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned long, signed char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned long, short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned long, unsigned short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned long, int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned long, unsigned int>::value));
}
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<long, long>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<long, long long>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<unsigned long, unsigned long>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<unsigned long, unsigned long long>::value));
if (sizeof(long long) > sizeof(long)) {
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long long, char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long long, unsigned char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long long, signed char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long long, short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long long, unsigned short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long long, int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long long, unsigned int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long long, long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long long, unsigned long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned long long, char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned long long, unsigned char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned long long, signed char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned long long, short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned long long, unsigned short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned long long, int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned long long, unsigned int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned long long, long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned long long, unsigned long>::value));
}
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<long long, long long>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<unsigned long long, unsigned long long>::value));
// integral to integral with different signedness. smaller ones tested above
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<signed char, unsigned char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<signed char, unsigned short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<signed char, unsigned int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<signed char, unsigned long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<signed char, unsigned long long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned char, signed char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned char, short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned char, int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned char, long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned char, long long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<short, unsigned short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<short, unsigned int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<short, unsigned long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<short, unsigned long long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned short, short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned short, int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned short, long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned short, long long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<int, unsigned int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<int, unsigned long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<int, unsigned long long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned int, int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned int, long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned int, long long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long, unsigned long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long, unsigned long long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned long, long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned long, long long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<long long, unsigned long long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<unsigned long long, long long>::value));
// enum to smaller integral
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<UnscopedEnum, UnscopedEnum>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<SignedUnscopedEnum, SignedUnscopedEnum>::value));
if (std::is_signed<typename std::underlying_type<UnscopedEnum>::type>::value) {
if (sizeof(UnscopedEnum) > sizeof(char))
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<UnscopedEnum, signed char>::value));
else
QVERIFY(!(QtPrivate::AreArgumentsNarrowedBase<UnscopedEnum, signed char>::value));
if (sizeof(UnscopedEnum) > sizeof(short))
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<UnscopedEnum, short>::value));
else
QVERIFY(!(QtPrivate::AreArgumentsNarrowedBase<UnscopedEnum, short>::value));
QVERIFY(!(QtPrivate::AreArgumentsNarrowedBase<UnscopedEnum, int>::value));
QVERIFY(!(QtPrivate::AreArgumentsNarrowedBase<UnscopedEnum, long>::value));
QVERIFY(!(QtPrivate::AreArgumentsNarrowedBase<UnscopedEnum, long long>::value));
} else {
if (sizeof(UnscopedEnum) > sizeof(bool))
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<UnscopedEnum, bool>::value));
else
QVERIFY(!(QtPrivate::AreArgumentsNarrowedBase<UnscopedEnum, bool>::value));
if (sizeof(UnscopedEnum) > sizeof(char))
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<UnscopedEnum, unsigned char>::value));
else
QVERIFY(!(QtPrivate::AreArgumentsNarrowedBase<UnscopedEnum, unsigned char>::value));
if (sizeof(UnscopedEnum) > sizeof(short))
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<UnscopedEnum, unsigned short>::value));
else
QVERIFY(!(QtPrivate::AreArgumentsNarrowedBase<UnscopedEnum, unsigned short>::value));
QVERIFY(!(QtPrivate::AreArgumentsNarrowedBase<UnscopedEnum, unsigned int>::value));
QVERIFY(!(QtPrivate::AreArgumentsNarrowedBase<UnscopedEnum, unsigned long>::value));
QVERIFY(!(QtPrivate::AreArgumentsNarrowedBase<UnscopedEnum, unsigned long long>::value));
}
QVERIFY(std::is_signed<typename std::underlying_type<SignedUnscopedEnum>::type>::value);
if (sizeof(SignedUnscopedEnum) > sizeof(char))
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<SignedUnscopedEnum, signed char>::value));
else
QVERIFY(!(QtPrivate::AreArgumentsNarrowedBase<SignedUnscopedEnum, signed char>::value));
if (sizeof(SignedUnscopedEnum) > sizeof(short))
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<SignedUnscopedEnum, short>::value));
else
QVERIFY(!(QtPrivate::AreArgumentsNarrowedBase<SignedUnscopedEnum, short>::value));
QVERIFY(!(QtPrivate::AreArgumentsNarrowedBase<SignedUnscopedEnum, int>::value));
QVERIFY(!(QtPrivate::AreArgumentsNarrowedBase<SignedUnscopedEnum, long>::value));
QVERIFY(!(QtPrivate::AreArgumentsNarrowedBase<SignedUnscopedEnum, long long>::value));
enum class ScopedEnumBackedBySChar : signed char { A };
enum class ScopedEnumBackedByUChar : unsigned char { A };
enum class ScopedEnumBackedByShort : short { A };
enum class ScopedEnumBackedByUShort : unsigned short { A };
enum class ScopedEnumBackedByInt : int { A };
enum class ScopedEnumBackedByUInt : unsigned int { A };
enum class ScopedEnumBackedByLong : long { A };
enum class ScopedEnumBackedByULong : unsigned long { A };
enum class ScopedEnumBackedByLongLong : long long { A };
enum class ScopedEnumBackedByULongLong : unsigned long long { A };
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedBySChar, ScopedEnumBackedBySChar>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUChar, ScopedEnumBackedByUChar>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByShort, ScopedEnumBackedByShort>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUShort, ScopedEnumBackedByUShort>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByInt, ScopedEnumBackedByInt>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUInt, ScopedEnumBackedByUInt>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLong, ScopedEnumBackedByLong>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULong, ScopedEnumBackedByULong>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLongLong, ScopedEnumBackedByLongLong>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULongLong, ScopedEnumBackedByULongLong>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedBySChar, signed char>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUChar, unsigned char>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByShort, short>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUShort, unsigned short>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByInt, int>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUInt, unsigned int>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLong, long>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULong, unsigned long>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLongLong, long long>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULongLong, unsigned long long>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedBySChar, signed char>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedBySChar, short>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedBySChar, int>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedBySChar, long>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedBySChar, long long>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUChar, unsigned char>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUChar, unsigned short>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUChar, unsigned int>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUChar, unsigned long>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUChar, unsigned long long>::value));
if (sizeof(short) > sizeof(char)) {
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByShort, char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUShort, char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByInt, char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUInt, char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLong, char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULong, char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLongLong, char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULongLong, char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByShort, signed char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUShort, signed char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByInt, signed char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUInt, signed char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLong, signed char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULong, signed char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLongLong, signed char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULongLong, signed char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByShort, unsigned char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUShort, unsigned char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByInt, unsigned char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUInt, unsigned char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLong, unsigned char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULong, unsigned char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLongLong, unsigned char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULongLong, unsigned char>::value));
}
if (sizeof(int) > sizeof(short)) {
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByInt, short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUInt, short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLong, short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULong, short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLongLong, short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULongLong, short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByInt, unsigned short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUInt, unsigned short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLong, unsigned short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULong, unsigned short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLongLong, unsigned short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULongLong, unsigned short>::value));
}
if (sizeof(long) > sizeof(int)) {
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLong, int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULong, int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLongLong, int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULongLong, int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLong, unsigned int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULong, unsigned int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLongLong, unsigned int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULongLong, unsigned int>::value));
}
if (sizeof(long long) > sizeof(long)) {
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLongLong, long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULongLong, long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLongLong, unsigned long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULongLong, unsigned long>::value));
}
// different signedness of the underlying type
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<SignedUnscopedEnum, unsigned char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<SignedUnscopedEnum, unsigned short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<SignedUnscopedEnum, unsigned int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<SignedUnscopedEnum, unsigned long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<SignedUnscopedEnum, unsigned long long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedBySChar, unsigned char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedBySChar, unsigned short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedBySChar, unsigned int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedBySChar, unsigned long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedBySChar, unsigned long long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByShort, unsigned char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByShort, unsigned short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByShort, unsigned int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByShort, unsigned long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByShort, unsigned long long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByInt, unsigned char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByInt, unsigned short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByInt, unsigned int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByInt, unsigned long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByInt, unsigned long long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLong, unsigned char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLong, unsigned short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLong, unsigned int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLong, unsigned long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLong, unsigned long long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLongLong, unsigned char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLongLong, unsigned short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLongLong, unsigned int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLongLong, unsigned long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByLongLong, unsigned long long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUChar, signed char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUChar, short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUChar, int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUChar, long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUChar, long long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUShort, signed char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUShort, short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUShort, int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUShort, long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUShort, long long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUInt, signed char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUInt, short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUInt, int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUInt, long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByUInt, long long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULong, signed char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULong, short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULong, int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULong, long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULong, long long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULongLong, signed char>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULongLong, short>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULongLong, int>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULongLong, long>::value));
QVERIFY((QtPrivate::AreArgumentsNarrowedBase<ScopedEnumBackedByULongLong, long long>::value));
// other types which should be always unaffected
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<void *, void *>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<QString, QString>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<QString &, QString &>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<const QString &, const QString &>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<QObject, QObject>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<QObject *, QObject *>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<const QObject *, const QObject *>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<std::nullptr_t, std::nullptr_t>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<QString, QObject>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<QString, QVariant>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<QString, void *>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<QString, long long>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<bool, const QObject *&>::value));
QVERIFY((!QtPrivate::AreArgumentsNarrowedBase<int (*)(bool), void (QObject::*)()>::value));
}
// Test for QtPrivate::HasQ_OBJECT_Macro
Q_STATIC_ASSERT(QtPrivate::HasQ_OBJECT_Macro<tst_QObject>::Value);
Q_STATIC_ASSERT(!QtPrivate::HasQ_OBJECT_Macro<SiblingDeleter>::Value);