diff options
-rw-r--r-- | src/corelib/kernel/qobjectdefs_impl.h | 77 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qobject/tst_qobject.cpp | 268 |
2 files changed, 94 insertions, 251 deletions
diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h index aed50d6c5a..0624dd2584 100644 --- a/src/corelib/kernel/qobjectdefs_impl.h +++ b/src/corelib/kernel/qobjectdefs_impl.h @@ -257,55 +257,32 @@ 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 - { - }; - + // Traits to detect if there is a conversion between two types, + // and that conversion does not include a narrowing conversion. template <typename T> - using is_bool = std::is_same<bool, typename std::decay<T>::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_pointer<From>::value || std::is_member_pointer<From>::value) && QtPrivate::is_bool<To>::value) || - ((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_signed<To>::value && sizeof(From) == sizeof(To))))) || - (std::is_enum<From>::value && std::is_integral<To>::value - && (sizeof(From) > sizeof(To) - || (IsEnumUnderlyingTypeSigned<From>::value ? !std::is_signed<To>::value - : (std::is_signed<To>::value && sizeof(From) == sizeof(To))))) - > - { - }; + struct NarrowingDetector { T t[1]; }; // from P0608 + + template <typename From, typename To, typename Enable = void> + struct IsConvertibleWithoutNarrowing : std::false_type {}; + + template <typename From, typename To> + struct IsConvertibleWithoutNarrowing<From, To, + std::void_t< decltype( NarrowingDetector<To>{ {std::declval<From>()} } ) > + > : std::true_type {}; + + // Check for the actual arguments. If they are exactly the same, + // then don't bother checking for narrowing; as a by-product, + // this solves the problem of incomplete types (which must be supported, + // or they would error out in the trait above). + template <typename From, typename To, typename Enable = void> + struct AreArgumentsConvertibleWithoutNarrowingBase : std::false_type {}; + + template <typename From, typename To> + struct AreArgumentsConvertibleWithoutNarrowingBase<From, To, + std::enable_if_t< + std::disjunction_v<std::is_same<From, To>, IsConvertibleWithoutNarrowing<From, To>> + > + > : std::true_type {}; /* Logic that check if the arguments of the slot matches the argument of the signal. @@ -318,8 +295,8 @@ namespace QtPrivate { static const typename RemoveRef<A1>::Type &dummy(); enum { value = sizeof(test(dummy())) == sizeof(int) }; #ifdef QT_NO_NARROWING_CONVERSIONS_IN_CONNECT - using AreArgumentsNarrowed = AreArgumentsNarrowedBase<typename RemoveRef<A1>::Type, typename RemoveRef<A2>::Type>; - Q_STATIC_ASSERT_X(!AreArgumentsNarrowed::value, "Signal and slot arguments are not compatible (narrowing)"); + using AreArgumentsConvertibleWithoutNarrowing = AreArgumentsConvertibleWithoutNarrowingBase<std::decay_t<A1>, std::decay_t<A2>>; + Q_STATIC_ASSERT_X(AreArgumentsConvertibleWithoutNarrowing::value, "Signal and slot arguments are not compatible (narrowing)"); #endif }; template<typename A1, typename A2> struct AreArgumentsCompatible<A1, A2&> { enum { value = false }; }; diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index 05599f9585..b977761995 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -6967,14 +6967,13 @@ void tst_QObject::mutableFunctor() void tst_QObject::checkArgumentsForNarrowing() { - enum UnscopedEnum {}; - enum SignedUnscopedEnum { SignedUnscopedEnumV1 = -1, SignedUnscopedEnumV2 = 1 }; + enum UnscopedEnum { UnscopedEnumV1 = INT_MAX, UnscopedEnumV2 }; + enum SignedUnscopedEnum { SignedUnscopedEnumV1 = INT_MIN, SignedUnscopedEnumV2 = INT_MAX }; - // a constexpr would suffice, but MSVC2013 RTM doesn't support them... -#define IS_UNSCOPED_ENUM_SIGNED (std::is_signed<typename std::underlying_type<UnscopedEnum>::type>::value) + static constexpr bool IsUnscopedEnumSigned = std::is_signed_v<std::underlying_type_t<UnscopedEnum>>; -#define NARROWS_IF(x, y, test) Q_STATIC_ASSERT((QtPrivate::AreArgumentsNarrowedBase<x, y>::value) == (test)) -#define FITS_IF(x, y, test) Q_STATIC_ASSERT((QtPrivate::AreArgumentsNarrowedBase<x, y>::value) != (test)) +#define NARROWS_IF(x, y, test) Q_STATIC_ASSERT((QtPrivate::AreArgumentsConvertibleWithoutNarrowingBase<x, y>::value) != (test)) +#define FITS_IF(x, y, test) Q_STATIC_ASSERT((QtPrivate::AreArgumentsConvertibleWithoutNarrowingBase<x, y>::value) == (test)) #define NARROWS(x, y) NARROWS_IF(x, y, true) #define FITS(x, y) FITS_IF(x, y, true) @@ -6982,9 +6981,14 @@ void tst_QObject::checkArgumentsForNarrowing() Q_STATIC_ASSERT(sizeof(SignedUnscopedEnum) <= sizeof(int)); // floating point to integral + + // GCC < 9 does not consider floating point to bool to be narrowing, + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65043 +#if !defined(Q_CC_GNU) || Q_CC_GNU >= 900 NARROWS(float, bool); NARROWS(double, bool); NARROWS(long double, bool); +#endif NARROWS(float, char); NARROWS(double, char); @@ -7008,12 +7012,19 @@ void tst_QObject::checkArgumentsForNarrowing() // floating point to a smaller floating point - NARROWS_IF(double, float, (sizeof(double) > sizeof(float))); - NARROWS_IF(long double, float, (sizeof(long double) > sizeof(float))); + NARROWS(double, float); + NARROWS(long double, float); FITS(float, double); FITS(float, long double); - NARROWS_IF(long double, double, (sizeof(long double) > sizeof(double))); + // GCC thinks this is narrowing only on architectures where + // sizeof(long double) > sizeof(double) + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92856 +#if defined(Q_CC_GNU) + NARROWS_IF(long double, double, sizeof(long double) > sizeof(double)); +#else + NARROWS(long double, double); +#endif FITS(double, long double); @@ -7202,21 +7213,21 @@ void tst_QObject::checkArgumentsForNarrowing() FITS(UnscopedEnum, UnscopedEnum); FITS(SignedUnscopedEnum, SignedUnscopedEnum); - NARROWS_IF(UnscopedEnum, char, ((sizeof(UnscopedEnum) > sizeof(char)) || (sizeof(UnscopedEnum) == sizeof(char) && IS_UNSCOPED_ENUM_SIGNED == std::is_signed<char>::value))); - NARROWS_IF(UnscopedEnum, signed char, ((sizeof(UnscopedEnum) > sizeof(char)) || (sizeof(UnscopedEnum) == sizeof(char) && !IS_UNSCOPED_ENUM_SIGNED))); - NARROWS_IF(UnscopedEnum, unsigned char, ((sizeof(UnscopedEnum) > sizeof(char)) || IS_UNSCOPED_ENUM_SIGNED)); + NARROWS_IF(UnscopedEnum, char, ((sizeof(UnscopedEnum) > sizeof(char)) || (sizeof(UnscopedEnum) == sizeof(char) && IsUnscopedEnumSigned == std::is_signed<char>::value))); + NARROWS_IF(UnscopedEnum, signed char, ((sizeof(UnscopedEnum) > sizeof(char)) || (sizeof(UnscopedEnum) == sizeof(char) && !IsUnscopedEnumSigned))); + NARROWS_IF(UnscopedEnum, unsigned char, ((sizeof(UnscopedEnum) > sizeof(char)) || IsUnscopedEnumSigned)); - NARROWS_IF(UnscopedEnum, short, ((sizeof(UnscopedEnum) > sizeof(short)) || (sizeof(UnscopedEnum) == sizeof(short) && !IS_UNSCOPED_ENUM_SIGNED))); - NARROWS_IF(UnscopedEnum, unsigned short, ((sizeof(UnscopedEnum) > sizeof(short)) || IS_UNSCOPED_ENUM_SIGNED)); + NARROWS_IF(UnscopedEnum, short, ((sizeof(UnscopedEnum) > sizeof(short)) || (sizeof(UnscopedEnum) == sizeof(short) && !IsUnscopedEnumSigned))); + NARROWS_IF(UnscopedEnum, unsigned short, ((sizeof(UnscopedEnum) > sizeof(short)) || IsUnscopedEnumSigned)); - NARROWS_IF(UnscopedEnum, int, (sizeof(UnscopedEnum) == sizeof(int) && !IS_UNSCOPED_ENUM_SIGNED)); - NARROWS_IF(UnscopedEnum, unsigned int, IS_UNSCOPED_ENUM_SIGNED); + NARROWS_IF(UnscopedEnum, int, sizeof(UnscopedEnum) > sizeof(int) || (sizeof(UnscopedEnum) == sizeof(int) && !IsUnscopedEnumSigned)); + NARROWS_IF(UnscopedEnum, unsigned int, IsUnscopedEnumSigned); - NARROWS_IF(UnscopedEnum, long, (sizeof(UnscopedEnum) == sizeof(long) && !IS_UNSCOPED_ENUM_SIGNED)); - NARROWS_IF(UnscopedEnum, unsigned long, IS_UNSCOPED_ENUM_SIGNED); + NARROWS_IF(UnscopedEnum, long, sizeof(UnscopedEnum) > sizeof(long) || (sizeof(UnscopedEnum) == sizeof(long) && !IsUnscopedEnumSigned)); + NARROWS_IF(UnscopedEnum, unsigned long, IsUnscopedEnumSigned); - NARROWS_IF(UnscopedEnum, long long, (sizeof(UnscopedEnum) == sizeof(long long) && !IS_UNSCOPED_ENUM_SIGNED)); - NARROWS_IF(UnscopedEnum, unsigned long long, IS_UNSCOPED_ENUM_SIGNED); + NARROWS_IF(UnscopedEnum, long long, sizeof(UnscopedEnum) > sizeof(long long) || (sizeof(UnscopedEnum) == sizeof(long long) && !IsUnscopedEnumSigned)); + NARROWS_IF(UnscopedEnum, unsigned long long, IsUnscopedEnumSigned); Q_STATIC_ASSERT(std::is_signed<typename std::underlying_type<SignedUnscopedEnum>::type>::value); @@ -7226,203 +7237,58 @@ void tst_QObject::checkArgumentsForNarrowing() FITS(SignedUnscopedEnum, long); FITS(SignedUnscopedEnum, long long); - - 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 }; - - FITS(ScopedEnumBackedBySChar, ScopedEnumBackedBySChar); - FITS(ScopedEnumBackedByUChar, ScopedEnumBackedByUChar); - FITS(ScopedEnumBackedByShort, ScopedEnumBackedByShort); - FITS(ScopedEnumBackedByUShort, ScopedEnumBackedByUShort); - FITS(ScopedEnumBackedByInt, ScopedEnumBackedByInt); - FITS(ScopedEnumBackedByUInt, ScopedEnumBackedByUInt); - FITS(ScopedEnumBackedByLong, ScopedEnumBackedByLong); - FITS(ScopedEnumBackedByULong, ScopedEnumBackedByULong); - FITS(ScopedEnumBackedByLongLong, ScopedEnumBackedByLongLong); - FITS(ScopedEnumBackedByULongLong, ScopedEnumBackedByULongLong); - - FITS(ScopedEnumBackedBySChar, signed char); - FITS(ScopedEnumBackedByUChar, unsigned char); - FITS(ScopedEnumBackedByShort, short); - FITS(ScopedEnumBackedByUShort, unsigned short); - FITS(ScopedEnumBackedByInt, int); - FITS(ScopedEnumBackedByUInt, unsigned int); - FITS(ScopedEnumBackedByLong, long); - FITS(ScopedEnumBackedByULong, unsigned long); - FITS(ScopedEnumBackedByLongLong, long long); - FITS(ScopedEnumBackedByULongLong, unsigned long long); - - FITS(ScopedEnumBackedBySChar, signed char); - FITS(ScopedEnumBackedBySChar, short); - FITS(ScopedEnumBackedBySChar, int); - FITS(ScopedEnumBackedBySChar, long); - FITS(ScopedEnumBackedBySChar, long long); - - FITS(ScopedEnumBackedByUChar, unsigned char); - FITS(ScopedEnumBackedByUChar, unsigned short); - FITS(ScopedEnumBackedByUChar, unsigned int); - FITS(ScopedEnumBackedByUChar, unsigned long); - FITS(ScopedEnumBackedByUChar, unsigned long long); - - NARROWS_IF(ScopedEnumBackedByShort, char, (sizeof(short) > sizeof(char) || std::is_unsigned<char>::value)); - NARROWS_IF(ScopedEnumBackedByUShort, char, (sizeof(short) > sizeof(char) || std::is_signed<char>::value)); - NARROWS_IF(ScopedEnumBackedByInt, char, (sizeof(int) > sizeof(char) || std::is_unsigned<char>::value)); - NARROWS_IF(ScopedEnumBackedByUInt, char, (sizeof(int) > sizeof(char) || std::is_signed<char>::value)); - NARROWS_IF(ScopedEnumBackedByLong, char, (sizeof(long) > sizeof(char) || std::is_unsigned<char>::value)); - NARROWS_IF(ScopedEnumBackedByULong, char, (sizeof(long) > sizeof(char) || std::is_signed<char>::value)); - NARROWS_IF(ScopedEnumBackedByLongLong, char, (sizeof(long long) > sizeof(char) || std::is_unsigned<char>::value)); - NARROWS_IF(ScopedEnumBackedByULongLong, char, (sizeof(long long) > sizeof(char) || std::is_signed<char>::value)); - - NARROWS_IF(ScopedEnumBackedByShort, signed char, (sizeof(short) > sizeof(char))); - NARROWS(ScopedEnumBackedByUShort, signed char); - NARROWS_IF(ScopedEnumBackedByInt, signed char, (sizeof(int) > sizeof(char))); - NARROWS(ScopedEnumBackedByUInt, signed char); - NARROWS_IF(ScopedEnumBackedByLong, signed char, (sizeof(long) > sizeof(char))); - NARROWS(ScopedEnumBackedByULong, signed char); - NARROWS_IF(ScopedEnumBackedByLongLong, signed char, (sizeof(long long) > sizeof(char))); - NARROWS(ScopedEnumBackedByULongLong, signed char); - - NARROWS(ScopedEnumBackedByShort, unsigned char); - NARROWS_IF(ScopedEnumBackedByUShort, unsigned char, (sizeof(short) > sizeof(char))); - NARROWS(ScopedEnumBackedByInt, unsigned char); - NARROWS_IF(ScopedEnumBackedByUInt, unsigned char, (sizeof(int) > sizeof(char))); - NARROWS(ScopedEnumBackedByLong, unsigned char); - NARROWS_IF(ScopedEnumBackedByULong, unsigned char, (sizeof(long) > sizeof(char))); - NARROWS(ScopedEnumBackedByLongLong, unsigned char); - NARROWS_IF(ScopedEnumBackedByULongLong, unsigned char, (sizeof(long long) > sizeof(char))); - - NARROWS_IF(ScopedEnumBackedByInt, short, (sizeof(int) > sizeof(short))); - NARROWS(ScopedEnumBackedByUInt, short); - NARROWS_IF(ScopedEnumBackedByLong, short, (sizeof(long) > sizeof(short))); - NARROWS(ScopedEnumBackedByULong, short); - NARROWS_IF(ScopedEnumBackedByLongLong, short, (sizeof(long long) > sizeof(short))); - NARROWS(ScopedEnumBackedByULongLong, short); - - NARROWS(ScopedEnumBackedByInt, unsigned short); - NARROWS_IF(ScopedEnumBackedByUInt, unsigned short, (sizeof(int) > sizeof(short))); - NARROWS(ScopedEnumBackedByLong, unsigned short); - NARROWS_IF(ScopedEnumBackedByULong, unsigned short, (sizeof(long) > sizeof(short))); - NARROWS(ScopedEnumBackedByLongLong, unsigned short); - NARROWS_IF(ScopedEnumBackedByULongLong, unsigned short, (sizeof(long long) > sizeof(short))); - - NARROWS_IF(ScopedEnumBackedByLong, int, (sizeof(long) > sizeof(int))); - NARROWS(ScopedEnumBackedByULong, int); - NARROWS_IF(ScopedEnumBackedByLongLong, int, (sizeof(long long) > sizeof(int))); - NARROWS(ScopedEnumBackedByULongLong, int); - - NARROWS(ScopedEnumBackedByLong, unsigned int); - NARROWS_IF(ScopedEnumBackedByULong, unsigned int, (sizeof(long) > sizeof(int))); - NARROWS(ScopedEnumBackedByLongLong, unsigned int); - NARROWS_IF(ScopedEnumBackedByULongLong, unsigned int, (sizeof(long long) > sizeof(int))); - - NARROWS_IF(ScopedEnumBackedByLongLong, long, (sizeof(long long) > sizeof(long))); - NARROWS(ScopedEnumBackedByULongLong, long); - - NARROWS(ScopedEnumBackedByLongLong, unsigned long); - NARROWS_IF(ScopedEnumBackedByULongLong, unsigned long, (sizeof(long long) > sizeof(long))); - - // different signedness of the underlying type - NARROWS(SignedUnscopedEnum, unsigned char); - NARROWS(SignedUnscopedEnum, unsigned short); - NARROWS(SignedUnscopedEnum, unsigned int); - NARROWS(SignedUnscopedEnum, unsigned long); - NARROWS(SignedUnscopedEnum, unsigned long long); - - NARROWS(ScopedEnumBackedBySChar, unsigned char); - NARROWS(ScopedEnumBackedBySChar, unsigned short); - NARROWS(ScopedEnumBackedBySChar, unsigned int); - NARROWS(ScopedEnumBackedBySChar, unsigned long); - NARROWS(ScopedEnumBackedBySChar, unsigned long long); - - NARROWS(ScopedEnumBackedByShort, unsigned char); - NARROWS(ScopedEnumBackedByShort, unsigned short); - NARROWS(ScopedEnumBackedByShort, unsigned int); - NARROWS(ScopedEnumBackedByShort, unsigned long); - NARROWS(ScopedEnumBackedByShort, unsigned long long); - - NARROWS(ScopedEnumBackedByInt, unsigned char); - NARROWS(ScopedEnumBackedByInt, unsigned short); - NARROWS(ScopedEnumBackedByInt, unsigned int); - NARROWS(ScopedEnumBackedByInt, unsigned long); - NARROWS(ScopedEnumBackedByInt, unsigned long long); - - NARROWS(ScopedEnumBackedByLong, unsigned char); - NARROWS(ScopedEnumBackedByLong, unsigned short); - NARROWS(ScopedEnumBackedByLong, unsigned int); - NARROWS(ScopedEnumBackedByLong, unsigned long); - NARROWS(ScopedEnumBackedByLong, unsigned long long); - - NARROWS(ScopedEnumBackedByLongLong, unsigned char); - NARROWS(ScopedEnumBackedByLongLong, unsigned short); - NARROWS(ScopedEnumBackedByLongLong, unsigned int); - NARROWS(ScopedEnumBackedByLongLong, unsigned long); - NARROWS(ScopedEnumBackedByLongLong, unsigned long long); - - NARROWS(ScopedEnumBackedByUChar, signed char); - FITS_IF(ScopedEnumBackedByUChar, short, (sizeof(char) < sizeof(short))); - FITS_IF(ScopedEnumBackedByUChar, int, (sizeof(char) < sizeof(int))); - FITS_IF(ScopedEnumBackedByUChar, long, (sizeof(char) < sizeof(long))); - FITS_IF(ScopedEnumBackedByUChar, long long, (sizeof(char) < sizeof(long long))); - - NARROWS(ScopedEnumBackedByUShort, signed char); - NARROWS(ScopedEnumBackedByUShort, short); - FITS_IF(ScopedEnumBackedByUShort, int, (sizeof(short) < sizeof(int))); - FITS_IF(ScopedEnumBackedByUShort, long, (sizeof(short) < sizeof(long))); - FITS_IF(ScopedEnumBackedByUShort, long long, (sizeof(short) < sizeof(long long))); - - NARROWS(ScopedEnumBackedByUInt, signed char); - NARROWS(ScopedEnumBackedByUInt, short); - NARROWS(ScopedEnumBackedByUInt, int); - FITS_IF(ScopedEnumBackedByUInt, long, (sizeof(ScopedEnumBackedByUInt) < sizeof(long))); - FITS(ScopedEnumBackedByUInt, long long); - - NARROWS(ScopedEnumBackedByULong, signed char); - NARROWS(ScopedEnumBackedByULong, short); - NARROWS(ScopedEnumBackedByULong, int); - NARROWS(ScopedEnumBackedByULong, long); - FITS_IF(ScopedEnumBackedByULong, long long, (sizeof(ScopedEnumBackedByULong) < sizeof(long long))); - - NARROWS(ScopedEnumBackedByULongLong, signed char); - NARROWS(ScopedEnumBackedByULongLong, short); - NARROWS(ScopedEnumBackedByULongLong, int); - NARROWS(ScopedEnumBackedByULongLong, long); - NARROWS(ScopedEnumBackedByULongLong, long long); - // other types which should be always unaffected FITS(void *, void *); FITS(QString, QString); - FITS(QString &, QString &); - FITS(const QString &, const QString &); - FITS(QObject, QObject); FITS(QObject *, QObject *); FITS(const QObject *, const QObject *); FITS(std::nullptr_t, std::nullptr_t); - FITS(QString, QObject); - FITS(QString, QVariant); - FITS(QString, void *); - FITS(QString, long long); - FITS(bool, const QObject *&); - FITS(int (*)(bool), void (QObject::*)()); + // classes with conversion operators undergoing implicit conversions + struct ConvertingToDouble { + /* implicit */ operator double() const { return 42.0; } + }; + + NARROWS(ConvertingToDouble, char); + NARROWS(ConvertingToDouble, short); + NARROWS(ConvertingToDouble, int); + NARROWS(ConvertingToDouble, long); + NARROWS(ConvertingToDouble, long long); + NARROWS(ConvertingToDouble, float); + FITS(ConvertingToDouble, double); + FITS(ConvertingToDouble, long double); + + // no compiler still implements this properly. +#if 0 + struct ConstructibleFromInt { + /* implicit */ ConstructibleFromInt(int) {} + }; + + FITS(char, ConstructibleFromInt); + FITS(short, ConstructibleFromInt); + FITS(int, ConstructibleFromInt); + NARROWS(unsigned int, ConstructibleFromInt); + NARROWS_IF(long, ConstructibleFromInt, sizeof(long) > sizeof(int)); + NARROWS_IF(long long, ConstructibleFromInt, sizeof(long long) > sizeof(int)); + NARROWS(float, ConstructibleFromInt); + NARROWS(double, ConstructibleFromInt); +#endif + + // forward declared classes must work + class ForwardDeclared; + FITS(ForwardDeclared, ForwardDeclared); + +#if 0 // waiting for official compiler releases that implement P1957... { // wg21.link/P1957 NARROWS(char*, bool); NARROWS(void (QObject::*)(), bool); } - -#undef IS_UNSCOPED_ENUM_SIGNED +#endif #undef NARROWS_IF #undef FITS_IF |