is there a good way to save data of different types ?

M

mast2as

Hi there, for a long time I've been trying to think of way of saving
different data of different types using one single class (well 2 in
reality, a class for the data, and 1 class for a list of data). The
problem that I try to solve is the following. Imagine a class
"Attribute" that needs to save multiple "Parameters" (the number of
parameters for 1 attribute will vary each time we run the application).
Each parameter can be of a different type (float, integer, double...)
and we can have 1 value per parameter or an array of values.

So I tried to create a template class (parameter) that would hold the
data, the name of the parameter & its type (using typeid). Then i
created a list (deque) in the Attribute class which is a list of
pointers to Parameter objects (which are cast to void*). I was hoping i
could save the type of the created parameters using something like
typeid for example to cast a parameter object when I read them back
from the list. Something like:

if ( attr.m_parameters[ 0 ]->m_type == "f" ) {
float afloat = (float)attr.m_parameters[ 0 ]->get( 0 );
}

It doesn't seem to work so well. The last line of code fails to compile
(`void*' is not a pointer-to-object type). I imagine that this is a
need that a lot of developper must have had before and that maybe
there's a good/better way of doing that. What I am trying to avoid is
something like that

class Parameter {
deque<float> m_floats;
deque<double> m_doubles;
deque<string> m_strings;
...
void insertFloat( float arg ) { m_floats.push_back( arg ); }
void insertInterger( int arg ) m_integers.push_back( arg ); }
...
};

I am happy to go with that if experienced developpers tell me it is
still the best way to go otherwise would be happy to learn of a better
way ...

Many thanks for your help. -mark

template<typename T>
class TParameter {
public:
TParameter( const char *name ) : m_name( name ) {
m_type = typeid( T ).name();
}
~TParameter() {}
void insert( T arg ) {
m_data.push_back( (T)arg );
}

T get( int i ) {
if ( i <= ( m_data.size() - 1 ) && i >= 0 )
return (T)(m_data[ i ]);
}
public:
deque<T> m_data;
const char* m_name;
const char* m_type;
};

class TAttribute {
public:
TAttribute() {}
~TAttribute() {}
public:
deque<void *> m_parameters;
};

int main()
{

TParameter<float> *floatArray = new TParameter<float>( "floatArray"
);
TAttribute attr;
attr.m_parameters.push_back( (void*)(floatArray) );

floatArray->insert( (float)-1.0 );
floatArray->insert( (double)-2.0 );
floatArray->insert( (float)-3.0 );

cout << floatArray->get( 0 ) << endl;
cout << floatArray->get( 1 ) << endl;
cout << floatArray->get( 2 ) << endl;

// compile fails here !
//cout << "Type of this attribute: " << attr.m_parameters[ 0
]->m_type << endl;
}
 
M

mast2as

Hi again for those who had the kindness of reading the post here's an
update. I've managed to get the code to work by doing the following
thing (see code below). There's still room for improvement (the const
char to save the type of the parameter could be an integer constant
from an enum type declaration (which would allow me to do a swich of
the type).

Let me know if that seems a good way to go or if I what i am doing is
messy or enifficient. thank you -

template<typename T>
class TParameter {
public:
TParameter( const char *name ) : m_name( name ) {
m_type = typeid( T ).name();
}
~TParameter() {}
void insert( T arg ) {
m_data.push_back( (T)arg );
}
T operator[]( int i ) {
if ( i < ( m_data.size() - 1 ) && i >= 0 )
return m_data[ i ];
}
T get( int i ) {
if ( i <= ( m_data.size() - 1 ) && i >= 0 )
return (T)(m_data[ i ]);
}
public:
deque<T> m_data;
const char* m_name;
const char* m_type;
};

class TAttribute {
public:
TAttribute() {}
~TAttribute() {}
public:
deque<pair<const char *, void *> > m_parameters;
};

int main()
{

TParameter<float> *floatArray = new TParameter<float>( "floatArray"
);
TAttribute attr;
attr.m_parameters.push_back( pair<const char*, void*>( "float",
(void*)(floatArray) ) );

floatArray->insert( (float)-1.0 );
floatArray->insert( (double)-2.0 );
floatArray->insert( (float)-3.0 );

cout << floatArray->get( 0 ) << endl;
cout << floatArray->get( 1 ) << endl;
cout << floatArray->get( 2 ) << endl;

// get the type of the parameter
cout << "Parameter type: " << attr.m_parameters[ 0 ].first << endl;

if ( attr.m_parameters[ 0 ].first == "float" ) {
TParameter<float> *tparam = (TParameter<float> *)(
attr.m_parameters[ 0 ].second );
cout << "Value at index 0: " << tparam->get( 0 ) << endl;
cout << "Value at index 1: " << tparam->get( 1 ) << endl;
cout << "Value at index 2: " << tparam->get( 2 ) << endl;
}
}
 
T

Thomas J. Gritzan

Hi there, for a long time I've been trying to think of way of saving
different data of different types using one single class (well 2 in
reality, a class for the data, and 1 class for a list of data). The
problem that I try to solve is the following. Imagine a class
"Attribute" that needs to save multiple "Parameters" (the number of
parameters for 1 attribute will vary each time we run the application).
Each parameter can be of a different type (float, integer, double...)
and we can have 1 value per parameter or an array of values.

Look at:
http://www.boost.org/doc/html/variant.html

And:
http://www.boost.org/doc/html/any.html
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top