I have a COM object named factory (IFactory
), and it has several methods like
virtual HRESULT STDMETHODCALLTYPE CreateDatabase(IDatabase** Result) = 0;
virtual HRESULT STDMETHODCALLTYPE CreateProcessor(IProcessor** Result) = 0;
virtual HRESULT STDMETHODCALLTYPE CreateDocument(IDocument** Result) = 0;
.....
when I need create a IDocument
, I need to do this:
IDocument* doc = nullptr;
factory->CreateDocument(&doc);
// some code here;
doc.Release();
So I want to create a common function to do this and generate a shared_ptr
, so taht I do not need to release it manually.
I created a function like this:
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;
}
This way, when I need create a new IDocument
I just need:
auto doc = create_new(factory, &IFactory::CreateDocument);
// do not need release it manually
but this does not work, because the compiler needs more information to instantiate the template, so I use
auto doc = create_new(factory, (HRESULT (IFactory::*)(IDocument**))&IFactory::CreateDocument);
this way seems correct, but when I compile my code, the compiler stops at
(void)p->*member(&pointer);
and says:
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]'
Could someone help me figure this out?
Compiler is MinGW-w64 GCC 4.8.5, but I tried GCC 5.3.0, with the same output.
First off, function calls bind tighter than member pointer dereference, so you need these parentheses:
(p->*member)(&pointer);
(Add cast to void
as you prefer).
Second, you can improve your call syntax by specifying the argument for T
explicitly; you should then not need the horrible cast:
auto doc = create_new<IDocument>(factory, &IFactory::CreateDocument);