Hi everyone. I would appreciate any help with this.
I have a simple container template class Dataset.
Also there is a specialization to allow a different implementation when a Dataset of Datasets is instantiated.
Since a Dataset of Datasets would be a heterogeneous container, there is a base abstract class List wich must declare a common interface for every Dataset. That would be get().
The problem is: I cannot specify a return type in List::get() so I need to override the void* return in descendants.
I´ve read the following restrictions for covariance:
•The function B::f returns a reference or pointer to a class of type T, and A::f returns > a pointer or a reference to an unambiguous direct or indirect base class of T.
•The const or volatile qualification of the pointer or reference returned by B::f has the same or less const or volatile qualification of the pointer or reference returned by A::f.
•The return type of B::f must be complete at the point of declaration of B::f, or it can be of type B.
Well, make the contained objects descend from the same base class is of no use to me.
So, is there a workaround to this? Better yet: what is the proper c++ way to do this?
In case you wonder, what I am trying to do is is a 'relational container', so to speak. But you won´t see the relational part in the code below anyway.
The goal is to store data keeping the container unaware of any relation beetween list.
Then I would store the relations in a list apart. For example:
Person list
0 John
1 Arthur
2 Caroline
Car list
0 - Ford
1 - Volkswagen
2 - Chrysler
Relations list
0 - 1;2
1 - 0;1
2 - 0;2
Pretty much as a relational database. Also, i have minor side problems, like making set() to accept a maxsize number of arguments. Couldn´t achieve this with va_list. Maybe I rushed through this, anyway.
Final point: I´m deliberately avoiding STL for learning sake, BUT if there is already such functionality available I would like to know.
Thanks a lot!
The code below:
#include <iostream>
using namespace std;
//--------------------------------------------------//
// TRIVIAL DUMMY CLASSES
class Person
{
public:
Person(char* n, unsigned int a): _name(n), _age(a){}
char* name(){cout << "Im " << _name << endl; return _name;}
unsigned int age(){cout << "Im " << _age << " years old." << endl; return _age;}
private:
char* _name;
unsigned int _age;
} p1("john", 28), p2("Arthur", 26), p3("Caoline", 31);
class Car
{
public:
Car(char* m, unsigned int y): _model(m), _year(y){}
char* model(){cout << "Its a " << _model << endl; return _model;}
unsigned int year(){cout << "Im" << _year << " years old." << endl; return _year;}
private:
char* _model;
unsigned int _year;
} c1("Chrysler C-300", 1955), c2("Chrysler VH Charger", 1971), c3("Ford Fairlane", 1960);
//--------------------------------------------------//
class List
{
public:
List(): length(0){}
// common interface so Lists of Lists can be created
// can´t specify a return type so it returns void*
// BUT need to override it in descendants. WHY IT DOESN´T WORK?
virtual void* get(unsigned int i) = 0;
protected:
unsigned int length;
};
//--------------------------------------------------//
template <class C, unsigned int maxsize>
class Dataset: public List
{
public:
Dataset()
{
// initialize pointers to null
for(int i = 0; i < maxsize; i++){
data[i] = 0;
}
};
// C* return type is ignored
C* get(unsigned int i)
{return data[i];};
int set(C* dataIn)
{
data[length] = dataIn;
return length++;
};
protected:
C* data[maxsize];
};
template <unsigned int maxsize>
class Dataset <List, maxsize>: public List
{
public:
Dataset()
{
// initialize pointers to null
for(int i = 0; i < maxsize; i++){
data[i] = 0;
}
};
List* get(unsigned int i)
{return data[i];};
int set(List* dataIn)
{
data[length] = dataIn;
return length++;
};
protected:
List* data[maxsize];
};
//--------------------------------------------------//
int main()
{
Dataset <Person, 3> columnPerson;
// populate person list
columnPerson.set(&p1);
columnPerson.set(&p2);
columnPerson.set(&p3);
Dataset <Car, 3> columnCar;
// populate car list
columnCar.set(&c1);
columnCar.set(&c2);
columnCar.set(&c3);
Dataset <List, 10> relations; // create a list of lists
// populate it
relations.set(&columnPerson);
relations.set(&columnCar);
// getting a void* and casting it
Person* ptrPerson = (Person*) relations.get(0)->get(0);
ptrPerson->name();
int i;
cin >> i;
};