0

Possible Duplicate:
“Inherited” types using CRTP and typedef

template<typename T>
struct A {
  typename T::Sub  s;
};

struct B : A<B> {
  struct Sub {};
};

Clang is reporting this error:

todo.cc:3:15: error: no type named 'Sub' in 'B'
  typename T::Sub  s;
  ~~~~~~~~~~~~^~~
todo.cc:6:12: note: in instantiation of template class 'A<B>' requested here
struct B : A<B> {
           ^

How can I get this to work?

Community
  • 1
  • 1
Łukasz Lew
  • 48,526
  • 41
  • 139
  • 208

2 Answers2

2

B is an incomplete class at the point it requests the instantiation of A<B>.

This means that you can only refer to B within template methods on A, as the instantiation of those will be delayed until B is complete.

ecatmur
  • 152,476
  • 27
  • 293
  • 366
1

Since B inherits from A<B>, A<B> must be constructed before B is.

Since you are using the CRTP, this means that B is an incomplete class when A<B> is being constructed. Due to this, the compiler cannot tell if B has a member field Sub, thus failing at compiling.

Note that, this time, gcc gives a more meaningful error:

$ cat crtp.cpp

template<typename T>
struct A {
      typename T::Sub  s;
};

struct B : A<B> {
      struct Sub {};
};

$ g++ -c crtp.cpp -o crtp.o

crtp.cpp: In instantiation of ‘A<B>’:
crtp.cpp:6:17:   instantiated from here
crtp.cpp:3:21: error: invalid use of incomplete type ‘struct B’
crtp.cpp:6:8: error: forward declaration of ‘struct B’
akappa
  • 10,220
  • 3
  • 39
  • 56