Reputation: 10562
I've stumbled into a problem which, at a glance, is easy cplusplusable, but on careful study appears not to be.
I have items in my program which I will need to work with many types, so I have decided to handle these in a generic, extensible way:
class ItemBase
{
public:
virtual ~ItemBase() = 0 {}
// pure virtual class, some extra members
};
template<typename T>
class ItemT : public ItemBase
{
public:
ItemT(const T &data) : m_Data(data) {}
T m_Data;
};
I can now store any type in a collection:
std::vector<ItemBase*> items;
This is fine. Now I have GUI components I want to keep separate from this class so I want to generate the GUI components depending on type:
GuiComponent* BuildComponent(ItemT<int> &item)
{
// do whatever based on this type, the int is needed
}
GuiComponent* BuildComponent(ItemT<double> &item)
{
// do whatever based on this type, the double is needed
}
Which is almost beautiful coding. Unfortunately it does not work. As this program shows:
std::vector<ItemBase*> m_Items;
m_Items.push_back(new ItemT<int>(3));
m_Items.push_back(new ItemT<double>(2.0));
BuildComponent(*m_Items[0]);
Because m_Items[0] is of type ItemBase*.
So how do I solve this problem? What design pattern or template trickery can help me out here?
Upvotes: 1
Views: 304
Reputation: 76755
The easy answer would be : add a virtual buildComponent
method in ItemBase
. However, as you want to keep the GUI Components separated, I'd recommend a Visitor pattern.
A very simple implementation would consist of :
accept(AbstractVisitorType &)
virtual method in ItemBase
visitor.visit(*this)
, which means that the AbstractVisitorType
must provide a virtual visit
method for every concrete type it might be called with (see note below)visit
overload based on the parameter type.Note however that the Visitor pattern is only appropriate for a reasonably stable class hierarchy : using a new instantiation of the ItemT template will require maintenance on the Visitor side to handle this new type (but your initial idea had the same issue).
Chapter 10 of Modern C++ Design (Andrei Alexandrescu) is a great read regarding the visitor pattern.
Upvotes: 4