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

Reply via email to