How to use std :: unique_ptr for handles and pointers using custom delters (I don’t know how to translate deleter) is understandable. But how should this be followed if, instead of a deleter, you need to call a class method (for example, & SomeClass :: Release)?

Sort of:

std::unique_ptr<void, decltype(&IADs::Release)> lock(pRoot, &IADs::Release); 

This is not, of course, and works to free the resource as a parameter for the deleter.

Is it possible to transfer an object instance when instantiating a 2x template? (this and a pointer to the method).

I understand that this is a container, and it seems like it should not solve such tasks, but the question remains. It begs a class wrapper. But maybe there is a solution with std :: unique_ptr?

    2 answers 2

    You can do this:

     std::function<void(IADs*)> deleter{&IADs::Release}; std::unique_ptr<IADs, decltype(fun)> lock{pRoot, deleter}; 

    If this example is not collected, it means an error in the compiler. Update to the last, or try this code:

     auto deleter= std::bind(&IADs::Release, std::placeholders::_1); std::unique_ptr<IADs, decltype(deleter)> lock{pRoot, deleter}; 

    Here is a complete example with an abstract class:

     #include <iostream> #include <memory> #include <functional> class I { public: virtual void Release() = 0; }; class IA: public I { public: void Release() override { std::cout << "Released"; } }; int main(int argc, char* argv[]) { IA pRoot; std::function<void(I*)> deleter{&I::Release}; std::unique_ptr<I, decltype(deleter)> lock(&pRoot, deleter); return 0; } 
    • I apparently did not fully understand the question. It is necessary that the deleter was a method call of the object itself. those. IADs* pRoot PS: VS2013 swears on the first line 'void std::_Func_class<_Ret,IADs *>::_Set(std::_Func_base<_Ret,IADs *> *)' : cannot convert argument 1 from '_Myimpl *' to 'std::_Func_base<_Ret,IADs *> *' - Alexander Petrovskiy
    • @AlexanderPetrovskiy, updated the answer. My code does exactly what you are talking about. Calls IADs::Release on pRoot - ixSci
    • Yes. Swears and mine. I did not specify that IADs::Release is an abstract method ULONG IUnknown() = 0; . Maybe this is the case. Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast - Alexander Petrovskiy
    • @AlexanderPetrovskiy, updated the answer with a fully working example. I don't have MSVC13, for 2015 and other compilers, everything is going fine. - ixSci Sep.
    • yes with std :: bind () everything works. Apparently incomplete support for C ++ 11 in VS2013 ( msdn.microsoft.com/en-us/library/hh567368.aspx#featurelist ) makes itself felt. Thank you for such comprehensive attention to my question. - Alexander Petrovskiy

    The simplest (IMHO), write a separate class to call:

     struct call_release { template<typename T> void operator() (T* ptr) const { ptr->Release(); } }; std::unique_ptr< IADs, call_release > ptr( pRoot ); 
    • Thanks for the idea, @Chorkov. It turned out a hybrid solution wrapper and unique_ptr. But, it is necessary either to do the class for the class as a template and instantiated as std::unique_ptr< IADs, call_release<IADs>> ptr(pRoot); , or just use a non-template method for the delider class void operator() (IADs* ptr) const - Alexander Petrovskiy
    • I was wrong. Works without a template class. - Alexander Petrovskiy