如何将 std::variant 作为 VARIANT* 传递给 ExecWB?
Posted
技术标签:
【中文标题】如何将 std::variant 作为 VARIANT* 传递给 ExecWB?【英文标题】:How can I pass a std::variant as a VARIANT* to ExecWB? 【发布时间】:2021-10-27 07:34:40 【问题描述】:我看过这篇关于使用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 %d\n", 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
使用带有多个类型指针的裸联合“联合”:请改用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 %d\n", vZoom.lVal);
//kill the timer
KillTimer(nIDEvent);
GetParent()->PostMessage(UWM_HTMLVIEW_CHANGE_ZOOM_MSG, vZoom.lVal);
return;
CHtmlView::OnTimer(nIDEvent);
但问题是 ExecWB
需要 VARIANT *
而我不知道如何传递 std::variant
。
【问题讨论】:
使用VARIANT vZoom; VariantInit(&vZoom);
进行初始化。或者按照建议使用variant_t
或CComVariant
,它们会自动执行此操作。
@BarmakShemirani 谢谢 - VariantInit
- 我不知道的另一个新功能!
【参考方案1】:
诊断是正确的,即使建议过于笼统而无用。虽然std::variant
通常是表示类型安全discriminated unions 的好方法,但它与COM 中使用的VARIANT
结构无关。
在这种情况下,您需要使用不同的类型,例如 Microsoft 的 _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);
【讨论】:
谢谢。我不知道variant_t
!
Microsoft 提供了一个由_bstr_t
、_com_error
、_com_ptr
和_variant_t
组成的 COM 支持库,可提供资源管理和更强的类型安全性。这几乎涵盖了您将在 COM 编程中看到的整个类型表面。由于VARIANT
结构的复杂性,_variant_t
特别有用。【参考方案2】:
抱歉,您不能在此处使用std::variant
。
VARIANT
是 COM 中用于不同组件互操作的类型,即使使用不同的语言编写并驻留在不同的进程中。
std::variant
提供作为模板参数传递的任意类型集的类型安全变体。即使是两个std::variant
,如果模板参数不同,也是不兼容的,没有一个是兼容VARIANT
的。
使程序更健壮的最佳方法是使用 ATL 中的 CComVariant
,或者为 VARIANT
结构查找/创建另一个包装器。不确定它是否会使警告消失。
【讨论】:
谢谢。我决定按照接受的答案中的建议使用_variant_t
。以上是关于如何将 std::variant 作为 VARIANT* 传递给 ExecWB?的主要内容,如果未能解决你的问题,请参考以下文章
如何将 boost::hana::tuple 转换为 std::variant
如何将 std::variant 与非平凡的用户对象(稍后构建)一起使用,并让访问者使用自动 lambda?
将 std::unique_ptr 的子类与 std::variant 一起使用
我可以将 std::variant<Ts...> 分配给/从 std::variant<Ts..., Ys...> 分配/构造吗?