Why am I getting an error when accessing a typedef in a derived class via CRTP?

I am having trouble understanding why the code below is not compiling - can anyone explain it?

How to access typedef in a derived class from a base class?

template<class Derived> struct Test { template<class T> typename Derived::value_type foo(T); }; struct Derived : public Test<Derived> { typedef int value_type; }; 
+4
source share
2 answers

At the time of the Derived announcement, Derived is not yet a complete type - you just started declaring it! Therefore, in the specialization Test<Derived> the template argument is an incomplete type, and therefore you should not refer to a nested name, for example Derived::value_type , to this circular logic.

You can solve the problem by creating a separate argument for the return type:

 template <typename T, typename R> struct Test { template <typename U> R foo(U); }; template <typename R> struct BasicDerived : public Test<BasicDerived, R> { typedef R value_type; }; typedef BasicDerived<int> Derived; 
+6
source

You cannot access typedef or members of a template class directly in the base class, because at this point it is not a complete type. This can lead to cyclical behavior:

 template<class Derived> struct Test { typedef typename Derived::value_type foo; }; struct Derived : public Test<Derived> { typedef Test<Derived>::foo value_type; }; 

However, you can refer to the members of the template class in methods, since they are not fully created:

 template<class Derived> struct Test { void foo() { typename Derived::value_type bar; } }; struct Derived : public Test<Derived> { typedef int value_type; }; 

Alternatively, depending on what you are trying, you can pass a typedef as an additional template parameter:

 template<typename value_type, class Derived> struct Test { template<class T> value_type foo(T); }; struct Derived : public Test<int, Derived> { typedef int value_type; }; 
+5
source

All Articles