使用地图将COM VARIANT类型映射到实际类型

时间:2010-09-01 13:56:51

标签: c++ com map variant

我正在为COM对象编写一个COM包装器,它从客户端发送不同类型的值,并希望将Map中的这些类型映射到它们的实际C ++类型,例如VT_BSTR到wstring等。

我正在考虑定义所有COM Variant类型的枚举,然后使用map将Enum作为键和包含检索值的实际类型,但是我遇到了我似乎无法找到的问题一个全局类型放在我的地图中,我可以将其转换为字符串或双精度或任何交给我放置在地图中的内容。

也许我对如何做到这一点的想法是完全错误的,请指教?

我在考虑一个无效指针,但似乎编译器不喜欢我的演员:

(实施例)

    enum Type
    {
        VT_INTEGER=0,
        VT_DBL=1

    };


    map<Type, void*> typemap;
    typedef pair<Type, void*> m_typepair;
    typemap.insert( m_typepair(VT_INTEGER, 0));
    typemap.insert( m_typepair(VT_DBL, (double)2.5));  // it does not like this cast

    map<Type, void*>::iterator m_typeiter;

迭代这个地图可能需要一个switch语句来找到合适的类型,我不确定是否有更好的方法?

3 个答案:

答案 0 :(得分:1)

不确定你要做什么,这听起来肯定是错的。您从客户端获得的VARIANT需要转换为您知道如何处理的类型。这很容易做到,只需调用VariantToXxxx()函数即可。例如,如果要获取字符串,请使用VariantToString()。

现有几种C ++包装类可以使这更容易。 _variant_t,CComVariant,COleVariant。他们都做同样的事情,只是不同的#include文件。 _variant_t是一个很好的,因为它不会将你绑定到MFC或ATL。除非你已经在使用它们。他们的ChangeType()方法进行转换。内存管理是自动的。

答案 1 :(得分:0)

我通常使用模板专业化来完成这类任务。我有一个模板函数,它从变体类型转换为C ++类型,如下所示:

template <typename T>
T variantToCpp(const Variant&);

template <>
int variantToCpp<int>(const Variant& v)
{
  // Check that v really contains an int, if not, you can silently fail or throw an exception
  // Get and return the int
}

template <>
std::wstring variantToCpp<std::wstring>(const Variant& v)
{
  // Check that v really contains a string, if not, you can silently fail or throw an exception
  // Get and return the string
}

// etc. for each C++ type

// Usage
int i = variantToCpp<int>(someVariantIGotViaCOM);

通过这种方式,您可以获得从Variant到C ++类型的恒定时间转换。另请注意,默认模板化函数没有正文 - 如果有人尝试将转换用于非特殊类型,则会导致链接器错误(在大多数编译器上)。

类似地,您可以执行从C ++类型到Variant的转换:

template <typename T>
Variant cppToVariant(T);

template <>
Variant cppToVariant<int>(int val)
{
  // Convert to variant and return it
}

// etc. for each type

// Usage:
int i = 10;
Variant var = cppToVariant(i);  // You don't even need to explicitly specify the type here, the compiler deduces it

如果您坚持使用地图和大量ifs进行此类转换,您可以使用void *指针,只需使用指向该类型的指针对其进行初始化:

int *myInteger = new int; *myInteger = 42;
double *myDouble = new double; *myDouble = 42;
typemap.insert( m_typepair(VT_INTEGER, myInteger));
typemap.insert( m_typepair(VT_DBL, myDouble));
// Don't forget to free them when you clear the map

如果您对上述任何解决方案不满意,boost::any可能值得一看。

答案 2 :(得分:0)

您知道_variant_t吗?你可能正在重新发明轮子。它有所有相关的建设者和超载的任务。即_variant_t var = 0.0按预期工作(VT_R8