We help IT Professionals succeed at work.

Need method for CString::Format function in GNU compiler

prgrmmer93231
on
I'm trying to make a CString class that can work in Linux, but I'm running into a problem with the Format function.
In MFC you can pass a CString object to the Format function without using the "&" sign.
CString Name = "Tom";
CString data;
data.Format("My name is %s",Name);

That works in MFC (VC++), but it does not work in the GNU compiler.  The GNU compiler requires that I use the LPCTSTR operator.
Like
data.Format("My name is %s",(LPCTSTR)Name);
or
data.Format("My name is %s",Name.operator LPCTSTR());

Is there any way I can get the Format function to be able to accept the syntax in the original code?
Comment
Watch Question

CERTIFIED EXPERT
Author of the Year 2009

Commented:
Why not go right to the horsey's mouth?  The file StrEx.cpp contains the complete code for CString::Format.  and the file Strcore.cpp and Afx.h provide the rest of the clues.  It's pretty obvious what they do...

A CString contains exactly one data member... a pointer to its null-terminated string data.  So when you pass a CString by value, you pass all of its data members... which means that you pass one pointer.  Any function that doesn't know any better can treat that pointer as a pointer to a regular old character string.  

Functions that use the StdArg.h or VarArgs.h macros for variable argument lists will see the %s and assume that there is a pointer-to-char there and whadayaknow! there is one!

So the complete and final answer to your question is: Redesign your Linux CString class so that it contains just one data member and make that data member a pointer to a character string.

-- Dan

Author

Commented:
>>So the complete and final answer to your question is:
>>Redesign your Linux CString class so that it contains
>>just one data member and make that data member a pointer
>>to a character string.

My class is already designed that way.  Most of my code is the code taken from MFC, but it does not work on a GNU compiler.



>>Functions that use the StdArg.h or VarArgs.h macros for
>>variable argument lists will see the %s and
>>assume that there is a pointer-to-char there and
>>whadayaknow! there is one!

This is not the case.  Functions that use VarArg do not convert the veriable to a pointer-to-char.

This method works in VC++ but it does not work in the GNU compiler.

I'm not sure why this method doesn't work in the GNU compiler, but I think it has something to do with the fact that the class is not a POD class.

Author

Commented:
If someone comes up with a working method that will work on the GNU compiler, I'll award more points for this.
>>I'm not sure why this method doesn't work in the GNU
>>compiler, but I think it has something to do with
>>the fact that the class is not a POD class.

You are correct.  The problem has to do with your class being a non-POD class.

Check out this thread:
http://experts-exchange.com/jsp/qShow.jsp?ta=cplusprog&qid=12020180

It doesn't look like anything got resolved from it, but it gives you a good place to start from, and it explains why your code doesn't work in the GNU compiler.

The bottom line is that the MFC code is not portable.  It is not garanteed to work from one compiler to another.

The ANSI C++ standard address the ArgVar issue in a non-standard way.
It states that the results are implementation defined.

That means each compiler can handle non-POD on a va_list function the way it feels like handling it.

So if you use the MFC code for the Format function, your code is not going to be portable, and most likely will not work in many compilers.

It works in VC++ because VC designed the MFC class, and the compiler.
AxterSenior Software Engineer

Commented:
Zulma9999,
I did come up with a solution to this problem.  Although I didn't posted on my question.

I'm going to posted on my question, and then I'll posted on this question.

prgrmmer93231,
I'm not sure if you'll like my solution, but I believe is the best that you can do if you want the code to be portable to any ANSI C++ compiler.
AxterSenior Software Engineer

Commented:
My solution to this problem was to use template functions for Format.
I also used overloaded Translate Functions.  The overloaded Translate functions force any object to use what over string operators it had.
Since CString has a LPCTSTR operator, the translate functions force the CString object to output the via the LPCTSTR() operator.
AxterSenior Software Engineer

Commented:
Here's the top part of the template code.

     //Format Functions
private:
     void Format_Main(const TCHAR * lpszFormat, ...);//This is the original MFC-Format function
     //zArg overloaded functions for Format function
     char zArg(char Arg){return Arg;}
     unsigned char zArg(unsigned char Arg){return Arg;}
     int zArg(int Arg){return Arg;}
     unsigned int zArg(unsigned int Arg){return Arg;}
     long zArg(long Arg){return Arg;}
     unsigned long zArg(unsigned long Arg){return Arg;}
     double zArg(double Arg){return Arg;}
     float zArg(float Arg){return Arg;}
     const char* zArg(const char* Arg){return Arg;}
     const char* zArg(const std::string &Arg){return Arg.c_str();}
     LPCTSTR zArg(const CString &Arg){return Arg.operator LPCTSTR();}
public:
     //Unix flavor Format Functions
     //21 Overloaded Format functions
     void Format(const TCHAR * lpszFormat)
     {
          Format_Main(lpszFormat);
     }
     
     template<class T0>
          void Format(const TCHAR * lpszFormat, const T0 &arg0)
     {
          Format_Main(lpszFormat, zArg(arg0));
     }
Senior Software Engineer
Commented:
The zArg() functions are the overloaded translate functions.

Format_Main is the original MFC Format function.

In order for this to work, you need about 20 overloaded template Format functions.  Each one with a different quantity of arguments.

Code:
      template<class T0, class T1>
            void Format(const TCHAR * lpszFormat, const T0 &arg0, const T1 &arg1)
      {
            Format_Main(lpszFormat, zArg(arg0), zArg(arg1));
      }
      
      template<class T0, class T1, class T2>
            void Format(const TCHAR * lpszFormat, const T0 &arg0, const T1 &arg1, const T2 &arg2)
      {
            Format_Main(lpszFormat, zArg(arg0), zArg(arg1), zArg(arg2));
      }
      
      template<class T0, class T1, class T2, class T3>
            void Format(const TCHAR * lpszFormat, const T0 &arg0, const T1 &arg1, const T2 &arg2, const T3 &arg3)
      {
            Format_Main(lpszFormat, zArg(arg0), zArg(arg1), zArg(arg2), zArg(arg3));
      }
      
      template<class T0, class T1, class T2, class T3, class T4>
            void Format(const TCHAR * lpszFormat, const T0 &arg0, const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4)
      {
            Format_Main(lpszFormat, zArg(arg0), zArg(arg1), zArg(arg2), zArg(arg3), zArg(arg4));
      }
      
      template<class T0, class T1, class T2, class T3, class T4, class T5>
            void Format(const TCHAR * lpszFormat, const T0 &arg0, const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4, const T5 &arg5)
      {
            Format_Main(lpszFormat, zArg(arg0), zArg(arg1), zArg(arg2), zArg(arg3), zArg(arg4), zArg(arg5));
      }
      
      template<class T0, class T1, class T2, class T3, class T4, class T5, class T6>
            void Format(const TCHAR * lpszFormat, const T0 &arg0, const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4, const T5 &arg5, const T6 &arg6)
      {
            Format_Main(lpszFormat, zArg(arg0), zArg(arg1), zArg(arg2), zArg(arg3), zArg(arg4), zArg(arg5), zArg(arg6));
      }
      
      template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7>
            void Format(const TCHAR * lpszFormat, const T0 &arg0, const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4, const T5 &arg5, const T6 &arg6, const T7 &arg7)
      {
            Format_Main(lpszFormat, zArg(arg0), zArg(arg1), zArg(arg2), zArg(arg3), zArg(arg4), zArg(arg5), zArg(arg6), zArg(arg7));
      }
      
      template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
            void Format(const TCHAR * lpszFormat, const T0 &arg0, const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4, const T5 &arg5, const T6 &arg6, const T7 &arg7, const T8 &arg8)
      {
            Format_Main(lpszFormat, zArg(arg0), zArg(arg1), zArg(arg2), zArg(arg3), zArg(arg4), zArg(arg5), zArg(arg6), zArg(arg7), zArg(arg8));
      }
      
      template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
            void Format(const TCHAR * lpszFormat, const T0 &arg0, const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4, const T5 &arg5, const T6 &arg6, const T7 &arg7, const T8 &arg8, const T9 &arg9)
      {
            Format_Main(lpszFormat, zArg(arg0), zArg(arg1), zArg(arg2), zArg(arg3), zArg(arg4), zArg(arg5), zArg(arg6), zArg(arg7), zArg(arg8), zArg(arg9));
      }
      
      template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10>
            void Format(const TCHAR * lpszFormat, const T0 &arg0, const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4, const T5 &arg5, const T6 &arg6, const T7 &arg7, const T8 &arg8, const T9 &arg9, const T10 &arg10)
      {
            Format_Main(lpszFormat, zArg(arg0), zArg(arg1), zArg(arg2), zArg(arg3), zArg(arg4), zArg(arg5), zArg(arg6), zArg(arg7), zArg(arg8), zArg(arg9), zArg(arg10));
      }
      
      template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11>
            void Format(const TCHAR * lpszFormat, const T0 &arg0, const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4, const T5 &arg5, const T6 &arg6, const T7 &arg7, const T8 &arg8, const T9 &arg9, const T10 &arg10, const T11 &arg11)
      {
            Format_Main(lpszFormat, zArg(arg0), zArg(arg1), zArg(arg2), zArg(arg3), zArg(arg4), zArg(arg5), zArg(arg6), zArg(arg7), zArg(arg8), zArg(arg9), zArg(arg10), zArg(arg11));
      }
      
      template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12>
            void Format(const TCHAR * lpszFormat, const T0 &arg0, const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4, const T5 &arg5, const T6 &arg6, const T7 &arg7, const T8 &arg8, const T9 &arg9, const T10 &arg10, const T11 &arg11, const T12 &arg12)
      {
            Format_Main(lpszFormat, zArg(arg0), zArg(arg1), zArg(arg2), zArg(arg3), zArg(arg4), zArg(arg5), zArg(arg6), zArg(arg7), zArg(arg8), zArg(arg9), zArg(arg10), zArg(arg11), zArg(arg12));
      }
      
      template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13>
            void Format(const TCHAR * lpszFormat, const T0 &arg0, const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4, const T5 &arg5, const T6 &arg6, const T7 &arg7, const T8 &arg8, const T9 &arg9, const T10 &arg10, const T11 &arg11, const T12 &arg12, const T13 &arg13)
      {
            Format_Main(lpszFormat, zArg(arg0), zArg(arg1), zArg(arg2), zArg(arg3), zArg(arg4), zArg(arg5), zArg(arg6), zArg(arg7), zArg(arg8), zArg(arg9), zArg(arg10), zArg(arg11), zArg(arg12), zArg(arg13));
      }
      
      template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14>
            void Format(const TCHAR * lpszFormat, const T0 &arg0, const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4, const T5 &arg5, const T6 &arg6, const T7 &arg7, const T8 &arg8, const T9 &arg9, const T10 &arg10, const T11 &arg11, const T12 &arg12, const T13 &arg13, const T14 &arg14)
      {
            Format_Main(lpszFormat, zArg(arg0), zArg(arg1), zArg(arg2), zArg(arg3), zArg(arg4), zArg(arg5), zArg(arg6), zArg(arg7), zArg(arg8), zArg(arg9), zArg(arg10), zArg(arg11), zArg(arg12), zArg(arg13), zArg(arg14));
      }
      
      template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15>
            void Format(const TCHAR * lpszFormat, const T0 &arg0, const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4, const T5 &arg5, const T6 &arg6, const T7 &arg7, const T8 &arg8, const T9 &arg9, const T10 &arg10, const T11 &arg11, const T12 &arg12, const T13 &arg13, const T14 &arg14, const T15 &arg15)
      {
            Format_Main(lpszFormat, zArg(arg0), zArg(arg1), zArg(arg2), zArg(arg3), zArg(arg4), zArg(arg5), zArg(arg6), zArg(arg7), zArg(arg8), zArg(arg9), zArg(arg10), zArg(arg11), zArg(arg12), zArg(arg13), zArg(arg14), zArg(arg15));
      }
      
      template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15, class T16>
            void Format(const TCHAR * lpszFormat, const T0 &arg0, const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4, const T5 &arg5, const T6 &arg6, const T7 &arg7, const T8 &arg8, const T9 &arg9, const T10 &arg10, const T11 &arg11, const T12 &arg12, const T13 &arg13, const T14 &arg14, const T15 &arg15, const T16 &arg16)
      {
            Format_Main(lpszFormat, zArg(arg0), zArg(arg1), zArg(arg2), zArg(arg3), zArg(arg4), zArg(arg5), zArg(arg6), zArg(arg7), zArg(arg8), zArg(arg9), zArg(arg10), zArg(arg11), zArg(arg12), zArg(arg13), zArg(arg14), zArg(arg15), zArg(arg16));
      }
      
      template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15, class T16, class T17>
            void Format(const TCHAR * lpszFormat, const T0 &arg0, const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4, const T5 &arg5, const T6 &arg6, const T7 &arg7, const T8 &arg8, const T9 &arg9, const T10 &arg10, const T11 &arg11, const T12 &arg12, const T13 &arg13, const T14 &arg14, const T15 &arg15, const T16 &arg16, const T17 &arg17)
      {
            Format_Main(lpszFormat, zArg(arg0), zArg(arg1), zArg(arg2), zArg(arg3), zArg(arg4), zArg(arg5), zArg(arg6), zArg(arg7), zArg(arg8), zArg(arg9), zArg(arg10), zArg(arg11), zArg(arg12), zArg(arg13), zArg(arg14), zArg(arg15), zArg(arg16), zArg(arg17));
      }
      
      template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15, class T16, class T17, class T18>
            void Format(const TCHAR * lpszFormat, const T0 &arg0, const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4, const T5 &arg5, const T6 &arg6, const T7 &arg7, const T8 &arg8, const T9 &arg9, const T10 &arg10, const T11 &arg11, const T12 &arg12, const T13 &arg13, const T14 &arg14, const T15 &arg15, const T16 &arg16, const T17 &arg17, const T18 &arg18)
      {
            Format_Main(lpszFormat, zArg(arg0), zArg(arg1), zArg(arg2), zArg(arg3), zArg(arg4), zArg(arg5), zArg(arg6), zArg(arg7), zArg(arg8), zArg(arg9), zArg(arg10), zArg(arg11), zArg(arg12), zArg(arg13), zArg(arg14), zArg(arg15), zArg(arg16), zArg(arg17), zArg(arg18));
      }
      
      template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10, class T11, class T12, class T13, class T14, class T15, class T16, class T17, class T18, class T19>
            void Format(const TCHAR * lpszFormat, const T0 &arg0, const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4, const T5 &arg5, const T6 &arg6, const T7 &arg7, const T8 &arg8, const T9 &arg9, const T10 &arg10, const T11 &arg11, const T12 &arg12, const T13 &arg13, const T14 &arg14, const T15 &arg15, const T16 &arg16, const T17 &arg17, const T18 &arg18, const T19 &arg19)
      {
            Format_Main(lpszFormat, zArg(arg0), zArg(arg1), zArg(arg2), zArg(arg3), zArg(arg4), zArg(arg5), zArg(arg6), zArg(arg7), zArg(arg8), zArg(arg9), zArg(arg10), zArg(arg11), zArg(arg12), zArg(arg13), zArg(arg14), zArg(arg15), zArg(arg16), zArg(arg17), zArg(arg18), zArg(arg19));
      }
      
AxterSenior Software Engineer

Commented:
It's not a pretty solution, because of all the overloaders you have to add, but the solution does work, and you don't have to change original code syntax that calls the CString object.

You'll have to use the same method with the sprintf function if that is used in your code.

Explore More ContentExplore courses, solutions, and other research materials related to this topic.