I’m trying to use a typedef from a subclass in my project, I’ve isolated my problem in the example below.
Does anyone know where I’m going wrong?
template<typename Subclass> class A { public: //Why doesn't it like this? void action(typename Subclass::mytype var) { (static_cast<Subclass*>(this))->do_action(var); } }; class B : public A<B> { public: typedef int mytype; B() {} void do_action(mytype var) { // Do stuff } }; int main(int argc, char** argv) { B myInstance; return 0; }
This is the output I get:
sean@SEAN-PC:~/Documents/LucadeStudios/experiments$ g++ -o test test.cpp test.cpp: In instantiation of ‘A<B>’: test.cpp:10: instantiated from here test.cpp:5: error: invalid use of incomplete type ‘class B’ test.cpp:10: error: forward declaration of ‘class B’
The reason is that when instantiating a class template, all its declarations (not the definitions) of its member functions are instantiated too. The class template is instantiated precisely when the full definition of a specialization is required. That is the case when it is used as a base class for example, as in your case.
So what happens is that
A<B>is instantiated atat which point
Bis not a complete type yet (it is after the closing brace of the class definition). However,A<B>::action‘s declaration requiresBto be complete, because it is crawling in the scope of it:What you need to do is delaying the instantiation to some point at which
Bis complete. One way of doing this is to modify the declaration ofactionto make it a member template.It is still type-safe because if
varis not of the right type, passingvartodo_actionwill fail.