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 <thiago.macieira@intel.com>
This commit is contained in:
parent
04d17b2e22
commit
874be50e7b
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user