【问题标题】:How can I pass a std::variant as a VARIANT* to ExecWB?如何将 std::variant 作为 VARIANT* 传递给 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(&amp;vZoom);进行初始化。或者按照建议使用variant_tCComVariant,它们会自动执行此操作。
  • @BarmakShemirani 谢谢 - VariantInit - 我不知道的另一个新功能!

标签: visual-c++ mfc code-analysis variant


【解决方案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
猜你喜欢
  • 2016-08-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-20
  • 1970-01-01
  • 2016-06-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多