c++ strong types holy grail

This is the second installment of an aptly named “c++ strong duck” post. (a title is an act of deliberate sarcasm vs ‘duck typing’ ). If you haven’t before please make a slight detour to that post, for a brief introduction on strong types, as an antidote to “type punning“.

Exact types of Fasteners
Exact types of Fasteners type. It is impossible to confuse them with each other.

I just thought to make a little post about the use-case scenarios of this seemingly “toy concept”, whatever that label “toy concept” means.

For me the core benefits are simplicity and applicability to both C and C++. And , I indeed might think, I can show a few, perhaps surprisingly effective, examples.

I see nothing wrong with using macros in this instance. Here is the core single macro.  Please rename it if it clashes with something in your development environment.

That creates the strong type , a simple struct with the required type name and with the member v of the required value_type.

That is not “C”. I am sure C aficionados, will be more than able to make a C version.  But. This is one context where C++ comes out as superior. Especially because of the ability to have nested typedefs.

How allowing typedefs inside C structs will “ruin” the C, I honestly do fail to see?  Yes, I know that will introduce the scope resolution operator in C aka :: . Let’s just not “go there” in this post. Disclaimer: I do like C and often, I am reminded how effective it can be.

Let’s dive into some hopefully convincing use cases.

First classical use case: strong types as “units”. We want units to be distinctive types, not intrinsic (native) types, where only values are named appropriately.

There are also numerous examples where people have been inventing and coding quite complex unit types, as large C++ classes.

I do not do that. Here is how we generate few declaration of strong types, representing various units.

That’s about it.  Above we have eight strong types. They al have name and value_type. They are all structs. Extremely simple structs.

Do not lose the fact, about the simplicity of the code generated above.  I have not seen a simpler implementation of the concept of the strong type.  But that is not all in the goodie bag.

Strong types are literals

If, value types are literals too.  The above “unit” Meter is a literal.

The Use

Now we can easily code rather safe and simple transformations of linear units, aka lengths. For example.

Above we follow the C++ “pass by value” mandate. Thus we can pass temporaries, and we need no constant arguments.

Above can be all used at compile time, too.

Also, note how these overloads will never confuse the compiler, and in turn, the compiler will never confuse you. One quality, I am sure you being a C++ aficionado, do appreciate very much.

The usage.

Non allowed transformations simply do not compile.

Nested strong types

Strong types are indeed useful as class members. In which case they are nested strong types.

That is indeed simple and it works smoothly as long as intrinsic types are used for value types of nested types.  Otherwise things will go very complex very quickly.

(Note: in this post I am using C++20 “designated initializers“. They are already working in all three main compilers.)

So, let’s nest the above nested struct into the Point struct.

Not so bad. But. To reach the actual X and Y values, on the Point, one must type:

Not exactly simple or trivial.  So, please stick to single level nesting.

The above declaration is useful and allows for simple, elegant and safe code. No deep nesting necessary. Example.

The key point is one can not make a mistake of mixing x and y. They are  strong types, not intrinsic arithmetic types. That is the whole point of using strong types. One simply can not make a mistake.

Complex nested strong types

Often times , we have complex scenarios and we simply can not evade nesting complex strong types as class members. With a bit of thinking we can solve that issue too.

Let us assume we want to add some color to our Duffy, the strong  duck from the fist post on strong types.

Color is combination of red, green and blue components.  And them components are expressed as hex values. Let’s generate the required code for this  design.

With the method mix() above we have solved the complexity required by users actually wishing to use the Color instances. Here is the Duck type.

Using the above here is how we create duffy but with some color added.

It even looks simple and logical. Now let’s see the usability.

And to actually use the color we do

Which type is std::array<Hex,3>.

I certainly will use this in production code. I hope, you have seen some value of this simple concept for your projects too.