There are three leading C++ frameworks for consuming and implementing Windows Runtime types. The current recommendation (as of this writing) is C++/WinRT.
WRL | C++/CX | C++/WinRT | |
---|---|---|---|
Error handling | HRESULT -based |
Exception-based | Exception-based |
Interop with C++ standard library |
Poor | Middling | Good |
Code verbosity | Very high | Low | Low |
Code generation | Small | Explosively large | Small |
Compile time | Low | Low | High¹ |
IDL file | Manually authored | Automatically generated² | Manually authored |
Static class constructor³ | Supported | Not supported | Supported |
COM static lifetime for factories⁴ |
Can implement manually | Cannot implement | Built-in |
Default threading model | It’s complicated⁵ | Free | Free |
Can choose nondefault threading model |
Yes | No | Yes |
Language | Standard C++ | Nonstandard extension | Standard C++ |
Static analysis tools | Supported | Not supported | Supported |
Language standard required |
C++11 and higher | C++14 or C++17 with /await |
C++17 and higher |
Forward compatibility | Compatible | Incompatible with C++20 | Compatible |
XAML compiler support | No | Yes | Yes |
Coroutine support | No | Yes via PPL⁶ | Yes |
License/source code | Ships in SDK | Closed source | Open source |
Support | Maintenance | None | Active |
Notes
¹ C++/WinRT contains a large number of types and template specializations, which slows down the compiler. The precompiled header file easily exceeds 1GB in size. You can define WINRT_
to remove rarely-used features and improve compile times.
² Automatic generation of the IDL file is a two-edged sword. Although it saves a lot of effort, it can also get in the way: If you need to make a runtime class object marshallable, you need to register a marshaller for the autogenerated interface, which will have an ugly autogenerated name, and whose UUID may not be stable. Autogeneration also conflicts with versioning, makes it harder to interop with other languages, and it can result in puzzling behavior if you don’t understand how the autogeneration works. Furthermore, the autogenerated interface names do not follow Windows Runtime naming conventions.
³ Static class constructors allow class statics to be delay-initialized. This is significant because running constructors at DLL_
creates the risk of deadlocks and other unfortunate behaviors. C++/CX clients must work around this by having a static InitializeStatics()
method which initializes the statics (e.g., dependency properties) and calling it at an opportune moment.
⁴ COM static lifetime allows you to register an object in the COM static lifetime store, which allows you to (1) obtain it later, and (2) destruct it automatically when COM is uninitialized. The former provides a persistent-lifetime object for things like global event sources. The latter permits the object’s destructors to run while COM is still initialized.
⁵ Default is normally free-threaded, but if BUILD_
is set, then default is single-threaded.
⁶ PPL coroutine support is very large.
Am I missing something but why is so much time still being spent here when almost no one is using these tools?
WinRT really is just a failed sandbox API platform built on top of Win32/Win64 correct? As illustrated above way to much abstraction is needed for it to even work making it complex slow & confusing. Feels like a rift that never closed in the MS world.
“WinRT really is just a failed sandbox API” – are Windows devs not flocking to use WinRT? Honest question.
That question isn't the question that you think it is. It is like asking "are devs not flocking to use C style functions" or "are devs not flocking to use classes/objects". The App Container portion of Windows wasn't success. This is what Andrew Witte is referring to.
But the UWP has historical issues that are difficult to talk about in such a limited response. But one of the big important points here is the Windows...
My understanding is that COM and WinRT are really an object-oriented ABI and RPC protocol. They’re kind of the equivalent of D-Bus on Linux and are not inherently platform-specific (xlang).
Well, it isn't really necessary to tie the WinRT style API with the sandbox. There are some new Windows features that are only available through the WinRT style interfaces that also work with desktop applications. For example, Windows.UI.Composition was designed as a better replacement for DirectComposition. I have certainly used these tools in a desktop application, more recently it was a quick way to generate a SHA1 hash for files since it was simpler than...
The table misses Visual Studio authoring support.
So are there any significant downsides or limitations to the C++/WinRT choice in this context? It looks like an all-win situation here.
A very big one for anyone that cares about productivity.
After 30 years of COM, and 5 after declaring C++/CX as deprectated, Visual Studio still has an IDL authoring experience that is comparable to using Notepad, and forces developers to manually merge generated code.
C++ developer productivy is definitly not a concern for the teams responsible to deprecate C++/CX and replace it with a less stelar developer experience.
Apparently they never used C++ Builder or QtCreator during the...
Perhaps “C++17 and higher” if you work in an organisation burdened by the usual levels of corporate technical debt.
You might also miss the hat.
Note that in theory you should be able to use a C++17-enabled compiler for writing one component in C++/WinRT while keeping the rest of the code base on a legacy compiler (or even in a different language), since everything a Windows Runtime component exposes has a stable ABI.
Interesting idea…
I have to say that C++/WinRT seems to be a very slick product.
Is the pendulum swinging back towards C++ out there for Windows? I’ve not been a Windows dev for some years now, and ended on c# (not because of c# mind).