Properly designing types and data structures is, I think, a very important step when programming. It forces to get a good grasp on the domain of the problem uphill, and ensures that a good level of granularity and modularity will make coding safe and easy downhill. It's also a key point to benefit from the power of compiled and typed languages: typed data structures are one way for the compiler to check that the code does what it was intended to do, unlike untyped interpreted languages where one can code absolute nonsense which will never be noticed until it crashes in the hands of the user.
As I was thinking again about this, I wondered if and how it could be possible (in C) to check quantity unit at compile time. In other word, how to detect at compile time a mistake like qtyUnitA += qtyUnitB. If each quantity is an integer or float or any basic type, the compiler won't see any problem here. At best we may have a message about mixing signed and unsigned types.
If you wonder if that's really a problem, think about development in an international context. For example, in a financial software manipulating various currencies, how to guarantee that you're not adding yen and euro values while both are represented with some kind of integer type. Or, a software dealing with distance both in meter and in foot ? Or liter and gallon ? That kind of catastrophic little details...
It's actually quite simple: wrapping the desired type into a structure is all it takes. To create new type quantity easily, I define a macro as follow:
Then one can define "unit quantity" types as follow:
Then, instead of having, for example:
One would have:
A tad more verbose, no pain no gain. Now you can't mistakenly write distA + distB. Yes, because the compiler don't know what to do with that + on two structures, hence you can't neither do distA += distA. Let's solve that by redefining the basic operators for our "unit quantity" types:
To support operations like distA = 3 * distA one can also define operator mixing "unit quantity" and scalar quantity:
Mathematical functions could be supported as follow:
And there would also certainly be need for logical operator which would look like this:
Operations can now be performed on those types:
And most importantly, mistakenly mixing types doesn't compile any more:
Using _Generic one could also make some automatic unit conversion for valid pairs if desired (see also this previous post on that subject).
In term of performance, the "unit quantity" type has one single field, hence it's the same size in memory as using the wrapped basic type (assert(sizeof(q1)==sizeof(qty_t)); ok!), and it produces exactly the same assembly code.
Note that this concept of "unit quantity" isn't limited to standard units. For example, imagine a physic engine where you want to be sure you're not mixing vectors representing position and vectors representing speed. It may look like this (here using a macro for step to illustrate the use of _Generic but a function may be more appropriate):
So far that looks promising. I hope I'll find an occasion to try this on a personal project to see if it holds on a real, large and complex project.