我看过这篇关于使用std::variant
的文章。这是因为以下代码引发了代码分析警告:
void CChristianLifeMinistryHtmlView::OnTimer(UINT_PTR nIDEvent)
{
if (nIDEvent == ID_TIMER_ZOOM)
{
//get the zoom value
VARIANT vZoom{};
vZoom.vt = VT_I4;
vZoom.lVal = 0;
ExecWB(OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, nullptr, &vZoom);
TRACE("zoom %dn", vZoom.lVal);
//kill the timer
KillTimer(nIDEvent);
GetParent()->PostMessage(UWM_HTMLVIEW_CHANGE_ZOOM_MSG, vZoom.lVal);
return;
}
CHtmlView::OnTimer(nIDEvent);
}
警告:
警告C26476:表达式/符号
{{0, 0, 0, 0, {0}}}
使用带有多个类型指针的裸联合'union ':使用variant
代替(type.7).
我开始尝试修改代码:
void CChristianLifeMinistryHtmlView::OnTimer(UINT_PTR nIDEvent)
{
if (nIDEvent == ID_TIMER_ZOOM)
{
//get the zoom value
std::variant<long> vZoom(0);
ExecWB(OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, nullptr, &vZoom);
TRACE("zoom %dn", vZoom.lVal);
//kill the timer
KillTimer(nIDEvent);
GetParent()->PostMessage(UWM_HTMLVIEW_CHANGE_ZOOM_MSG, vZoom.lVal);
return;
}
CHtmlView::OnTimer(nIDEvent);
}
但问题是ExecWB
期望VARIANT *
,我不知道如何通过这个std::variant
。
诊断是正确的,尽管该建议太过通用而没有用处。虽然std::variant
通常是表示类型安全区分联合的好方法,但它与COM中使用的VARIANT
结构无关。
_variant_t
类。它封装了原始的VARIANT
,并处理其鉴别联合的内部。
它提供了几个构造函数来适当地管理设置内部状态,并且从VARIANT
派生,因此任何实例的地址都可以传递给任何接受VARIANT*
的函数:
#include <comutil.h>
#pragma comment(lib, "comsuppw.lib")
int main() {
auto zoom{ _variant_t(long{ 0 }) };
ExecWB(OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, nullptr, &zoom);
}
对不起,这里不能使用std::variant
。
VARIANT
是COM中用于不同组件互操作的类型,即使是用不同的语言编写并驻留在不同的进程中。
std::variant
提供了作为模板形参传递的任意类型集的类型安全变体。如果两个std::variant
具有不同的模板参数,则它们是不兼容的,并且它们都不与VARIANT
兼容。
使程序更健壮的最好方法是使用ATL中的CComVariant
,或者为VARIANT
结构找到/创建另一个包装器。但我不确定它是否会让警告消失。