Federico Fuga

Engineering, Tech, Informatics & science

Strong Typing PODs

07 Sep 2017 21:29 +0000 c++ Code
Identifiying object by a numerical integer is an almost trivial task. In DISPLACE, a very complex simulator I am involved with, there are many of different categories of objects that model different categoris of agents in the simulator, like vessels, marine locations, ships, ports, and so on.







Each object has an Id, and it was very natural, at the start of the project, to implement it using an **int**.







Problems started when we decided, for optimization purpose, to shrink the memory footprint, to use smaller int instead.







Indeed, there could be at most 65535 nodes, and at most 256 node types, and each was modeled with an int.







The mess started when we found that ids were mixed, and assigning a "Vessel Id" to a "Node Id" was very easy... with obvious, tragic effect.







So there were two problems here: the type opacity, and the strong typing. 







Using PODs were natural, but POD can be assigned to each other (weak types) and, since their storage is predefined, they cannot be changed easily (they aren't opaque).







If the PODs we're using do not require complex methods but they must only represent an integer (a POD) with some meaning, a concept, wrapping them in a class can be tedious. This is why I created the following header file:







template <typename T, typename TAG>
class strong_type {
    T value;
public:
    using Base = T;
    using Tag = TAG;

    explicit strong_type (T v)
    : value (v) {}

    T get() const { return value; }
};







 







The class is very simple: Base and Tag allow extracting the types, **Base** of the container/Wrapped POD, and **Tag** of the structure implementing the Tagging of the new type. I implemented **Get()** to access the POD value, because we don't want the type to be deduced using a **cast**.







Here the test file (I'm a fanatic of TDD, of course.)







 







#include <gtest/gtest.h>
#include <strongtype.h>
#include <type_traits>

TEST(StrongType, usage)
{
    struct IdTag {};
    using ID = strong_type<int,IdTag>;

    ID i (10);

    struct ValueTag {};
    using Value = strong_type<ID::Base, ValueTag>;

    Value j (10);

    static_assert(!std::is_convertible<ID,Value>::value, "ID and values are convertible!");

    ASSERT_EQ(i.get(), j.get());
}






Note the usage of **static_assert** to check that the types cannot be assigned or converted automatically by the compiler.







You can find the [snippet here](https://bitbucket.org/snippets/ffuga/pKedxr/making-pod-strong-typed).







Happy Coding!