ゆとりーなの日記

日記的な事を書いて行くと思はれる

unique_ptrでCOM初期化󠄁

unique_ptrでCOMを管理するならReleaseする專用デリータを作つて

template <typename Com>
struct com_delete {
  static_assert(std::is_base_of<IUnknown, Com>::value, "Com require inherits IUnknown.");
  void operator ()(Com *com) {com->Release();}
};

template <typename Com>
using unique_com_ptr = std::unique_ptr<Com, com_delete<Com>>;

こんな感じで運󠄁用する事になる。

ID2D1Factory1 *tmp
if (FAILED(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &temp)) {
  thorw std::runtime_error("D2D1ファクトリの作成󠄁に失敗しました。");
}
unique_com_ptr<ID2D1Factory1> d2d1_factory{tmp};

作成󠄁方法の性質上一時生ポインタを使󠄁はないとスマートポインタに入れる事ができない(その面倒臭󠄁さ
を解決したのが_com_ptr_tだつたりCComPtrだつたりするのだが&演算子オーバーロードで管理する生ポインタをReleaseしてからそのアドレスを返󠄁すと云ふのはどうも好かない)。これで澤山のCOMを初期化󠄁するのは萎えるので邪󠄁惡なマクロに甘える。

#define COM_INIT_TEMP &temp

#define COM_INIT_FAILED_THROW(p, f, str)\
__pragma(warning(push))\
__pragma(warning(disable: 4127))\
  do {\
    decltype(p)::pointer temp;\
    const auto ret = f;\
    if (FAILED(ret)) {\
      thorw std::runtime_error(str);\
    }\
    p.reset(temp);\
  } while (false)\
__pragma(warning(pop))

例外を投げるところ迄セットで纏めた。__pragmaはマクロ內で例外を抑制するMSVC固有のキーワードである。これを付ければ警吿レベル4でもループの條件式が定數でも文󠄁句言はれなくなる。decltypeが絡んだネストした型名はMSVCではまだ非對應だつた樣な氣もしたが13ではコンパイルが通󠄁つた。ただインテリセンスの方でエラーが出る樣でマクロ呼出しのところに赤い波線が登場する。
これを使󠄁へばこんな感じで初期化󠄁ができる樣になる。

unique_com_ptr<ID2D1Factory1> d2d1_factory;
COM_INIT_FAILED_THROW(d2d1_factory, D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, COM_INIT_TEMP), "D2D1ファクトリの作成󠄁に失敗しました。");

マクロ力低いので大分󠄁怪しい感はあるが、これで一應大分󠄁樂に初期化󠄁ができる。