Archived

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

CommanderXXL

Converting a string to a templated value

Recommended Posts

I have a little problem in my game engine. i have a class which is defined as:
template <typename VarType> class CCVar
{
protected:
    VarType   Value;

public:
   operator Vartype(){return Value}
   CCVar <VarType> &operator=(VarType NewVal)
   {
       Value = NewVal;
       return *this;
   }
}
Now this class stores one value for my Variable Management. I want i function or something else which gets called from my Management class (which stores pointers to these classes), whenever a user enters a string value at the console like "Test 5". The Management class splits that into the varname (test) and in the value (5). Now the function SetNewValue(char* NewVal) is called with 5 in the parameter. This seems to be no problem for ints but is there a way to write that function in my template that it RECOCNISES what vartype its stores and converts it probably. I cannot use atof or atoi cause i don't know what vartype it stores. I hope you understand what i want. This is basically for my console system which needs to be able to change the values given by text. And the values itself need to be stored as normal variables (int,float, bool) for speed purposes. Thanks for your help. ---------------------------- By CommanderXXL Commander@bloomm.de ---------------------------- [edited by - CommanderXXL on October 15, 2003 4:51:31 PM]

Share this post


Link to post
Share on other sites
Your only option is to analyze (parse) the string and then explicitly create a CCVar with the correct type. There is no template magic that will do it.

Share this post


Link to post
Share on other sites
create a function for each type that converts the string into that type. give all the functions the same name, but only with different parameters, so the compiler can automatically choise the function with the right parameter type.

void Convert(const std::string &string,int &result);
void Convert(const std::string &string,float &result);
void Convert(const std::string &string,double &result);
etc...

My Site

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Here you go CommanderXXL. I faced a similar problem writing my templated database class.



template <class Type> struct Converter //templated converter class converts string -> type

{
static Type convert( char const* p_str )
{
throw;///proably good idea to define a compile time error here too

return 0;
}
};

float Converter<float>::convert( char const* p_str ) //specialzied converter for string->float

{
if (p_str==NULL)
return 0.f;

return atof(p_str);
}

int Converter<int>::convert( char const* p_str ) //specialzied converter for string->int

{
if (p_str==NULL)
return 0;

return atoi(p_str);
}

template <class Type> struct Fundemental_Type_ID //type safety enumerator class

{
static int get_type(){ throw; return 0; } // define compile time error here too

};

int Fundemental_Type_ID<float>::get_type(){ return 1; }
int Fundemental_Type_ID<int>::get_type() { return 2; }

//functional base CCVar class allows for assignment/retrival of inherited data value

//important to check return value, due to possible conflict of types..


class CCVar_Base
{
public:

virtual bool set ( char const* p_str ) = 0;
virtual int get_type ( void ) = 0;

template <class Type> bool get ( Type& r_out )
{
if (get_type() != Fundemental_Type_ID<Type>::get_type())
return false;

return safe_assign((void*)&r_out);
}

protected:

virtual bool safe_assign ( void* p_data ) = 0;

};

//templated derived CCVar class speclzied to store a particualr type of data


template <class Type, class ConvertPolicy> class CCVar : public CCVar_Base
{
protected:

Type m_value;

public:

operator Type() { return m_value; }

CCVar& operator= ( Type new_val )
{
m_value = new_val;
return *this;
}

virtual bool set ( char const* p_str )
{
m_value = ConvertPolicy::convert(p_str);
return true;
}

virtual int get_type ( void )
{
return Fundemental_Type_ID<Type>::get_type();
}

protected:

virtual bool safe_assign ( void* p_data )
{
*((Type*)p_data) = m_value;
return true;
}
};



I think it''s pretty self explanatory. Bascially there are 3 issues. Type safety, defining the converter policy, and solving the problem of communication between the base class and its templated inherited classes.

I used an eunmerator class for type safety but you can also use RTTI if you have that enabled. This sample doesnt use it, but you can change that.

The converter polciy from str->Type is done through another object. You must define a converter policy for each type of data or it will throw an exception. A thing to note about templates. If you do not include the converter defintion in the header, there will be no compile time error, but it will be wrong. So its proablly a good idea to define some sort of compile error.

The last part about the base class -> inherited templated class communication is done through an safe_assign function which after it has verified the types passes a void ptr to the inherited class to get assingment. So in that way the base class is fully functional and no need to know or cast to the dervied class to use it.

Good Luck.

-ddn

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
I was addressing the entire scope of the problem not just the string->value conversion. You can use boost lib to convert from string -> value but how do u retrive that information or do it from a base class which doesnt have any info on the templated derived classes.

-ddn

Share this post


Link to post
Share on other sites
Thanks for all your help. Especially thanks to Anonymous Poster ddn, i''ll use you method as it sounds to me to be the best in view of typesafe problems. Also it seems to be the easiest expandable one for additional types.

----------------------------
By CommanderXXL
Commander@bloomm.de
----------------------------

Share this post


Link to post
Share on other sites