title: C++ casting of templated class
body: <p>I have a question about templates. I would like to have a templated class that contains, say, an array of either float's or double's.</p>
  
  <p>I can write a clone() function that duplicates it. No problem. However, I would like to have another function called cast() that does a translation back and forth between double and float. This has been somewhat discussed before but I don't think the problem is the same:</p>
  
  <p><a href="https://stackoverflow.com/questions/714213/c-template-casting">stackoverflow.com/questions/714213/c-template-casting</a></p>
  
  <p>The problem I have is a compiler error, not a linker error. The error message is:</p>
  
  <pre class="lang-none prettyprint-override"><code>main.cpp: In function `void caster()':
  main.cpp:63: error: expected primary-expression before "double"
  main.cpp:63: error: expected `;' before "double"
  main.cpp:64: error: expected primary-expression before "float"
  main.cpp:64: error: expected `;' before "float"
  main.cpp:65: error: expected primary-expression before '&gt;' token
  main.cpp:65: error: expected primary-expression before ')' token
  </code></pre>
  
  <p>I dumped the code below. The lines 63, 64, and 65 are where I commented with "Error here". </p>
  
  <p>By the way, my compiler is "GNU C++ version 3.4.5 20051201 (Red Hat 3.4.5-2) (x86_64-redhat-linux) compiled by GNU C version 3.4.5 20051201 (Red Hat 3.4.5-2)".</p>
  
  <p>After some Googling, it turns out that someone has already experienced this problem:</p>
  
  <p><a href="http://gcc.gnu.org/ml/gcc-help/2006-04/msg00022.html" rel="nofollow noreferrer">gcc.gnu.org/ml/gcc-help/2006-04/msg00022.html</a></p>
  
  <p>There is a solution here:</p>
  
  <p><a href="http://gcc.gnu.org/ml/gcc-help/2006-04/msg00023.html" rel="nofollow noreferrer">gcc.gnu.org/ml/gcc-help/2006-04/msg00023.html</a></p>
  
  <p>But when the original poster asks as to <strong>why</strong> it works, the answer is not very clear:</p>
  
  <p><a href="http://gcc.gnu.org/ml/gcc-help/2006-04/msg00025.html" rel="nofollow noreferrer">gcc.gnu.org/ml/gcc-help/2006-04/msg00025.html</a></p>
  
  <p>Unfortunately, the link is dead, and I don't own the third edition of Stroustrup. Now, I have my fix, my code works. But, Stackoverflow, <strong>why</strong> does it work?</p>
  
  <hr>
  
  <pre><code>#include &lt;stdio.h&gt;
  
  // =================== This would be the header ===================
  template &lt;class T&gt;
  class foo
  {
  public:
               foo(const T val) {d_data = new double; *d_data = val;}
      virtual ~foo() {delete d_data;};
  
      foo* clone() const;
  
      template&lt;class U&gt;
      foo&lt;U&gt;* cast() const;
  
  private:
      double *d_data;
  };
  
  // =================== This would be the implementation of the class ===================
  template&lt;class T&gt;
  foo&lt;T&gt;* foo&lt;T&gt;::clone() const
  {
      return new foo&lt;T&gt;(*d_data);
  }
  
  template&lt;class T&gt;
  template&lt;class U&gt;
  foo&lt;U&gt;* foo&lt;T&gt;::cast() const
  {
      return new foo&lt;U&gt;(*d_data);
  }
  
  template class foo&lt;float&gt;;
  template class foo&lt;double&gt;;
  
  template foo&lt;float&gt;* foo&lt;float&gt;::cast() const;
  template foo&lt;float&gt;* foo&lt;double&gt;::cast() const;
  template foo&lt;double&gt;* foo&lt;float&gt;::cast() const;
  template foo&lt;double&gt;* foo&lt;double&gt;::cast() const;
  
  // =================== Using the class ===================
  template &lt;class T&gt;
  void caster()
  {
      foo&lt;double&gt; *f1 = NULL;
      foo&lt;float&gt;  *f2 = NULL;
      foo&lt;T&gt;      *f3 = NULL;
  
      // I am looking at something that compiles
      // I don't care about linking for now
      // This will crash at runtime because of
      // NULL, but that's just an example
  
      f1-&gt;cast&lt;double&gt;(); // compiler OK
      f1-&gt;cast&lt;float&gt;();  // compiler OK
      f1-&gt;cast&lt;T&gt;();      // compiler OK
  
      f2-&gt;cast&lt;double&gt;(); // compiler OK
      f2-&gt;cast&lt;float&gt;();  // compiler OK
      f2-&gt;cast&lt;T&gt;();      // compiler OK
  
      f3-&gt;cast&lt;double&gt;(); // Error here
      f3-&gt;cast&lt;float&gt;();  // Error here
      f3-&gt;cast&lt;T&gt;();      // Error here
  
      f3-&gt;foo&lt;T&gt;::template cast&lt;double&gt;(); // It works!
      f3-&gt;foo&lt;T&gt;::template cast&lt;float&gt;();  // It works!
      f3-&gt;foo&lt;T&gt;::template cast&lt;T&gt;();      // It works!
  }
  
  int main(int argc, char **argv)
  {
      return 0;
  }
  </code></pre>