Modern C++ for systems, part 1

In today’s world, there are two main types of programming languages. Well, there are a lot of main types, depending on how you want to look at it, but you can definitely see a distinction between those languages intended for, say, web applications and operating systems. It’s that distinction that I want to look at here.

For web apps (and most desktop ones), we have plenty of options. JavaScript is becoming more and more common on the desktop, and it’s really the only choice for the web. Then we’ve got the “transpilers” bolted on top of JS, like TypeScript, but those are basically the same thing. And we can also write our user applications in Python, C#, or just about anything else.

On the other side—and this is where it gets interesting, in my opinion—the “systems” side of the equation doesn’t look so rosy. C remains the king, and it’s a king being assaulted from all sides. We constantly see articles and blog posts denigrating the old standby, and wouldn’t you know it? Here’s a new, hip language that can fix all those nasty buffer overflows and input-sanitization problems C has. A while back, it was Go. Now, it’s Rust. Tomorrow, it might be something entirely different, because that’s how fads work. Here today, gone tomorrow, as they say.

A new (or old) challenger

C has its problems, to be sure. Its standard library is lacking, the type system is pretty much a joke, and the whole language requires a discipline in coding that really doesn’t mesh with the fast and loose attitudes of today’s coders. It’s also mature, which hipsters like to translate as “obsolete”, but here that age does come with a cost. Because C has been around so long, because it’s used in so many places, backwards compatibility is a must. And that limits what can be done to improve the language. Variable-length arrays, for instance, are 18 years old at this point, and they still aren’t that widely used.

On the other hand, “user-level” languages such as Python or Ruby tend to be slow. Too slow for the inner workings of a computer, such as on the OS level or in embedded hardware. Even mobile apps might need more power. And while the higher-level languages are more expressive and generally easier to work with, they often lack necessary support for lower-level operations.

Go and Rust are attempts at bridging this gap. By making languages that allow the wide range of operations needed at the lowest levels of a system, while preventing the kinds of simple programming errors a C compiler wouldn’t even notice, they’re supposed to be the new wave in system-level code. But Go doesn’t have four decades of evolution behind it. Rust can’t compile a binary for an 8-bit AVR microcontroller. And neither has the staying power of the venerable C. As soon as something else comes along, Rust coders will chase that next fad. It happened with Ruby, so there’s no reason it can’t happen again.

But what if I told you there’s a language out there that has most of C’s maturity, more modern features, better platform support1, and the expressive power of a high-level language? Well, if you didn’t read the title of this post, you might be surprised. Honestly, even if you did, you might still be surprised, because who seriously uses C++ nowadays?

Modern world

C++ is about as old as I am. (I’m 33 for the next week or so, and the original Cfront compiler was released in 1985, so not too much difference.) That’s not quite C levels of endurance, but it’s pretty close, and the 32-bit clocks will overflow before most of today’s crop of lower-level languages reach that mark. But that doesn’t mean everything about C++ is three decades out of date.

No, C++ has evolved, and never so much as in 2011. With the release of that version of the standard, so much changed that experienced programmers consider “Modern” C++ to be a whole new language. And I have to agree with them on that. Compared to what we have now, pre-2011 C++ looks and feels ancient, clunky, baroque. Whatever adjectives your favorite hater used in 2003, they were probably accurate. But no more. Today, the language is modern, it’s fresh, and it is much improved. So much improved, in my opinion, that it should be your first choice when you need a programming language that is fast, safe, and expressive. Nowhere else can you get all three.

Why not Java/C#?

C++ often gets compared to Java and C#, especially when talk turns to desktop applications. But on the lower levels, there’s no contest. For one, both Java and C# require a lot of infrastructure. They’re…not exactly lightweight. Look at Android development if you don’t believe me on the Java side. C# is a little bit better, but still nowhere near as efficient in terms of space.

Second, you’re limited in platform support. You can’t very well run Java apps on an iPhone, for instance, and while Microsoft has opened up on .NET in the past few years, it’s still very much a Windows-first ecosystem. And good luck getting either of them on an embedded architecture. (Or an archaic one.)

That’s not to say these aren’t good languages. They have their uses, and each has its own niche. Neither fits well for our purposes, though.

Why not Go/Rust?

Go, Rust, and whatever other hot new ideas are kicking around out there don’t suffer from the problem of being unfit for low levels. After all, they’re made for that purpose, and it’d be silly to make a programming language that didn’t fill its intended role.

However, these lack the maturity of C++, or even Java or C#. They don’t have the massive weight of history, the enormous library of documentation and third-party code and support. Worse, they aren’t really standardized, so you’re basically at the mercy of their developers. Tech companies have a reputation for short attention spans, which means you can’t be sure they won’t stop development tomorrow because they think they’ve come up with something even better. (Ask me about Angular.)

Why C++?

Even if you think some other language works better for your system, I’d still argue that you should give Modern C++ a shot. It can do essentially everything the others can, and that’s not just an argument about what’s Turing-complete. With the additions of C++11, 14, and 17, we’re not talking about the “old” style anymore. You won’t be seeing screen-long type declarations and dizzying levels of bracket nesting. Things are different now, and C++ even has a few features lacking from other popular languages. So give it a shot.

I know I will. Later on, I hope to show you how C++ can replace both the old, dangerous C and the new, limiting languages like Rust. Stay tuned for that.


  1. Strictly speaking, Microsoft doesn’t have a C compiler, only a C++ one. MSVC basically doesn’t track new versions of the C standard unless they come for free with C++ support. 

First glance: C++17, part 3

It’s not all good in C++ land. Over the past two posts, we’ve seen some of the great new features being added in next year’s update to the standard, but there are a few things that just didn’t make the cut. For some, that might be good. For others, it’s a shame.

Concepts

Concepts have been a hot topic among C++ insiders for over a decade. At their core, they’re a kind of addition to the template system that would allow a programmer to specify that a template parameter must meet certain conditions. For example, a parameter must be a type that is comparable or iterable, because the function of the template depends on such behaviors.

The STL already uses concepts behind the scenes, but only as a prosaic description; adding support for them to the language proper has been a goal that keeps receding into the future, like strong AI or fusion power. Some had hoped they’d be ready for C++11, but that obviously didn’t happen. A few held out for C++14, but that came and went, too. And now C++17 has shattered the concept dream yet again. Mostly, that’s because nobody can quite agree on what they should look like and how they should work under the hood. As integral as they will be, these are no small disagreements.

Modules

Most “modern” languages have some sort of module system. In Python, for instance, you can say import numpy, and then NumPy is right there, ready to be used. Java, C#, JavaScript, and many others have similar functionality, often with near-identical syntax.

But C++ doesn’t. It inherited C’s “module” system: header files and the #include directive. But #include relies on the preprocessor, and a lot of people don’t like that. They want something better, not because it’s the hip thing to do, but because it has legitimate benefits over the older method. (Basically, if the C preprocessor would just go away, everyone would be a lot better off. Alas, there are technical reasons why it can’t…yet.)

Modules were to be something like in other languages. The reason they haven’t made the cut for C++17 is because there are two main proposals, neither truly compatible with the other, but both with their supporters. It’s almost a partisan thing, except that the C++ Standards Committee is far more professional than Congress. But until they get their differences sorted out, modules are off the table, and the preprocessor lives (or limps) on.

Coroutines and future.then

These fit together a bit, because they both tie in with the increased focus on concurrency. With multicore systems everywhere, threading and IPC are both more and less important than ever. A system with multiple cores can run more than one bit of code at a time, and that can give us a tremendous boost in speed. But that’s at the cost of increased complexity, as anyone who’s ever tried programming a threaded application can tell you.

C++, since its 2011 Great Leap Forward, has support for concurrency. And, as usual, it gives you more than one way to do it. You have the traditional thread-based approach in std::thread, mutex, etc., but then there’s also the fancier asynchronous set of promise, future, and async.

One thing C++ doesn’t have, however, is the coroutine. A function can’t just pause in the middle and resume where it left off, as done by Python’s yield keyword. But that doesn’t mean there aren’t proposals. Yet again, it’s the case that two varieties exist, and we’re waiting for a consensus. Maybe in 2020.

Related to coroutines is the continuation, something familiar to programmers of Lisp and Scheme. The C++ way to support these is with future.then(), a method on a std::future object that invokes a given function once the future is “ready”, i.e., when it’s done doing whatever it had been created to do. More calls to then() can then (sorry!) be added, creating a whole chain of actions that are done sequentially yet asynchronously.

Why didn’t then() make it? It’s a little hard to say, but it seems that the prevailing opinion is that it needs to be added in the company of other concurrency-related features, possibly including coroutines or Microsoft’s await.

Unified call syntax

From what I’ve read, this one might be the most controversial addition to C++, so it’s no surprise that it was passed over for inclusion in C++17. Right now, there are two ways to call a function in the language. If it’s a free function or some callable object, you write something like f(a, b, c), just like you always have. But member functions are different. With them, the syntax is o.f(a, b, c) for references, o->f(a, b, c) for pointers. But that makes it hard to write generic code that doesn’t care about this distinction.

One option is to extend the member function syntax so that o.f() can fall back on f(o) if the object o doesn’t have a method f. The converse is to let f(o) instead try to call o.f().

The latter form is more familiar to C++ coders. It’s basically how Modern C++’s std::begin and end work. The former, however, is a close match to how languages like Python define methods. Problem is, the two are mutually incompatible, so we have to pick one if we want a unified call syntax.

But do we? The arguments against both proposals make some good points. Either option will make parsing (both by the compiler and in the programmer’s head) much more complex. Argument-dependent lookup is already a difficult problem; this only makes it worse. And the more I think about it, the less I’m sure that we need it.

Reflection

This, on the other hand, would be a godsend. Reflection in Java and C# lets you peer into an object at run-time, dynamically accessing its methods and generally poking around. In C++, that’s pretty much impossible. Thanks to templates, copy elision, proxy classes, binders, and a host of other things, run-time reflection simply cannot be done. That’s unfortunate, but it’s the price we pay for the unrivaled speed and power of a native language.

We could, however, get reflection in the compile-time stage. That’s not beyond the realm of possibility, and it’s far from useless, thanks to template metaprogramming. So a few people have submitted proposals to add compile-time reflection capabilities to C++. None of them made the cut for C++17, though. Granted, they’re still in the early stages, and there are a lot of wrinkles that need ironing out. Well, they’ve got three (or maybe just two) years to do it, so here’s hoping.

And that’s all

C++17 may not be as earth-shattering as C++11 was, but it is a major update to the world’s biggest programming language. (Biggest in sheer size and scope, mind you, not in usage.) And with the new, faster release schedule, it sets the stage for an exciting future. Of course, we’ll have to wait for “C++Next” to see how that holds up, but we’re off to a great start.

First glance: C++17, part 2

Last time, we got a glimpse of what the future of C++ will look like from the language perspective. But programming isn’t just about the language, so here are some of the highlights of the C++ Standard Library. It’s getting a bit of a makeover, as you’ll see, but not enough to cover its roots.

Variants

Without even looking through the whole list of changes and additions, I already knew this was the big one, at least for me. The variant is a type-safe (or tagged) union. It’s an object that holds a value of one type chosen from a compile-time list. You know, like C’s union. Except variant keeps track of what kind of value it’s holding at the moment, and it’ll stop you from doing bad things:

variant<int, double> v;
v = 42;

// This works...
auto w = get<int> v;    // w = 42

// ...but this one throws an error
auto u = get<double> v; // nope!

Optional values

This one’s similar, and it was supposed to be in C++14. An optional is either a value, or it’s not. In that, it’s like Haskell’s Maybe. You can use it to hold the value of a function that can fail, and it works like an error signal. When converted to a boolean (as in an if), it acts as true if it contains a value, or false if it doesn’t. Not huge, but a bit of a time-saver:

optional<unsigned int> i;

// some function that can return an int or fail
i = f();

if (i)
{
    // work with a proper value
}
else
{
    // handle an error condition
}

Any values

The third of this little trinity is any, an object that can—as you might imagine—hold a value of any type. You’re expected to access the value through the any_cast function, which will throw an exception if you try the wrong type. It’s not quite a dynamic variable, but it’s pretty close, and it’ll likely be faster.

apply

If you’ve ever used JavaScript, you know about its apply method. Well, C++ will soon have something similar, but it’s a free function. It calls a function (or object or lambda or whatever) with a tuple of arguments, expanding the tuple as if it were a parameter pack.

Searching

Yes, C++ lacked a standard way of searching a sequence for a value until now. Rather, it lacked a general way of searching for a value. Some searches can be made faster by using a different algorithm, and that’s how C++17 upgrades std::search. And they’re nice enough to give you a couple to get started: bayer_moore_searcher and bayer_moore_horspool_searcher. No points for guessing which algorithms those use.

Clamping

It’s common to need to clamp a value to within certain bounds, but programming languages don’t seem to realize this. Libraries have functions to this, but languages rarely do. Well, C++ finally did it. That’ll instantly shave off 50% of the lines of code working with lighting and colors, and the rest of us will find some way to benefit.

Mathematical special functions

C++ is commonly used for numeric computation, but this set of functions is something else. They likely won’t be of interest to most programmers, but if you ever need a quick beta function or exponential integral, C++17 has got you covered.

Filesystem

Alright, I’ll admit, I was holding back. Everything above is great, but the real jewel in the C++17 Standard Library is the Filesystem library. If you’ve ever used Boost.Filesystem, you’re in luck! It’s the same thing, really, but it’s now standard. So everybody gets to use it. Files, paths, directories, copying, moving, deleting…it’s all here. It certainly took long enough.

Still not done

That’s not nearly everything, but those are my favorite parts. In next week’s finale, we’ll switch to the lowlights. We’ll see those features that just didn’t make the cut.

First glance: C++17, part 1

C++ is a language that is about as old as I am. Seriously. It was first called “C++” in December 1983, two months after I was born, although it had been in the works for a few years before that. So it’s an old language, but that doesn’t mean it’s obsolete or dead. No, far from it. In fact, the latest update to the language, called C++17, is scheduled for release in—you guessed it—2017, i.e., next year.

Why is that important? Well, if you know the history of C++, you know the story of its standardization. The first true standard only came out in 1998, and it was only then that all the template goodness was finally available to all. (Let’s all try to imagine Visual C++ 6 never happened.) Five years later, in 2003, we got a slight update that didn’t do much more than fill in a few blanks. Really, for over a decade, C++ was essentially frozen in time, and that was a problem. It missed the dot-com boom and the Java explosion, and the growth of the Internet and dynamic scripting languages seemed to relegate it to the dreaded “legacy” role.

Finally, after what seemed like an eternity, C++11 came about. (It was so delayed that its original codename was C++0x, because everyone thought it’d be out before 2010.) And it was amazing. It was such a revolution that coders speak of two different languages: C++ and Modern C++. Three years later, C++14 added in a few new bits, but it was more evolutionary than revolutionary.

What C++ did, though, was prepare programmers for a faster release schedule. Now, we’ve seen how disastrous that has been for projects like Firefox, but hear them out. Instead of waiting forever for all the dust to settle and a new language standard to form, they want to do things differently, and C++17 will be their first shot.

C++ is now built on a model that isn’t too different from version control systems. There’s a stable trunk (standard C++, of whatever vintage), and that’s the “main” language. Individual parts are built in what they call Technical Specifications, which are basically like Git branches. There’s one for the standard library, networking, filesystem support, and so on. These are largely independent of the standard, at least in development terms. When they’re mature enough, they’ll get merged into the next iteration of Standard C++. (Supposedly, that’ll be in 2019, but 2020 is far more likely.) But compilers are allowed—required, actually, as the language needs implementations before standardization—to support some of these early; these go under std::experimental until they’ve cooked long enough.

So C++17 is not exactly the complete overhaul of C++11, but neither is it the incremental improvement of C++14. It stands between the two, but it sets the stage for a future more in line with, say, JavaScript.

New features

I have neither the time nor the knowledge to go through each new feature added to C++17. Instead, I’ll touch on those I feel are most important and interesting. Some of these are available in current compilers. Others are in the planning stages. None of that matters as long as we stay in the realm of theory.

Fold expressions

Okay, I don’t care much for Haskell, but these look pretty cool. They take a parameter pack and reduce or fold it using some sort of operation, in the same way as Haskell’s foldl and foldr. Most of the binary operators can be used, which gives us some nifty effects. Here are a few basic examples:

// Returns true if all arguments are true
template <typename... Args>
bool all(Args... args) { return (... && args); }

// Returns true if *any* arguments is true
template <typename... Args>
bool any(Args... args) { return (... || args); }

// Returns the sum of all arguments
template <typename... Args>
int sum(Args... args) { return (args + ... + 0); }

// Prints all values to cout (name references JS)
template <typename... Args>
void console_log(Args&&... args)
    { (std::cout << ... << args) << '\n'; }

Yeah, implementing any, all, and even a variadic logging function can now be done in one line. And any functional fan can tell you that’s only the beginning.

Structured bindings

Tuples were a nice addition to C++11, except that they’re not terribly useful. C++, remember, uses static typing, and the way tuples were added made that all too evident. But then there’s the library function std::tie. As its name suggests, one of its uses is to “wire up” a connection between a tuple and free variables. That can be used for a kind of destructuring assignment, as found in Python. But C++17 is going beyond that by giving this style of value binding its own syntax:

using Point3D = tuple<double, double, double>;

// This function gives us a point tuple...
Point3D doSomething() { /* ... */ }

// ...but we want individual X/Y/Z

// With std::tie, we have to do this:
//
// double x, y, z;
// std::tie(x,y,z) = doSomething();

// But C++17 will let us do it this way:
auto [x,y,z] = doSomething();

Even better: this works with arrays and pairs, and it’s a straight shot from there to any other kind of object. It’s a win all around, if you ask me.

if initializers

This one’s less “Wow!” than “Finally!”, but it’s good to have. With C++17, you’ll be able to declare a variable inside the conditional of an if or switch, just like you’ve been able to do with (old-style) for loops for decades:

if (int value; value >= 0)
{
    // do stuff for positive/zero values
}
else
{
    // do stuff for negative values
    // Note: value is still in scope!
}

Again, not that big a deal, but anything that makes an overcomplicated language more consistent is for the best.

constexpr if

This was one of the later additions to the standard, and it doesn’t look like much, but it could be huge. If you’ve paid any attention to C++ at all in this decade, you know it now has a lot of compile-time functionality. Really, C++ is two separate languages at this point, the one you run and the one that runs while you compile.

That’s all thanks to templates, but there’s one big problem. Namely, you can’t use the run-time language features (like, say, if) based on information known only to the compile-time half. Languages like D solve this with “static” versions of these constructs, and C++17 gives us something like that with the constexpr if:

template<typename H, typename... Ts>
void f(H&& h, Ts&& ...ts)
{
    doItTo(h);

    // Now, we need to doItTo all of the ts,
    // but what if there aren't any?
    // That's where constexpr if helps.
    if constexpr(sizeof...(ts) > 0)
        doItTo(ts...);
}

If implemented properly (and I trust that they’ll be able to do that), this will get rid of a ton of template metaprogrammming overhead. For simple uses, it may be able to replace std::enable_if and tag dispatch, and novice C++ programmers will never need to learn how to pronounce SFINAE.

Continuation

Those are some of my favorite features that are on the table for C++17. In the next post, we’ll look at the changes to the standard library.

More fun with constexpr

Continuing from my earlier post, here’s another look at how we can abuse the compiler and C++11’s compile-time abilities. This one might even be useful!

The Problem

Trigonometry functions are common in a lot of programming. On modern hardware, they’re usually highly optimized, too. But C++ developers are taught to use the compiler as much as possible. That’s why we have templates and constexpr, after all. So, can we do trig calculations this way?

The answer, of course, is “yes”. (If it wasn’t, then this post wouldn’t exist.) We’ll start with the cosine function, since it’s probably the easiest to implement. One way to define the cosine function is as an infinite series that I don’t really want to try to recreate in math notation here. As it turns out, that definition is fairly easily convertible to a recursive function that can be evaluated at compile-time.

The Code

template <int Iterations = 10>
constexpr double cosine (double theta)
{
    return (power(-1, Iterations) * power(theta, 2 * Iterations)) /
            static_cast<double>(factorial(2ull * Iterations))
        + cosine<Iterations-1>(theta);
}

template <>
constexpr double cosine<0> (double theta)
{
    return 1.0;
}

Since the Taylor series is an infinite one, we obviously can’t run the whole thing. So we approximate. I’ve decided on a default of 10 iterations, but the function, you should note, actually calculates the series “in reverse”. The base (i.e., last) case, when Iterations == 0, is the first term in the series expansion. It’s okay, though. The algorithm still works this way, although it might look a little weird.

Also, note that this cosine function uses two other constexpr functions. The first, power(), is our creation from last time, slightly renamed. The second is a typical factorial function. (It’s a good thing every single constexpr tutorial uses this one, otherwise I’d have to write it myself!) factorial takes an integer and returns another one, so I used an explicit cast to double. You could just change the definition of factorial, though, if you don’t mind the possible loss of precision. You’d probably want to template the whole thing on the type, too, instead of only using doubles.

The other trig functions can, for the most part, work off this base. The sine series raises the angle to the power of 2n+1 instead of 2n (and takes the factorial of 2n+1, as well), but it’s otherwise the same. Tangent, as you know, is sine divided by cosine. The reciprocals (secant, cosecant, cotangent) are trivial. You’d also need conversions between degrees and radians (this function uses radians), but that’s so easy you can do it in your sleep.

In a real application, you might want to combine this with lookup tables or something, especially because of rounding errors and the limited precision of floating-point numbers.

Now What?

If I can find any more constexpr contortions, I’ll definitely be making more posts. There’s still so much of the standard math library left, you know.

A simple constexpr power function (C++)

Since C++11, programmers have been given the power of compile-time calculation without the hassles of template metaprogramming. (And they are hassles, believe me.) The canonical example is a factorial function completely evaluated by the compiler, but here’s another, different use, one that has much more utility.

The Power Function

It’s a sad fact that C++ has no power operator. Sure, we have the std::pow function inherited from C, but that works at runtime, which means we can’t use it in template arguments. Most notably, we can’t say something like array<int, pow(4,4)>. In other words, we aren’t allowed to use a power function when declaring the size of a C++11 array. Most users, of course, will never need it, but you never know when it might come in handy, so here it is:

template <typename T>
constexpr T ipow(T num, unsigned int pow)
{
    return (pow >= sizeof(unsigned int)*8) ? 0 :
        pow == 0 ? 1 : num * ipow(num, pow-1);
}

There are a few caveats. First, it’s (obviously) a template, so you can use it on integers, doubles, or anything else that has a binary operator* (i.e., the arithmetic one, not the pointer one). All it does is the classic “raise to a power” algorithm: repeatedly multiply a number by itself. Like the typical factorial function, it’s really written in a function mode. It even has a proper tail call, if you’re into that sort of thing. Incidentally, that’s why the second argument (the power to raise to) must be an unsigned int: you can’t use the elementary-school method with fractional powers, and raising an integer to a negative power gives you a fraction, which means that there could be type issues.

The second thing to notice is that it could use some better error handling. I put a check in to keep somebody from calling it with some huge power like 1,000,000, but all it does is return 0. It should probably throw an exception, instead. Maybe I’ll change it in version 2.

Last, this clearly won’t be useful for a class where “raise to a power” isn’t the same thing as “multiply by itself over and over”. But if I had to guess, I’d say that there aren’t too many places where you’d want to raise that kind of object to a power at compile-time. I’d love to see a counterexample, though.

Anyway, that’s all for this time. I intend to expand on this idea (complex arithmetic at compile-time) later, so I’ll see you then.