shared_ptr 和 COM 对象

shared_ptr and COM object

我有一个名为 factory (IFactory) 的 COM 对象,它有几个方法,例如

virtual HRESULT STDMETHODCALLTYPE CreateDatabase(IDatabase** Result) = 0;
virtual HRESULT STDMETHODCALLTYPE CreateProcessor(IProcessor** Result) = 0;
virtual HRESULT STDMETHODCALLTYPE CreateDocument(IDocument** Result) = 0;
.....

当我需要创建一个 IDocument 时,我需要这样做:

IDocument* doc = nullptr;
factory->CreateDocument(&doc);
// some code here;
doc.Release();

所以我想创建一个通用函数来执行此操作并生成一个 shared_ptr,所以我不需要手动释放它。

我创建了一个这样的函数:

template <typename T, typename K>
shared_ptr<T> create_new(K* p, HRESULT (K::*member)(T**)) {
    T* pointer = nullptr;
    (void)p->*member(&pointer);
    shared_ptr<T> result(pointer, [=](T* o) {
        o->Release();
    });
    return result;
}

这样,当我需要创建一个新的 IDocument 时,我只需要:

auto doc = create_new(factory, &IFactory::CreateDocument);
// do not need release it manually

但这不起作用,因为编译器需要更多信息来实例化模板,所以我使用

auto doc = create_new(factory, (HRESULT (IFactory::*)(IDocument**))&IFactory::CreateDocument);

这种方式似乎是正确的,但是当我编译我的代码时,编译器停止在

(void)p->*member(&pointer);

并说:

must use '.*' or '->*' to call pointer-to-member function in 'member (...)', e.g. '(... ->* member) (...)'

In instantiation of 'std::shared_ptr<_Tp1> create_new(K*, HRESULT (K::*)(T**)) [with T = IDocument; K = IFactory; HRESULT = long int]'

谁能帮我解决这个问题?

编译器是 MinGW-w64 GCC 4.8.5,但我试过 GCC 5.3.0,输出相同。

首先,函数调用比成员指针解引用绑定得更紧密,因此您需要这些括号:

(p->*member)(&pointer);

(根据需要将演员表添加到 void)。

其次,您可以通过显式指定 T 的参数来改进调用语法;那么你应该不需要可怕的演员表:

auto doc = create_new<IDocument>(factory, &IFactory::CreateDocument);