c++templatescrtp

C++ and CRTP pattern implementation and compiler dilemma


I'm trying to compile the following bit of code, however there seems to be an issue that I can't seem to resolve:

template <int x>
struct count_x
{
   enum { x_size = x };
};

template <typename y>
struct crtp_base
{
   typedef typename y::count_t count_t;
   crtp_base(const count_t&){}
};

template <int x>
struct derived : public crtp_base<derived<x> >
{
   typedef typename count_x<x> count_t;
   typedef crtp_base<derived<x> > base_t;
   derived(const count_t& c) : base_t(c){}
};


int main()
{
   derived<2> d((count_x<2>()));
   return 0;
}

When compiled wth clang 3.1, the following is the error:

c:\clangllvm\code\example.cc:18:21: error: expected a qualified name after 'typename'
   typedef typename count_x<x> count_t;
                    ^
c:\clangllvm\code\example.cc:18:21: error: typedef name must be an identifier
   typedef typename count_x<x> count_t;
                    ^~~~~~~~~~
c:\clangllvm\code\example.cc:18:28: error: expected ';' at end of declaration list
   typedef typename count_x<x> count_t;
                           ^
                           ;
c:\clangllvm\code\example.cc:20:18: error: no template named 'count_t'; did you mean 'count_x'?
   derived(const count_t& c)
                 ^~~~~~~
                 count_x
c:\clangllvm\code\example.cc:2:8: note: 'count_x' declared here
struct count_x
       ^
c:\clangllvm\code\example.cc:20:18: error: use of class template count_x requires template arguments
   derived(const count_t& c)
                 ^
c:\clangllvm\code\example.cc:2:8: note: template is declared here
struct count_x
       ^
5 errors generated.

I believe it has got something to do with the way the templates are determined at compile time and if they are determined as being a type at the right time. I've also tried adding "using base_t::count_t; " to no avail. Other than that, the diagnostic produced by the compiler has left me really lost. An answer or a suggestion on something to read about this error would be appreciated.


Solution

  • count_x<x> is not a qualified name (it has no :: at all!), so it cannot be preceeded with typename.

    Once you fix this, the code will still fail because the derived type's nested typedefs were not seen by the compiler yet when it instantiates the CRTP base. This other question shows some alternatives.