How typed C++ is, and why it matters
For the third time I attended the meetup of Software Craftmanship in Paris. And like the first time and the second one, it was superb experience again.
This meetup lets the participants collectively choose the topics to be discussed. There I proposed to confront, as a group, the various languages that the people in the room knew (the crew wasn’t especially C++ oriented), in order to point out some of the differences between the languages. The point was to discover new approaches taken by other languages, and by comparison, to better understand our own.
This experience allowed me to understand C++ a bit better, and for this reason I want to share with you what was exchanged during the event.
The biggest part of the debate was oriented on the theme of typing. And in C++ we use typing as a powerful tool to make code more expressive, like with strong types.
But while some common languages like C++ and Java are classified as typed, some others – just as common – aren’t, like JavaScript or Python. And some languages – like Haskell or Idris – are even more typed than C++. More about this in just a moment.
In general, people coding with strongly typed languages can’t imagine how the others can live a decent life, and vice versa. And I think this is a wrong-headed approach: there are lots of people coding with both categories of languages, so there are necessarily at least pros (and probably cons) in both.
And I believe that understanding where your language lies in the spectrum of typing strength provides you with an enriching perspective.
So let’s get into it, like if you were there!
We will start by the advantages of typing.
Typing brings protection
The first advantage of typing is profoundly anchored in the mindset of C++ programmers: typing prevents programmers from making a whole class of mistakes. And these mistakes essentially consist in passing the wrong object to the wrong context.
A type is embodied in C++ by a struct
, a class
or a primitive type (int
, double
, char
, etc.). It represents a concept after which all objects of this type are modeled. For example, int
models an integral number, Employee
represents someone from the personnel, and Date
represents a moment in time.
By stating what type is expected in a certain context – like the arguments of a function – the compiler ensures that the type of the object passed to this context is the one expected. Some languages try to go further in this direction, by using the type system to prevent unexpected states to occur. The video Making impossible states impossible about the language Elm was proposed to illustrate this point.
For this reason, strong typing in a language typically reduce the amount of necessary tests. Since some things cannot happen by construction of the language, there is no need to confirm it with tests. In a typed language like C++, you wouldn’t write a test that passes an int to a function that expects a std::string
, to make sure it behaves ok, because such code would be downright rejected by the compiler.
Typing brings expressiveness
Someone rose an interesting question during the debate: do types serve the compiler?
And the answer that was given was: No, typing helps human developers seeing more clearly in their programs. Sure enough, the compiler is aware of types and make checks based on them, but these are merely to prevent humans from being overwhelmed by their code growing in complexity. When you think about it, once a source file is compiled down to machine code, there are nothing but 0s and 1s remaining. The types are then long gone.
In fact, typing can act as a form of documentation. For instance, if you consider a function taking an object of type FirstName
and an object of type LastName
, and returning an Age
, you immediately get a very strong intuition that this function somehow retrieves the age of a person. And one can understand this without any other information than the types involved in the prototype.
Some languages go further than this, by defining prototypes that can involve any type. For example, consider a function that can take an object of any type A as an argument, and return an object of type A. At first glance there must be a great number of functions that could fit this prototype. But it turns out that there is only one: the identity function. This is a surprising way of how types can provide information in a prototype. More about this and how this can be useful in C++ in the excellent talk Using Types Effectively given by Ben Deane at CppCon.
An interesting parallel to typing was brought up with how real life objects look like. Indeed, Their appearance provide information about what they are and how they are meant to be used. Types in code are a bit like that too, because they are inherently part of the objects they model, and they convey meaning and useful information about them.
To go deeper into this way of thinking, the following book was suggested: The Design Of Everyday Things. It’s not the first that time this book comes up in a developers discussion, and it is definitely in my reading list now. When I’ve read it, you can count on me to make a dedicated post to share its relevant insights to make code more expressive, if there are any.
Isn’t there anything wrong with typing?
So far only positive aspects of typing have been brought up. But aren’t there any downside coming with it? Even though I’m a hardened C++ programmer, I refuse to believe that typing is all good. I mean, there are so many people and so much code out there that use weakly typed languages that there must be interesting aspects in doing so. So I asked the question: what do you find annoying with typing? Here is what came out of the discussion.
The first interest of weakly typed language is that they provide a sensation of freedom, by not being constrained by the type system. This puts typed languages in perspective as more unpleasant and complex.
Developing in weakly typed languages go faster. Quite a lot faster. I didn’t quite catch a concrete illustration of this point though.
With typed languages, you’re brought to write casts at some point or other, even in cases where you precisely know what types you’re expecting in the code. Someone brought up an example involving system calls to illustrate this point.
Finally, it can be useful to be able to perform operations on objects that offer certain functionalities, regardless of their type. This is called duck-typing (because if a something runs like a duck, flies like a duck and makes “quacks” like a duck, we may as well consider it a duck and use it like so). This correspond exactly to C++ implicit interfaces, which is the current state for templates.
To Type or Not To Type
So there are upsides and downsides to typing. Is there a way to decide when typing is more appropriate, and when it isn’t?
A interesting point of view was suggested. Typing brings protection and clarity, but with some hassle along the way. So this is appropriate for complex applications, like large software. For smaller tasks, like scripts for examples, typing isn’t worth the hassle and a weakly typed language will do. A compelling illustration of this is that scripting languages tend to be very weakly typed.
This idea really resonated with me, but was finally argued against, because it may involve a sampling bias. Indeed if you’ve worked on big projects involving C++ it’s easy to conceive that typing is necessary. But when you think about it, there are also many very big projects that are written in weekly typed languages, and that are still successful! Facebook is written in PHP for example. So I’m not too sure what to think of this.
C++ in the midst of all this
The following has been explained to me by the one of organizers of the Software Craftmanship meetup himself, Xavier Detant, who has a very rich knowledge about software development.
The type system is so important and useful in C++ that we may think that C++ is a really strongly typed language. But it turns out that there are languages that make even more use of their type system. Here are two:
- Haskell: Haskell is arguably more strongly typed that C++, because types include richer information. This is well illsutrated by Algebraic Data Types, that consist of describing a type with several different forms. For example, a
Tree
can be either aNode
or aTree
bearing a value and twoTree
s as children. And functions taking aTree
perform pattern matching on the two forms of the type. More about how this can be applied to C++ in the talk of Ben Deane cited above.
- Idris: Idris is a very strongly typed language, even more so than Haskell. It share a lot of commonalities with it in its syntax, but the possibilities of the type system are even wider. Idris use dependent types, which means that the choice of a type, like the return type of a function, can be determined by a value. You can look at the doc here if you’re curious about it. I must admit that I haven’t completely wrapped my head around this (for the moment its rather this concept that has wrapped itself around my head), but I think there must be some interesting takeaways from this way of programming. When I get to it, you’ll certainly have a new post about how to use them to write expressive… C++!
If you’re around Paris, I really suggest that you come to the Software Craftmanship meetup. Trust me, you won’t regret it.
Don't want to miss out ? Follow:   Share this post!