简体   繁体   中英

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:

  • CA2CT
  • CW2T
  • CA2W

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.

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 list-initialization

CStringA a { CW2A(L"123") };

This is a somewhat more historic[ally known] issue methinks. AFAIK this relates to implicit handling of CString classes (implicit operators: operator LPCTSTR() etc. - eg 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 eg 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM