I had a similar case where I wanted to distinguish different meanings of some integer values, and forbid implicit conversions between them. I wrote a generic class like this:
template <typename T, typename Meaning>
struct Explicit
{
//! Default constructor does not initialize the value.
Explicit()
{ }
//! Construction from a fundamental value.
Explicit(T value)
: value(value)
{ }
//! Implicit conversion back to the fundamental data type.
inline operator T () const { return value; }
//! The actual fundamental value.
T value;
};
Of course if you want to be even more safe, you can make the T
constructor explicit
as well. The Meaning
is then used like this:
namespace internal {
struct EntityIDTag { };
struct ModelIDTag { };
}
typedef Explicit<int, internal::struct EntityIDTag> EntityID;
typedef Explicit<int, internal::struct ModelIDTag> ModelID;