A pointer to abstract template base class? - c++

I cannot figure this out. I need to have an abstract template base class, which
is the following:
template <class T> class Dendrite
{
public:
Dendrite()
{
}
virtual ~Dendrite()
{
}
virtual void Get(std::vector<T> &o) = 0;
protected:
std::vector<T> _data;
};
Now, I derive from this which specifies exact usage of Dendrite.
Now the problem.
How do I create a vector of pointers to the base-class with no specific type, which
I want to specify by pushing elements to it later? Something like:
class Foo
{
public:
...
private:
std::vector<Dendrite *> _inputs; //!< Unfortunately, this doesn't work...
//! Now I could later on push elements to this vector like
//!
//! _inputs.push_back(new DeriveFromDendrite<double>()) and
//! _inputs.push_back(new DeriveFromDendrite<int>()).
};
Is this possible or am I missing something very basic here?

Typically this is done by your template inheriting from an interface class, IE:
template <class T> class Dendrite : public IDendrite
{
public:
Dendrite()
{
}
virtual ~Dendrite()
{
}
void Get(std::vector<T> &o) = 0;
protected:
std::vector<T> _data;
};
and then you're IDendrite class could be stored as pointers:
std::vector<IDendrite*> m_dendriteVec;
However, in your situation, you are taking the template parameter as part of your interface. You may also need to wrap this also.
class IVectorParam
{
}
template <class T>
class CVectorParam : public IVectorParam
{
std::vector<T> m_vect;
}
giving you
class IDendrite
{
...
public:
virtual ~IDendrite()
virtual void Get(IVectorParam*) = 0;
}
template <class T> class Dendrite : public IDendrite
{
...
// my get has to downcast to o CVectorParam<T>
virtual void Get(IVectorParam*);
};

Yes it is possible. Just make sure to provide virtual functions, and virtual destructor. In addition, you can use typeid to get the actual type (as well as dynamic_cast to check the type)

Related

How to iterate through all typenames in a class template?

I want to design a component-based weapon template for my game. However, it seems no way to add/remove a class member or create a code?
Sorry for my expression and lack of terminology, for I am not graduated from dept. of computer science or software engineer, I know little of what those stuff called by professionals.
Here is the component code looks like:
class CBaseWpnCmpt : public std::enable_shared_from_this<CBaseWpnCmpt>
{
public:
typedef std::shared_ptr<CBaseWpnCmpt> PTR;
private:
CBaseWpnCmpt() = default;
public:
CBaseWpnCmpt(const CBaseWpnCmpt& s) = default;
CBaseWpnCmpt(CBaseWpnCmpt&& s) = default;
CBaseWpnCmpt& operator=(const CBaseWpnCmpt& s) = default;
CBaseWpnCmpt& operator=(CBaseWpnCmpt&& s) = default;
virtual ~CBaseWpnCmpt() {}
protected:
CBaseWeaponInterface::PTR m_pWeapon { nullptr };
public:
template <class CComponent>
static std::shared_ptr<CComponent> Create(CBaseWeaponInterface::PTR pWeapon)
{
std::shared_ptr<CComponent> pComponent = std::make_shared<CComponent>();
pComponent->m_pWeapon = pWeapon;
return pComponent;
}
};
And this is what a weapon body code looks like: (And the problem occurs)
template < class CWeapon,
class ...CComponents
>
class CBaseWeaponTemplate : public CBaseWeaponInterface
{
public:
std::list<CBaseWpnCmpt::PTR> m_lstComponents;
public:
virtual void SecondaryAttack(void) // Example method.
{
for (auto& pComponent : m_rgpComponents)
{
pComponent->SecondaryAttack();
}
}
};
How am I suppose to create all these argument packs as member of the template? Currently I tried to enlist them into a pointer std::list container, but I just can't figure out how to achieve it at all.
In other words, how can I make a template when I fill in blank likt this:
class CAK47 : public CBaseWeaponTemplate<CAK47, CLongMagazine, CWoodenStock>
will generate this:
class CAK47
{
CLongMagazine m_comp1;
CWoodenStock m_comp2;
//... other stuff
};
Or alternatively, generate this:
class CAK47
{
CAK47() // constructor
{
for (/* somehow iterate through all typenames */)
{
CBaseWpnCmpt::PTR p = std::make_shared<typename>();
m_lstComponents.emplace_back(p);
}
}
};
One way of doing so from C++11 on-wards would be to store the template types used for this particular weapon inside an std::tuple
template <typename Weapon, typename... Attachments>
class WeaponWithAttachments {
protected:
WeaponWithAttachments() {
return;
}
std::tuple<Attachments...> attachment_types;
};
and then using that tuple to initialise a vector of shared pointers with a protected constructor taking a tuple to access the template types again.
class SomeWeaponWithAttachments: public WeaponWithAttachments<SomeWeapon,SomeAttachment,AnotherAttachment> {
public:
SomeWeaponWithAttachments()
: SomeWeaponWithAttachments{attachment_types} {
return;
}
protected:
template <typename... Attachments>
SomeWeaponWithAttachments(std::tuple<Attachments...> const&)
: attachments{std::make_shared<Attachments>()...} {
return;
}
std::vector<std::shared_ptr<BaseAttachment>> attachments;
};
Try it here!
If the attachments vector is already declared inside the parent class like it seems to be the case for you might also avoid the tuple and the protected constructor with initialising the attachments already inside the parent class
template <typename Weapon, typename... Attachments>
class WeaponWithAttachments {
protected:
WeaponWithAttachments()
: attachments{std::make_shared<Attachments>()...} {
return;
}
std::vector<std::shared_ptr<BaseAttachment>> attachments;
};
and then only calling the constructor of the base class in the derived class
class SomeWeaponWithAttachments: public WeaponWithAttachments<SomeWeapon,SomeAttachment,AnotherAttachment> {
public:
SomeWeaponWithAttachments()
: WeaponWithAttachments<SomeWeapon,SomeAttachment,AnotherAttachment>() {
return;
}
};
Try it here!
If that is no option for you, then you can use the tuple to iterate over all the template arguments using C++17 fold expressions:
class SomeWeaponWithAttachments: public WeaponWithAttachments<SomeWeapon,SomeAttachment,AnotherAttachment> {
public:
SomeWeaponWithAttachments()
: SomeWeaponWithAttachments{attachment_types} {
return;
}
protected:
template <typename... Attachments>
SomeWeaponWithAttachments(std::tuple<Attachments...> const&) {
(attachments.push_back(std::make_shared<Attachments>()), ...);
return;
}
};
Try it here!
In C++17 you might also add a static assertion with fold expressions into the constructor to make sure that the types actually inherit from BaseAttachment:
static_assert((std::is_base_of_v<BaseAttachment, Attachments> && ...), "Template arguments must inherit from 'BaseAttachment'.");

Storing a pointer to a base object that has template functions

Based on the following code how can I store a pointer to Base in my 'Controller' class?
template< class Derived >
class Base
{
public:
template < typename T >
void Serialise( T* t )
{
Derived* d = static_cast< Derived* >( this );
d->Serialise( t );
}
};
class Derived : public Base< Derived >
{
public:
template < typename T >
void Serialise( T* t )
{
printf( "serialising to object T\n" );
}
};
So if I have a Controller class that will call the Serialise function and pass in the object to serialise to I end up having to store the pointer with its derived type known because it's part of the object's type when what I need is to be able to use the Base type without knowing what it's actual type is:
class Controller
{
public:
void DoSerialise();
private:
Base< Derived >* m_myObject; // I want this to just be Base* m_myObject but cant due to template!
};
Short answer - you can't.
Assuming the template argument doesn't affect Base's interface (ie: Derived doesn't appear in any function signatures) you could have a non template Base class, and the derived classes could be templates. This however doesn't fit at all with your current pattern.
In your case if the template argument DOES affect the interface (and I strongly suspect it does in this case) then the Controller would need to know about Derived in order to use Base, so where's the harm in it also knowing about Derived in order to declare Base.
EDIT after comment:
Are you sure that you want any derived class to be able to serialise to any type? Why not to have a heirarchy of classes that derive from a Serialiser base class, then Serialise() can accept a reference to type Serialiser and lose the template parameter.
You can't do that. But the only thing Base::Serialise does is call the derived class's Serialise method. Why not just make it pure virtual, so that Base doesn't need a template parameter?
The specific approach that you seem to want to take to the problem is not possible because the type of the base class is dependent on the type of the derived class. That means the base class template instantiations cannot be represented as a single type, which would be necessary to achieve the approach you're taking.
However, this looks to be a problem begging for the visitor pattern. The visitor pattern makes double dispatch possible without casting, which is exactly what you want here. Here's a possible solution:
// First declare a base serializable interface that accepts a serializer.
struct ISerializer;
struct ISerializable {
virtual void accept_serializer(ISerializer const &) const = 0;
};
// Now declare a base serializer type that can accept any serializable type.
struct Serializable1;
struct Serializable2;
...
struct ISerializer {
virtual void serialize(Serializable1 const &) = 0;
virtual void serialize(Serializable2 const &) = 0;
...
};
// Then implement your concrete serializable types to accept the serializer and
// invoke it on themselves.
struct Serializable1 : public ISerializable {
void acceptSerializer(ISerializer const &s) const {
s.serialize(*this);
}
};
struct Serializable2 : public ISerializable {
void acceptSerializer(ISerializer const &s) const {
s.serialize(*this);
}
};
// You can actually be a bit more clever to eliminate redundant code:
template<typename DerivedT>
struct SerializableAdapter {
void acceptSerializer(ISerializer const &s) const {
s.serialize(*static_cast<DerivedT const *>(this));
}
};
struct Serializable1 : public SerializableAdapter<Serializable1> {
};
struct Serializable2 : public SerializableAdapter<Serializable2> {
};
// Finally, implement your concrete serializers, including one function for each
// serializable type.
struct Serializer1 : public ISerializer {
void serialize(Serializable1 const &s) const {
...
}
void serialize(Serializable2 const &s) const {
...
}
};
struct Serializer2 : public ISerializer {
void serialize(Serializable1 const &s) const {
...
}
void serialize(Serializable2 const &s) const {
...
}
};
// Now you can store the serializers through the base interface.
struct Controller {
void doSerialize(ISerializable &p_serializable) {
p_serializable.acceptSerializer(*m_serializer)
}
private:
ISerializer *m_serializer;
};

How to simulate virtuality for method template

I have a class hierarchy where I want to introduce a method template that would behave like if it was virtual. For example a simple hierarchy:
class A {
virtual ~A() {}
template<typename T>
void method(T &t) {}
};
class B : public A {
template<typename T>
void method(T &t) {}
};
Then I create object B:
A *a = new B();
I know I can get the type stored in a by typeid(a). How can I call the correct B::method dynamically when I know the type? I could probably have a condition like:
if(typeid(*a)==typeid(B))
static_cast<B*>(a)->method(params);
But I would like to avoid having conditions like that. I was thinking about creating a std::map with typeid as a key, but what would I put as a value?
You can use the "Curiously Recurring Template Pattern"
http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
Using this pattern, the base class takes the derived class type as a template parameter, meaning that the base class can cast itself to the derived type in order to call functions in the derived class. It's a sort of compile time implementation of virtual functions, with the added benefit of not having to do a virtual function call.
template<typename DERIVED_TYPE>
class A {
public:
virtual ~A() {}
template<typename T>
void method(T &t) { static_cast<DERIVED_TYPE &>(*this).methodImpl<T>(t); }
};
class B : public A<B>
{
friend class A<B>;
public:
virtual ~B() {}
private:
template<typename T>
void methodImpl(T &t) {}
};
It can then be used like this...
int one = 1;
A<B> *a = new B();
a->method(one);
Is there any common code you could extract and make virtual?
class A {
virtual ~A() {}
template<typename T>
void method(T &t)
{
...
DoSomeWork();
...
}
virtual void DoSomeWork() {}
};
class B : public A {
virtual void DoSomeWork() {}
};
As you may know, you cannot have templates for virtual functions, since the entirety of the virtual functions is part of the class type and must be known in advance. That rules out any simple "arbitrary overriding".
If it's an option, you could make the template parameter part of the class:
template <typename T> class A
{
protected:
virtual void method(T &);
};
template <typename T> class B : public A<T>
{
virtual void method(T &); // overrides
};
A more involved approach might use some dispatcher object:
struct BaseDispatcher
{
virtual ~BaseDispatcher() { }
template <typename T> void call(T & t) { dynamic_cast<void*>(this)->method(t); }
};
struct ConcreteDispatcher : BaseDispatcher
{
template <typename T> void method(T &);
};
class A
{
public:
explicit A(BaseDispatcher * p = 0) : p_disp(p == 0 ? new BaseDispatcher : p) { }
virtual ~A() { delete p_disp; };
private:
BaseDispatcher * p_disp;
template <typename T> void method(T & t) { p_disp->call(t); }
};
class B : public A
{
public:
B() : A(new ConcreteDispatcher) { }
// ...
};
Oops. Initially answered at the wrong question - ah well, at another question
After some thinking I recognized this as the classic multi-method requirement, i.e. a method that dispatches based on the runtime type of more than one parameter. Usual virtual functions are single dispatch in comparison (and they dispatch on the type of this only).
Refer to the following:
Andrei Alexandrescu has written (the seminal bits for C++?) on implementing multi-methods using generics in 'Modern C++ design'
Chapter 11: "Multimethods" - it implements basic multi-methods, making them logarithmic (using ordered typelists) and then going all the way to constant-time multi-methods. Quite powerful stuff !
A codeproject article that seems to have just such an implementation:
no use of type casts of any kind (dynamic, static, reinterpret, const or C-style)
no use of RTTI;
no use of preprocessor;
strong type safety;
separate compilation;
constant time of multimethod execution;
no dynamic memory allocation (via new or malloc) during multimethod call;
no use of nonstandard libraries;
only standard C++ features is used.
C++ Open Method Compiler, Peter Pirkelbauer, Yuriy Solodkyy, and Bjarne Stroustrup
The Loki Library has A MultipleDispatcher
Wikipedia has quite a nice simple write-up with examples on Multiple Dispatch in C++.
Here is the 'simple' approach from the wikipedia article for reference (the less simple approach scales better for larger number of derived types):
// Example using run time type comparison via dynamic_cast
struct Thing {
virtual void collideWith(Thing& other) = 0;
}
struct Asteroid : Thing {
void collideWith(Thing& other) {
// dynamic_cast to a pointer type returns NULL if the cast fails
// (dynamic_cast to a reference type would throw an exception on failure)
if (Asteroid* asteroid = dynamic_cast<Asteroid*>(&other)) {
// handle Asteroid-Asteroid collision
} else if (Spaceship* spaceship = dynamic_cast<Spaceship*>(&other)) {
// handle Asteroid-Spaceship collision
} else {
// default collision handling here
}
}
}
struct Spaceship : Thing {
void collideWith(Thing& other) {
if (Asteroid* asteroid = dynamic_cast<Asteroid*>(&other)) {
// handle Spaceship-Asteroid collision
} else if (Spaceship* spaceship = dynamic_cast<Spaceship*>(&other)) {
// handle Spaceship-Spaceship collision
} else {
// default collision handling here
}
}
}
I think the only solution is the http://en.wikipedia.org/wiki/Visitor_pattern
See this topic:
How to achieve "virtual template function" in C++

c++ template problem

i have a class which has a template by other purposes:
template<class t>
class MyClass {
public: //of course public...
t foo;
std::string text;
}
and i have another class which method get all kind of these class through the arguments, and want to store the pointer in an array. The class dont want to access the specific (tempalted) parts of the classes only the common attributes/methods.
class Container {
public: //of course public...
MyClass* array; //this is allocated with some magic.
void bar(MyClass& m) {
and want to store the class in a MyClass* array.
}
}
here is the error that argument list for template missing
how can i solve this?
The simplest method would be to make that function a template as well:
template <class t>
void bar(MyClass<t>& m) {
// ...
}
Note that that should probably be const MyClass<t>&, because you don't need to modify it.
Your new code is meaningless. There is no such that as an object of type MyClass, because MyClass is a template. If you want to operate on these classes irrespective of their template argument, then you need to factor out the non-template portions as a base class:
class MyClassBase
{
public:
// polymorphic base classes should always have virtual destructors
~MyClassBase() {}
virtual void some_function() = 0;
};
template <typename T>
class MyClass : public MyClassBase
{
public:
// implement abstract functions
void some_function()
{
// template argument T is available here
}
};
Then you can refer to that base, and when you call a virtual function it will dynamically dispatch:
class Container
{
public:
// no magic: use a std::vector for dynamic arrays
std::vector<MyClassBase*> array; // not by value! avoid slicing
void bar(MyClassBase& m)
{
array.push_back(&m);
}
void baz()
{
array[0]->some_function(); // for example
}
};
How about putting a common base class.
class MyClassCommon {
protected:
~MyClassCommon() { }
public:
std::string text;
};
template<class t>
class MyClass : public MyClassCommon {
public: // of course public...
t foo;
};
class Container {
public: // of course public...
MyClassCommon* array; // this is allocated with some magic.
void bar(MyClassCommon& m) {
/* ... */
}
};
If you want to create a "multi-template" array, you'd better use a non-template class as a base class of a template class. Or you can make a template array and store any objects in it.
the text variable in your class is private so unless you bar function is a method of the class you can't legally use it like that

class containing a generic type of a child

Is there any possible way that a generic type can be used to contain a child of a base class.
From the assignment given to me, I am to create something similar to the following in structure.
template <class T>
class Fruit {
private:
int count;
int location_id;
T type;
public:
virtual void displayInfo();
};
class Apple : private Fruit<Apple> {
private:
int variety;
public:
void displayInfo() {
printf("Location %i has %i of %s in stock", location_id, count, variety);
}
};
Fruit<Apple> appleinventory[SIZE];
Basically, I think you can't have a template generic type be the same as a derived class. Am I wrong? Is there something similar that would possibly work?
Update:
For the assignment, I believe we are to use inheritance to show use of virtual functions. I've updated the code above. I think this would work, but does NOT need templates to be successful. We have not covered any advanced, redundant inheritance methods in class.
This is perfectly fine, in principle.
Read up about Curiously Recurring Template Pattern (CRTP) for more info on usage of derived class as the instantiating type in a class template that is its base, esp the example about static polymorphism which should look 'curiously' familiar.
template <class Derived> struct Base
{
void interface()
{
// ...
static_cast<Derived*>(this)->implementation();
// ...
}
static void static_func()
{
// ...
Derived::static_sub_func();
// ...
}
};
struct Derived : Base<Derived>
{
void implementation();
static void static_sub_func();
};
Ignoring questions of why you want to do this....you can get some of the way by doing this following:
template <class T> class Fruit
{
private:
int count;
int location_id;
T* type;
};
class Apple : private Fruit<Apple>
{
private:
int seeds;
bool red;
};
Fruit<Apple> appleinventory[SIZE];
Note the T* type is now a pointer to Apple rather than an instance of Apple.