Reputation: 77
A parameter of function requires an LPCTSTR
type variable; what if we pass a CString
type variable? Is it safe or is there anything that we should look at in this case?
For example this function :
Add(new CAToolbar, _T("Command Toolbar"), xtpBarTop);
Here I want to replace _T("Command Toolbar")
(LPCTSTR
type) with CString str;
. Something like this:
Add(new CAToolbar, str , xtpBarTop);
Is it safe ?
Upvotes: 2
Views: 872
Reputation: 51854
Is it safe or is there anything that we should look at in this case?
Generally (see note, below), yes, it is safe. The CString
class has an operator LPCTSTR()
, which returns the content of the string as a C-style, nul-terminated char
or wchar_t
array (well, a pointer to its first element), depending on the current compiler setting of the "Character Set" option (i.e. whether or not UNICODE
and/or _UNICODE
is/are defined). Thus, the returned type will (or should) match the required const char*
vs const wchar_t*
pointer type for your function parameter. (Note that this is not safe to use for function parameters that are not const
qualified).
In "olden days", there were some compilers that I used that would complain about the 'implicit' conversion when doing just this, so I used the CString::GetString()
function, instead. However, these do exactly the same thing. From the "atlsimpstr.h" header:
template< typename BaseType , bool t_bMFCDLL = false>
class CSimpleStringT
{
//...
operator PCXSTR() const throw()
{
return( m_pszData );
}
//...
PCXSTR GetString() const throw()
{
return( m_pszData );
}
//...
Important Note: One case where using this "implicit conversion" is not safe is for functions that take variadic arguments, like printf
or the .Format()
member of CString
itself; in such cases, the compiler will (rightly) complain of non-portable use of a class object. Take the following code:
#include <afx.h>
int main()
{
CString param = _T("param");
CString text;
text.Format(_T("Param is %s"), param);
return 0;
}
The clang-cl compiler gives this error:
error : cannot pass object of non-trivial type 'CString' (aka 'CStringT<wchar_t, StrTraitMFC_DLL<wchar_t>>') through variadic method; call will abort at runtime [-Wnon-pod-varargs]
And even MSVC itself gives:
warning C4840: non-portable use of class 'ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>' as an argument to a variadic function
In such a case, you can either use the .GetString()
function mentioned earlier, or make the conversion explicit:
text.Format(_T("Param is %s"), param.operator LPCTSTR());
// or ...
text.Format(_T("Param is %s"), static_cast<LPCTSTR>(param));
Upvotes: 8
Reputation: 308382
CString
contains an implicit conversion operator for LPCTSTR
. It was designed for this exact usage.
It's the fact that you're passing a const
string that can't be modified that makes it safe.
Upvotes: 3