Welcome to a new series in MSDN Magazine exploring the essentials and internals of the Windows Runtime. You can read the first installment right now in the July 2015 issue:
Windows Runtime Components
Over the next few months I’m going to explore the essentials of the Windows Runtime. The purpose is to break down the higher-level abstractions that developers use in the various language projections and toolchains in order to examine how the Windows Runtime works at the application binary interface (ABI)—the boundary between applications and the binary components they rely on to access OS services.
Many thanks to Larry Osterman for his feedback on this series.
Yesterday Stephan Lavavej announced on the Visual C++ blog that their compiler would be constexpr complete for the Visual Studio 2015 build that is released to manufacturing. While that sounds exciting – and it is – I don’t think many developers really know what that means and may make certain reasonable assumptions about what is achievable at compile time. Stephan alluded to a difference between the original goals and aspirations for constexpr in the earlier C++11 standard compared to what is found in the newer C++14 standard. So what does this mean?
The original notion of a generalized constant expression is careful to limit the definition to sufficiently simple functions. That meant that such functions could not contain local variables, iteration statements, or selection statements. Such restrictions quickly became onerous and were lifted in C++14. I’m not a language lawyer so I’ll just give you an illustration. Imagine I need to count the occurrences of some character within a string. I would naturally like to express this at compile time as follows:
static_assert(Count("a % b % c % d") == 3, "fail");
With Visual Studio 2015, I need to be careful to implement the Count constexpr function to avoid using any of the aforementioned constructs. This is a reasonably simple problem so it doesn’t take a great leap of the imagination to write a simple recursive function:
constexpr unsigned Count(char const * const string)
return *string == '\0' ? 0 : (*string == '%') + Count(string + 1);
While this is a recursive function, the recursion happens at compile time. In fact, the compiler may choose to unroll or transform the implementation to avoid recursion. From what I can tell, the Visual C++ compiler does not attempt to transform this so if I have a very large string then it will hit the compiler’s call-depth limit. Fortunately, this can be avoided with a compiler option. On the other hand, recursion is clearly not ideal and writing such contrived expressions quickly becomes error prone to say the least. The C++14 definition of constexpr functions makes it possible to write this function with more of the C++ language at my disposal:
constexpr unsigned Count(char const * string)
unsigned count = 0;
for (; *string != '\0'; ++string)
count += *string == '%';
Notice that I’m able to manually transform the recursive function with an iteration statement and use a local variable to keep track of the count. I am even able to increment the pointer. While this is a simple example and there’s nothing wrong with the recursive example above (unless I have very large strings) it sure is handy to be able to have the expressive power of C++14 constexpr functions at my fingertips.
The first beta of the .NET Framework arrived in 2000. As I look back at the decade following its unveiling, I cannot help but think of it as the first dark age of C++. Following on the success of Java, Microsoft likewise chose to distance itself from its strong roots in C and C++. The mighty developer division embraced managed code and worked tirelessly to build incredible tooling for C#. For a time the Visual C++ team tried to play catch-up with not one but two different language extensions for the Common Language Runtime (CLR), but they quickly realized that they were the unwelcome guest at the party. Thankfully, they returned to their roots in native code and so began the C++ renaissance championed by the likes of Charles Torre and others. This eventually culminated in amazing achievements such as the Concurrency Runtime, C++11 and dramatic improvements to the Visual C++ C Runtime (CRT) and Standard Template Library.
Just over ten years following the arrival of .NET, Microsoft announced Windows 8 and the new Windows Runtime. While .NET had arguably succeeded splendidly on the server, it always had an uneasy relationship to the Windows client mainly due to poor performance and the lack of a universal UI framework. With the advent of smaller devices, the operating system group decided to remedy the client problem by returning to the proven performance of C++ and the essentials of COM. The Windows Runtime would become the universal platform for not only the ultimate XAML implementation but also the entire Windows API.
At this point, any optimistic C++ programmer would be forgiven for thinking that the dark ages have passed and good times are ahead. Unfortunately, while the operating system group has embraced C++, the developer division remains largely unchanged. The CLR was retrofitted with support for the Windows Runtime. This is beyond ironic since .NET was specifically designed as a departure from COM with an incompatible vtable model. Performance isn’t great despite the fact that the Windows Runtime does make a number of concessions for the CLR, but at least most of the heavy lifting is now done by the operating system so C# code gets a pass.
While the operating system group has embraced C++, the developer division continues to champion C# as the tool of choice and the Visual C++ team continues to focus on standards compliance and more recently cross-platform development. Little has been done to support the Windows Runtime, certainly nothing that has captured the hearts and minds of C++ developers. C++/CLI was dusted off – a language extension designed for a garbage-collected runtime – and now offers an unnecessarily complex way to work with the Windows Runtime that makes no sense for COM. C++ is a language for library developers. The library developer’s job may not be a simple one, but you certainly have the tools at your disposal to do some amazing things. So when you hit some feature that isn’t directly supported by the language, then you write a library – you don’t go and invent a new language or write a set of language extensions. Prior to C++11 you could be forgiven for thinking in that way, but not now.
Microsoft desperately needs an infusion of modern C++ for Windows. The Universal Windows Platform built on the Windows Runtime is the ideal environment for C++ to thrive. What is missing is the determination to make it happen. Modern C++ for the Windows Runtime is the jumpstart that the Windows platform needs but it cannot happen without the support of both the operating system group and the developer division.
Jim Radigan has done some incredible work bringing code written for Android and iOS apps to Windows. Now we need to bring modern C++ to Windows as well. The C++ community is stronger than ever and forging ahead with incredible innovations to the C++ language and standard libraries. Will Windows be part of this new C++ renaissance or will this be another dark age for C++ programmers on the Windows platform?
It was a pleasure joining Rob Irving and Jason Turner on the CppCast podcast!
We chatted about the future of C++ (lots of concurrency). We also talked about C++/CX, Modern C++ for the Windows Runtime, SQLite and my Pluralsight courses, and more. Enjoy!
My latest course, SQLite with Modern C++, is free for a limited time on Pluralsight. If you don’t yet have a Pluralsight subscription then be sure to check it out right now.
If you do have a Pluralsight subscription, be sure to check out my growing collection of courses. My next course, Windows Runtime Internals, will also be available to subscribers within a few weeks.
I have started publishing information about the Modern C++ project at moderncpp.com and I hope that you’ll go and take a look to see what I’ve been up to. Subscribe here for updates or follow me on Twitter:
I recently made the case that Modern C++ for the Windows Runtime offers the productivity of C# and performance that beats even C++/CX. Surely this would be tremendously valuable to the Universal Windows Platform. And I topped it off with my biggest video demo yet of the Modern library.
1. A Classy Type System for Modern C++
2. Modern C++ as a Better Compiler
3. When Standard C++ Isn’t Enough
Video: Universal Windows Apps with Standard C++
I’m off to work on my next course for Pluralsight entitled Windows Runtime Internals, but I’ll be back to continue the work of bringing modern ISO C++ to the Windows platform.
Here’s my article in the May 2015 issue of MSDN Magazine. This is the special edition of the magazine that was available at Build 2015.
Adding Compile-Time Type Checking to Printf
I explored some techniques for making printf more convenient to use with modern C++ in my March 2015 column. I showed how to transform arguments using a variadic template in order to bridge the gap between the official C++ string class and the antiquated printf function. Why bother? Well, printf is very fast, and a solution for formatted output that can take advantage of that while allowing developers to write safer, higher-level code is certainly desirable.
While this is a convenient bridge between modern C++ and the traditional printf function, it does nothing to resolve the difficulties of writing correct code using printf. printf is still printf and I’m relying on the not entirely omniscient compiler and library to sniff out any inconsistencies between conversion specifiers and the actual arguments provided by the caller.
Surely modern C++ can do better.