Polymorphic containers are not an easy problem. There are a couple of options.
1) Use boost::any instances to hold your data values. Solution is something like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
struct node {
template< typename T >
node( const T& d ): data( d ), next() {}
private:
boost::any data;
node* next;
};
struct List {
template< typename T >
void insert( const T& d ) {
if( !head ) {
head = new node<T>( d );
} else {
node* tmp = head;
for( ; tmp->next; tmp = tmp->next ); // <- yes, semicolon here
tmp->next = new node<T>( d );
}
}
private:
node* head;
};
|
2) Use boost::variant to hold the data. Solution is similar to 1), except that
you must know at compile time all of the types you'll store in the list.
3) Custom solution. For example:
(I'm omitting some of the details in case this is a school project.)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
class node_base {
node_base* next;
public:
node_base(): next() {}
};
template< typename T >
class node : public node_base {
T data;
public:
node( const T& d ) : data( d ) {}
};
class polymorphic_list {
node_base* head;
public:
polymorphic_list() : head() {}
template< typename T >
void insert( const T& d ) {
node_base* n = new node<T>( d );
// ... etc ...
}
};
|
In all three cases, the limitation is that someone, somehow has to know the type of the data stored in each node if you want to do anything with it.
In solution 3, you could write polymorphic_list::print() to walk the list and call the print() method on each node, in which case node_base::print() would be declared pure virtual and the derived classes would need to implement it. For example,