Skip to main content

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;

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::EntityIDTag> EntityID;
typedef Explicit<int, internal::ModelIDTag> ModelID;

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:

typedef Explicit<int, struct EntityIDTag> EntityID;
typedef Explicit<int, struct ModelIDTag> ModelID;
Source Link
mindriot
  • 264
  • 2
  • 4

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::EntityIDTag> EntityID;
typedef Explicit<int, internal::ModelIDTag> ModelID;