What is the macro for std::string/std::wstring in vc++? - c++

According to MSDN:
https://msdn.microsoft.com/en-us/library/windows/desktop/ff381407%28v=vs.85%29.aspx
You can write TCHAR for char or wchar_t depend on compiler MACRO UNICODE
Is there a similar symbol for std::string and std::wstring?
Thanks!
(My VC++ version is 2013)

You could define it yourself:
typedef basic_string<TCHAR, char_traits<TCHAR>, allocator<TCHAR> > tstring;

I did not find one. I wrote one myself in my code like this -
#ifdef UNICODE
#define tstring std::wstring
#else
#define tstring std::string
#endif

You can also tweak a bit by adding the namespace in your stdafx.h
namespace std {
typedef basic_string<TCHAR, char_traits<TCHAR>, allocator<TCHAR> > tstring;
}

Related

converting between const wchar_t* and const char* and the reverse using macros

I'm trying to make my win32 program interchangeable between character sets (Unicode and Multi-Byte) the macros such as CreateWindowEx() use wchar_t* and char* depending on the set and for my class name I have it stored in a variable in a windowClass Class.
static constexpr const wchar_t* wndClassName = L"windowclass";
at the moment for other functions I've been using macros I have created defined in a header file
#pragma once
#include <sstream>
#ifdef _UNICODE
#define ConstString(constStringIn) (std::wstringstream() << constStringIn).str().c_str() //used as arguments in functions
#define STRINGALIASMACRO wchar_t* //Used as function return tpyes and wndClassName
#endif // _UNICODE
#ifdef _MBCS
#define ConstString(constStringIn) (std::stringstream() << constStringIn).str().c_str()
#define STRINGALIASMACRO char*
#endif // _MBCS
when trying to replace the wchar_t* with STRINGALIASMACRO and ConstString("windowclass") for the wndClassName variable value the error expression must have a constant value
What could I do to fix this and is it good practice to use macros as type definitions and return types instead of e.g typedef wchar_t* STRINGALIAS I did try this and I got a whole bunch of other errors.
The Win32 API (and the C runtime library) already provide their own sets of preprocessor macros for this exact purpose. Look at:
TCHAR/_TCHAR = char or wchar_t
LP(C)TSTR = (const) char* or (const) wchar_t*
TEXT("literal")/_T("literal") = "literal" or L"literal"
TEXT('literal')/_T('literal') = 'literal' or L'literal'
For example:
#pragma once
#include <windows.h>
#define ConstString(constStringIn) TEXT(constStringIn) //used as arguments in functions
typedef LPTSTR STRINGALIASMACRO; //Used as function return tpyes and wndClassName
typedef LPCTSTR CONSTSTRINGALIASMACRO; //Used as function return tpyes and wndClassName
static constexpr CONSTSTRINGALIASMACRO wndClassName = ConstString("windowclass");
Or simply:
static constexpr LPCTSTR wndClassName = TEXT("windowclass");
See the following for more details:
Win32 Data Types
Working With Strings
Generic-Text Mappings in tchar.h
What are TCHAR, WCHAR, LPSTR, LPWSTR, LPCTSTR (etc.)?

How to port Windows C++ that handles unicode with tchar.h to iOS app

I have some c++ code that I need to integrate into an iOS app. The windows c++ code handles unicode using tchar.h. I have made the following defines for iOS:
#include <wchar.h>
#define _T(x) x
#define TCHAR char
#define _tremove unlink
#define _stprintf sprintf
#define _sntprintf vsnprintf
#define _tcsncpy wcsncpy
#define _tcscpy wcscpy
#define _tcscmp wcscmp
#define _tcsrchr wcsrchr
#define _tfopen fopen
When trying to build the app many of these are either missing (ex. wcscpy) or have the wrong arguments. The coder responsible for the c++ code said I should use char instead of wchar so I defined TCHAR as char. Does anyone have a clue as to how this should be done?
The purpose of TCHAR (and FYI, it is _TCHAR in the C runtime, TCHAR is for the Win32 API) is to allow code to switch between either char or wchar_t APIs at compile time, but your defines are mixing them together. The wcs functions are for wchar_t, so you need to change those defines to the char counterparts, to match your other char-based defines:
#define _tcsncpy strncpy
#define _tcscpy strcpy
#define _tcscmp strcmp
#define _tcsrchr strrchr
Also, you are mapping _sntprintf to the wrong C function. It needs to be mapped to snprintf() instead of vsnprintf():
#define _sntprintf snprintf
snprintf() and vsnprintf() are declared very differently:
int snprintf ( char * s, size_t n, const char * format, ... );
int vsnprintf (char * s, size_t n, const char * format, va_list arg );
Which is likely why you are getting "wrong arguments" errors.

How to get %AppData% path as std::string?

I've read that one can use SHGetSpecialFolderPath(); to get the AppData path. However, it returns a TCHAR array. I need to have an std::string.
How can it be converted to an std::string?
Update
I've read that it is possible to use getenv("APPDATA"), but that it is not available in Windows XP. I want to support Windows XP - Windows 10.
The T type means that SHGetSpecialFolderPath is a pair of functions:
SHGetSpecialFolderPathA for Windows ANSI encoded char based text, and
SHGetSpecialFolderPathW for UTF-16 encoded wchar_t based text, Windows' “Unicode”.
The ANSI variant is just a wrapper for the Unicode variant, and it can not logically produce a correct path in all cases.
But this is what you need to use for char based data.
An alternative is to use the wide variant of the function, and use whatever machinery that you're comfortable with to convert the wide text result to a byte-oriented char based encoding of your choice, e.g. UTF-8.
Note that UTF-8 strings can't be used directly to open files etc. via the Windows API, so this approach involves even more conversion just to use the string.
However, I recommend switching over to wide text, in Windows.
For this, define the macro symbol UNICODE before including <windows.h>.
That's also the default in a Visual Studio project.
https://msdn.microsoft.com/en-gb/library/windows/desktop/dd374131%28v=vs.85%29.aspx
#ifdef UNICODE
typedef wchar_t TCHAR;
#else
typedef unsigned char TCHAR;
#endif
Basically you can can convert this array to std::wstring. Converting to std::string is straightforward with std::wstring_convert.
http://en.cppreference.com/w/cpp/locale/wstring_convert
You should use SHGetSpecialFolderPathA() to have the function deal with ANSI characters explicitly.
Then, just convert the array of char to std::string as usual.
/* to have MinGW declare SHGetSpecialFolderPathA() */
#if !defined(_WIN32_IE) || _WIN32_IE < 0x0400
#undef _WIN32_IE
#define _WIN32_IE 0x0400
#endif
#include <shlobj.h>
#include <string>
std::string getPath(int csidl) {
char out[MAX_PATH];
if (SHGetSpecialFolderPathA(NULL, out, csidl, 0)) {
return out;
} else {
return "";
}
}
Typedef String as either std::string or std::wstring depending on your compilation configuration. The following code might be useful:
#ifndef UNICODE
typedef std::string String;
#else
typedef std::wstring String;
#endif

How do I convert an ATL/MFC CString to a QString?

Given the encoding of the project is probably Unicode (but not for sure) what is the best way of converting ATL::CString to QString?
What I have thought of is this:
CString c(_T("SOME_TEXT"));
//...
std::basic_string<TCHAR> intermediate((LPCTSTR)c);
QString q;
#ifdef _UNICODE
q = QString::fromStdWString(intermediate);
#else
q = QString::fromStdString(intermediate);
#endif
Do you think that it works? Any other ideas?
You don't need the intermediate conversion to a std::string. The CString class can be treated as a simple C-style string; that is, an array of characters. All you have to do is cast it to an LPCTSTR.
And once you have that, you just need to create the QString object depending on whether the characters in your CString are of type char or wchar_t. For the former, you can use one of the standard constructors for QString, and for the latter, you can use the fromWCharArray function.
Something like the following code (untested, I don't have Qt installed anymore):
CString c(_T("SOME_TEXT"));
QString q;
#ifdef _UNICODE
q = QString::fromWCharArray((LPCTSTR)c, c.GetLength());
#else
q = QString((LPCTSTR)c);
#endif
Edit: As suggested in the comments, you have to disable "Treat wchar_t as a built-in type` in your project's Properties to get the above code to link correctly in Visual Studio (source).
For _UNICODE, I believe you could also use the fromUtf16 function:
CString c(_T("SOME TEXT"));
QString q = QString::fromUtf16(c.GetBuffer(), c.GetLength());

How to cout the std::basic_string<TCHAR>

I am trying to cout a basic_string<TCHAR>. But cout is throwing error. Can I know how to do that
As dauphic said, std::wcout is for wide strings and std::cout for narrow ones. If you want to be able to compile for either type of string (TCHAR is meant to make this sort of thing easier) something like this sometimes makes life easier:
#if defined(UNICODE) || defined(_UNICODE)
#define tcout std::wcout
#else
#define tcout std::cout
#endif
With this in place use tcout instead.
TCHAR is a winapi define for the character type used by your application. If you have the character set as multi-byte characters, it will be char. If you have it set to Unicode, it will be wchar_t.
If it's wchar_t, you need to use std::wcout. Otherwise, just plain std::cout should be fine.
Generally it helps to also explain what errors you're getting, but most likely you're trying to insert an std::basic_string<wchar_t> into std::cout, and there probably isn't an operator<< overload for that.
As #Bo Persson mentioned, another way of defining a tcout type would be using references with the correct stream types. Though there are a few more things to consider when doing that, as you'll easily end up with linker issues due to multiple or missing definitions.
What works for me is declaring these types as external references in a header and defining them once in a source file. This also works in a precompiled header (stdafx).
Header
namespace std
{
#ifdef UNICODE
extern wostream& tcout;
#else
extern ostream& tcout;
#endif // UNICODE
}
Implementation
namespace std
{
#ifdef UNICODE
wostream& tcout = wcout;
#else
ostream& tcout = cout;
#endif // UNICODE
}