I'm having trouble passing a class DerivedObject
(part of class DerivedClass
derived from template class BaseClass
) derived from BaseObject
(part of template class BaseClass
) as a template argument to template class BaseClass
.
This way, both Base and Derived classes have the access to the object pool, that can contain derived objects. This sounds a bit confusing, so here is the example:
template <class TDerivedClass, class TDerivedObject>
class BaseClass
{
protected:
class BaseObject
{
// Class implementation
}
void foo()
{
static_cast<TDerivedClass*>(this)->foo();
}
std::vector<TDerivedObject*> m_objectPool;
};
The above is the base class implementation.
error C2065: 'DerivedObject' undeclared identifier
The above error is cause by the first line of the class definition bellow:
class DerivedClass : public BaseClass<DerivedClass, DerivedClass::DerivedObject>
{
protected:
class DerivedObject : public BaseObject
{
// Class implementation
}
void foo()
{
// Method implementation
}
};
Is there a way to do this? If not, is there a better solution that would give me the same / similar functionality?
At this point
class DerivedClass : public BaseClass<DerivedClass, DerivedClass::DerivedObject>
The compiler has not seen DerivedClass::DerivedObject
so you get an undeclared identifier error. As they type has not been seen you cannot use it as a template parameter. You don't get one for DerivedClass
as you already have declared DerivedClass
as a class
.
You could change you base class and have it store a std::vector<BaseObject*>
in it and if you do that then you can change your code to:
template <class TDerivedClass>
class BaseClass
{
protected:
class BaseObject
{
// Class implementation
};
void foo()
{
static_cast<TDerivedClass*>(this)->foo();
}
std::vector<BaseObject*> m_objectPool;
};
class DerivedClass : public BaseClass<DerivedClass>
{
protected:
class DerivedObject : public BaseObject
{
// Class implementation
};
void foo()
{
// Method implementation
}
};
From your example code, I get the impression that you want to provide different implementations for different base classes. Is there any special reason for using templates? If not, you could use classic polymorphism instead:
class BaseClass
{
class BaseObject {};
virtual ~BaseClass() {} // <- do not forget to provide virtual dtor!
virtual void foo() = 0;
std::vector<BaseObject*> m_objectPool;
};
class DerivedClass : public BaseClass
{
class DerivedObject : public BaseObject {/*...*/};
virtual void foo(){/*...*/}
};
Again, BaseObject would offer virtual or pure virtual functions - as you need.
One thing, however, you lose this way: the guarantee that in the vector there are always the objects of one specific BaseObject sub-type. If this matters for you, you could protect the pool and only allow to add new BaseObjects via DerivedClass. If this is not applicable, I might think up another solution from within BaseClass.
Here is one way of doing something similar to what was requested:
#include <vector>
using std::vector;
template <class TDerivedClass, class TDerivedObject>
class BaseClass
{
public:
class BaseObject
{
// Class implementation
};
protected:
// void foo()
// {
// static_cast<TDerivedClass*>(this)->foo();
// }
// std::vector<TDerivedObject*> m_objectPool;
};
class DerivedClass;
class DerivedObject : public BaseClass<DerivedClass, DerivedObject>::BaseObject
{
// Class implementation
};
class DerivedClass : public BaseClass<DerivedClass, DerivedObject>
{
public:
void foo()
{
// Method implementation
}
};
If you do not mind having the DerivedObject structure separately from the DerivedClass you may do something like that:
template <class T>
struct ObjectTypeTrait
{
static_assert(sizeof(T) == 0, "undefined trait");
};
template <class TDerivedClass>
class BaseClass
{
protected:
class BaseObject
{
// Class implementation
};
void foo()
{
static_cast<TDerivedClass*>(this)->foo();
}
std::vector<typename ObjectTypeTrait<TDerivedClass>::obj*> m_objectPool;
};
class DerivedClass;
class DerivedObject
{
// Class implementation
};
template<>
struct ObjectTypeTrait<DerivedClass>
{
using obj = DerivedObject;
};
class DerivedClass : public BaseClass<DerivedClass>
{
protected:
void foo()
{
// Method implementation
}
};
I do not claim this to be very brilliant solution, but you can get the idea - using type traits or typedefs
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.