Wrapping of C-code with a unique_ptr and custom deleter

£可爱£侵袭症+ 提交于 2019-12-11 02:47:40

问题


I'm trying to wrap an object from the C-API of OpenCV (CvPOSITObject) in a smart-pointer. To my understanding it should be something like the following:

unique_ptr<CvPOSITObject, decltype(cvReleasePOSITObject)> positObject;
positObject = unique_ptr<CvPOSITObject, decltype(cvReleasePOSITObject)>(cvCreatePOSITObject(param1, param2), cvReleasePOSITObject);

But I get a compiler error, and google didn't really help.

The declarations of the two functions are:

CVAPI(CvPOSITObject*)  cvCreatePOSITObject( CvPoint3D32f* points, int point_count );
CVAPI(void)  cvReleasePOSITObject( CvPOSITObject**  posit_object );

I get something like

1>C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\memory(1227): error C2207: 'std::_Unique_ptr_base<_Ty,_Dx,_Empty_deleter>::_Mydel' : a member of a class template cannot acquire a function type
1>C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\memory(1322): warning C4180: qualifier applied to function type has no meaning; ignored
1>  Myfile.cpp
1>C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\memory(1221): warning C4180: qualifier applied to function type has no meaning; ignored
1>          C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\memory(1283) : see reference to class template instantiation 'std::_Unique_ptr_base<_Ty,_Dx,_Empty_deleter>' being compiled
1>          with
1>          [
1>              _Ty=CvPOSITObject,
1>              _Dx=void (CvPOSITObject **),
1>              _Empty_deleter=false
1>          ]
1>          C:\MyDir\Myfile.hpp(71) : see reference to class template instantiation 'std::unique_ptr<_Ty,_Dx>' being compiled
1>          with
1>          [
1>              _Ty=CvPOSITObject,
1>              _Dx=void (CvPOSITObject **)
1>          ]

How do I do that correctly?


回答1:


There are two problems with your code. The first, as BenVoigt mentions in his answer, is that decltype will not trigger the implicit conversion from function type to pointer to function type, so you must take the address of the function explicitly. Your code changes to

positObject = unique_ptr<CvPOSITObject, 
                         decltype(&cvReleasePOSITObject)>(
                         cvCreatePOSITObject(param1, param2), 
                         cvReleasePOSITObject);

However, this will now fail to compile for a different reason, which brings us to the second problem. cvReleasePOSITObject takes an argument of type CvPOSITObject ** but the unique_ptr above will attempt to call its deleter with CvPOSITObject *. To fix this, just use a lambda expression for the deleter.

positObject = unique_ptr<CvPOSITObject, 
                         void(*)(CvPOSITObject *)>(
                         cvCreatePOSITObject(param1, param2), 
                         [](CvPOSITObject *p) { cvReleasePOSITObject(&p); });

If you want to separate the declaration and initialization of the unique_ptr there are a couple of options. The first example demonstrates how to use a lamda expression for this.

auto deleter = [](int *p) {
    delete p;
};

int main()
{
    std::unique_ptr<int, decltype(deleter)> p(nullptr, deleter);    
    p.reset(new int(42));
}

You'll still have to pass the deleter instance to the unique_ptr, otherwise it'll attempt to default construct the deleter, which fails because closures generated from lambda expressions have deleted default constructors (§5.1.2/20 from N3691).

The other option is to write the deleter as a functor, which allows default construction.

struct deleter
{
    void operator()(int *p) const
    {
        delete p;
    }
};

int main()
{
    std::unique_ptr<int, deleter> p;

    p.reset(new int(42));
}



回答2:


Try

decltype(&cvReleasePOSITObject)

There's an implicit conversion from the name of a function to a pointer to that function, but function types and function pointer types are not the same, and decltype doesn't cause implicit conversions.



来源:https://stackoverflow.com/questions/19166283/wrapping-of-c-code-with-a-unique-ptr-and-custom-deleter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!