Stringstreams and CStrings

R

Rob Richardson

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_stringstream<TCHAR> ustringstream;

I have a function that somewhat resembles the following:

void DoSomething(CString TitleString)
{
TryToDoSomething();
if (ItDidntWork())
{
ustringstream theStream;
theStream << TitleString << _T("\n");
theStream << WhyItDidntWork();
TellTheUserItDidntWork(theStream);
}
}

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(LPCTSTR)
conversion method is called. Then basic_ostream<>'s operator<<(const
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<<(uostream& theStream, const CString& theString)
{
return operator<<(theStream, (LPCTSTR)theString);
}

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
 
B

Bobo

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(LPCTSTR)
conversion method is called. Then basic_ostream<>'s operator<<(const
void*) method is called, which just puts the pointer's value into the
stream.

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::eek:perator<<(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<<(uostream& theStream, const CString& theString)
{
theStream.write(theString, theString.GetLength());
return theStream;
}

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

HTH
Bobo
 
W

wpcmame

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

using std::eek:perator<<;

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

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top