3

OpenCV の C-API (CvPOSITObject) からオブジェクトをスマート ポインターでラップしようとしています。私の理解では、次のようなものでなければなりません。

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

しかし、コンパイル エラーが発生し、Google はあまり役に立ちませんでした。

2 つの関数の宣言は次のとおりです。

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

どうすればそれを正しく行うことができますか?

4

2 に答える 2

7

コードには 2 つの問題があります。1 つ目は、BenVoigt が彼の回答で言及しているdecltypeように、関数型から関数型へのポインターへの暗黙的な変換をトリガーしないため、関数のアドレスを明示的に取得する必要があることです。コードは次のように変更されます

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

ただし、これは別の理由でコンパイルに失敗するため、2 つ目の問題が発生します。cvReleasePOSITObject型の引数を取りますCvPOSITObject **が、unique_ptr上記は でそのデリータを呼び出そうとしCvPOSITObject *ます。これを修正するには、デリータにラムダ式を使用します。

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

の宣言と初期化を分離したい場合unique_ptrは、いくつかのオプションがあります。最初の例は、これにラムダ式を使用する方法を示しています。

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

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

unique_ptrそうしないと、ラムダ式から生成されたクロージャーがデフォルトのコンストラクターを削除したため、失敗します(N3691の§5.1.2/20)。

もう 1 つのオプションは、deleter をファンクターとして記述することです。これにより、デフォルトの構築が可能になります。

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

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

    p.reset(new int(42));
}
于 2013-10-03T18:41:59.627 に答える