title: Function template declaration order affects visibility (sometimes)
body: <p>I'm trying to create a function:</p>
  
  <pre><code>template &lt;typename T&gt;
  void doIt( T*&amp; p )
  {
     if ( !p ) { return; }
     T&amp; ref = *p;
     getClassName( ref );
  }
  </code></pre>
  
  <p>where the behavior varies according to the type of <code>p</code> passed in. In particular, the version of <code>getClassName</code> called should depend upon the type of <code>p</code>. In the following example, I can successfully call:</p>
  
  <pre><code>doIt&lt;myClass1&gt;( myClass1*&amp; )
  doIt&lt;myClass1&lt;int&gt; &gt;( myClass1*&amp; )
  doIt&lt;myClass2&gt;( myClass2*&amp; )
  doIt&lt;myClass2&lt;int&gt; &gt;( myClass2*&amp; )
  </code></pre>
  
  <p>but it fails when I call:</p>
  
  <pre><code>doIt&lt; std::vector&lt;int, std::allocator&lt;int&gt; &gt; &gt;( std::vector&lt;int, std::allocator&lt;int&gt;&gt;*&amp; )
  </code></pre>
  
  <p>with the error:</p>
  
  <pre><code>a.cxx: In function ‘void doIt(T*&amp;) [with T = std::vector&lt;int, std::allocator&lt;int&gt; &gt;]’:
  ba.cxx:87:   instantiated from here
  a.cxx:33: error: invalid initialization of reference of type ‘MyClass1&amp;’ from expression of type ‘std::vector&lt;int, std::allocator&lt;int&gt; &gt;’
  a.cxx:16: error: in passing argument 1 of ‘const char* getClassName(MyClass1&amp;)’
  </code></pre>
  
  <p>(gcc 4.2.4). </p>
  
  <p>If I move the declaration of: </p>
  
  <pre><code>template&lt;typename T, typename A&gt;
  char const* getClassName( std::vector&lt;T,A&gt;&amp; ) { printf("std::vector&lt;T,A&gt;\n"); return NULL; }
  </code></pre>
  
  <p>before doIt -- then it compiles. So,</p>
  
  <ul>
  <li>Why is it required that <code>getClassName( std::vector&lt;T,A&gt;&amp; )</code> appears before <code>doIt</code> but not <code>getClassName( MyClass2T&lt;T&gt;&amp; )</code></li>
  <li>What can I do to make <code>doIt</code> independent of <code>std::vector</code>? (I want to be able to place <code>doIt</code> in its own header and not have to know about <code>std::vector</code>, or any of the specializations, which will be user-defined).</li>
  </ul>
  
  <p>.</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;assert.h&gt;
  #include &lt;vector&gt;
  
  //template&lt;typename T&gt;
  //char const* getClassName( T&amp; );
  
  //template&lt;typename T, typename A&gt;
  ////char const* getClassName( std::vector&lt;T,A&gt;&amp; ) { printf("std::vector&lt;T,A&gt;\n"); return NULL; }
  
  #if 1
  // ---------  MyClass2
  struct MyClass1
  {};
  
  char const* getClassName( MyClass1&amp; ) { printf("MyClass1\n"); return NULL; }
  
  // ---------  MyClass1T
  template&lt; typename T&gt;
  struct MyClass1T
  {};
  
  template&lt;typename T&gt;
  char const* getClassName( MyClass1T&lt;T&gt;&amp; ) { printf("MyClass1T&lt;T&gt;\n"); return NULL; }
  #endif
  
  
  template &lt;typename T&gt;
  void doIt( T*&amp; p )
  {
     if ( !p ) { return; }
     T&amp; ref = *p;
     getClassName( ref );
  }
  
  
  // ---------  MyClass2
  struct MyClass2
  {};
  
  
  // declared after doIt, OK.
  char const* getClassName( MyClass2&amp; ) { printf("MyClass2\n"); return NULL; }
  
  // ---------  MyClass2T
  template&lt; typename T&gt;
  struct MyClass2T
  {};
  
  // declared after doIt, OK.
  template&lt;typename T&gt;
  char const* getClassName( MyClass2T&lt;T&gt;&amp; ) { printf("MyClass2T&lt;T&gt;\n"); return NULL; }
  
  template&lt;typename T, typename A&gt;
  char const* getClassName( std::vector&lt;T,A&gt;&amp; ) { printf("std::vector&lt;T,A&gt;\n"); return NULL; }
  
  
  
  void test()
  {
  #if 1
     MyClass1 mc1;
     MyClass1* mc1p = &amp;mc1;
     doIt( mc1p );
  
     MyClass2 mc2;
     MyClass2* mc2p = &amp;mc2;
     doIt( mc2p );
  
     MyClass1T&lt;int&gt; mc1t;
     MyClass1T&lt;int&gt;* mc1tp = &amp;mc1t;
     doIt( mc1tp );
  
     MyClass2T&lt;int&gt; mc2t;
     MyClass2T&lt;int&gt;* mc2tp = &amp;mc2t;
     doIt( mc2tp );
  
     // Nested templates are OK.
     MyClass2T&lt;MyClass1&gt; mc2t2;
     MyClass2T&lt;MyClass1&gt;* mc2tp2 = &amp;mc2t2;
     doIt( mc2tp2 );
  #endif
  
  #if 1
     std::vector&lt;int&gt; v;
     std::vector&lt;int&gt;* vp = &amp;v;
     doIt( vp );                   // FAIL!
  #endif
  }
  </code></pre>