title: Splitting template class definitions and declarations fails for nested templates
body: <p>I know what I want, but I don't know how to tell the compiler what I want. I have split declarations and method definitions in .h and .cpp file, but the .cpp file gets included in the header, so all I did was separate declarations and definitions.</p>
  <p>header file (avltree.h) - it includes the source file!:</p>
  <pre><code>template &lt; class KEY_T, class DATA_T &gt;
  class CAvlTree {
      public:
  
          //----------------------------------------
  
          template &lt; class KEY_T, class DATA_T &gt;
          class CNode;
  
          typedef CNode&lt; KEY_T, DATA_T&gt; * tNodePtr;
  
          template &lt; class KEY_T, class DATA_T &gt;
          class CNode {
              public:
                  KEY_T       key;
                  DATA_T      data;
                  CNode&lt; KEY_T, DATA_T &gt; *    left;
                  CNode&lt; KEY_T, DATA_T &gt; *    right;
                  char        balance;
  
                  CNode() : left(nullptr), right(nullptr), balance(0) {}
  
                  CNode(KEY_T key, DATA_T data) : 
                      key (key), data (data), left(nullptr), right(nullptr), balance(0) {}
              };
  
          //----------------------------------------
  
          template &lt; class KEY_T, class DATA_T &gt;
          struct tAvlInfo {
              CNode&lt; KEY_T, DATA_T&gt; * root;
              CNode&lt; KEY_T, DATA_T&gt; * current;
              KEY_T       key;
              bool        isDuplicate;
              bool        branchChanged;
          };
  
          typedef bool (* tNodeProcessor) (CNode&lt; KEY_T, DATA_T&gt; * nodePtr);
  
      private:
  
          tAvlInfo&lt; KEY_T, DATA_T &gt;   m_info;
  
          //----------------------------------------
  
      public:
  
          DATA_T* Find(KEY_T&amp; key);
  
      private:
  
          CNode&lt; KEY_T, DATA_T&gt; * AllocNode(void);
  };
  
  #include &quot;avltree.cpp&quot;
  </code></pre>
  <p>source file (avltree.cpp):</p>
  <pre><code>template &lt; typename KEY_T, typename DATA_T &gt;
  DATA_T* CAvlTree&lt; KEY_T, DATA_T &gt;::Find (KEY_T&amp; key)
  E0276   name followed by '::' must be a class or namespace name
  {
     CNode* root;
  
     for (CNode* node = m_info.root; node; ) {
         if (key &lt; node-&gt;key)
             node = node-&gt;left;
         else if (key &gt; root-&gt;key)
             node = node-&gt;right;
         else {
             m_info.current = node;
             return &amp;node-&gt;data;
         }
     }
  return nullptr;
  }
  
  
  template &lt; typename KEY_T, typename DATA_T &gt;
  CNode* CAvlTree&lt; KEY_T, DATA_T &gt;::AllocNode (void)
  E0020   identifier &quot;CNode&quot; is undefined
  E0864   CAvlTree is not a template
  {
      if (m_info.current = new CNode &lt; KEY_T, DATA_T &gt;) {
          m_info.branchChanged = true;
          return m_info.current;
      }
      return nullptr;
  }
  </code></pre>
  <p>What the compiler says (VS 2019 community, c++2020 enabled):</p>
  <pre><code>E0276   name followed by '::' must be a class or namespace name
  E0020   identifier &quot;CNode&quot; is undefined
  E0864   CAvlTree is not a template
  </code></pre>
  <p>I have no bloody clue how to write this down the correct way. Please enlighten me.</p>
  <p>I have similar code for a template class with a single typename which works, but cannot conclude from that how to do this for two typenames.</p>
  <p>Using the tNodePtr type instead of CNode&lt; KEY_T, DATA_T &gt; * in my source code also doesn't work.</p>
  <p>Btw, I know that the compiler doesn't &quot;transfer&quot; KEY_T and DATA_T from the CAvlTree declaration just because I am using the same names.</p>