Converting a string to a templated value

Started by
6 comments, last by CommanderXXL 20 years, 6 months ago
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]
---------------------------- By CommanderXXLCommander@bloomm.de----------------------------
Advertisement
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.
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
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 datatemplate <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
God, no. Use C++ string streams - boost::lexical_cast.

[ Google || Start Here || ACCU || STL || Boost || MSDN || GotW || CUJ || MSVC++ Library Fixes || BarrysWorld || E-Mail Me ]

[edited by - Lektrix on October 15, 2003 3:12:28 PM]
[ Google || Start Here || ACCU || STL || Boost || MSDN || GotW || CUJ || MSVC++ Library Fixes || BarrysWorld || [email=lektrix@barrysworld.com]E-Mail Me[/email] ]
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
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
----------------------------
---------------------------- By CommanderXXLCommander@bloomm.de----------------------------
Template Specialization. It is your friend.
daerid@gmail.com

This topic is closed to new replies.

Advertisement