title: Cannot use nested class of templated class as a type
body: <p>I'm playing with an implementation of a generic <code>Tokenizer</code> class wrapped inside a <code>tok</code> namespace.</p>
  <pre class="lang-cpp prettyprint-override"><code>template &lt;typename TokenEnum&gt;
  class Tokenizer {
  public:
      struct Token {
          // ...
      };
  
      class Context {
          // ...
      };
  
      // Important for later.
      using MatchFunc = std::function&lt;std::size_t(Context &amp;ctx)&gt;;
  
      // ...
  
  private:
      // ...
  
  };
  </code></pre>
  <p>At the moment, I can declare methods and member variables for the <code>Tokenizer</code> class alright.</p>
  <pre class="lang-cpp prettyprint-override"><code>// Example method of Tokenizer
  template &lt;typename TokenEnum&gt;
  void Tokenizer&lt;TokenEnum&gt;::addMatchFunc(MatchFunc func, TokenEnum type)
  {
      // ...
  }
  </code></pre>
  <p>Although sometimes I've had to add the <code>typename</code> keyword in front of some types for certain methods of <code>Tokenizer</code> for reasons I have half understood from StackOverflow.</p>
  <pre class="lang-cpp prettyprint-override"><code>// Does not compile unless I specify typename near &quot;std::vector&lt;typename Tokenizer&lt;TokenEnum&gt;::Token&gt;&gt;&quot;
  template &lt;typename TokenEnum&gt;
  std::unique_ptr&lt;std::vector&lt;typename Tokenizer&lt;TokenEnum&gt;::Token&gt;&gt; Tokenizer&lt;TokenEnum&gt;::tokenize(const std::string &amp;rawString)
  {
      // ...
  }
  </code></pre>
  <p>I can also declare methods and member variables for the <code>Tokenizer::Context</code> nested class just fine.</p>
  <pre class="lang-cpp prettyprint-override"><code>// Example method of Tokenizer::Context
  template &lt;typename TokenEnum&gt;
  bool Tokenizer&lt;TokenEnum&gt;::Context::match(const std::string &amp;comp) const
  {
      // ...
  }
  </code></pre>
  <p>Following that, I have defined a <code>Matchers</code> class outside the <code>Tokenizer</code> class. It contains a bunch of static functions which comply to <code>Tokenizer::MatchFunc</code>.</p>
  <p>Here is the definition for the <code>Matchers</code> class.</p>
  <pre class="lang-cpp prettyprint-override"><code>#include &quot;Tokenizer.hpp&quot;
  
  template &lt;typename TokenEnum&gt;
  class Matchers {
  public:
      static std::size_t whitespace(Tokenizer&lt;TokenEnum&gt;::Context &amp;ctx);
      template &lt;char charValue&gt;
      static std::size_t character(Tokenizer&lt;TokenEnum&gt;::Context &amp;ctx);
      template &lt;char *stringValue&gt;
      static std::size_t string(Tokenizer&lt;TokenEnum&gt;::Context &amp;ctx);
      static std::size_t word(Tokenizer&lt;TokenEnum&gt;::Context &amp;ctx);
      static std::size_t integer(Tokenizer&lt;TokenEnum&gt;::Context &amp;ctx);
  
  private:
  
  };
  </code></pre>
  <p>This <code>Matchers</code> class fails to compile. For each method of <code>Matchers</code>, it throws the following errors.</p>
  <pre><code>In file included from tests/tok/Matchers.cpp:11:
  deps/tok/Matchers.hpp:19:35: error: ‘Tokenizer&lt;TokenEnum&gt;::Context’ is not a type
     19 |     static std::size_t whitespace(Tokenizer&lt;TokenEnum&gt;::Context &amp;ctx);
        | 
  </code></pre>
  <pre><code>In file included from deps/tok/Matchers.hpp:33,
                   from tests/tok/Matchers.cpp:11:
  deps/tok/Matchers.ipp:13:13: error: ‘std::size_t tok::Matchers&lt;TokenEnum&gt;::whitespace’ is not a static data member of ‘class tok::Matchers&lt;TokenEnum&gt;’
     13 | std::size_t Matchers&lt;TokenEnum&gt;::whitespace(Tokenizer&lt;TokenEnum&gt;::Context &amp;ctx)
        |             ^~~~~~~~~~~~~~~~~~~
  </code></pre>
  <pre><code>deps/tok/Matchers.ipp:13:67: error: template definition of non-template ‘std::size_t tok::Matchers&lt;TokenEnum&gt;::whitespace’
     13 | std::size_t Matchers&lt;TokenEnum&gt;::whitespace(Tokenizer&lt;TokenEnum&gt;::Context &amp;ctx)
        | 
  </code></pre>
  <pre><code>deps/tok/Matchers.ipp:13:76: error: ‘ctx’ was not declared in this scope
     13 | std::size_t Matchers&lt;TokenEnum&gt;::whitespace(Tokenizer&lt;TokenEnum&gt;::Context &amp;ctx)
        |   
  </code></pre>
  <p>For reference, here is the full list of header files used.</p>
  <p><strong>Tokenizer.hpp</strong></p>
  <pre class="lang-cpp prettyprint-override"><code>#pragma once
  
  #include &lt;string&gt;
  #include &lt;vector&gt;
  #include &lt;memory&gt;
  #include &lt;functional&gt;
  #include &lt;utility&gt;
  
  namespace tok {
  
  template &lt;typename TokenEnum&gt;
  class Tokenizer {
  public:
      struct Token {
          Token(TokenEnum type, std::size_t start, std::size_t length);
  
          TokenEnum type;
          std::size_t start;
          std::size_t length;
      };
  
      class Context {
      public:
          Context(const std::vector&lt;Token&gt; &amp;tokens, const std::string &amp;rawString, const std::size_t &amp;pos);
          bool isAtEnd() const;
          bool match(char character) const;
          bool match(const std::string &amp;comp) const;
          bool matchDigit() const;
          bool matchAlpha() const;
          bool consume(char character);
          bool consume(const std::string &amp;comp);
          bool consume(std::size_t chars = 1);
          bool consumeDigit();
          bool consumeAlpha();
          void reset();
          char currentChar() const;
          std::size_t result() const;
  
      private:
          const std::vector&lt;Token&gt; &amp;tokens;
          const std::string &amp;rawString;
          const std::size_t length;
          const std::size_t &amp;pos;
          std::size_t index;
      };
  
      using MatchFunc = std::function&lt;std::size_t(Context &amp;ctx)&gt;;
  
      void setUndefinedToken(TokenEnum type);
      void setWhitespaceMatchFunc(MatchFunc func);
      void addMatchFunc(MatchFunc func, TokenEnum type);
      std::unique_ptr&lt;std::vector&lt;Token&gt;&gt; tokenize(const std::string &amp;rawString);
  
  protected:
  
  private:
      std::vector&lt;std::pair&lt;MatchFunc, TokenEnum&gt;&gt; matchers;
      MatchFunc whitespaceMatcher;
      TokenEnum undefinedToken;
      bool handlesWhitespace{false};
  
  };
  
  #include &quot;Tokenizer.ipp&quot;
  #include &quot;Context.ipp&quot;
  #include &quot;Token.ipp&quot;
  
  }
  </code></pre>
  <p><strong>Matchers.hpp</strong></p>
  <pre class="lang-cpp prettyprint-override"><code>#pragma once
  
  #include &lt;cstdint&gt;
  #include &quot;Tokenizer.hpp&quot;
  
  namespace tok {
  
  template &lt;typename TokenEnum&gt;
  class Matchers {
  public:
      static std::size_t whitespace(Tokenizer&lt;TokenEnum&gt;::Context &amp;ctx);
      template &lt;char charValue&gt;
      static std::size_t character(Tokenizer&lt;TokenEnum&gt;::Context &amp;ctx);
      template &lt;char *stringValue&gt;
      static std::size_t string(Tokenizer&lt;TokenEnum&gt;::Context &amp;ctx);
      static std::size_t word(Tokenizer&lt;TokenEnum&gt;::Context &amp;ctx);
      static std::size_t integer(Tokenizer&lt;TokenEnum&gt;::Context &amp;ctx);
  
  protected:
  
  private:
  
  };
  
  #include &quot;Matchers.ipp&quot;
  
  }
  </code></pre>
  <p><strong>Notes</strong></p>
  <p>Before implementing the <code>Matchers</code> class. The following compiled and ran fine.</p>
  <pre class="lang-cpp prettyprint-override"><code>enum class GolangToken {
      OpenBrace,
      ClosedBrace,
      Integer,
      For,
      While,
      // ...
  };
  
  tok::Tokenizer&lt;GolangToken&gt; tokenizer;
  tokenizer.addMatchFunc(matchOpenBrace, GolangToken::OpenBrace);
  tokenizer.addMatchFunc(matchClosedBrace, GolangToken::ClosedBrace);
  tokenizer.addMatchFunc(matchInteger, GolangToken::Integer);
  tokenizer.addMatchFunc(matchWhile, GolangToken::While);
  tokenizer.addMatchFunc(matchFor, GolangToken::For);
  auto tokens = tokenizer.tokenize(&quot;{}1293 for while&quot;);
  </code></pre>