title: long long int vs. long int vs. int64_t in C++
body: <p>I experienced some odd behavior while using C++ type traits and have narrowed my problem down to this quirky little problem for which I will give a ton of explanation since I do not want to leave anything open for misinterpretation.</p>
  
  <p>Say you have a program like so:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;cstdint&gt;
  
  template &lt;typename T&gt;
  bool is_int64() { return false; }
  
  template &lt;&gt;
  bool is_int64&lt;int64_t&gt;() { return true; }
  
  int main()
  {
   std::cout &lt;&lt; "int:\t" &lt;&lt; is_int64&lt;int&gt;() &lt;&lt; std::endl;
   std::cout &lt;&lt; "int64_t:\t" &lt;&lt; is_int64&lt;int64_t&gt;() &lt;&lt; std::endl;
   std::cout &lt;&lt; "long int:\t" &lt;&lt; is_int64&lt;long int&gt;() &lt;&lt; std::endl;
   std::cout &lt;&lt; "long long int:\t" &lt;&lt; is_int64&lt;long long int&gt;() &lt;&lt; std::endl;
  
   return 0;
  }
  </code></pre>
  
  <p>In both 32-bit compile with GCC (and with 32- and 64-bit MSVC), the output of the program will be:</p>
  
  <pre><code>int:           0
  int64_t:       1
  long int:      0
  long long int: 1
  </code></pre>
  
  <p>However, the program resulting from a 64-bit GCC compile will output:</p>
  
  <pre><code>int:           0
  int64_t:       1
  long int:      1
  long long int: 0
  </code></pre>
  
  <p>This is curious, since <code>long long int</code> is a signed 64-bit integer and is, for all intents and purposes, identical to the <code>long int</code> and <code>int64_t</code> types, so logically, <code>int64_t</code>, <code>long int</code> and <code>long long int</code> would be equivalent types - the assembly generated when using these types is identical.  One look at <code>stdint.h</code> tells me why:</p>
  
  <pre><code># if __WORDSIZE == 64
  typedef long int  int64_t;
  # else
  __extension__
  typedef long long int  int64_t;
  # endif
  </code></pre>
  
  <p>In a 64-bit compile, <code>int64_t</code> is <code>long int</code>, not a <code>long long int</code> (obviously).</p>
  
  <p>The fix for this situation is pretty easy:</p>
  
  <pre><code>#if defined(__GNUC__) &amp;&amp; (__WORDSIZE == 64)
  template &lt;&gt;
  bool is_int64&lt;long long int&gt;() { return true; }
  #endif
  </code></pre>
  
  <p>But this is horribly hackish and does not scale well (actual functions of substance, <code>uint64_t</code>, etc).  <strong>So my question is:</strong> Is there a way to tell the compiler that a <code>long long int</code> is the also a <code>int64_t</code>, just like <code>long int</code> is?</p>
  
  <hr>
  
  <p>My initial thoughts are that this is not possible, due to the way C/C++ type definitions work.  There is not a way to specify type equivalence of the basic data types to the compiler, since that is the compiler's job (and allowing that could break a lot of things) and <code>typedef</code> only goes one way.</p>
  
  <p>I'm also not too concerned with getting an answer here, since this is a super-duper edge case that I do not suspect anyone will ever care about when the examples are not horribly contrived (does that mean this should be community wiki?).</p>
  
  <hr>
  
  <p><strong>Append</strong>: The reason why I'm using partial template specialization instead of an easier example like:</p>
  
  <pre><code>void go(int64_t) { }
  
  int main()
  {
      long long int x = 2;
      go(x);
      return 0;
  }
  </code></pre>
  
  <p>is that said example will still compile, since <code>long long int</code> is implicitly convertible to an <code>int64_t</code>.</p>
  
  <hr>
  
  <p><strong>Append</strong>: The only answer so far assumes that I want to know if a type is 64-bits.  I did not want to mislead people into thinking that I care about that and probably should have provided more examples of where this problem manifests itself.</p>
  
  <pre><code>template &lt;typename T&gt;
  struct some_type_trait : boost::false_type { };
  
  template &lt;&gt;
  struct some_type_trait&lt;int64_t&gt; : boost::true_type { };
  </code></pre>
  
  <p>In this example, <code>some_type_trait&lt;long int&gt;</code> will be a <code>boost::true_type</code>, but <code>some_type_trait&lt;long long int&gt;</code> will not be.  While this makes sense in C++'s idea of types, it is not desirable.</p>
  
  <p>Another example is using a qualifier like <code>same_type</code> (which is pretty common to use in C++0x Concepts):</p>
  
  <pre><code>template &lt;typename T&gt;
  void same_type(T, T) { }
  
  void foo()
  {
      long int x;
      long long int y;
      same_type(x, y);
  }
  </code></pre>
  
  <p>That example fails to compile, since C++ (correctly) sees that the types are different.  g++ will fail to compile with an error like: no matching function call <code>same_type(long int&amp;, long long int&amp;)</code>.</p>
  
  <p>I would like to stress that I understand <em>why</em> this is happening, but I am looking for a workaround that does not force me to repeat code all over the place.</p>