Qt Contributor Summit 2019 - C++17 Features Notes
Notes for the Qt Contributor Summit 2019 Wednesday session titled "C++17 language and std library features for Qt 6".
- 1 Language
- 2 Library
- 3 Co-operation with compiler vendors
- 4 Testing
- 5 Getting rid of moc
- 6 Replacing conditional compilation flags with if constexpr
- 7 Minimum compiler versions for 6.0
Very useful for our containers.
Shortcut for handling parameter packs of vadiadic templates. No need to write recursive template helpers.
Volker: What is the impact of using inline variables to static data initialization? How do we deal with
Inline variables are safer than static globals. Compiler and linker guarantee that there will be just one definition.
Q_GLOBAL_STATIC still provides lazy initialization. So inline variables are not a full replacement. Any big globals that aren't necessarily used should be gated by lazy initialization to avoid constructing them unnecessarily.
What is it? It has auto as its parameter type. So the same lambda can be used with multiple invocations with parameters of different types.
Most common use is just for brevity. It gives you perfect forwarding as well, if you use auto && as the type.
But these are not API visible, just perhaps useful inside the implementation.
QRect and QPoint might be possible candidates. But there will not be many that this makes sense for.
Some of these will already be aggregates and work automatically. But perhaps they for example have user-defined constructors and so don't fulfill the requirements of that.
There are macros for many standard attributes, like nodiscard, deprecated, fallthrough, likely and unlikely.
When is the right point to remove this macros and use the attributes directly? When all compilers support it. Although that causes pain when backporting to older branches.
That applies to all language features, though. Some backporting is really hairy, like converting if constexpr solutions back to template specializations.
Properly modularizing Qt is going to be a huge undertaking. There should be some prototyping done by an energetic volunteer.
There are rumors that moc generated code leads to some issues here.
QT_CONFIG() macros work together with modules? Every permutation would need to be shipped as a separate module. But they are going to be constant within a built Qt. Not something the user of the library can change.
Modules are not supported by build systems (including qmake and CMake) yet. CMake developer Kitware is working on it, though.
QDialog::call/exec() are already coroutines, but stackful ones. So converting to them stackless is not really possible. But there might be better candidates in networking or elsewhere with callbacks.
Standard coroutines are quite cumbersome to use. Would we use an external helper library with that or would Qt provide their own helper for coroutines? Having Qt-friendly coroutine helpers would be nice.
Test data supplying is currently a huge matrix of QVariants and is actually a performance bottleneck for our tests. Using generators for these might be helpful? They are not going to make a difference compared to a good hand-written generator. So the performance issues might be fixed with other approaches.
Contributions to any of these would be welcome.
std::any is like a QVariant that does not need registration.
Could there be conversions between QVariant and std::any? Ville is skeptical about how to do that. Olivier suggested adding support for conversion from std::any to QVariant into QMetatype. But can that be done with just a reference to
std::any is a replacement for void*. It knows the type that it holds.
Giuseppe: Should be use std::filesystem::path types consistently in our APIs instead of QString? Ville: There should be a prototype patch to see how big the effect is. I'm concerned that the impact would be too big.
Is std::filesystem::path API stable enough? Standard committee cares about API stability a lot, so that's not a worry. Although some want a new version of the API that uses std::expected.
Parallel STL algorithms
We could allow parallel execution tags in our API to let users ask for use of parallel algorithms.
But what are the places in Qt API that actually need these? More data analysis stuff (if developed) would find it helpful. But often users get to choose their own algorithms and so can use parallel algorithms without our containers needing to know about it.
If a parallel STL implementation is not available, falling back to single-threaded implementation is always an option. So support could be utilized only when available and not demanded from all platforms. Or the platfrom support can be a shim that still always processes everything without parallelism.
Better support for
std::unique_ptr for Qt APIs?
A patch for more explicit ownership for QObject hierarchy has been suggested in the past. Maybe out of scope for this session.
std::unique_ptr is not new in C++17.
Would it be worth changing API to return std::optionals instead of bool output parameters? It would be a big source-incompatible change.
Do we want to use
std::string_view? Or do we need a QByteArrayView? In order to match QByteArray API?
Will QByteArray still be for string data in Qt 6? That's a topic for tomorrows session.
QByteArray has some API that expects the contents to be string-like. Unfortunately, because they don't really belong there. QByteArray's future should be clarified before making decisions about these can be made.
Not available to us yet. And will work with
std::basic_string only pretty much. Not with QString.
Co-operation with compiler vendors
Ville has talked to INTEGRITY multiple times. Technically they can provide a C++17 compatible compiler due to using IDG frontend. They haven't provided a timeline when that is actually released.
Embedded (and other) platforms that don't provide C++17 launch will be initially dropped from being supported. They will be added later once their compilers catch up.
QNX has gcc-based compiler so they should also be able to update their systems.
Testlib feels old and unfriendly. Reflection is the real killer feature for nice testing. It would allow much less macro use and other boilerplate. It's also the solution for everything else.
Getting rid of moc
Reflection should also replace moc at some point.
Andrew (one of the reflection proposal authors) is working on something very moc-like and would like feedback from the Qt community. So far he has not gotten any. People who know our metaobject system well should engage with standard committee members so that the final reflection solution will serve us well. Ville Voutilainen is one possible contact point in addition to Andrew Sutton.
Replacing conditional compilation flags with if constexpr
if constexpr demands that all branches are valid. Other branch can only not compile when it is inside a template.
Conditional compilation still needs the preprocessor, because if a feature is disabled, the branch using it would not be valid code.
Minimum compiler versions for 6.0
Lars had a proposal on the mailing list and there has been no opposition.
The set of minimum versions would be:
- GCC 9
- Clang 9
- Apple Clang 11 (Clang 9)
- MSVC 2019
Thiago would like it to be a bit more conservative. But when 6.0 comes out, GCC 9 will be one and a half years old. So it's not bleeding edge. 18 months old compilers should be fine, but probably not much newer than that.
Qt 6 will require C++17. So compiler will be need to switched to C++17 mode. But users might still be able to have codebases that only use C++11, since not much API will necessarily require C++17 features to use. So codebases with compatibility for older language versions (in other builds) should be largely possible.