On 12/05/2020 17.21, Thiago Macieira wrote:
On Tuesday, 12 May 2020 08:42:28 PDT Matthew Woehlke wrote:
How will this work? As I understand, the main advantage to
QStringLiteral is that it statically encodes the *length* as well as the
data. This isn't possible with raw literals, which are merely
NUL-terminated.
Black magic!
I mean, templates and constexpr.
Yeah... I'm not sure what I was thinking when I wrote that...
Oh, wait...
I don't see us ever getting rid of some form of QString
literal short of templatizing *everything* that takes a T* (for T in
char, char16_t, etc.) to take a T(&)[N] instead.
...I was thinking this. You might be able to escape this for methods
that don't take both QString *and* QStringView. Otherwise, well, see my
later message on that point.
And on that note...
But QStringView(u"foo") should call that first constructor. Doesn't it? I
never remember if the literal decays to pointer before the overload
resolution.
Uh... no, actually it doesn't. (Which TBH smells a bit like a defect to
me, but we're stuck with it for now.)
Note: https://godbolt.org/z/FbjQkM
(That was experimenting with QString/QStringView overload
disambiguation, but also includes the relevant ctors. Comment out the
templated overload of `foo` and one of the others, and you'll see that
the invocation with a literal calls the "wrong" ctor.)
So, we either need to retain literals in some form, or, as I was saying,
every method needs to have a templated flavor for string literals.
The "nice" thing about QStringView is that it does not have ownership;
you have to be careful about how long you hold onto it lest it turn into
a dangling pointer. You can't construct a QString from any old bag of
byt^Wcharacters because a QString is implicitly valid until it is destroyed.
That's the problem we've had with QStringLiteral and QString::fromRawData().
You *can* create it from read-only data and tell it never to try to modify.
The trick is guaranteeing that it remains valid until the last user finished
using it. Because of copy-on-write, that last user can be much later than the
statement that created the QString in the first place.
Right, but if you're using QStringLiteral / QString::fromRawData, you
"know" you're taking on that responsibility. (And for QStringLiteral,
you only run into problems in some instances with library unloading,
which is a non-issue for many applications.)
What I worry about with trying to avoid QStringView is that we either
lose the ability to avoid copies when the input is a *temporary* (e.g.
stack-allocated) buffer, or else we silently accept such uses and
produce broken programs.
Note that you can't rely on adding non-const overloads as a work-around;
the string might be coming from an intermediate function that doesn't
have a non-const overload, but was called with a (non-const) temporary
buffer.
Example:
void foo(char const* s)
{
...
method_taking_qt_string(s);
...
}
void bar()
{
char buffer[MAX_SIZE];
...do stuff to put data in buffer...
foo(buffer);
}
Non-owning QString is dangerous. QStringLiteral is less dangerous
because it is almost never used with non-rodata storage (and indeed, I
would consider any such usage highly suspect, if not outright broken).
QString::fromRawData is dangerous, but "obviously" so.
We should not implement any way of creating a non-owning QString that is
not explicit, and if we adhere to that, I don't see us *not* wanting
QStringView in many instances.
--
Matthew
_______________________________________________
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development