Click here to Skip to main content
Click here to Skip to main content

A TCHAR style header file for STL strings and streams

By , 11 Feb 2006
 

Introduction

I had asked on the Visual C++ forum if there was a standard header file that would provide a way of declaring std::strings so that a single code source could be compiled in either ANSI or UNICODE builds without any changes, much in the same way tchar.h is used. The response I got back is that there is no standard way of doing this so I decided to write my own header file to accomplish this task.

The TSTL.H header file

The header file is a simple one that uses a series of typedefs to define new synonyms for some of the commonly used STL classes that use chars and wchar_ts. The idea being that you can now use new names wherever you would have previously had to use either one or the other of the standard names. For example, a piece of code may have been written:

#ifdef _UNICODE
   std::wostringstream stream;
   stream.setf(std::wios::fixed);
#else
   std::ostringstream stream;
   stream.setf(std::ios::fixed);
#endif

and can now be written:

std::tostringstream stream;
stream.setf(std::tios::fixed);

and it will compile in either ANSI or Unicode builds. The file is probably not complete as there may be other STL classes that I do not know about or did not think of that should be included in this file. If there are, let me know which ones and I can include them and update the file.

To use the file, simply include it in your precompiled header file (stdafx.h) or include it in any file that uses any of the STL string or stream classes. The file is listed here and it can be downloaded from the download link at the top of this article.

// tstl.h - header file for TCHAR equivalents of STL
//          string and stream classes
//
// Copyright (c) 2006 PJ Arends
//
// This file is provided "AS-IS". Use and/or abuse it
// in any way you feel fit.
// 
 
#pragma once

#include <string>
 
namespace std
{
#if defined UNICODE || defined _UNICODE
 
    typedef wstring         tstring;
 
    typedef wstringbuf      tstringbuf;
    typedef wstringstream   tstringstream;
    typedef wostringstream  tostringstream;
    typedef wistringstream  tistringstream;
 
    typedef wstreambuf      tstreambuf;
 
    typedef wistream        tistream;
    typedef wiostream       tiostream;
 
    typedef wostream        tostream;
 
    typedef wfilebuf        tfilebuf;
    typedef wfstream        tfstream;
    typedef wifstream       tifstream;
    typedef wofstream       tofstream;
 
    typedef wios            tios;
 
#   define tcerr            wcerr
#   define tcin             wcin
#   define tclog            wclog
#   define tcout            wcout
 
#else // defined UNICODE || defined _UNICODE
 
    typedef string          tstring;
 
    typedef stringbuf       tstringbuf;
    typedef stringstream    tstringstream;
    typedef ostringstream   tostringstream;
    typedef istringstream   tistringstream;
 
    typedef streambuf       tstreambuf;
 
    typedef istream         tistream;
    typedef iostream        tiostream;
 
    typedef ostream         tostream;
 
    typedef filebuf         tfilebuf;
    typedef fstream         tfstream;
    typedef ifstream        tifstream;
    typedef ofstream        tofstream;
 
    typedef ios             tios;
 
#   define tcerr            cerr
#   define tcin             cin
#   define tclog            clog
#   define tcout            cout
 
#endif // defined UNICODE || defined _UNICODE
} // namespace std

License

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

About the Author

PJ Arends
President
Canada Canada
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralNot so sure about adding to the std namespace... how about this solution.memberLudvik Jerabek26 Sep '09 - 10:25 
The namespace below would allow you to have a special namespace "tstd". This way you keep your hands of the std namespace.
 
#include "tstdlibs.h"
 
using namespace tstd;
 
int main()
{
    tcout << _T("Hello") << tendl;
}
 
 
Below is a dump of "tstdlibs.h"
 
#ifndef _TSTDLIBS_H
#define _TSTDLIBS_H
 
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <stdlib.h>

#ifdef _UNICODE
    typedef wchar_t tchar;
	#ifndef _T
		#define _T(s) L##s
    #endif
    #ifndef _TSTR
		#define _TSTR(s) L##s
    #endif
#else
    typedef char tchar;
	#ifndef _T
        #define _T(s) s
    #endif
    #ifndef _TSTR
        #define _TSTR(s) s
    #endif
#endif
 
namespace tstd
{
#ifdef _UNICODE
	typedef std::wstring			tstring;
	typedef std::wostream			tostream;
	typedef std::wistream			tistream;
	typedef std::wiostream			tiostream;
	typedef std::wistringstream		tistringstream;
	typedef std::wostringstream		tostringstream;
	typedef std::wstringstream		tstringstream;
	typedef std::wifstream			tifstream;
	typedef std::wofstream			tofstream;
	typedef std::wfstream			tfstream;
	typedef std::wfilebuf			tfilebuf;
	typedef std::wios			    tios;
	typedef std::wstreambuf			tstreambuf;
	typedef std::wstreampos			tstreampos;
	typedef std::wstringbuf			tstringbuf;
 
// declare an unnamed namespace as a superior alternative to the use of global static variable declarations.
namespace
{
    tostream& tcout = std::wcout;
	tostream& tcerr = std::wcerr;
	tostream& tclog = std::wclog;
	tistream& tcin	= std::wcin;
 
    std::wostream& tendl( std::wostream& output )
    {
        output << std::endl;
        return output;
    }
 
	tstring wstr_to_tstr(const std::wstring& arg)
	{
		return arg;
	}
 
	tstring str_to_tstr(const std::string& arg)
	{
		tstring res(arg.length(), L'\0');
		mbstowcs(const_cast<wchar_t*>(res.data()), arg.c_str(), arg.length());
		return res;
	}
 
	std::wstring tstr_to_wstr(const tstring& arg)
	{
		return arg;
	}
 
	std::string tstr_to_str(const tstring& arg)
	{
		std::string res(arg.length(), '\0');
		wcstombs(const_cast<char*>(res.data()), arg.c_str(), arg.length());
		return res;
	}
}
 
#else
 
	typedef std::string			    tstring;
	typedef std::ostream			tostream;
	typedef std::istream			tistream;
	typedef std::iostream			tiostream;
	typedef std::istringstream		tistringstream;
	typedef std::ostringstream		tostringstream;
	typedef std::stringstream		tstringstream;
	typedef std::ifstream			tifstream;
	typedef std::ofstream			tofstream;
	typedef std::fstream			tfstream;
	typedef std::filebuf			tfilebuf;
	typedef std::ios				tios;
	typedef std::streambuf			tstreambuf;
	typedef std::streampos			tstreampos;
	typedef std::stringbuf			tstringbuf;
 
// declare an unnamed namespace as a superior alternative to the use of global static variable declarations.
namespace
{
    tostream& tcout = std::cout;
	tostream& tcerr = std::cerr;
	tostream& tclog = std::clog;
	tistream& tcin	= std::cin;
 
    std::ostream& tendl( std::ostream& output )
    {
        output << std::endl;
        return output;
    }
 
	tstring wstr_to_tstr(const std::wstring& arg)
	{
		tstring res( arg.length(), '\0' );
		wcstombs( const_cast<char*>(res.data()) , arg.c_str(), arg.length());
           return res;
	}
 
	tstring str_to_tstr(const std::string& arg)
	{
		return arg;
	}
 
	std::wstring tstr_to_wstr(const tstring& arg)
	{
		std::wstring res(arg.length(), L'\0');
        mbstowcs(const_cast<wchar_t*>(res.data()), arg.c_str(), arg.length());
        return res;
	}
 
    std::string tstr_to_str(const tstring& arg)
    {
        return arg;
    }
}
 
#endif
}
 
#endif
 
Let me know what you guys think. I was reading some of the other comments about Ansi \ Unicode conversions. It's true when it comes to saving files in unicode the stream is converted to ansi. This requires you to manipulate your locale settings so overcome this issue.
 

Regards,
 
Lu
GeneralRe: Not so sure about adding to the std namespace... how about this solution.memberStuart Dootson20 Oct '09 - 1:12 
You want to put them into the std namespace, as ADL[^] on stream operators then works more smoothly.
 
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

Generalstd::string causes memory corruption on multi-processors PCmemberana_v12329 Aug '07 - 21:24 
std::string (VC++6, STL version) causes memory corruption on multi-processors PC.
 
MSDN site has article giving given few work-arounds. Has any one experienced to which one is more suitable option for VC++ 6 apps running for variety of Windows (98/ME/2000/XP/2003) (without upgrading to .NET) ?
 
Thanks for sharing your views.
Ana

GeneralUseful, butmembercozy dude15 Feb '06 - 0:17 
But i think every programmer had already made such file for himself.
 
dude
GeneralRe: Useful, butmemberPJ Arends15 Feb '06 - 5:17 
cozy dude wrote:
i think every programmer had already made such file for himself

 
You may be right*, but I did not find any such file already posted on CP. So now there is one for anyone else who comes here looking to solve the same problem I had.
 
*cue Billy Joel:
You may be right,
I may be crazy,
But it just might be a lunitic you're looking for...

 


"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
 
"Obviously ???  You're definitely a superstar!!!" - mYkel - 21 Jun '04
 
"There's not enough blatant self-congratulatory backslapping in the world today..." - HumblePie - 21 Jun '05
 
Within you lies the power for good - Use it!
GeneralRe: Useful, butstaffNishant Sivakumar15 Feb '06 - 15:55 
I've done this in the past, but never in a comprehensive manner. Each time, I'd just conditionally declare macros for just those functions/objects I am interested in (using at that moment) Smile | :)
 
PJ's done everyone a big help by posting this. Now we'd just have to #include the PJ header!
 
Regards,
Nish
Nish’s thoughts on MFC, C++/CLI and .NET (my blog)
The Ultimate Grid - The #1 MFC grid out there!

GeneralRe: Useful, butmemberDavid Pritchard27 Mar '06 - 10:27 
Well I haven't, and in fact I've never troubled to look into using STL strings until now. This header is very useful and will probably get me experimenting more with STL. Good job!
GeneralNice. Just...memberNemanja Trifunovic12 Feb '06 - 7:38 
... be sure to read this article[^] before diving into Unicode with C++ Standard Library.
 


My programming blahblahblah blog. If you ever find anything useful here, please let me know to remove it.
GeneralRe: Nice. Just...memberPJ Arends12 Feb '06 - 14:54 
Thanks for the link Nemanja.
 
I am not a big fan of the fstream classes, I much rather prefer to use MFC's CFile and CStdioFile. What I am after though is the stringstream classes. I have read somewhere (can not find the link right now) that the wfstream classes were designed to read and write MBCS files and DBCS memory in order to minimize file sizes, so if one keeps that in mind one would only use wfstreams for text files, and fstreams for binary. So in my case use tfstreams for text, and fstreams for binary data. Do that and the problems descibed in the article should not be a problem. Or am I, in my naivety, mistaken?
 


"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
 
"Obviously ???  You're definitely a superstar!!!" - mYkel - 21 Jun '04
 
"There's not enough blatant self-congratulatory backslapping in the world today..." - HumblePie - 21 Jun '05
 
Within you lies the power for good - Use it!
GeneralRe: Nice. Just...memberNemanja Trifunovic13 Feb '06 - 4:47 
For the record - it wasn't me who voted this post down.
 
Anyway, I almost agree - C++ Standard Library IO is not exactly my favorite code, mostly because it is slow. Most benchmarks aiming to "prove" that Java is faster than C++ are actually (ab)using fstream.
 


My programming blahblahblah blog. If you ever find anything useful here, please let me know to remove it.

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

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 12 Feb 2006
Article Copyright 2006 by PJ Arends
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid