Find the answer to your Linux question:
Results 1 to 8 of 8
Hi, I am trying to generic way to convert the string datatype to other primitive data type. To achieve, i used Template . But i getting error and couldn't resolve ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    Mar 2011
    Posts
    2

    Unhappy Template error


    Hi,
    I am trying to generic way to convert the string datatype to other primitive data type. To achieve, i used Template . But i getting error and couldn't resolve the issue and error reported is also clueless. Any help is apprecriated.

    Thanks in Advance
    Shan

    Code
    ====

    #include <vector>
    #include <iostream>
    #include <string>
    using namespace std;

    typedef enum{tdtiDate=0,tdtiLong=1, tdtiLongLong=2, tdtiDouble=3, tdtiFloat=4, tdtiChar=5, tdtiString=6, tdtiPChar =7, tdtiNone=8 } TDataType;



    class TBase
    {
    public :
    };

    typedef void (TBase::*TStrFPtr)(std::string piString);
    typedef void (TBase::*TPCharFPtr)(char *piPChar);
    typedef void (TBase::*TLongFPtr)(long piLong);
    typedef void (TBase::*TDoubleFPtr)(double &);



    class Test : public TBase
    {
    public :
    void SetQuantity( long piQuantity ) {m_Quantity = piQuantity;}
    void SetCount( long piCount ) {m_Count = piCount;}
    void SetIndex( long piIndex ) {m_Index = piIndex;}
    void SetAmt( double piIndex ) {m_Amount = piIndex;}

    void SetPtr();
    void Print() { cout << m_Quantity << "\t" << m_Count << "\t" << m_Index << endl;}
    private :
    long m_Quantity;
    short m_Count;
    short m_Index;
    double m_Amount;

    };


    template <typename T>
    class TFunctor
    {
    public :
    void SetPtr( T piFuncPtr, TDataType piDataType);
    void SetLongData( string m_Data );
    void SetStrData( string m_Data );
    void SetPCharData( string m_Data );
    void SetDoubleData( string m_Data );

    void SetData( string &piData );

    private:
    T m_FuncPointer; // we'll store the data as block of dynamically allocated
    void (TFunctor::*TFP)(std::string piString);
    TBase *mBaseObj;

    };

    template <typename T>
    void TFunctor<T>::SetPtr( T piFuncPtr, TDataType piDataType)
    {
    m_FuncPointer = piFuncPtr;
    if (piDataType == tdtiLong)
    TFP = &TFunctor::SetLongData;
    else if (piDataType == tdtiDouble)
    TFP = &TFunctor::SetDoubleData;
    else if (piDataType == tdtiPChar)
    TFP = &TFunctor::SetPCharData;
    else if (piDataType == tdtiString)
    TFP = &TFunctor::SetStrData;
    }

    template <typename T>
    void TFunctor<T>::SetLongData( string m_Data )
    {
    long lData = atol(m_Data.c_str());
    cout << "Long" << endl;
    ((*mBaseObj).*m_FuncPointer)(lData);
    }

    template <typename T>
    void TFunctor<T>::SetStrData( string m_Data )
    {
    ((*mBaseObj).*m_FuncPointer)(m_Data);
    cout << "String" << endl;
    }

    template <typename T>
    void TFunctor<T>::SetPCharData( string m_Data )
    {
    ((*mBaseObj).*m_FuncPointer)(m_Data.c_str());
    cout << "PChar" << endl;
    }

    template <typename T>
    void TFunctor<T>::SetDoubleData( string m_Data )
    {
    double lData = atof(m_Data.c_str());
    ((*mBaseObj).*m_FuncPointer)(lData);
    cout << "Double" << endl;
    }

    template <typename T>
    void TFunctor<T>::SetData( string &piData )
    {
    ((*this).*TFP)(piData);
    }



    int main()
    {

    TFunctor<TLongFPtr> lFunctor;
    lFunctor.SetPtr((TLongFPtr)&Test::SetQuantity, tdtiLong);
    string lStr = "10";
    lFunctor.SetData(lStr);


    return 0;
    }

    And error Reported is

    test.cpp: In member function `void
    TFunctor<T>::SetDoubleData(std::basic_string<char, std::char_traits<char>,
    std::allocator<char> >) [with T = void (TBase::*)(long int)]':
    test.cpp:67: instantiated from `void TFunctor<T>::SetPtr(T, TDataType) [with T = void (TBase::*)(long int)]'
    test.cpp:116: instantiated from here
    test.cpp:100: warning: argument passing to `long int' from `double'
    test.cpp:100: warning: argument to `long int' from `double'
    test.cpp: In member function `void
    TFunctor<T>::SetPCharData(std::basic_string<char, std::char_traits<char>,
    std::allocator<char> >) [with T = void (TBase::*)(long int)]':
    test.cpp:69: instantiated from `void TFunctor<T>::SetPtr(T, TDataType) [with T = void (TBase::*)(long int)]'
    test.cpp:116: instantiated from here
    test.cpp:92: invalid conversion from `const char*' to `long int'
    test.cpp: In member function `void
    TFunctor<T>::SetStrData(std::basic_string<char, std::char_traits<char>,
    std::allocator<char> >) [with T = void (TBase::*)(long int)]':
    test.cpp:71: instantiated from `void TFunctor<T>::SetPtr(T, TDataType) [with T = void (TBase::*)(long int)]'
    test.cpp:116: instantiated from here
    test.cpp:85: cannot convert `std::basic_string<char, std::char_traits<char>,
    std::allocator<char> >' to `long int' in argument passing

  2. #2
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, in Chicago, or in a galaxy far, far away.
    Posts
    11,655
    For better/quicker help, please post your code inside code blocks so that your indentations and other code stuff is rendered properly (no smileys generated from some end-parens tokens), and include the full class definition for the classes you are declaring/defining.
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

  3. #3
    Just Joined!
    Join Date
    Mar 2011
    Posts
    2
    Hi I attaching the indented code

    Can you please help us
    Attached Files Attached Files

  4. $spacer_open
    $spacer_close
  5. #4
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, in Chicago, or in a galaxy far, far away.
    Posts
    11,655
    Here is the attachment as an inline block of code:
    Code:
    
    #include <vector>
    #include <iostream>
    #include <string>
    using namespace std;
    
    typedef enum{tdtiDate=0,tdtiLong=1, tdtiLongLong=2, tdtiDouble=3, tdtiFloat=4, tdtiChar=5, tdtiString=6, tdtiPChar =7, tdtiNone=8 } TDataType;
    
    
    
    class TBase 
    {
    	public :
    };
    
    typedef void (TBase::*TStrFPtr)(std::string piString);
    typedef void (TBase::*TPCharFPtr)(char *piPChar);
    typedef void (TBase::*TLongFPtr)(long piLong);
    typedef void (TBase::*TDoubleFPtr)(double &);
    
    
    
    class Test : public TBase
    {
    	public :
    		void SetQuantity( long piQuantity ) {m_Quantity = piQuantity;}
    		void SetCount( long piCount ) {m_Count = piCount;}
    		void SetIndex( long piIndex ) {m_Index = piIndex;}
    		void SetAmt( double piIndex ) {m_Amount = piIndex;}
    
    		void SetPtr();
    		void Print() { cout << m_Quantity << "\t" << m_Count << "\t" << m_Index << endl;} 
    	private :
    		long m_Quantity;
    		short m_Count;
    		short m_Index;
    		double m_Amount;
    
    };
    
    
    template <typename T>
    class TFunctor 
    {
    	public :
    		void SetPtr( T piFuncPtr, TDataType piDataType);
    		void SetLongData( string m_Data );
    		void SetStrData( string m_Data );
    		void SetPCharData( string m_Data );
    		void SetDoubleData( string m_Data );
    
    		void SetData( string &piData );
    
    	private:
    		T m_FuncPointer;  
    		void (TFunctor::*TFP)(std::string piString);
    		TBase *mBaseObj;
    };
    
    template <typename T>
    void TFunctor<T>::SetPtr( T piFuncPtr, TDataType piDataType) 
    { 
    	m_FuncPointer = piFuncPtr;
    	if (piDataType == tdtiLong)
    	TFP = &TFunctor::SetLongData;
    	else if (piDataType == tdtiDouble)
    	TFP = &TFunctor::SetDoubleData;
    	else if (piDataType == tdtiPChar)
    	TFP = &TFunctor::SetPCharData;
    	else if (piDataType == tdtiString)
    	TFP = &TFunctor::SetStrData;
    }
    
    template <typename T>
    void TFunctor<T>::SetLongData( string m_Data )
    {
    	long lData = atol(m_Data.c_str());
    	cout << "Long" << endl;
    	((*mBaseObj).*m_FuncPointer)(lData);
    }
    
    template <typename T>
    void TFunctor<T>::SetStrData( string m_Data )
    {
    	((*mBaseObj).*m_FuncPointer)(m_Data);
    	cout << "String" << endl;
    }
    
    template <typename T>
    void TFunctor<T>::SetPCharData( string m_Data )
    {
    	((*mBaseObj).*m_FuncPointer)(m_Data.c_str());
    	cout << "PChar" << endl;
    }
    
    template <typename T>
    void TFunctor<T>::SetDoubleData( string m_Data )
    {
    	double lData = atof(m_Data.c_str());
    	((*mBaseObj).*m_FuncPointer)(lData);
    	cout << "Double" << endl;
    }
    
    template <typename T>
    void TFunctor<T>::SetData( string &piData )
    {
    	((*this).*TFP)(piData);
    }
    
    
    
    int main()
    {
    	TFunctor<TLongFPtr> lFunctor;
    	lFunctor.SetPtr((TLongFPtr)&Test::SetQuantity, tdtiLong);
    	string lStr = "10";
    	lFunctor.SetData(lStr);
    
    	return 0;
    }
    I will comment as soon as I have analyzed your code.
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

  6. #5
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, in Chicago, or in a galaxy far, far away.
    Posts
    11,655
    Please provide the rest of the TBase class. Thanks. Also, why are you using typedefs for the function pointer declarations such as:


    typedef void (TBase::*TStrFPtr)(std::string piString);
    typedef void (TBase::*TPCharFPtr)(char *piPChar);
    typedef void (TBase::*TLongFPtr)(long piLong);
    typedef void (TBase::*TDoubleFPtr)(double &);
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

  7. #6
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, in Chicago, or in a galaxy far, far away.
    Posts
    11,655
    Ok. This is a mess. Please explain in simple terms, but in detail, what you are trying to accomplish. Remember the first rule of programming, KISS (Keep It Simple ...).
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

  8. #7
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, in Chicago, or in a galaxy far, far away.
    Posts
    11,655
    FWIW, I did a lot of this (convert primitive types as needed) in an application framework I developed some years (over 15) ago. In my opinion, you are trying to be too clever by far. The simplest method of converting one primitive type to another is to convert it first to a string, and then from there to the target type. You may not think it so efficient, but with todays' processors (especially Intel chips with their built-in string processing instructions), it isn't much of a burden.

    If you need more, I'll have to address this at a later time. It is now almost 2am here and I'm heading to bed...
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

  9. #8
    Linux Guru Rubberman's Avatar
    Join Date
    Apr 2009
    Location
    I can be found either 40 miles west of Chicago, in Chicago, or in a galaxy far, far away.
    Posts
    11,655
    Ok. Here's some example code how to do this with templates. Note that you don't need the specify type convert() functions if you pass the conversion format string to the template function. In any case, this will allow you to convert a std:string object to any suitable scalar type such as integer, float, double, or whatever. Enjoy!
    Code:
    #include <string>
    #include <iostream>
    #include <sstream>
    #include <stdio.h>
    
    using namespace std;
    
    template<class T> T& convert(T& result, const string& s, const char* fmt)
    {
        cout << "calling convert(" << result << ", \"" << s << "\", \""
             << fmt << "\")" << endl;
        sscanf(s.c_str(), fmt, &result);
        return result;
    }
    
    int convert(int& output, const string& input)
    {
        return convert(output, input, "%d");
    }
    
    double convert(double& output, const string& input)
    {
        return convert(output, input, "%lf");
    }
    
    int main(void)
    {
        string sinput = "999.99";
        int ioutput = 0;
        double doutput = 0.0;
        
        cout << convert(ioutput, sinput) << endl;
        cout << convert(doutput, "999.99") << endl;
    
        cout << convert(ioutput, "bogus") << endl;
        cout << convert(doutput, "bogus") << endl;
    
        return 0;
    }
    Note that you need an argument for the output type, otherwise the template function won't work. It can be a throw-away placeholder variable. Also note that the "heavy lifting" of the conversion function is done by the "C" sscanf() function. As shown, converting again with an invalid string ("bogus") is a NOP. The old values are maintained. The lesson here is that you ALWAYS want to initialize your output variables to some sane value so that you don't get random noise if the input string is invalid for the type. Also, doing an integer conversion with a string representation of a float still works - you just get the integer part as a result as shown.
    Sometimes, real fast is almost as good as real time.
    Just remember, Semper Gumbi - always be flexible!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •