Re: templated virtual functions??
jorka2@hotmail.com wrote:
Hi
Let say that I wanted to do a filesystem browser. The filesystem is a
tree structure, so my idea was to make an general tree browser that
could browse anything that implemented the ITreeStructure interface.
Now I want to make a generic container class that is a tree and can
hold any data type.
The declarations for this look like this:
template<typename T>
class Tree : public ITreeStructure
{
typedef unsigned int size_type;
typedef std::vector<Tree>::iterator iterator;
typedef const std::vector<Tree>::iterator const_iterator;
bool is_leaf() = 0;
ITreeStructure& parent() = 0;
iterator children_begin() = 0;
iterator children_end() = 0;
T get_value(void) = 0;
};
class TreeBrowser : public IWindowControl
{
public:
TreeBrowser();
TreeBrowser(ITreeStructure& tree);
void BrowseTree(ITreeStructure& tree);
private:
ITreeStructure* m_treep;
};
Now the question is how to define the ITreeStructure interface?
I would like to define it like this
class ITreeStructure
{
public:
virtual bool is_leaf() = 0;
virtual ITreeStructure& parent() = 0;
virtual std::vector<ITreeStructure>::iterator children_begin() = 0;
virtual std::vector<ITreeStructure>::iterator children_end() = 0;
template<typename T> virtual T get_value(void) = 0;
};
The problem is the get_value method since templated virtual functions
are not allowed.
I could have parameterized the whole interface like this
template<typename T>
class ITreeStructure
{
public:
virtual bool is_leaf() = 0;
virtual ITreeStructure& parent() = 0;
virtual std::vector<ITreeStructure>::iterator children_begin() = 0;
virtual std::vector<ITreeStructure>::iterator children_end() = 0;
virtual T get_value(void) = 0;
};
But that defeats the whole purpose of having an interface, since I
want to decouple the TreeBrowser from any implementation of a tree
structure. If the whole interface is parameterized so must the
TreeBrowser class be.
So my questions are:
1. Why isn't templated virtual functions allowed in C++?
The problem is that a function template is not a function at all.
Rather, it is a recipe for generating a number of similar functions.
A typical way of implementing virtual functions is to have a table of
function pointers (a so called v-table). So, how many slots would I
have to reserve in my v-table for the instantiations of your virtual
template function?
2. Is there an reasonably simple way around this? Or can I change my
design some way and have both decoupling and still be able to have an
parameterized implementation of a tree structure?
I would use an extra, intermediate, base-class.
class ITreeStructure
{
public:
virtual bool is_leaf() = 0;
virtual ITreeStructure& parent() = 0;
virtual std::vector<ITreeStructure>::iterator children_begin() = 0;
virtual std::vector<ITreeStructure>::iterator children_end() = 0;
};
template <typename T>
class ITreeValue : public ITreeStructure
{
public:
virtual T get_value(void) = 0;
};
In the navigation code, you can work exclusively in terms of
ITreeStructure. When you then need to retrieve the value, you cast to
ITreeValue<MyT> (with a dynamic_cast), and call its get_value member.
Thanks in advance
/JK
Bart v Ingen Schenau
--
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://c-faq.com/
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]