7
votes

I have an MFC application in C++ that uses std::string and std::wstring, and frequently casts from one to the other, and a whole lot of other nonsense. I need to standardize everything to a single format, so I was wondering if I should go with CString or std::wstring.

In the application, I'll need to generate strings from a string table, work with a lot of windows calls that require constant tchar or wchar_t pointers, Edit Controls, and interact with a COM object's API that requires BSTR.

I also have vectors of strings, so is there any problem with a vector of CStrings?

Which one is better? What are the pros and cons of each?

Examples

BSTR to wstring

CComBSTR tstr;  
wstring album;  
if( (trk->get_Info((BSTR *)&tstr)) == S_OK  && tstr!= NULL)  
    album = (wstring)tstr;

wstring to BSTR

CComBSTR tstr = path.c_str();  
if(trk->set_Info(tstr) == S_OK)
    return true;

String resource to wstring

CString t;
wstring url;
t.LoadString(IDS_SCRIPTURL);
url = t;

GetProfileString() returns a CString.

integer to string format:

wchar_t total[32];
swprintf_s(total, 32, L"%d", trk->getInt());
wstring tot(total);
3
Wasn't really a duplicate -- I wanted to compare the two given my particular case, which had pros and cons for both.Vanwaril

3 Answers

10
votes

std::basic_string<> (or rather its specialisations) is horrible to work with, it's imo one of the major shortcomings of the STL (and I'd say C++ in general). It doesn't even know about encodings - c'mon, this is 2010. Being able to define the size of your character isn't enough, 'cause there's no way indicate variable-size characters in a basic_string<>. Now, utf-8 isn't nice to work with with a CString, but it's not as bad as trying to do it with basic_string. While I agree with the spirit of the above posters that a standard solution is better than the alternatives, CString is (if your project uses MFC or ATL anyway) much nicer to work with than std::string/wstring: conversions between ANSI/Unicode (through CStringA and CStringW), BSTR, loading from string table, cast operators to TCHAR (.c_str()? really?), ...

CString also has Format(), which, although not safe and somewhat ugly, is convenient. If you prefer safe formatting libraries, you'll be better off with basic_string.

Furthermore, CString has some algorithms as member functions that you'll need boost string utilities for to do on basic_string such as trim, split etc.

Vectors of CString are no problem.

Guard against a dogmatic dismissal of CString on the basis of it being Windows-only: if you use it in a Windows GUI, the application is Windows-only anyway. That being said, if there's any chance that your code will need to be cross-platform in the future, you're going to be stuck with basic_string<>.

9
votes

I personally would go with CStrings in this case, since you state that you're working with BSTRs, using COM, and writing this in MFC. While wstrings would be more standards compliant you'll run into issues with constant converting from one to another. Since you're working with COM and writing it in MFC, there's no real reason to worry about making it cross-platform, since no other OS has COM like Windows and MFC is already locking you into Windows.

As you noted, CStrings also have built-in functions to help load strings and convert to BSTRs and the like, all pre-made and already built to work with Windows. So while you need to standardize on one format, why not make it easier to work with?

3
votes

std::wstring would be much more portable, and benefit from a lot of existing prewritten code in STL and in boost. CString would probably go better with windows API's.

wchat_t : remember that you can get the data out of wstring any time by using the data() function, so you get the needed wchar_t pointer anyway.

BSTR : use SysAllocString to get the BSTR out of a wstring.data().

As for the platform dependance, remember that you can use std::basic_string<T> to define your own string, based on what you want the length of a single character to be.

I'd go for wstring every day....