Search code examples
stringcommfccstringwstring

Which wide-character string structure do I use? CString vs wstring


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);

Solution

  • 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<>.