使用gsl::narrow失败



我知道有类似的问题,我不知道这个问题最好的措辞。

我觉得有点讽刺的是,代码分析警告的原因首先是它告诉我在两个实例中使用gsl::narrow:

实例1:

auto* pCell1 = gsl::narrow<CGridCellBase*>(lParam1);
auto* pCell2 = gsl::narrow<CGridCellBase*>(lParam2);

编译错误:

6>D:My LibrariesGSL-mainincludegslutil(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 LibrariesGSL-mainincludegslutil(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 LibrariesGSL-mainincludegslnarrow(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 LibrariesGSL-mainincludegslnarrow(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风格强制转换或函数风格强制转换

在兜圈子!考虑到当时的情况,我是否应该理解正确的前进道路是:

  1. 使用reinterpret_cast和…
  2. 添加适当的prama警告来抑制告警

正确吗?

您不能(也不应该尝试)使用reinterpret_cast以外的任何东西在指针和非指针之间进行转换,或者在指向不同(不相关)类型的指针之间进行转换。gsl::narrow函数只是static_cast的一个"花哨"版本:理解gsl::窄实现。

进一步,当编写使用WinAPI或MFC的程序时,几乎不可能完全避免指针和非指针类型之间的强制转换;值得注意的是,许多消息处理例程将指向某些数据的指针作为其lParam参数(LPARAM类型定义为__int64int,具体取决于目标平台)。

所以,依我之见,你的建议是最好的选择:

  1. 使用reinterpret_cast和…
  2. 添加合适的编译指示警告抑制警告。
但是,您很可能需要在many中添加#pragma...指令。代码中的位置。所以,你能做的就是创建一个你自己的'helper'(或包装器)强制转换,然后你可以在你的代码中使用它。

例如,您可以将以下内容添加到您的"stdafx.h"(或"pch.h")文件(或任何需要强制转换的头文件):

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。下面是一个典型的例子,在自定义对话框类中使用WM_NOTIFY消息的潜在消息处理程序:

BOOL MyDialog::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT *pResult)
{
NMHDR* pHdr = pointer_cast<NMHDR*>(lParam);
switch (pHdr->code) {
//... remaining code ...

注意:关于__pragma()指令(而不是#pragma)的使用,请参见此处。

相关内容

  • 没有找到相关文章

最新更新