summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGiuseppe D'Angelo <[email protected]>2025-02-24 16:09:18 +0100
committerGiuseppe D'Angelo <[email protected]>2025-02-26 15:27:32 +0100
commit874be50e7b773698abf0b099b0b32a9cbb3cff2d (patch)
tree9a3e78e2d17fe6984f8264e732fadc3e838ce65b
parent04d17b2e229cee5e63596832b021c2316d9e4a05 (diff)
QStringView: introduce a user-defined literal operator
Although char16_t string literals implicitly convert to QStringView, there are corner-cases where one may want to explicitly create a QStringView out of them. A couple of examples I've found is where these string literals decay into pointers: // range is a std::initializer_list<const char16_t *> for (QStringView v : { u"foo", u"bar" }) { ... } // ternary will decay arguments void print(QStringView); print(check ? u"hi" : u"there"); When this happens the resulting code gets pessimized and polluted by runtime calls to qustrlen in order to build the QStringView objects [1]. We can restore optimal codegen by directly dealing with QStringView objects instead. Adding explicit conversions may make the code cumbersome to read, so I'm introducing a UDL for QStringView, matching the one for QString (and std::string_view). [1] for instance: https://gcc.godbolt.org/z/eY7xvEje3 Apply the new operator to a couple of places. [ChangeLog][QtCore][QStringView] Is it now possible to create QStringView objects by using the u""_sv user-defined literal. Fixes: QTBUG-123851 Change-Id: I8af7d2e211b356d284de160a222eab9e91d09500 Reviewed-by: Thiago Macieira <[email protected]>
-rw-r--r--src/corelib/ipc/qtipccommon.cpp2
-rw-r--r--src/corelib/text/qstringview.cpp40
-rw-r--r--src/corelib/text/qstringview.h11
-rw-r--r--src/widgets/styles/qcommonstyle.cpp2
-rw-r--r--tests/auto/corelib/text/qstringview/tst_qstringview.cpp23
5 files changed, 76 insertions, 2 deletions
diff --git a/src/corelib/ipc/qtipccommon.cpp b/src/corelib/ipc/qtipccommon.cpp
index 3d9a7281a00..355f6fbc602 100644
--- a/src/corelib/ipc/qtipccommon.cpp
+++ b/src/corelib/ipc/qtipccommon.cpp
@@ -200,7 +200,7 @@ QNativeIpcKey QtIpcCommon::platformSafeKey(const QString &key, QtIpcCommon::IpcT
QStringView prefix;
QStringView payload = key;
// see https://learn.microsoft.com/en-us/windows/win32/termserv/kernel-object-namespaces
- for (QStringView candidate : { u"Local\\", u"Global\\" }) {
+ for (QStringView candidate : { u"Local\\"_sv, u"Global\\"_sv }) {
if (!key.startsWith(candidate))
continue;
prefix = candidate;
diff --git a/src/corelib/text/qstringview.cpp b/src/corelib/text/qstringview.cpp
index 64d4ffc1f1d..923eed5539c 100644
--- a/src/corelib/text/qstringview.cpp
+++ b/src/corelib/text/qstringview.cpp
@@ -1496,4 +1496,44 @@ or the character \a ch
Returns maxSize().
*/
+/*!
+ \fn Qt::Literals::StringLiterals::operator""_sv(const char16_t *str, size_t size)
+
+ \relates QStringView
+ \since 6.10
+
+ Literal operator that creates a QStringView out of the first
+ \a size characters in the char16_t string literal \a str.
+
+ There is rarely need to explicitly construct a QStringView from a
+ char16_t string literal, as QStringView is implicitly constructible
+ from one:
+
+ \code
+ QStringView greeting = u"hello"; // OK even without _sv
+
+ void print(QStringView s);
+ print(u"world"); // OK even without _sv
+ \endcode
+
+ To use this operator, you need to be using the corresponding
+ namespace(s):
+
+ \code
+ using namespace Qt::Literals::StringLiterals;
+ auto sv = u"peace"_sv;
+ \endcode
+
+ Note that the returned QStringView will span over any NUL embedded
+ in the string literal. This is different from passing the string
+ literal to QStringView's constructor (explicitly or implicitly):
+
+ \code
+ QStringView sv1 = u"abc\0def"; // sv1 == "abc"
+ QStringView sv2 = u"abc\0def"_sv; // sv2 == "abc\0def"
+ \endcode
+
+ \sa Qt::Literals::StringLiterals
+*/
+
QT_END_NAMESPACE
diff --git a/src/corelib/text/qstringview.h b/src/corelib/text/qstringview.h
index 454dd1fdad9..abf57e0ac8c 100644
--- a/src/corelib/text/qstringview.h
+++ b/src/corelib/text/qstringview.h
@@ -512,6 +512,17 @@ qsizetype QtPrivate::findString(QStringView str, qsizetype from, QChar ch, Qt::C
return -1;
}
+namespace Qt {
+inline namespace Literals {
+inline namespace StringLiterals {
+constexpr QStringView operator""_sv(const char16_t *str, size_t size) noexcept
+{
+ return QStringView(str, qsizetype(size));
+}
+} // StringLiterals
+} // Literals
+} // Qt
+
QT_END_NAMESPACE
#endif /* QSTRINGVIEW_H */
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp
index 4f78c8d7072..a86964122ab 100644
--- a/src/widgets/styles/qcommonstyle.cpp
+++ b/src/widgets/styles/qcommonstyle.cpp
@@ -6071,7 +6071,7 @@ QIcon QCommonStylePrivate::iconFromResourceTheme(QCommonStyle::StandardPixmap st
addIconFiles(u"normalizedockup-", dockTitleIconSizes, icon);
break;
case QStyle::SP_ToolBarHorizontalExtensionButton:
- addIconFiles(rtl(option) ? u"toolbar-ext-h-rtl-" : u"toolbar-ext-h-", toolBarExtHSizes, icon);
+ addIconFiles(rtl(option) ? u"toolbar-ext-h-rtl-"_sv : u"toolbar-ext-h-"_sv, toolBarExtHSizes, icon);
break;
case QStyle::SP_ToolBarVerticalExtensionButton:
addIconFiles(u"toolbar-ext-v-", toolBarExtVSizes, icon);
diff --git a/tests/auto/corelib/text/qstringview/tst_qstringview.cpp b/tests/auto/corelib/text/qstringview/tst_qstringview.cpp
index 237abcc498d..aa470ac7991 100644
--- a/tests/auto/corelib/text/qstringview/tst_qstringview.cpp
+++ b/tests/auto/corelib/text/qstringview/tst_qstringview.cpp
@@ -287,6 +287,7 @@ private Q_SLOTS:
void tokenize() const;
void std_stringview_conversion();
+ void userDefinedLiterals();
private:
template <typename String>
@@ -974,5 +975,27 @@ void tst_QStringView::std_stringview_conversion()
QCOMPARE(sv, std::u16string_view(u"Hello\0world\0", 12));
}
+void tst_QStringView::userDefinedLiterals()
+{
+ using namespace Qt::StringLiterals;
+ auto sv = u"test"_sv;
+ static_assert(std::is_same_v<decltype(sv), QStringView>);
+
+ QCOMPARE(sv.size(), 4);
+ QCOMPARE(sv, "test");
+
+ sv = u""_sv;
+ QCOMPARE(sv.size(), 0);
+ QCOMPARE(sv, "");
+
+ sv = u"embedded\0nul"_sv;
+ QCOMPARE(sv.size(), 12);
+ QCOMPARE(sv, QStringView(u"embedded\0nul", 12));
+
+ constexpr auto csv = u"constexpr test"_sv;
+ static_assert(csv.size() == 14);
+ QCOMPARE(csv, "constexpr test");
+}
+
QTEST_APPLESS_MAIN(tst_QStringView)
#include "tst_qstringview.moc"