Jdv
Jdv

Reputation: 993

C++ creating CString from std::string fails

In my MFC based application this code:

std::string stdString("MappingName");
std::cout << "as String: " << stdString << std::endl;
CString cString(stdString.c_str());
std::cout << "as CString: " << cString << std::endl;

Produces this output:

as String: MappingName
as CString: 01DEA060

The value of the CString is different every time I run it, but the length seems to be constant. Some other results are 042219B0 and 042C4378.

I've tried every variation discussed in this thread, with the results being the same. I've also tried to change the Character Set in the Visual Studio project from Use Unicode Character Set to Use Multi-Byte Character Set, again with no effect.

What could be the reason the conversion fails?

Edit: More tests show that the value of the std::string doesn't seem to make a difference:

tmp as String: The quick brown fox jumps over the lazy dog
tmp as CString: 00EAAF88

I've also set the Character Set to Not Set which didn't help either.

Upvotes: 1

Views: 1028

Answers (2)

IInspectable
IInspectable

Reputation: 51345

The issue is a combination of two aspects:

  • Mixture of string types with explicit encoding (std::string) and generic-text mapping (CString vs. CStringA/CStringW).
  • CString's ability to convert between encodings through conversion c'tors.

The std::string converted to the CString just fine, presumably constructing a CStringW object. Since there is no operator<< overload for the std::ostream that takes a wchar_t const* (which CStringW implicitly converts to), it merely prints the address, matching the generic void const* overload.

The solution here is to take the generic-text mappings out of the picture, and construct a CString specialization matching the source encoding (ANSI for std::string, i.e. CStringA):

std::string stdString("MappingName");
std::cout << "as String: " << stdString << std::endl;
CStringA cString(stdString.c_str());
std::cout << "as CString: " << cString.GetString() << std::endl;

To get notified about implicit conversions when constructing CStrings, you can #define the _CSTRING_DISABLE_NARROW_WIDE_CONVERSION proprocessor symbol. This will in turn generate compiler errors in case you are trying to invoke any of the conversion c'tors.

Upvotes: 3

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275190

The problem is printing not conversion.

CString can implicilty convert to TCHAR const*. When built with unicode enabled, this is wchar_t const*.

std::cout has no wchar_t const* overload for <<. It does have a void const* overload.

The void pointer overload prints a pointer address in hex.

Cast to CStringA before printing:

std::cout << "as CString: " << static_cast<CStringA>(cString) << std::endl;

Or print using wcout.

Upvotes: 6

Related Questions