简体   繁体   English

指定 C++20 时无法在 Visual Studio 2022 中使用 CA2CT 和 CW2T

[英]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:我在尝试将 C++20 与 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>>>错误 C2440:“初始化”:无法从ATL::CA2W转换为ATL::CStringT<wchar_t,StrTraitMFC<wchar_t,ATL::ChTraitsCRT<wchar_t>>>

If I revert to C++17 it is fine.如果我恢复到 C++17 就可以了。

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") .请注意, rStrProgId可能是_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>>>错误 C2440:“初始化”:无法从ATL::CW2W转换为ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>


Other code snippets as examples:其他代码片段为例:

Example 2示例 2

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

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


Update更新

Doing what @Inspectable says resolves the one issue.做@Inspectable 所说的解决了一个问题。

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.还有其他编译问题,但我觉得它们不在这个问题的 scope 范围内。

The issue evidently relates to /permissive- compiler option.该问题显然与/permissive-编译器选项有关。 If c++20 is selected, the compiler forces /permissive- option.如果选择 c++20,编译器会强制使用/permissive-选项。

/permissive- (Standards conformance) /permissive- (符合标准)

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-选项由 /std:c++latest 选项在 Visual Studio 2019 版本 16.8 中隐式设置,在版本 16.11 中由 /std:c++20 选项隐式设置。 /permissive- is required for C++20 Modules support. /permissive-C++20模块支持所必需的。

With /permissive- or /std:c++20 enabled, the compiler will not allow CStringA a = CW2A(L"123");启用/permissive-/std:c++20 ,编译器将不允许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 (我认为因为CW2A/CA2W使用转换运算符将TCHAR*缓冲区返回到CString ),所以它需要列表初始化

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

This is a somewhat more historic[ally known] issue methinks.在我看来,这是一个更具历史意义的 [ally known] 问题。 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.).据我所知,这与CString类的隐式处理有关(隐式运算符: operator LPCTSTR()等 - 例如,与std::string可能有意显式的.c_str()等相反)。

[ Likely related topic: https://aras-p.info/blog/2008/10/09/implicit-to-pointer-operators-must-die/ ] [ 可能相关的主题: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这导致所需的“双重转换”/“双重转换”(对于不准确的术语表示抱歉:()从 RHS 到 LHS( CString ),MSVC 一直草率地接受它(就像其他烦人的草率 MSVC 处理一样),然而,例如 gcc 很长一段时间(永远?)一直不允许(可能是由于语言规范要求),导致在尝试使用 gcc 对CString进行某些转换时失败(最好不要问我我是怎么知道的)。这里的问题应该可以通过做来解决

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 .m_psz是实现细节(特定成员)但有趣的是与 T 无关
  • static_cast<LPCTSTR> is non-implementation-specific but T-specific static_cast<LPCTSTR>是非特定于实现但特定于 T

) )

Though, as commented elsewhere, these are source changes (potentially many) required for this C++ spec change switch.但是,正如其他地方所评论的那样,这些是此 C++ 规范更改开关所需的源代码更改(可能很多)。 Though this is the quite usual business of making existing [imperfectly precise] code fit for other (usually more strict/precise) specs/environments.尽管这是使现有 [不完全精确] 代码适合其他(通常更严格/精确)规范/环境的常见业务。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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