[Development] RFC: Proposal for a semi-radical change in Qt APIs taking strings

Marc Mutz marc.mutz at kdab.com
Tue Oct 13 22:46:36 CEST 2015


Hi,

After looking quite a bit into the current state of string handling in Qt for 
my QtWS talk last week, I have become frustrated by the state of string 
handling in Qt.

We have such powerful tools for string handling (QStringRef, QStringBuilder), 
but all APIs outside QString and its immediate surroundings only deal in 
QString. The correct way would be to overload every function taking QString 
with QLatin1String and QStringRef versions, and then, for some other rare 
cases, const QChar *, int size. Let alone std::basic_string<char16_t>.

I would therefore like to propose to abandon QString for new API (and over 
time phase it out of existing API), and only provide (const QChar*, size_t) as 
the most general form. I would propose to package the two into a class, called 
- you guessed it - QStringView.

=FAQ=

Q: Why not just use QStringRef?

A: QStringRef is tied to QString. E.g. you can't create a QStringRef from a 
pair of QChar*, int. It also is kind of stuck in historic mistakes making it 
undesireable as a cheap-to-pass parameter type.

Q: What mistakes do you refer to?

A: The fact that it has copy ctor and assignment operator, so it's not a 
trivally-copyable type and thus cannot efficiently passed by-value. It may also 
be too large for pass-by-value due to the rather useless QString pointer 
(should have been QStringData*, if any). Neither can be fixed before Qt 6.

Q: Why size_t?

A: The intent of QStringView (and std::experimental::string_view) is to act as 
an interface between modules written with different compilers and different 
flags. A std::string will never be compatible between compilers or even just 
different flags, but a simple struct {char*, size_t} will always be, by way of 
it's C compatibility.

So the goal is not just to accept QString, QStringRef, and (QChar*,int) (and 
QVarLengthArray<QChar>!) as input to QStringView, but also 
std::basic_string<char16_t> and std::vector<char16_t>.

Q: What about the plans to make QString UTF-8-backed?

A: QStringView-using code will need to be ported just as QString-using code 
will.

Q: What future do you have in mind for QStringRef?

A: None in particular, though I have found a need for an owning QStringRef in 
some places. But I expect Qt 6' QString to be able to provide a restricted 
view on shared data, such that it would subsume QStringRef completely.

Q: What about QLatin1String?

A: Once QString is backed by UTF-8, latin-1 ceases to be a special charset. We 
might want something like QUsAsciiString, but it would just be a UTF-8 string, 
so it could be packed into QStringView.

Q: What about QByteArray, QVector?

A: I'm unsure about QByteArrayView. It might not pull its weight compared to 
std::(experimental::)string_view, but I also note that we're currently missing 
a QByteArrayRef, so a QBAView might make sense while we wait for the std one 
to become available to us.

I'm actively opposed to a QArrayView, because I don't think it provides us 
with anything std::(experimental::)array_view doesn't already.

Q: What about a rope?

A: A rope is a more complex string that can provide complex views on existing 
data as well as store rules for generating stretches of data (as opposed to 
the data itself).

A rope is a very complex data structure and would not work as a universal 
interface type. It would be cool if Qt had a rope, but that is outside the 
scope of my proposal.

Q: What do you mean when you say "abandon QString"?

A: I mean that functions should not take QStrings as arguments, but 
QStringViews. Then users can transparently pass QString, QStringRef and any of 
a number of other "string" types without overloading the function on each of 
them.

I do not mean to abandon QString, the class. Only QString, the interface type.

Q: What API should QStringView have?

A: Since it's mainly an interface type, it should have implicit conversions 
from all kinds of "string" types, but explicit conversion _to_ those string 
types. It should carry all the API from QString that can be implemented on 
just a (QChar*, size_t) (e.g. trimmed(), left(), mid(), section(), split(), 
but not append(), replace() (except maybe the (QChar,QChar) overload. 
Corresponding QString/Ref API could (eventually) just forward to the 
QStringView one.

Thanks, now fire away,
Marc

-- 
Marc Mutz <marc.mutz at kdab.com> | Senior Software Engineer
KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company
Tel: +49-30-521325470
KDAB - The Qt Experts



More information about the Development mailing list