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’
Not exactly what you were asking, but you can make action a template member function:
template<typename Subclass>
class A {
public:
//Why doesn't it like this?
template<class V> void action(V var) {
(static_cast<Subclass*>(this))->do_action();
}
};
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;
}
You need to use a pointer or a reference as the proper type is not known at this time the compiler can not instantiate it.
Instead try:
void action(const typename Subclass::mytype &var) {
(static_cast<Subclass*>(this))->do_action();
}
You can get around this by using a traits class:
It requires you set up a specialsed traits class for each actuall class you use.
template<typename SubClass>
class SubClass_traits
{};
template<typename Subclass>
class A {
public:
void action(typename SubClass_traits<Subclass>::mytype var)
{
(static_cast<Subclass*>(this))->do_action(var);
}
};
// Definitions for B
class B; // Forward declare
template<> // Define traits for B. So other classes can use it.
class SubClass_traits<B>
{
public:
typedef int mytype;
};
// Define B
class B : public A<B>
{
// Define mytype in terms of the traits type.
typedef SubClass_traits<B>::mytype mytype;
public:
B() {}
void do_action(mytype var) {
// Do stuff
}
};
int main(int argc, char** argv)
{
B myInstance;
return 0;
}
You derive B
from A<B>
, so the first thing the compiler does, once it sees the definition of class B
is to try to instantiate A<B>
. To do this it needs to known B::mytype
for the parameter of action
. But since the compiler is just in the process of figuring out the actual definition of B
, it doesn't know this type yet and you get an error.
One way around this is would be to declare the parameter type as another template parameter, instead of inside the derived class:
template<typename Subclass, typename Param>
class A {
public:
void action(Param var) {
(static_cast<Subclass*>(this))->do_action(var);
}
};
class B : public A<B, int> { ... };
Source: Stackoverflow.com