I am having a problem trying to use C++20 with Visual Studio 2022:
For example:
CA2CT
CW2T
CA2W
error C2440: 'initializing': cannot convert from
ATL::CA2W
toATL::CStringT<wchar_t,StrTraitMFC<wchar_t,ATL::ChTraitsCRT<wchar_t>>>
If I revert to C++17 it is fine.
Why is this?
Here is an example:
CLSID AppCLSID ;
if (SUCCEEDED(::CLSIDFromProgID(CT2W(rstrProgID), &AppCLSID) ) )
{
LPOLESTR pszName = NULL ;
if (SUCCEEDED(::ProgIDFromCLSID(AppCLSID, &pszName) ) )
{
CString strAppID = CW2T(pszName);
}
}
Note that rStrProgId
could be values like _T("Word.Application")
.
The above scpecific case the error is:
error C2440: 'initializing': cannot convert from
ATL::CW2W
toATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>
Other code snippets as examples:
CString strCalendarName = CA2CT(pName->GetText(), CP_UTF8);
(the value of pName->GetText()
is const char *)
.
Doing what @Inspectable says resolves the one issue.
The others (examples) that won't compile are:
std::string s1 = CT2A(strNameText);
CString strStudent1 = CA2CT(pElement1->GetText(), CP_UTF8);
There are other compiling issues but I feel they are outside the scope of this question.
The issue evidently relates to /permissive-
compiler option. If c++20 is selected, the compiler forces /permissive-
option.
/permissive-
(Standards conformance)The
/permissive-
option is implicitly set by the /std:c++latest option starting in Visual Studio 2019 version 16.8, and in version 16.11 by the /std:c++20 option./permissive-
is required forC++20
Modules support.
With /permissive-
or /std:c++20
enabled, the compiler will not allow CStringA a = CW2A(L"123");
(I think because CW2A/CA2W
use a conversion operator to return TCHAR*
buffer to CString
), so it needs {}
initialization
CStringA a { CW2A(L"123") };
In this case it makes no difference with or without conformance, as far as I understand. But {}
is preferred for initialization since c++11. For example it can check for narrowing conversion, and it's more consistent with other initialization forms:
char c = 256;//compiles with warning, narrowing conversion
char c {256};//won't compile
char c[] = { 1,2 };//ok
auto c {256};//compiles, auto -> int c
auto c = {256};//std::initializer_list, cout << *c.begin();
foo::foo(int i) : m_int{ i } {};//member initialization list
RECT rc{};//set all members to zero