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;
}
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;
}