【问题标题】:Warning on using std::remove_if on std::wstring (msvc c++20)在 std::wstring (msvc c++20) 上使用 std::remove_if 的警告
【发布时间】:2020-08-29 06:47:17
【问题描述】:

当接受一个winapi HWND并返回wstring时,我有一个函数。

std::wstring utility::winapi::window_class(HWND hwnd) {
    int title_length = 20;
    std::wstring class_name;
    class_name.resize(title_length, '\0');
    GetClassName(hwnd, const_cast<LPWSTR>(class_name.c_str()), title_length);
    class_name.erase(std::remove_if(class_name.begin(), class_name.end(), [](const char &x){return x == '\0';}), class_name.end());
    return class_name;
}

我收到以下错误:

C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.27.29110\include\xmemory(2040): error C2220: the following warning is treated as an error
..\..\libs\utility\src\winapi.cpp(44): note: see reference to function template instantiation '_FwdIt std::remove_if<std::_String_iterator<std::_String_val<std::_Simple_types<_Elem>>>,utility::winapi::window_class::<lambda_1>>(_FwdIt,const _FwdIt,_Pr)' being compiled
        with
        [
            _FwdIt=std::_String_iterator<std::_String_val<std::_Simple_types<wchar_t>>>,
            _Elem=wchar_t,
            _Pr=utility::winapi::window_class::<lambda_1>
        ]
C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.27.29110\include\xmemory(2040): warning C4244: 'argument': conversion from 'wchar_t' to 'const char', possible loss of data
C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.27.29110\include\xutility(5667): warning C4244: 'argument': conversion from '_Elem' to 'const char', possible loss of data
        with
        [
            _Elem=wchar_t
        ]
C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.27.29110\include\xmemory(2036): note: see reference to function template instantiation '_InIt std::find_if<wchar_t*,_Fn>(_InIt,const _InIt,_Pr)' being compiled
        with
        [
            _InIt=wchar_t *,
            _Fn=utility::winapi::window_class::<lambda_1>,
            _Pr=utility::winapi::window_class::<lambda_1>
        ]
..\..\libs\utility\src\winapi.cpp(44): note: see reference to function template instantiation '_FwdIt std::remove_if<std::_String_iterator<std::_String_val<std::_Simple_types<_Elem>>>,utility::winapi::window_class::<lambda_1>>(_FwdIt,const _FwdIt,_Pr)' being compiled
        with
        [
            _FwdIt=std::_String_iterator<std::_String_val<std::_Simple_types<wchar_t>>>,
            _Elem=wchar_t,
            _Pr=utility::winapi::window_class::<lambda_1>
        ]
ninja: build stopped: subcommand failed.

这个错误是什么意思?

UPD:更新时出现完全错误。

【问题讨论】:

  • 还有编译器输出吗?它表示存在警告,但您问题中唯一的内容是注释。注释通常伴随错误或警告,它们不会单独出现。
  • @cdhowie 已更新
  • const_cast&lt;LPWSTR&gt;(class_name.c_str()) 通常是一个真的坏主意。首先,字符串的大小不会正确更新(std::string/std::wstring 可以包含嵌入的零,这是正常的空终止符)。使用wchar_t 的普通数组,然后使用它来初始化std::wstring 对象。
  • 或许这就是您使用 erase/remove_if 位的原因?改变字符串的结尾?那么,如果您使用数组,则不必这样做,然后您只需return 该数组,就会创建一个具有适当长度的std::wstring 对象。
  • 请注意,从 C++17 开始,data() 成员函数返回的指针不是指向常量的指针。如果您使用的是 C++17,只需将 const_cast&lt;LPWSTR&gt;(class_name.c_str()) 替换为 class_name.data()。但是,按照上面的评论使用本地数组作为缓冲区会更好。

标签: c++ visual-c++


【解决方案1】:

class_name 被声明为std::wstring。这是 wchar_t 值的字符串,但您的 lambda 参数的类型为 const char &amp;,它更窄。警告告诉您该值可能被截断。这可能会导致测试x == '\0' 在应注意时评估为真。这就是编译器试图告诉你的:

warning C4244: 'argument': conversion from 'wchar_t' to 'const char', possible loss of data

附带说明,没有理由通过引用来获取数字参数。在这种情况下,它可能会导致相同的程序集,因为 lambda 几乎肯定会被内联,但不使用引用会更简洁。

要修复警告,请将 lambda 更改为接受 wchar_t

[](wchar_t x){return x == '\0';})

从C++14开始你也可以使用auto作为参数的类型:

[](auto x){return x == '\0';})

【讨论】:

  • 谢谢,使用 wchar_t 和更改 const char& 都有效。使用 wchar_t 数组看起来更好。
猜你喜欢
  • 2014-08-07
  • 2021-08-08
  • 2016-03-15
  • 1970-01-01
  • 1970-01-01
  • 2014-10-18
  • 1970-01-01
  • 1970-01-01
  • 2012-11-12
相关资源
最近更新 更多