3

多くの C API は**p、リソースを解放するだけでなく、ポインターを に設定するを受け取る解放関数を提供しますNULL。このような C API 呼び出しをカスタムのデリータで
ラップしたいと考えています。boost::shared_ptr

FFMPEG の例を次に示します。

AVFrame* frame = av_frame_alloc(); // allocate resource
// Do stuff with frame
av_frame_free(&frame)              // free resource

RAII を活用するには、次のように書き直します。

AVFrame* frame = av_frame_alloc();
boost::shared_ptr<AVFrame*> frame_releaser(&frame, av_frame_free);
// Do stuff with frame

はポインター型ではなくshared_ptr<>型であることに注意してください。 このアプローチでは、リソースとリリーサーを別々に保持する必要があり、これにはいくつかの欠点があります。<AVFrame*><AVFrame>

  1. frame外部から変更され、リークが発生する可能性があります。
  2. 1 つではなく 2 つの変数が必要なため、コードのバグが発生しやすくなります。

shared_ptr単一の変数を使用して、リソース保持し、必要に応じて解放したいと考えています。

の精神でboost::ref、私は次のようなものを書くことを可能にするデリータのジェネリックを作成または使用しようとしています: address_of_arg_wrapper

boost::shared_ptr<AVFrame> frame_handle(av_frame_alloc(), address_of_arg_wrapper(av_frame_free));
// Do stuff with frame_handle.get()

また

boost::shared_ptr<AVFrame> frame_handle(av_frame_alloc(), address_of_arg_wrapper<av_frame_free>());
// Do stuff with frame_handle.get()

ラッパーが汎用であり、任意のポインター (ref) 型を受け入れることが重要です。これにより、そのような API 関数で使用できます。
また、タイプを指定したくありません。

Boost にはそのようなユーティリティがありますか?
そうでない場合、どうすればそのようなジェネリック ファンクターを書けるのでしょうか?

編集 - 完全性のための解決策:

このソリューションは@Rに基づいています。以下のMartinho Fernandesの回答

  1. テンプレート ファンクターを作成するためのテンプレート関数が含まれているため、テンプレートの種類を指定する必要はありません。
  2. コードは に依存しboost::decayます。メンバーを保持するだけのバージョンFun fun;も、私がテストした単純なケースで機能しました。
  3. に名前を変更しましたarg_ref_adaptor()。より良い名前の提案は大歓迎です!

コードは次のとおりです。

#include <boost\type_traits\decay.hpp>

//////////////////////////////////////////////////////////////////////////
// Given a function or callable type 'fun', returns an object with 
// a void operator(P ptr) that calls fun(&ptr)
// Useful for passing C API function as deleters to shared_ptr<> which require ** instead of *.
template <typename Fun>
struct arg_ref_adaptor_functor 
{
public:
   arg_ref_adaptor_functor(Fun fun): fun(fun) {}

   template <typename P> 
   void operator()(P ptr) 
   { fun(&ptr); }

private:
   typename boost::decay<Fun>::type fun;
};

template <typename Fun>
inline arg_ref_adaptor_functor<Fun> arg_ref_adaptor(Fun fun)
{  return arg_ref_adaptor_functor<Fun>(fun); }

使用法:

boost::shared_ptr<AVFrame> frame_handle(::av_frame_alloc() 
                                       ,arg_ref_adaptor(::av_frame_free));
// Do stuff with frame_handle.get()
// The resource will be released using ::av_frame_free() when frame_handle
// goes out of scope.
4

1 に答える 1