Stringstreams and CStrings

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Rob Richardson

    Stringstreams and CStrings

    Greetings!

    I am running into a problem with implicit conversion of arguments when
    trying to insert the contents of a CString object into a stringstream.

    I am using the following typedef:

    typedef std::basic_stri ngstream<TCHAR> ustringstream;

    I have a function that somewhat resembles the following:

    void DoSomething(CSt ring TitleString)
    {
    TryToDoSomethin g();
    if (ItDidntWork())
    {
    ustringstream theStream;
    theStream << TitleString << _T("\n");
    theStream << WhyItDidntWork( );
    TellTheUserItDi dntWork(theStre am);
    }
    }

    If _UNICODE is not defined, TCHAR evaluates to char, and everybody's
    happy. The stream is built as expected. But if _UNICODE is defined,
    TCHAR becomes unsigned short, and instead of the expected title, the
    stream contains a memory address in hexadecimal format.

    Stepping into the code at the point of the first insertion, I see that
    the first thing that happens is that CString's operator(LPCTST R)
    conversion method is called. Then basic_ostream<> 's operator<<(cons t
    void*) method is called, which just puts the pointer's value into the
    stream.

    If I explictly cast TitleString to an LPCTSTR, the title is inserted
    into the string as expected! But an explicit cast is really ugly, and
    there's a lot of places where I'd have to do it. In an attempt to
    find a better way, I wrote the following function:

    uostream& operator<<(uost ream& theStream, const CString& theString)
    {
    return operator<<(theS tream, (LPCTSTR)theStr ing);
    }

    But when this function was executed, the const char* that I got from
    the cast was converted back into a CString and I ended up in an
    endless loop and a stack overflow.

    Can anybody explain what is going on here and what the best way out of
    this morass is?

    Thanks very much!

    Rob Richardson
  • Bobo

    #2
    Re: Stringstreams and CStrings

    rrichardson@pre ssco.com (Rob Richardson) wrote in message news:<fefdaf6f. 0307111158.c780 fe8@posting.goo gle.com>...
    [snip]
    [color=blue]
    > If _UNICODE is not defined, TCHAR evaluates to char, and everybody's
    > happy. The stream is built as expected. But if _UNICODE is defined,
    > TCHAR becomes unsigned short, and instead of the expected title, the
    > stream contains a memory address in hexadecimal format.
    >
    > Stepping into the code at the point of the first insertion, I see that
    > the first thing that happens is that CString's operator(LPCTST R)
    > conversion method is called. Then basic_ostream<> 's operator<<(cons t
    > void*) method is called, which just puts the pointer's value into the
    > stream.[/color]

    I encountered this very problem a few days ago. I think that what
    happens is the following. The CString is converted to (const wchar_t*)
    and then there are two possible operator<< overloads to call:
    std::wostream & operator<<(std: :wostream &os, const wchar_t *ws);
    std::wostream & std::wostream:: operator<<(void *p);
    (well, actually the template versions of these functions, with wchar_t
    and so on)

    That is, a member function that writes a pointer and a nonmember
    function that writes a wide string. But now, when you write:
    wchar_t *x;
    os << x;
    which one is selected? Well, in MSVC6 it depends on the type of the
    dynamic stream: if the stream is of type the base type (std::wostream)
    the member function is selected (wrong), but if the stream is of a
    derived type, say wstringstream, then the nonmember function is called
    (right!).
    I'm not sure, but I think that this is not standard, and the compiler
    is wrong, maybe someone out there can confirm this.

    Actually, there are a few more cases in your code, but the idea is the
    same, sometimes MSVC takes it right, sometimes it doesn't.

    My solution was to write a function like the following:

    uostream& operator<<(uost ream& theStream, const CString& theString)
    {
    theStream.write (theString, theString.GetLe ngth());
    return theStream;
    }

    Using the write member function all should be fine. And even the cast
    goes away!!

    HTH
    Bobo

    Comment

    • wpcmame

      #3
      Re: Stringstreams and CStrings

      Had a similar problem and found that the compiler for some reason didn't see
      the friend operator>> functions.

      using std::operator<< ;

      solved the problem for me but I have no idea why it is needed.


      Comment

      Working...