使用 gsl::narrow 失败
Using gsl::narrow fails
我知道有类似的问题,但我不知道这个问题的最佳措辞。
我觉得有点讽刺,首先出现代码分析警告的原因是它告诉我将 gsl::narrow
用于两个实例:
实例 1:
auto* pCell1 = gsl::narrow<CGridCellBase*>(lParam1);
auto* pCell2 = gsl::narrow<CGridCellBase*>(lParam2);
编译错误:
6>D:\My Libraries\GSL-main\include\gsl\util(105,1): error C2440: 'static_cast': cannot convert from 'U' to 'T'
6> with
6> [
6> U=LPARAM
6> ]
6> and
6> [
6> T=CGridCellBase *
6> ]
6>D:\My Libraries\GSL-main\include\gsl\util(105,12): message : Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
实例 2:
auto* pItem = gsl::narrow<NM_GRIDVIEW*>(pNotifyStruct);
编译错误:
6>D:\My Libraries\GSL-main\include\gsl\narrow(58,1): error C2440: 'static_cast': cannot convert from 'const T' to 'U'
6> with
6> [
6> T=NM_GRIDVIEW *
6> ]
6> and
6> [
6> U=NMHDR *
6> ]
6>D:\My Libraries\GSL-main\include\gsl\narrow(58,9): message : Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
这些消息告诉我做相反的事情:
- 从整数类型到指针类型的转换需要reinterpret_cast、C 风格转换或函数风格转换
- 指向的类型不相关;转换需要 reinterpret_cast、C 风格转换或函数风格转换
兜兜转转!鉴于当时的情况,我是否理解正确的前进方向是:
- 使用
reinterpret_cast
和...
- 添加适当的
prama
警告以抑制警告。
正确吗?
您不能(也不应尝试)使用 reinterpret_cast
以外的任何东西在指针和 non-pointer 之间或在指向不同(不相关)类型的指针之间进行转换。 gsl::narrow
函数只是 static_cast
的 'fancy' 版本:Understanding gsl::narrow implementation.
此外,在编写使用 WinAPI 或 MFC 的程序时,实际上 不可能 完全避免指针和 non-pointer 类型之间的转换;值得注意的是,许多消息处理例程将指向某些数据或其他数据的指针作为它们的 lParam
参数(LPARAM
类型定义为 __int64
或 int
,具体取决于目标平台)。
所以,恕我直言,您的建议是最佳选择:
- Use
reinterpret_cast
and...
- Add appropriate pragma warning to suppress the warning.
但是,您很可能需要在代码中的许多 处添加该#pragma...
指令。因此,您可以做的是创建一个您自己的 'helper'(或 wrapper)转换,然后您可以在整个代码中使用它。
例如,您可以将以下内容添加到您的“stdafx.h”(或“pch.h”)文件(或任何 header 包含的任何需要转换的地方):
template<typename T, typename U> static T inline pointer_cast(U src) noexcept
{
static_assert(sizeof(T) >= sizeof(U), "Invalid pointer cast"); // Check sizes!
__pragma(warning(suppress:26490)) // Note: no semicolon after this expression!
return reinterpret_cast<T>(src);
}
然后您可以使用 pointer_cast
并避免每次都添加 pragma
。这是一个典型的例子,在自定义对话框 class:
中使用 WM_NOTIFY
消息的潜在消息处理程序
BOOL MyDialog::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT *pResult)
{
NMHDR* pHdr = pointer_cast<NMHDR*>(lParam);
switch (pHdr->code) {
//... remaining code ...
注意:关于使用__pragma()
指令(而不是#pragma
),see here.
我知道有类似的问题,但我不知道这个问题的最佳措辞。
我觉得有点讽刺,首先出现代码分析警告的原因是它告诉我将 gsl::narrow
用于两个实例:
实例 1:
auto* pCell1 = gsl::narrow<CGridCellBase*>(lParam1);
auto* pCell2 = gsl::narrow<CGridCellBase*>(lParam2);
编译错误:
6>D:\My Libraries\GSL-main\include\gsl\util(105,1): error C2440: 'static_cast': cannot convert from 'U' to 'T'
6> with
6> [
6> U=LPARAM
6> ]
6> and
6> [
6> T=CGridCellBase *
6> ]
6>D:\My Libraries\GSL-main\include\gsl\util(105,12): message : Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast
实例 2:
auto* pItem = gsl::narrow<NM_GRIDVIEW*>(pNotifyStruct);
编译错误:
6>D:\My Libraries\GSL-main\include\gsl\narrow(58,1): error C2440: 'static_cast': cannot convert from 'const T' to 'U'
6> with
6> [
6> T=NM_GRIDVIEW *
6> ]
6> and
6> [
6> U=NMHDR *
6> ]
6>D:\My Libraries\GSL-main\include\gsl\narrow(58,9): message : Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
这些消息告诉我做相反的事情:
- 从整数类型到指针类型的转换需要reinterpret_cast、C 风格转换或函数风格转换
- 指向的类型不相关;转换需要 reinterpret_cast、C 风格转换或函数风格转换
兜兜转转!鉴于当时的情况,我是否理解正确的前进方向是:
- 使用
reinterpret_cast
和... - 添加适当的
prama
警告以抑制警告。
正确吗?
您不能(也不应尝试)使用 reinterpret_cast
以外的任何东西在指针和 non-pointer 之间或在指向不同(不相关)类型的指针之间进行转换。 gsl::narrow
函数只是 static_cast
的 'fancy' 版本:Understanding gsl::narrow implementation.
此外,在编写使用 WinAPI 或 MFC 的程序时,实际上 不可能 完全避免指针和 non-pointer 类型之间的转换;值得注意的是,许多消息处理例程将指向某些数据或其他数据的指针作为它们的 lParam
参数(LPARAM
类型定义为 __int64
或 int
,具体取决于目标平台)。
所以,恕我直言,您的建议是最佳选择:
- Use
reinterpret_cast
and...- Add appropriate pragma warning to suppress the warning.
但是,您很可能需要在代码中的许多 处添加该#pragma...
指令。因此,您可以做的是创建一个您自己的 'helper'(或 wrapper)转换,然后您可以在整个代码中使用它。
例如,您可以将以下内容添加到您的“stdafx.h”(或“pch.h”)文件(或任何 header 包含的任何需要转换的地方):
template<typename T, typename U> static T inline pointer_cast(U src) noexcept
{
static_assert(sizeof(T) >= sizeof(U), "Invalid pointer cast"); // Check sizes!
__pragma(warning(suppress:26490)) // Note: no semicolon after this expression!
return reinterpret_cast<T>(src);
}
然后您可以使用 pointer_cast
并避免每次都添加 pragma
。这是一个典型的例子,在自定义对话框 class:
WM_NOTIFY
消息的潜在消息处理程序
BOOL MyDialog::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT *pResult)
{
NMHDR* pHdr = pointer_cast<NMHDR*>(lParam);
switch (pHdr->code) {
//... remaining code ...
注意:关于使用__pragma()
指令(而不是#pragma
),see here.