Click here to Skip to main content
11,495,371 members (63,062 online)
Click here to Skip to main content

CString-clone Using Standard C++

, 7 Dec 2011 CPOL 1.4M 11K 222
Rate this:
Please Sign up or sign in to vote.
A Drop-In replacement for CString that builds on the Standard C++ Library's basic_string template

Introduction

As much as I use and appreciate the Standard C++ Library, I've never liked its string template - basic_string<>. At times, it seems the designers went out of their way to make it difficult to use.

On the other hand, I've always loved the ease of use of MFC's CString class. It checks for NULL pointers, implicitly converts to const TCHAR*, and has some very handy member functions (Format, Load, etc.) that make string programming a breeze. But of course, I don't want to use MFC anymore. In fact, I don't want to rely on any proprietary library because I want portability.

Therefore I decided to combine the best of both worlds and create:

CStdString

This is a class (a template instantiation actually) that derives from from basic_string<TCHAR>. To the basic_string it adds the entire CString API. You get CString ease of use with 100% basic_string compatibility. In short, a CStdString object is a basic_string that (with very few exceptions (noted below) it is also a drop-in replacement for CString. The best part of this is that both APIs (basic_string and CString) are well known and well documented.

I originally submitted this article to another code site (which shall remain nameless Smile | :) ) a few years ago. I like CodeProject so much I thought I'd submit it here too. I have used this class in almost every professional project I've done over the past 4 years. It has proven to be the single most useful piece of code I've ever written. It is also extensively debugged. I hope you like it. If you ever have any problems with it, please e-mail me. I'm happy to help.

I provided a simple source application here to prove some of the CString functions work but it's really just a token. The list of sample projects out there that use CString and/or basic_string is massive.

Features

  • Drop in Replacement for CString (see below for exceptions)
  • Two instantiations available at all times -- wchar_t-based version CStdStringW and char-based version CStdStringA. The name CStdString is just a typedef of one of these two.
  • Safely checks for NULL string pointer inputs (like CString) in all functions
  • Extra constructors and assignment operators to automatically convert between wide (wchar_t-based) and thin (char-based) strings for you.
  • Implicit conversion to c_str(). The C++ committee doesn't like this but I sure do.
  • Builds on several platforms, including Windows, Unix and Linux. Works with several implementations of the Standard C++ Library, including Dinkumware, GNU, CodeWarrior, and STLPort.
  • Win32 builds give you some extra goodies like UNICODE/MBCS conversion macros (just like MFCs) as well as member functions for persisting CStdString objects to and from DCOM IStreams.
  • Makes no use of any implementation details of the base class template (basic_string)
  • The derived template adds no member data to basic_string and adds no virtual functions

There are a couple of issues about this code of that I should point out.

CString Compatibility

I was unable to exactly reproduce the CString API. There are a two functions that both CString and basic_string; share, but implement differently. In these cases, I felt it best to make CStdString behave like basic_string (the base class) rather than CString. To be specific.

  • CStdString::operator[] returns characters by value (unlike CString which returns them by reference)
  • The constructor that takes a character and a count takes them in the order (count, value) which is the opposite of the order CString declares them. That's the order that basic_string<>; needs and it was impossible to implement both versions.

There were also two CString functions I could not implement at all -- LockBuffer and UnlockBuffer.

Deriving From basic_string<>

The template I wrote derives from basic_string, a class template without a virtual destructor. Any introductory text to C++ will tell you that it is dangerous to derive from a class without a virtual destructor. It can lead to behavior that is undefined. So if you were to code the following (deleting a CStdStringA through a pointer to the base class), you would technically get undefined behavior:

// assign DERIVED object to  BASE pointer
std::string* pstr = new CStdStringA("Hi"); 

// delete  DERIVED through BASE class pointer -- UNDEFINED
delete pstr;   

Personally, I don't think this is much of an issue. I mean really how often do you actually do this with string objects? I have rarely (if ever) needed to dynamically allocate a string object on the heap. And if I ever do, I won't using a base-class pointer. So if you don't do this, you'll never have to worry. In fact, even if you do code this way, I doubt you'll have any problems with CStdString. I can tell you that at least with Microsoft Visual C++, even the above code runs just fine with no errors or memory leaks. I doubt many other compilers would give you problems either. However my doubt does not impose reality on the C++ world. Caveat Emptor.

History

  • 7 Dec 2011: Updated source code.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Joe O'Leary
Web Developer
United States United States
I've been a software developer since 1990.

While my main page is out of date (and I have therefore blanked it), you can read about the CStdString pages here

http://home.earthlink.net/~jmoleary/stdstring.htm

Comments and Discussions

 
AnswerRe: VS2010 unresolved symbols Pin
Joe O'Leary11-Dec-11 3:52
memberJoe O'Leary11-Dec-11 3:52 
QuestionWhere is the latest code? Pin
sisira10-Dec-11 19:47
membersisira10-Dec-11 19:47 
AnswerRe: Where is the latest code? Pin
Joe O'Leary10-Dec-11 20:54
memberJoe O'Leary10-Dec-11 20:54 
GeneralRe: Where is the latest code? Pin
sisira10-Dec-11 21:01
membersisira10-Dec-11 21:01 
Questiongcc compilation errors Pin
mirko busto9-Dec-11 1:33
membermirko busto9-Dec-11 1:33 
AnswerRe: gcc compilation errors Pin
Joe O'Leary9-Dec-11 4:59
memberJoe O'Leary9-Dec-11 4:59 
Questionfind two a small bug~ Pin
dnybz9-Dec-11 1:17
groupdnybz9-Dec-11 1:17 
AnswerRe: find two a small bug~ Pin
Joe O'Leary9-Dec-11 4:56
memberJoe O'Leary9-Dec-11 4:56 
GeneralRe: find two a small bug~ Pin
dnybz9-Dec-11 5:08
groupdnybz9-Dec-11 5:08 
GeneralRe: find two a small bug~ Pin
Joe O'Leary9-Dec-11 5:37
memberJoe O'Leary9-Dec-11 5:37 
GeneralRe: find two a small bug~ Pin
dnybz9-Dec-11 6:05
groupdnybz9-Dec-11 6:05 
GeneralRe: find two a small bug~ Pin
Joe O'Leary9-Dec-11 6:16
memberJoe O'Leary9-Dec-11 6:16 
GeneralRe: find two a small bug~ Pin
dnybz9-Dec-11 6:21
groupdnybz9-Dec-11 6:21 
GeneralRe: find two a small bug~ [modified] Pin
Joe O'Leary9-Dec-11 7:18
memberJoe O'Leary9-Dec-11 7:18 
For anyone else reading this, the problem was due to a long-known-and-acknowledged incompatibility between a CString constructor and a basic_string constructor. The CTOR that takes a single character and a count has the arguments reversed between the two classes. As I mentioned in the article, I was unable implement both constructors (due to compiler ambiguities) so I had to pick one. I figured the "is-a" relationship of inheritance (from basic_string) was more important than the "acts-like-a" relationship of the CString facade.

What I told 'dnybz' was that for now he could either explicitly call the constructor with the arguments reversed (forcing him to change his code) or he could just rewrite one of the CStdString constructor lines to reverse the arguments. Specifically to take the CTOR line that looks like this:

	CStdStr(MYVAL ch, MYSIZE nSize=1, const MYALLOC& al=MYALLOC())

...and change it to look like this:

	CStdStr(MYSIZE nSize, MYVAL ch, const MYALLOC& al=MYALLOC())

That will fix any CString incompatibilities in this area (and consequently break any code that explicitly calls that particular CStdString constructor expecting it to work like basic_string, which I suspect is rare...)

However enough people have asked about this, that I will add a preprocessor macro that will let you choose which behavior you want. I'll put it in the next drop along with an updated article and test project in a few days: Something like this.


#ifdef SS_MAX_CSTRING_COMPATIBILITY
	CStdStr(MYVAL ch, MYSIZE nSize=1, const MYALLOC& al=MYALLOC())
#else
	CStdStr(MYSIZE nSize, MYVAL ch, const MYALLOC& al=MYALLOC())
#endif
-Joe


modified 9-Dec-11 21:55pm.

GeneralMy vote of 5 Pin
Albert Holguin7-Dec-11 6:07
memberAlbert Holguin7-Dec-11 6:07 
GeneralRecommended Pin
Petr Prazak7-Dec-11 1:02
memberPetr Prazak7-Dec-11 1:02 
GeneralRe: Recommended Pin
Joe O'Leary9-Dec-11 5:00
memberJoe O'Leary9-Dec-11 5:00 
QuestionGreat, but... Pin
qiuqianren6-Dec-11 22:26
memberqiuqianren6-Dec-11 22:26 
AnswerRe: Great, but... Pin
Joe O'Leary7-Dec-11 4:10
memberJoe O'Leary7-Dec-11 4:10 
GeneralMy vote of 5 Pin
roman3136-Dec-11 21:03
memberroman3136-Dec-11 21:03 
GeneralMy vote of 5 Pin
Member 22124841-Dec-11 12:36
memberMember 22124841-Dec-11 12:36 
GeneralMy vote of 5 Pin
jjones779-Nov-11 14:21
memberjjones779-Nov-11 14:21 
GeneralMy vote of 5 Pin
Dean Rasmussen6-Oct-11 21:27
memberDean Rasmussen6-Oct-11 21:27 
QuestionGreat class but... yes a problem with Format Pin
BadJerry16-Sep-11 6:43
memberBadJerry16-Sep-11 6:43 
AnswerRe: Great class but... yes a problem with Format Pin
Joe O'Leary16-Sep-11 19:21
memberJoe O'Leary16-Sep-11 19:21 
GeneralRe: Great class but... yes a problem with Format Pin
BadJerry17-Sep-11 0:31
memberBadJerry17-Sep-11 0:31 
GeneralRe: Great class but... yes a problem with Format Pin
Joe O'Leary17-Sep-11 6:42
memberJoe O'Leary17-Sep-11 6:42 
GeneralRe: Great class but... yes a problem with Format Pin
BadJerry26-Sep-11 2:25
memberBadJerry26-Sep-11 2:25 
GeneralRe: Great class but... yes a problem with Format Pin
Joe O'Leary26-Sep-11 5:56
memberJoe O'Leary26-Sep-11 5:56 
GeneralRe: Great class but... yes a problem with Format Pin
BadJerry26-Sep-11 7:09
memberBadJerry26-Sep-11 7:09 
GeneralAnother easy way converting wchar_t to char and vice versa in StdCodeCvt Pin
steveb12-Jan-11 11:04
membersteveb12-Jan-11 11:04 
GeneralRe: Another easy way converting wchar_t to char and vice versa in StdCodeCvt Pin
wheregone5-Jul-11 22:53
memberwheregone5-Jul-11 22:53 
GeneralCrashing inside ssasn Pin
Member 332703320-Oct-10 11:02
memberMember 332703320-Oct-10 11:02 
GeneralRe: Crashing inside ssasn Pin
Joe O'Leary20-Oct-10 14:50
memberJoe O'Leary20-Oct-10 14:50 
GeneralRe: Crashing inside ssasn Pin
Joe O'Leary9-Dec-11 5:41
memberJoe O'Leary9-Dec-11 5:41 
QuestionErrors and Warnings with VS2010 Pin
pscholl9-Feb-10 5:35
memberpscholl9-Feb-10 5:35 
AnswerRe: Errors and Warnings with VS2010 Pin
Joe O'Leary9-Feb-10 6:13
memberJoe O'Leary9-Feb-10 6:13 
GeneralMy vote of 5 and ... [modified] Pin
wheregone6-Jan-10 16:59
memberwheregone6-Jan-10 16:59 
GeneralWow Awesome Pin
jasonp1229-Dec-09 8:40
memberjasonp1229-Dec-09 8:40 
GeneralRe: Wow Awesome Pin
Joe O'Leary29-Dec-09 9:01
memberJoe O'Leary29-Dec-09 9:01 
GeneralOutputDebugString prints ok, but _ftprintf_s does NOT... Pin
ehaerim16-Jun-09 11:08
memberehaerim16-Jun-09 11:08 
GeneralRe: OutputDebugString prints ok, but _ftprintf_s does NOT... Pin
Joe O'Leary30-Dec-09 6:07
memberJoe O'Leary30-Dec-09 6:07 
General[Message Deleted] Pin
balint25617-Mar-09 21:53
memberbalint25617-Mar-09 21:53 
GeneralRe: Modified CStdString for CString-like use in any var-arg (...) function (passing a non-POD type) Pin
ehaerim15-Jun-09 13:02
memberehaerim15-Jun-09 13:02 
GeneralRe: Modified CStdString for CString-like use in any var-arg (...) function (passing a non-POD type) Pin
Joe O'Leary15-Jun-09 13:22
memberJoe O'Leary15-Jun-09 13:22 
GeneralRe: Modified CStdString for CString-like use in any var-arg (...) function (passing a non-POD type) Pin
ehaerim15-Jun-09 14:14
memberehaerim15-Jun-09 14:14 
GeneralRe: Modified CStdString for CString-like use in any var-arg (...) function (passing a non-POD type) [modified] Pin
Joe O'Leary15-Jun-09 16:54
memberJoe O'Leary15-Jun-09 16:54 
GeneralRe: Modified CStdString for CString-like use in any var-arg (...) function (passing a non-POD type) Pin
ehaerim15-Jun-09 18:04
memberehaerim15-Jun-09 18:04 
GeneralRe: Modified CStdString for CString-like use in any var-arg (...) function (passing a non-POD type) Pin
Joe O'Leary16-Jun-09 4:48
memberJoe O'Leary16-Jun-09 4:48 
GeneralDemo won't compile with Visual Studio 2008 Professional Pin
Mikeanical30-Dec-08 1:28
memberMikeanical30-Dec-08 1:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150520.1 | Last Updated 7 Dec 2011
Article Copyright 2001 by Joe O'Leary
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid