Archived

This topic is now archived and is closed to further replies.

type maps (or not)

This topic is 5239 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Using std::map or something similar could likely suffice for what I need to do were it not for the fact that I can''t use it (and don''t want to) - although I don''t believe it would. Here''s what the situation is: I have a class which includes a list of variables. There''s quite a few of those and the number is always changing. I want to create an efficient loader for these values that would follow this very simple scheme:

class SomeSingletonClass
{
  public:
   static float Param1;
   static int Param2;
   static char* Param3;
   static DWORD Param4;
} *SomeClass;

union TValue {
  int IntVal;
  DWORD DwdVal;
  char* StrVal;
  float FltVal;
  };

struct TParam {
  char* Name;
  TValue Default;
  
  //this something I''m not sure how to do (read below)

  TValue* Reference; 

  TParam(char* pName, TValue pDefault, TValue * pReference)
    {
    //assign to proper memebers

    }
  };
Basically, TParam should wrap together a row in a map, which is initialized this way:
TParam* ParamList[] = {
  TParam("velocity or whatnot", DEFAULT_VALUE, &SomeClass::Param1),
  TParam("mass", DEFAULT_VALUE, &SomeClass::Param2),
  TParam("name", DEFAULT_VALUE, &SomeClass::Param3),
  TParam("haircount", VALUE, DEFAULT_VALUE, &SomeClass::Param4),
  };
Later on, I could then very easily write a self-sustaining function such as:
void LoadValue(char * pName, char * pValue)
{
  loop_through_ParamList_until_pName_matches_ParamList[n]->Name
    *(ParamList[n]->Reference) = convert_to_proper_format(pValue)

  later_on_if_a_param_hasn''t_been_loaded_give_it_the_default_value
}
So there. I don''t know how much that makes sense (it''s almost 6 AM), but one thing''s for sure, I don''t know how to do this (at least not the way I want to) - I''m especially confused about the union conversions - isn''t there a way to tell the compiler that it has to decide on its own which format the data should ne formatted into. For instance, if I pass DEFAULT_VALUE to TParam(), which is a string in one instance, automatically convert TParam::Default to a string as well, etc... Hope I didn''t make too many gross mistakes above - a person shouldn''t be up this early...

Share this post


Link to post
Share on other sites
Okay, not too much gusto on this thread... I'll just rumble on then .

Anyway, since assignment to a union cannot be done directly, I turned to templating the union, but evidently that's not very effective either because the type would have to be known at creation time. Here's the code I tested:



template <class T>
union TValue {
int IntVal;
DWORD DwdVal;
char* StrVal;
float FltVal;

TValue(T pValue)
{
char* Type = typeid(pValue).name();
//assign to proper value

}
};

void foo()
{
float v = 10;
TValue<float> Val(v); //<- type must be known at creation time

}



That's no good. Writing:


   
void foo()
{
float v = 10;
TValue<typeid(v).name()> Val(v);
}



won't work either because typeid.name() returns a string...

However, the most unelegan solution does work - overloading all of the assignment operators for all of the data types in the union. This is pretty impressive as regards the amount of menial work because overloading all of the operators (around 15 if I'm not istaken) for all of the data types would result in a massive ~60 function bodies...

Again, can anyone see a way to cut down the size of code here while not losing the functionality?

[edited by - crispy on August 9, 2003 7:29:58 AM]

Share this post


Link to post
Share on other sites
What are you trying to do? Writing 60 function bodies by hand is error prone at best, and a giant waste of time.

Load variables of different type from disk? Here''s how I do it:

// in app code

if(! prefs->Valid()) //loaded from disk?

{
prefs->Set("intTest", 42);
//etc

}
else
{
int test = prefs->GetInt("intTest");
}

// The set function just calls this function with the value type qualified, since it cannot deduce it:

// e.g. SetValue<int>(this->table, name, value)

template<typename ValueType, typename TableType> void
SetValue(TableType& table, const wstring& name, ValueType value)
{
table[name] = boost::lexical_cast<wstring>(value);
}

boost::lexical_cast merely dumps the argument into a [w]stringstream and does conversion on it.

Type-safe, easy to use, works for arbitary types that provide an overloaded <> operator.

Share this post


Link to post
Share on other sites