用unique_ptr和自定义删除器包装C代码 [英] Wrapping of C-code with a unique_ptr and custom deleter

查看:119
本文介绍了用unique_ptr和自定义删除器包装C代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将来自OpenCV的C-API(CvPOSITObject)的对象包装到智能指针中。据我了解,它应该类似于以下内容:

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);

但是我遇到了编译器错误,而Google并没有真正的帮助。

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

这两个函数的声明是:

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

我得到类似的东西

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>          ]

如何正确执行此操作?

推荐答案

您的代码有两个问题。正如BenVoigt在他的答案中提到的那样,第一个是 decltype 不会触发从函数类型到指针到函数类型的隐式转换,因此您必须显式获取函数的地址。您的代码更改为

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);

但是,现在由于不同的原因而无法编译,这使我们陷入第二个问题。 cvReleasePOSITObject 使用类型为 CvPOSITObject ** 的参数,但 unique_ptr 以上将尝试使用 CvPOSITObject * 调用其删除程序。要解决此问题,只需对删除程序使用lambda表达式。

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); });






如果要分开声明和初始化 unique_ptr 有两个选项。第一个示例演示如何为此使用lamda表达式。


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));
}

您仍然必须将删除程序实例传递给 unique_ptr ,否则它将尝试默认构造删除器,该操作将失败,因为从lambda表达式生成的闭包已从N3691中删除了默认构造函数(§5.1.2/ 20 )。

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));
}

这篇关于用unique_ptr和自定义删除器包装C代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆