[Development] User-defined literals for QString (and QByteArray)

Giuseppe D'Angelo giuseppe.dangelo at kdab.com
Wed Mar 3 17:57:03 CET 2021


Howdy,

Il 03/03/21 16:53, Andrei Golubev ha scritto:
> Hello,
> 
> I've been now working for a while with literals that have to 
> (eventually) be converted to QString one way or another. While in 
> certain cases (e.g. myMsg == u"This is my message" or u"Hello, " + 
> world) character literals are handled neatly by some underlying 
> machinery, pure assignments just don't work well:
> 
> QString hello = u"Hello"; // oops, compilation error
> 
> There's an explicit ctor that accepts QChar*, but if you end up with it, 
> QString would allocate a memory to store whatever QChar* points to. Same 
> is true for QString::fromUtf16().

Assuming that you do want the allocation (as QString constructors all 
allocate), the reason why a QString(char16_t*) constructor does not 
exist, IIRC, is to keep our API upgradable from QString to QStringView. 
Say you have a function taking QString today, and tomorrow you realize 
it could do with QStringView, it would constitute a very annoying source 
break if you just called it with f(u"text") (call becomes ambiguous).

But you can also decide to call this plan off and add the relevant 
constructor.

> There's QStringView (and friends) which may aid you, but what if there's 
> a list of strings that is populated? QList<QStringView> is not really an 
> option if half of the strings are not literals. Then the next choice is 
> QStringList in which case you need to do QStringView::toString() - well, 
> bad luck, you end up allocating memory again.
> 
> There's of course QStringLiteral:
> QString hello = QStringLiteral("Hello"); // yay, it works
> ... and, actually, QStringLiteral in Qt 6 is great, because it doesn't 
> allocate the memory* to store that literal.

Wasn't it the same in Qt 5 as well?


> But writing "QStringLiteral" each time is a bit inconvenient: let's be 
> honest, it's a lot of code to type. You may want to write it once or 
> twice, but how about a fifty or a hundred times?
> 
> * unless you modify the resulting string, of course
> 
> ---
> Here's my proposal: let's introduce a user-defined literal [1] for 
> QString (and I volunteer to do it).

At least in Qt 5 this was really complicated and subject to compiler 
limitations. With the new implementation of QString in Qt 6 I guess this 
should be relatively easy to do?


> How this would look for a user: instead of typing 
> *QStringLiteral*("Hello") you would have something like *u*"Hello"*_q*. 
> And the new code of course behaves exactly like the QStringLiteral()

This is actually a very open question: should it behave like 
QStringLiteral (not allocate, payload in .rodata, etc.) or like 
QString's constructor (allocate)? For instance, if you know you're going 
to allocate immediately afterwards (say, you're using .arg()), then does 
the QStringLiteral strategy still make sense here?


> Well, to be good citizens, we probably need to scope the user-defined 
> literal (e.g. similarly to std::chrono_literals [2]). Given that, how 
> you would really write your code is similar to:
> 
> using namespace <whatever>; // done only once in a .cpp file
> u"Hello"_q; // "u" in front and suffix "_q" are written every time
> 
> This is the proposal in a nutshell. I'd like to have some feedback and 
> then some suggestions regarding:
> 
>   * Whether we want this for QByteArray as well (similarly to QString it
>     allows "from raw data" construction, but then it's not really a
>     string class, is it?)

I don't see the difference; we have QByteArrayLiteral, so a UDL for it 
also makes sense.


>   * What suffix to use: in the example above I used "_q", but maybe
>     "_qs" is better or something totally different

I'd go for _qs.


>   * How to call a namespace: I'd probably go with "QtLiterals" but
>     (looking at [2]) maybe there should be a richer hierarchy? For
>     example, "QtLiterals::StringLiterals", so that the suffix could be
>     reused without conflicts, etc.

Exactly:

> https://codereview.qt-project.org/c/qt/qtbase/+/191717/16/src/corelib/tools/qangle.h#562



>   * Whether *View classes need it (in theory they should allow implicit
>     construction, so probably not)

They don't need it. QStringViewLiteral was scrapped as soon as we could 
rely on MSVC doing the right thing for u"foo". String view should be 
implictly constructible from any contiguous range of char-like types.


Thanks,

-- 
Giuseppe D'Angelo | giuseppe.dangelo at kdab.com | Senior Software Engineer
KDAB (France) S.A.S., a KDAB Group company
Tel. France +33 (0)4 90 84 08 53, http://www.kdab.com
KDAB - The Qt, C++ and OpenGL Experts

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4329 bytes
Desc: Firma crittografica S/MIME
URL: <http://lists.qt-project.org/pipermail/development/attachments/20210303/d7359c39/attachment.bin>


More information about the Development mailing list