[Development] Wishes for C++ standard or compilers

Olivier Goffart olivier at woboq.com
Sun Mar 19 10:24:56 CET 2017


On Samstag, 18. März 2017 22:20:49 CET Thiago Macieira wrote:
> Ville asked what would be nice to have, so I put together a list:
> 
> == SD-6 feature macros ==
> We made a decision not to add Q_COMPILER_xxx macros in Qt past C++11, and
> only depend on the ones from the standard. But there are several problems
> there:
> 
> * some compilers don't have them at all (MSVC). Our current answer is "if
> you don't #define them, they don't exist" and therefore for us, MSVC has
> zero C++14 features.
> 
> * some macros exist but are insufficient, as there are often bugs in
> implementations. 

Well, bugs are bugs. That's not intentional. Sometimes they are known in 
advance, sometimes not. But the standard can't do anything about that.


> You can see in qcompilerdetection.h where we've noted a
> feature being available in a compiler version further than where the
> compiler vendor said it is available (like GCC initializer_list, MSVC
> constexpr). If we use only what the compiler vendor claims, we may run into
> bugs.

But don't think it's wise for a feature to be disabled entierly only because 
of a bug in a edge case.  For example, on QNX, Q_COMPILER_UNICODE_STRINGS is 
disabled despite char16_t is there. And so one.

> * some features are only marked by __has_include, which sometimes isn't
> sufficient as the header is present by fails to compile.
> 
> == QString, QStringView, QByteArray ==
> 
> I've been thinking for the past 5 years what QString would look like then
> and how to avoid emitting atomic detaching code all over the place while
> not abandoning implicit sharing. I have some unfinished ideas I can share
> at a later time (glimpse given in the other thread).
> 
> There's a question of whether QString should change encoding. I feel that
> it's simply not possible to change this, ever.

Yes, depending what level of compatibility Qt6 want to keep. 

> In terms of what we'd need from the standard for UTF-16? Not much. Quite
> frankly, if the standard library sucks when it comes to Unicode, it's to
> Qt's benefit. As a former colleague of ours said some 10 years ago when we
> found QString symbols inside an application from a major OS vendor, "world
> domination starts with QString".
> 
> == Containers ==
> 
> And then there's what to do with the containers. Here's where Marc's opinion
> and mine differ considerably. Aside from the need to maintain source
> compatibility, I feel like we should keep our containers and keep implicit
> sharing (same solution as for QString). We know COW can be a pessimisation
> for performance-sentive code, but the question is whether it is so for
> regular developers who don't know how to write performance-sensitive code.
> If developers will make mistakes, can we reduce the impact?

Yes, cow is quite convenient in some cases.

> == Misc ==
> 
> Off the top of my head, here are some things. Not all of these will be
> standards things, but might be compiler-specific.
> 
> * better support for the Qt way of atomic implicitly-sharing. Specifically,
> that when the refcount is 1, the refcount stays at 1 unless the function in
> question increments it or calls a non-const function.
> Maybe this is about pre- and post-conditions? See
>   http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0542r0.html
> 
> * really const: The following reloads the s.i:
>         struct S
>         {
>           int i;
>           void f() const;
>         };
> 
>         void f(const S &);
>         int f()
>         {
>                 S s = { 0 };
>                 f(s);
>                 return s.i;
>         }
> https://godbolt.org/g/qaR9KU
> 
> Or, identically:
>         int f()
>         {
>                 S s = { 0 };
>                 s.f();
>                 return s.i;
>         }
> 
> This has a lot of impacts in the QString, QByteArray and the containers,
> since they have out-of-line functions. So, can we have a way to do "really
> const"?
> 
> Is that [[pure]] ?
> 
> * not quite [[pure]] functions
> 
> That's again the same thing as above: so long as a non-const function wasn't
> called, the result of many const member functions is supposed to remain the
> same. But these functions do read from memory. Example:
> 
>         int i = s.indexOf('/');
>         int j = s.indexOf('/');
> 
> i and j are guaranteed to be the same in our API, so long as the user did
> not violate our thread-safety conditions by writing to s from another
> thread.
> 
> * the case of qGlobalQHashSeed(): it always returns the same thing, but on
> the first call it may make I/O to get random data. So this function can't
> be [[pure]]...
> 
> * constexpr: as I said in std-proposals, I have asked Marc to sacrifice the
> constexprness of the QStringView's constructor taking a QChar* without
> length. This is not the only function in which we've had to do so; see
> qalgorithms.h for more.
> 
> [changing gears]
> * QVariant: need to investigate std::any and what std::any can benefit from
> the Qt 5 improvements (Q{Sequential,Associative}Iterable, QObject
> covariance, etc.)

The strength of QVariant compared to std::any is the connection with the 
QMetaType system.  If you know the Qt meta type of any type T, you can know if 
it is a pointer type, if it inherits from QObject, and in this case you can 
get a pointer to the QMetaObject, you can know if it's an enum, you can know 
if it can be converted to any other type ad you can even register converter.

> * QVariant & metatype id: (if not using std::any) we need a constant
> identifier for each type and we need the type's name. The constant
> identifier for us is an int, but we could probably use the typeinfo. The
> difficult part is actually getting the type's name, since std::typeinfo
> does not guarantee that it will readable. Even for the compilers we
> support, it's not easy to extract the type name. This may come from
> reflection.

The thing is, we don't always need the name. We need the name to be registered 
for QueuedConnection of signals and slot connected with the string syntax.
Appart from that, most useful features of the meta type system don't need the 
name.
But because QMetaType was historically made for QueuedConnection, it needs the 
name, and so needs to be declared or registered with Q_DECLARE_METATYPE/
qRegisterMetaType.  But the truth is that we could get rid of both already 
with what C++98. moc could generate the code that register the name for the 
signal arguments (it already does for some type, but that could be extended to 
all types).  QMetaTypeid::name() would not work for every type but that's not 
so important.

> * reflection: 'nuff said.
> 
> * PMFs: we're running into UBs when we try to use PMFs as identifiers for
> signals.

-- 
Olivier

Woboq - Qt services and support - https://woboq.com - https://code.woboq.org




More information about the Development mailing list