Re: heterogenous container class
"A" <a@a.a> wrote in message news:igiu59$ab2$1@gregory.bnet.hr...
I'd like to create a heterogenous container class of various objects.
I would use std::vector for holding such objects.
Let's assume we have ClassA, ClassB objects
struct TClassA
{
int i;
TClassA() : i(0) {} // default init
TClassA(int ii) : i(ii) {} // init with value
}
struct TClassB
{
float f;
TClassB() : f(0.0) {} // default init
TClassB(float ff) : f(ff) {} // init with value
}
struct TContainer
{
TClassA ca; // holds a
TClassB cb; // holds b
int type; // what is stored, a or b
TContainer(TClassA ainit) : ca(ainit), type(0) {} // init for a
TContainer(TClassB binit) : cb(binit), type(1) {} // init for b
}
// Using the above
std::vector<TContainer> Container;
Container.push_back(TClassA(123)); // Add integer
Container.push_back(TClassB(123.456)); // Add float
//read
if (Container[0].type == 0) int i = Container[0].ca;
if (Container[0].type == 1) float f = Container[0].cb;
The above works but for larger structures it leaves unnecessary memory
footprint because each class holds init functions and container also holds
all of the redundant data.
Can anyone give some clues how to restructure the above so it can be read
and written to similarly easy like the above but without the burden of
redundant constructors in each object e.g for TClassA to hold only "int i"
and not much else...
Any ideas are welcome.
I did some work on this many years ago, it basically re-allocates anytime
you change the data type of an element. I don't know if this is any use as
it would require some work to incorporate vector like behavior.
Please find some example code that demonstrates the general class design I
began with:
#include <iostream>
#include <vector>
typedef unsigned int UINT;
template<class T1, class T2,class T3>
class bMixedArray{
public:
virtual void Allocate(const T1& rhs){}
virtual void Allocate(const T2& rhs){}
virtual void Allocate(const T3& rhs){}
};
template<class T1, class T2,class T3>
class bDataItem{
private:
bMixedArray<T1,T2,T3>* itsContainer;
public:
virtual ~bDataItem(){}
//bDataItem():itsContainer(0){}
bDataItem(bMixedArray<T1,T2,T3>* p):itsContainer(p){}
virtual bDataItem& IndexMe(){return *this;}
virtual bDataItem& operator=(const T1& rhs){
if(itsContainer)
itsContainer->Allocate(rhs);
return *this;}
virtual operator T1(){return 0;}
virtual bDataItem& operator=(const T2& rhs){
if(itsContainer)
itsContainer->Allocate(rhs);
return *this;}
virtual operator T2(){return 0;}
virtual bDataItem& operator=(const T3& rhs){
if(itsContainer)
itsContainer->Allocate(rhs);
return *this;}
virtual operator T3(){return 0;}
};
template<class T,class T1,class T2,class T3>
class DataItem:public bDataItem<T1, T2,T3>{
private:
T itsData;
public:
~DataItem(){}
//DataItem(){}
DataItem(bMixedArray<T1,T2,T3>* p):bDataItem<T1,T2,T3>(p){}
DataItem& operator=(const T& rhs){itsData = rhs; return *this;}
operator T(){return itsData;}
DataItem<T,T1,T2,T3>& IndexMe(){return *this;}
};
template<class T1, class T2, class T3>
class MixedArray:public bMixedArray<T1,T2,T3>{
private:
bDataItem<T1,T2,T3>** itsArray;
UINT itsSize;
UINT lastIndexed;
public:
MixedArray(UINT size):itsSize(size),lastIndexed(0){
itsArray= new bDataItem<T1,T2,T3>*[size];
for(UINT i=0; i<itsSize; i++)
itsArray[i] = 0;
}
~MixedArray(){
for(UINT i=0; i<itsSize; i++){
delete itsArray[i];}
delete [] itsArray;
}
void Allocate(const T1& rhs){
delete itsArray[lastIndexed];
itsArray[lastIndexed] = new DataItem<T1,T1,T2,T3>(this);
*(itsArray[lastIndexed]) = rhs;
}
void Allocate(const T2& rhs){
delete itsArray[lastIndexed];
itsArray[lastIndexed] = new DataItem<T2,T1,T2,T3>(this);
*(itsArray[lastIndexed]) = rhs;
}
void Allocate(const T3& rhs){
delete itsArray[lastIndexed];
itsArray[lastIndexed] = new DataItem<T3,T1,T2,T3>(this);
*(itsArray[lastIndexed]) = rhs;
}
bDataItem<T1,T2,T3>& operator[](UINT i){
if(i<itsSize){
if(itsArray[i]){
return itsArray[i]->IndexMe();
}else{
itsArray[i] = new bDataItem<T1,T2,T3>(this);
lastIndexed = i;
return *(itsArray[i]);
}
}
}
};
int main(){
MixedArray<char*, int , float> myArray(100);//Template parameters define
allowed types.
myArray[0] = "hello\0";
myArray[0] = 5;
myArray[0] = 7.56f;
myArray[99] = "This is element 99\0"
std::cout<< sizeof(myArray)<<std::endl;
std::vector<int> v(100);
std::cout<< sizeof(v);
return 0;
}
This are some restrictions in this class desgin , the fact that you have a
limited amount of parameter types, 3 in this case. Also it lacked
compatability with the std lib.
I began a more advanced version which uses a different template organisation
but it is quite complicated. I willl post some code in a sep post to give
you the general idea.