title: What is the best way to tell the compiler to differentiate between two types which hold the same kind of data
body: <p>Suppose we have two types which are basically <code>int</code>s:</p>
  <pre><code>alias UserID = int;
  alias ItemID = int;
  </code></pre>
  <p>And suppose we have two functions which take arguments of the two types:</p>
  <pre><code>void add_user(UserID id) { std::cout &lt;&lt; &quot;Adding user with id &quot; &lt;&lt; id &lt;&lt; '\n'; }
  void add_item(ItemID id) { std::cout &lt;&lt; &quot;Adding item with id &quot; &lt;&lt; id &lt;&lt; '\n'; }
  </code></pre>
  <p>The problem is that we can do:</p>
  <pre><code>UserID uid {5};
  add_item(uid);
  </code></pre>
  <p>And the compiler will not be able to protect me from passing the wrong type because both types alias the same underlying type.</p>
  <p>What is the least boilerplate I need to add to make the compiler differentiate between the two types?</p>
  <p>My current solution is to define the types as structs like this:</p>
  <pre><code>struct UserID
  {
    int val;
    operator int() { return val; }
  };
  
  struct ItemID
  {
    int val;
    operator int() { return val; }
  };
  </code></pre>
  <p>The <code>operator int()</code> is to allow for an implicit conversion to the base type.</p>
  <p>One problem with this approach is that sometimes I need to do arithmetic operations on the types, like for example:</p>
  <pre><code>UserID uid {5};
  ++uid;
  </code></pre>
  <p>Another problem is when these types are passed to a template and a template-argument deduction takes place where the correct type to deduce is <code>int</code> but the compiler is not able to see through the conversion operator.</p>
  <p>I'm wondering if there's a more elegant solution where both types would seamlessly convert to their base type when the base type is required but would still be different when the wrapping type is required.
  What I want is the following:</p>
  <pre><code>add_user(UserID{1}); //compiles
  add_item(ItemID{2}); //compiles
  add_user(ItemID{3}); //doesn't compile
  UserID uid = UserID{4} + 1; //compiles
  ++uid; //compiles
  UserID uid2 = ItemID{5} + 1; //doesn't compile
  </code></pre>
  <p>By 'the least boilerplate' I mean the total boilerplate code I need to write both in the definition of the types as well as in the user code.</p>