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.
- 03-04-2011 #1Just Joined!
- Join Date
- Mar 2011
- Posts
- 2
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
- 03-04-2011 #2Linux Guru
- Join Date
- Apr 2009
- Location
- I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
- Posts
- 10,141
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!
- 03-05-2011 #3Just Joined!
- Join Date
- Mar 2011
- Posts
- 2
Hi I attaching the indented code
Can you please help us
- 03-05-2011 #4Linux Guru
- Join Date
- Apr 2009
- Location
- I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
- Posts
- 10,141
Here is the attachment as an inline block of code:
I will comment as soon as I have analyzed your 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; }Sometimes, real fast is almost as good as real time.
Just remember, Semper Gumbi - always be flexible!
- 03-05-2011 #5Linux Guru
- Join Date
- Apr 2009
- Location
- I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
- Posts
- 10,141
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!
- 03-05-2011 #6Linux Guru
- Join Date
- Apr 2009
- Location
- I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
- Posts
- 10,141
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!
- 03-05-2011 #7Linux Guru
- Join Date
- Apr 2009
- Location
- I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
- Posts
- 10,141
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!
- 03-05-2011 #8Linux Guru
- Join Date
- Apr 2009
- Location
- I can be found either 40 miles west of Chicago, or in a galaxy far, far away.
- Posts
- 10,141
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!
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.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; }Sometimes, real fast is almost as good as real time.
Just remember, Semper Gumbi - always be flexible!


Reply With Quote
