Andrew Truckle
Andrew Truckle

Reputation: 19087

Unable to use CA2CT and CW2T in Visual Studio 2022 when C++20 is specified

I am having a problem trying to use C++20 with Visual Studio 2022:

For example:

error C2440: 'initializing': cannot convert from ATL::CA2W to ATL::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 to ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>


Other code snippets as examples:

Example 2

CString strCalendarName = CA2CT(pName->GetText(), CP_UTF8);

(the value of pName->GetText() is const char *).


Update

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.

Upvotes: 6

Views: 2241

Answers (2)

LinuxDev
LinuxDev

Reputation: 325

This is a somewhat more historic[ally known] issue methinks. AFAIK this relates to implicit handling of CString classes (implicit operators: operator LPCTSTR() etc. - e.g. as opposed to std::string's likely intentionally explicit .c_str() etc.).

[ Likely related topic: https://aras-p.info/blog/2008/10/09/implicit-to-pointer-operators-must-die/ ]

Which results in a required "double conversion" / "double transition" (sorry for inexact terms :( ) from RHS to LHS (CString), which was sloppily accepted by MSVC all the time (like so much other annoying sloppy MSVC handling), yet which e.g. gcc for a long time (forever?) has been disallowing (likely due to language spec requirements), resulting in fail when trying to do certain transitions to CString with gcc (better do NOT ask me how I know this 😔 ). The issue here should be resolvable by doing

CString strAppID = static_cast<LPCTSTR>(CW2T(pszName));

or

CString strAppID = CW2T(pszName).m_psz;

(BTW which one is better?

  • .m_psz is implementation details (specific member) but interestingly T-agnostic
  • static_cast<LPCTSTR> is non-implementation-specific but T-specific

)

Though, as commented elsewhere, these are source changes (potentially many) required for this C++ spec change switch. Though this is the quite usual business of making existing [imperfectly precise] code fit for other (usually more strict/precise) specs/environments.

Upvotes: 1

Barmak Shemirani
Barmak Shemirani

Reputation: 31599

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 for C++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

Upvotes: 5

Related Questions