The examples given in the MFC library fail miserably most fo the time--
even for simple stuff that I'd expect to work without a hitch. For
instance, I can't do this:
CString kindOfFruit = "bananas";
... because I get "error C2440: 'initializing' : cannot convert from
'const char [8] to 'ATL::CString<BaseType,StringTraits>' etc. etc. etc.
For passing CString to a routine that expects "char *", the
documentation suggests casting to LPCTSTR. But when I try that, I get
error C2664 saying that the compiler can't convert LPCTSTR to 'char *'
because "Types pointed to are unrelated; conversion requires
reinterpret_cast, C-style cast or function-style cast."
No matter what I do, I can't seem to create anything that I can cast to
a 'char *'.
I figure there's got to be something really obvious here that I've
overlooked, but I'm not seeing it. Can anyone help me out?
-- Chris
(Remove the first "i" to reply.)
Use CStringA (for ASCII, and hence char*) or CStringW (for UNICODE, and
hence wchar_t* ).
If you want to write apps that easily change (why?) then use CString and it
will change between CStringA and CStringW depending upon the UNICODE project
settings (instead of mbcs).
--
- Mark Randall
http://www.temporal-solutions.co.uk
"We're Systems and Networks..."
"It's our job to know..."
"R. Christian Call" <rcc...@optionline.net> wrote in message
news:MPG.1eb05443...@msnews.microsoft.com...
--
Jonathan Wood
SoftCircuits
http://www.softcircuits.com
Available for consulting: http://www.softcircuits.com/jwood/resume.htm
"R. Christian Call" <rcc...@optionline.net> wrote in message
news:MPG.1eb05443...@msnews.microsoft.com...
>I recently got hold of a copy of VS 2005, and I've been playing around
>with writing a VC++ MFC application that needs to convert some CString
>values to C character strings, in order to pass them to a C function.
>I'm having trouble doing that, and I can't seem to find good info about
>the problem.
>
>The examples given in the MFC library fail miserably most fo the time--
>even for simple stuff that I'd expect to work without a hitch. For
>instance, I can't do this:
>
>CString kindOfFruit = "bananas";
****
Note that default for VS 2005 is Unicode, so a quoted string like above is meaningless.
You could either write
CStringA kindOfFruit = "bananans";
or
CStringW kindOfFruit = L"bananas";
or
CString kindOfFruite = _T("bananas");
but what you wrote should not compile, and the error message below is what you should get.
****
>
>... because I get "error C2440: 'initializing' : cannot convert from
>'const char [8] to 'ATL::CString<BaseType,StringTraits>' etc. etc. etc.
>
>For passing CString to a routine that expects "char *", the
>documentation suggests casting to LPCTSTR. But when I try that, I get
>error C2664 saying that the compiler can't convert LPCTSTR to 'char *'
>because "Types pointed to are unrelated; conversion requires
>reinterpret_cast, C-style cast or function-style cast."
****
That's because you are using a Unicode string. If you want a char *, either use CStringA
or use the ATL functions such as T2A to convert a CString to an 8-bit string. So indeed
it is unable to convert a Unicode string to a "char *" because they are incompatible,
which is what the error message tells you.
****
>
>No matter what I do, I can't seem to create anything that I can cast to
>a 'char *'.
****
Sure you can. But since you have a Unicode app, you have to go through one more level of
translation.
****
>
>I figure there's got to be something really obvious here that I've
>overlooked, but I'm not seeing it.
****
Unicode
***
>Can anyone help me out?
>
>
>-- Chris
>
>(Remove the first "i" to reply.)
Joseph M. Newcomer [MVP]
email: newc...@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
--
NewsGuy.Com 30Gb $9.95 Carry Forward and On Demand Bandwidth
Thanks for the help. Changing the project settings so that they didn't
specify UNICODE did the trick.
Chris
In article <#jkRTX#YGHA...@TK2MSFTNGP03.phx.gbl>, mark
[__OKTHISISFAKE_]y...@REMOVETHISgoogle.ANDTHIScom says...
--
Mihai Nita [Microsoft MVP, Windows - SDK]
http://www.mihai-nita.net
------------------------------------------
Replace _year_ with _ to get the real email
Joe:
That's interesting, but I disagree. In VC6, and I think VC7, in a
UNICODE build
CString kindOfFruit = "bananas";
will actually compile, because CString contains "conversion
constructors" which will initialize a CString from either narrow or wide
characters in both ANSI and UNICODE build.
IMO, this is a terrible feature, because (like most automatic
conversions) it prevents the compiler from type-checking the code. But I
find it hard to believe that MS would have removed this feature from
VC8, because much code (not mine!) relies on this feature to convert
between narrow/wide character strings.
David Wilkinson
"David Wilkinson" <no-r...@effisols.com> wrote in message
news:%23w1CH%23FZGH...@TK2MSFTNGP03.phx.gbl...
> There is macro that disables implicit conversion (will declare conversion
> constructors "explicit"). It may be set by default.
>
[snip}
Really? I did not know that. What is it called, and which versions of VC
support it?
But sometimes even an explicit conversion constructor is harmful. If you
have an application (I do) where all 8-bit strings are UTF-8 then the
conversion will not do the right thing, because it uses the local code
page. Even worse, the app will appear to work if it uses only ASCII strings.
David Wilkinson
I think the bigger issue with this is that it uses the ACP code page
(whatever is set) to do the conversion to multi-byte so you don't always get
a clean conversion. However, to be fair, I find the conversion feature to
be pretty handy at times when I know I am not doing something that would
mangle my strings. You're right though, it doesn't produce any error
message during compile. That makes me wonder how the OP got this error when
he was compiling.
Tom
"David Wilkinson" <no-r...@effisols.com> wrote in message
news:%23w1CH%23FZGH...@TK2MSFTNGP03.phx.gbl...
> Hi David,
>
> I think the bigger issue with this is that it uses the ACP code page
> (whatever is set) to do the conversion to multi-byte so you don't always get
> a clean conversion. However, to be fair, I find the conversion feature to
> be pretty handy at times when I know I am not doing something that would
> mangle my strings. You're right though, it doesn't produce any error
> message during compile. That makes me wonder how the OP got this error when
> he was compiling.
>
> Tom
Tom:
Yes, this puzzled me also. Surely Alexander's explicit constructor will
not prevent this usage?
CString kindOfFruit = "bananas";
It would however prevent the even more insidious
CString s2 = _T("Hello");
std::string s1 = " world";
s2 += s1.c_str();
which also compiles in a Unicode build in VC6 (and VC7 I think).
You are right that it is the code page issue which is the problem. If
you do not want to do conversions using the local code page, you're
hosed. IMHO, if you want to convert, you should use the conversion
macros (which are classes in VC7 and above, much better). Say what you
mean (and mean what you say).
David Wilkinson
Tom
"David Wilkinson" <no-r...@effisols.com> wrote in message
news:%23FWUXBJ...@TK2MSFTNGP03.phx.gbl...
> CString kindOfFruit("bananas");
> will compile because there is an overloaded constructor, overloaded for both LPCSTR and
> LPCWSTR, and depending on the build, one or the other will do the appropriate conversion.
> But the assignment statement doesn't work. I've seen it fail in a lot of programs.
> joe
>
[snip]
Hi Joe:
Now that IS interesting. In VC7, you are right. The following will not
compile in a UNICODE application:
CString kindOfFruit = "bananas";
However all of the following do:
CString kindOfFruit("bananas");
CString kindOfFruit = CString("bananas");
CString kindOfFruit;
kindOfFruit = "bananas";
CString kindOfFruit;
kindOfFruit += "bananas";
In my ideal world, none of them would compile (and I have fixed my VC6
headers so they don't). But why does the first one not compile? As I
understand it, when you do
CString kindOfFruit = "bananas";
this is not an assignment (though assignment would work!). Rather, the
compiler should first construct a temporary CString using the const
char* constructor, and then initialize kindOfFruit using the copy
constructor. It is also allowed to elide the temporary and use the const
char* constructor directly, provided the first method would have been
legal.
So why doesn't this work? Can it have to do with the fact that CString
is a template class in VC7 onward?
C++ experts?
David Wilkinson
=====================
>Joseph M. Newcomer wrote:
See if the relevant ctor is declared "explicit". If so, there's your
answer.
--
Doug Harrison
Visual C++ MVP
Hi Doug:
In VC7.1, none of the CStringT constructors is explicit (at least in the
documentation). But CStringT is derived from CSimpleStringT, which does
have an explicit constructor:
explicit CSimpleStringT(
IAtlStringMgr* pStringMgr
) throw( );
At this point my head started to spin. What is IAtlStringMgr? Anyway, I
do not see how this explicit declaration discriminates between LPCSTR
and LPCWSTR. Also, does explicit base constructor carry over to the
derived class? CString has gotten very complicated!
IMO, no matter what, MS missed a big opportunity to get rid of all the
conversion constructors when they redesigned the CString class using
templates. They must make the coding of CStringT very complicated. In
the standard library you can just do
typedef std::basic_string<TCHAR> tstring;
and you're done. No conversion constructors, thank you.
David Wilkinson
CString cs = "This is a test";
cs = "This is another test";
In my Unicode application.
Not that I think it should...
Tom
"David Wilkinson" <no-r...@effisols.com> wrote in message
news:eS6wxBUZ...@TK2MSFTNGP04.phx.gbl...
> What am I missing? This compiles fine for me:
>
> CString cs = "This is a test";
> cs = "This is another test";
>
> In my Unicode application.
>
> Not that I think it should...
>
> Tom
>
[snip]
Tom!
You have been converted (to non-converting CString). Now we need to work
on top-posting. :-)
What version of VC is this? This does not compile for me on V7.1 with
UNICODE enabled:
CString cs = "This is a test";
I'm pretty sure it did on VC6 before I yanked the conversion
constructors and assignments from my headers. You're using VC8, perhaps?
David Wilkinson
Tom
"David Wilkinson" <no-r...@effisols.com> wrote in message
news:ODxm3cVZ...@TK2MSFTNGP02.phx.gbl...
> I'm using VC++ 2005 (VC8). It's going to be tougher to get me to bottom
> post... too much work to post and read imo.
>
> Tom
>
> "David Wilkinson" <no-r...@effisols.com> wrote in message
> news:ODxm3cVZ...@TK2MSFTNGP02.phx.gbl...
>
>
>>You have been converted (to non-converting CString). Now we need to work
>>on top-posting. :-)
>>
Tom:
Oh, well.
That's strange, because the OP was using VS2005 and he said
CString kindOfFruit = "bananas";
would not compile in Unicode build.
David
>Hi Doug:
>
>In VC7.1, none of the CStringT constructors is explicit (at least in the
>documentation). But CStringT is derived from CSimpleStringT, which does
>have an explicit constructor:
>
>explicit CSimpleStringT(
> IAtlStringMgr* pStringMgr
>) throw( );
>
>At this point my head started to spin. What is IAtlStringMgr? Anyway, I
>do not see how this explicit declaration discriminates between LPCSTR
>and LPCWSTR. Also, does explicit base constructor carry over to the
>derived class? CString has gotten very complicated!
Ctors aren't inherited, so this couldn't be a factor. I seem to think
IAtlStringMgr may be an allocator of some kind, but I haven't looked at it
closely.
>IMO, no matter what, MS missed a big opportunity to get rid of all the
>conversion constructors when they redesigned the CString class using
>templates. They must make the coding of CStringT very complicated. In
>the standard library you can just do
>
>typedef std::basic_string<TCHAR> tstring;
>
>and you're done. No conversion constructors, thank you.
Yes, I've followed your comments for some time on that subject, and you've
convinced me they're evil. There I was thinking CString was *nice* to
provide a ctor for LPCSTR in Unicode builds, even better than tstring in
this respect. :)
> CString kindOfFruit = "bananas";
>
> ... because I get "error C2440: 'initializing' : cannot convert from
> 'const char [8] to 'ATL::CString<BaseType,StringTraits>' etc. etc. etc.
>
You can always construct your CString objects this way:
CString kindOfFruit("bananas");
But, probably you are getting this error 'cause you are not using the
correct "character type".
VC++ 8 projects defaults do UNICODE or Wide String instead of Ansi String.
So, use the _T() macro defined in <tchar.h>:
CString kindOfFunc(_T("bananas"));
this will ensure that you are using the right "character type"... Or, change
your project options to deal only with ANSI strings...
[]s
Fred
I've seen the failure when converting existing client code which was not written
Unicode-aware to Unicode. Usually when there is some odd reason my pattern-matcher missed
the assignment.
joe
Tom
"David Wilkinson" <no-r...@effisols.com> wrote in message
news:uWvbFkWZ...@TK2MSFTNGP02.phx.gbl...
Hummm... I'm not sure, but maybe "bananas" is a ANSI version of the
string...
CString kindOfFruit = L"bananas";
[]s
Fred
I think that is true too, but the original thought was that the new compiler
would gripe if we tried to do this thing rather than just converting the
ANSI string. I was saying it still doesn't, at least for me. The OP said
he got a compile error on a similar statement.
Tom
"Frederico Pissarra" <m...@nowhere.net> wrote in message
news:uNpBgtBa...@TK2MSFTNGP05.phx.gbl...