From 2021d3978dbceb92a94644cbbe35338cfd7281be Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 5 Dec 2024 10:25:32 +0100 Subject: [PATCH] QString::arg(): don't ignore signedness in (unscoped) enums std::is_signed doesn't work on enums. Instead of SFINAE'ing out for non-arithmetic types, it returns false. This changes the output of (unscoped) enums with signed underlying_type from signed to unsigned, compared to Qt 6.8. To fix, use an enum's underlying_type to determine signedness. This is complicated by the fact that std::underlying_type SFINAE's out (since C++20) or even constitutes UB (until C++17) when called on non-enums, so we have to be careful to limit the use of it to just enums, which we reach by passing the meta-function (underlying_type), not its result (underlying_type_t) to std::conditional and then calling he result. This requires the non-enum branch to be a meta-function, too (and not just a type), which is easily achieved using q20::type_identity. Use ::type::type instead of mixing _t and ::type to not confuse users (the leading `typename` is required, anyway, because at least one trailing ::type is required, and typename std::conditional_t looks wrong). Amends 563ed822f867c6c3040956017d4ca7f3795f172c. Fixes: QTBUG-131906 Change-Id: I6d122d5a48bffb1e09eb0d7841bb8f1f79cd882f Reviewed-by: Ivan Solovev Reviewed-by: Fabian Kosmale --- src/corelib/text/qstring.h | 7 ++++++- tests/auto/corelib/text/qstring/tst_qstring.cpp | 1 - 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/corelib/text/qstring.h b/src/corelib/text/qstring.h index a1d130c2b17..f3759718bc8 100644 --- a/src/corelib/text/qstring.h +++ b/src/corelib/text/qstring.h @@ -316,7 +316,12 @@ public: [[nodiscard]] QString arg(T a, int fieldWidth = 0, int base = 10, QChar fillChar = u' ') const { - if constexpr (std::is_signed_v) + using U = typename std::conditional< + // underlying_type_t is UB in C++17/SFINAE in C++20, so wrap: + std::is_enum_v, std::underlying_type, + q20::type_identity + >::type::type; + if constexpr (std::is_signed_v) return arg_impl(qlonglong(a), fieldWidth, base, fillChar); else return arg_impl(qulonglong(a), fieldWidth, base, fillChar); diff --git a/tests/auto/corelib/text/qstring/tst_qstring.cpp b/tests/auto/corelib/text/qstring/tst_qstring.cpp index 11e2232133d..d4a041a6c15 100644 --- a/tests/auto/corelib/text/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/text/qstring/tst_qstring.cpp @@ -6697,7 +6697,6 @@ void tst_QString::arg() // (unscoped) enums enum : int { FooS = -1 }; enum : uint { FooU = 1 }; - QEXPECT_FAIL("", "QTBUG-131906", Continue); // Qt 6.9 only QCOMPARE(s4.arg(FooS), QLatin1String("[-1]")); QCOMPARE(s4.arg(FooU), QLatin1String("[1]"));