6

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.

Switzy
  • 217
  • 1
  • 9

1 Answers1

2

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.

Community
  • 1
  • 1
R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
  • `It is an error to use the typename disambiguator when it is not needed` actually I think that is false. – Jesse Good Oct 12 '12 at 03:12
  • @Jesse I believe it was an error in C++03, but stopped being in C++11. – R. Martinho Fernandes Oct 12 '12 at 03:13
  • @Martinho: I made that change, it now gives another set of errors:c:\clangllvm\code\example.cc:10:24: error: no type named 'count_t' in 'derived<2>' typedef typename y::count_t count_t; ~~~~~~~~~~~~^~~~~~~ c:\clangllvm\code\example.cc:15:25: note: in instantiation of template class 'crtp_base >' requested here struct derived : public crtp_base > ^ c:\clangllvm\code\example.cc:25:15: note: in instantiation of template class 'derived<2>' requested here derived<2> d((count_x<2>())); – Switzy Oct 12 '12 at 03:13
  • GCC 4.7.2 was not sufficiently happy with just this change, and in fact I couldn't find a way to make it so. – ildjarn Oct 12 '12 at 03:21
  • 1
    @ildjarn yeah, this approach just won't work because the nested types were not seen yet at time of instantiation. – R. Martinho Fernandes Oct 12 '12 at 03:28