ACCU Home page ACCU Conference Page
Search Contact us ACCU at Flickr ACCU at GitHib ACCU at Google+ ACCU at Facebook ACCU at Linked-in ACCU at Twitter Skip Navigation

pinC++ with Meta-classes?

Overload Journal #143 - February 2018 + Design of applications and programs   Author: Francis Glassborow
Meta-classes will allow us to detail class requirements. Francis Glassborow compares them to developments of C++ in the 1990s.

Back in the early 80s, Bjarne Stroustrup produced an upgrade to C that was originally called ‘C with classes’. Superficially it was nothing special because it did not add anything that could not be done in C by a sufficiently competent programmer. At that time some were brave enough to call it a ‘better C’. C was in the early stages of being standardised both by ANSI (the US Standards body) and by ISO. The US Standard was published 1989 as ANSI C. A year later ISO effectively adopted ANSI C with a bit of editorial work to get it into the form required by ISO. The result was an international standard for C.

The C purists were not exactly on board with the idea that there could be an improvement to their chosen language. Indeed, some still feel that C is the best of breed and obstinately ignore the existence of C++. C still has a place in the world of programming but I am unconvinced that it deserves the time and effort that goes into evolving it. Modern optimisation technology can make good use of the added expressiveness of C++ to deliver small footprint, high performing executables from well written C++ source code.

It is worth noting that for most of the 80s ‘C with Classes’ or C++ as it came to be called was implemented via CFront. That was basically a translator that converted raw C++ into C which could be compiled by any suitable (effectively standard) C compiler. That allowed interested people to use C++ on any platform that had a C compiler.

Most significantly, CFront demonstrated that the core of C++ was C-based though additions such as templates (held with profound suspicion by many programmers for at least a decade) moved it into a realm of its own.

It took many years for writers and programmers to grasp that C++ was very different from C and that the idioms of the language were fundamentally different. Good C is largely not good C++. Unfortunately, part of the legacy that C++ has to cope with is attempting to maintain a compatible core that is also valid C. Those who program in both languages are all too aware of how difficult this can be. Just take the problem of implementing support for complex numbers. This is reasonably straight-forward for C++, even to the extent of supporting different levels of precision (float, double and long double). To do the same thing in C required considerable contortions including adding core support not only by adding new built-in types but added conversions to allow complex numbers to interact with floating point types.

C++ can often add new types as library extensions without changes to the core of the language. If you want quaternions or extended precision floats or Dr Conway’s Surreal Numbers you, as an individual, can implement them in C++ in a natural way including support for operators and transparent support for mixing them with other arithmetic types.

These days C++ has added a great deal including support for concurrency (hard because that field is littered with gotchas), support (initially via Technical Specification) for modules, contracts, concepts etc. Each of those additions has major impact for the programmer and makes heavy demands on language designers and implementers.

All this developed from a single step forward aimed at making C more expressive and usable. Classes are a powerful addition to C though the idea is relatively simple and makes relatively little demand on design and implementation. Of course, that is not true of the superstructures that have been built on top of classes. Without classes, the provision of support for generic programming via templates would have been the domain of a tiny number of master programmers (yes, you can do generic programming in C, but who would want the pain of doing so?). Templates enabled meta-programming because the implementation of them made demands on compilers that could easily support some aspects of meta-programming. More recently C++ has added more direct support for meta-programming.

Who could have foreseen the long-term consequences of introducing classes to C? Yet that step has produced the rich, vibrant living language that is C++ today. There have been and are attempts to produce a successor to C++. Some of these have some positive advantages (usually as a result of not having to worry about C compatibility). Java and D both have something to offer and yet seem, to me, to lack the vibrancy of C++.

It is time for something new

Almost everything that gets added to C++ increases the complexity either for the programmer or for the implementer. Hopefully, most complexity is for implementers but some things aimed at library designers can be daunting for the application programmer when they look at the resulting libraries (usually from curiosity but sometimes because a compilation error message takes them into library source code.)

This has remained true until April of 2017 when Herb Sutter gave the endnote to the ACCU Conference with the caveat that we would keep quiet about it until he had had a chance to present the idea to WG21 later in the year.

This new thing was ‘meta-classes’. Like classes, they do not appear to add anything that cannot be achieved without them. However, to this writer, they are just as much a game changer as were classes added to C.

Let me give you a very brief overview of the idea and then leave you with some links that will allow you to get real information and discover that you can already start exploring some aspects of their use.

First note that they rely on compile time reflection: another addition to C++ that is fast coming down the line. Have a look at http://jackieokay.com/2017/04/13/reflection1.html and https://meetingcpp.com/blog/items/reflections-on-the-reflection-proposals.html. Or search for C++ reflection.

It is clear that static reflection will be added to C++ and that compilers (Clang, G++ and Visual C++) are already providing experimental support for it. Be careful because whilst these are close to what will eventually be added to the C++ Standard you should be prepared to modify code using reflection to conform to the eventual standard specification.

So what are C++ meta-classes? The idea is that we should be able to specify what is required to produce a family of types. For example, a value type has a need for specific functions which we currently have to provide by hand. The compiler cannot assist us in either detecting that we have left one out, nor in providing a suitable default. The problem is that unless you can communicate that the class that you are writing is to implement a value type the compiler cannot use reflection to determine if you have implemented your intention. Nor can it provide suitable defaults.

A meta-class specifies a set of required functions to the compiler, a set of prohibited functions and defaults for functions that will be used if the programmer does not provide a version. Think of the way a class provides defaults for copying (assignment and cloning), construction and destruction. It wasn’t until we had =delete that we had an easy way to prohibit copying, and default construction. Yes, you can do it but by tricks and idioms (such as declaring and not defining a copy constructor to inhibit cloning). Such things are error prone and lack transparency. If you do not know the idiom for turning off copying you probably will be confused by it.

Meta-classes will allow us to define what constitutes an object type, a value type, an arithmetic type etc. They will enable the compiler to generate a great deal of what we currently have to do by hand. If you wish to see how much work we have to do to implement an arithmetic type have a look at the implementation of a complex number. Yet much of that is just boiler plate code. Perhaps the complexity of implementing std::pair is even more surprising (shocking).

Like classes, meta-classes achieve very much more than a superficial description suggests. Reflection is a useful tool but not a game changer in itself.

I assume that the reader is not someone who wishes to bury their head in the sand like the C programmers who wanted nothing to do with C++ and so bifurcated K&R C into ISO C and ISO C++.

Some of the debates on Reddit begin to look very similar to some of the comments made about C++ in the early 90s. Assuming that readers avoid the knee-jerk reaction and want to know more before forming an opinion, look on the web for C++ meta-classes. A good starting point is: https://herbsutter.com/2017/07/26/metaclasses-thoughts-on-generative-c/. You do not need to type that in, just search for ‘meta-classes in C++’.

When you have brought yourself up to date on meta-classes please start thinking about ways they would help you. There is partial support for meta-classes in Clang. You should be able to try out published examples and experiment with your own ideas. I invite you to report on your experiences both good and bad.

Have great coding experiences in 2018 and may all your bugs have six or more legs.

Overload Journal #143 - February 2018 + Design of applications and programs