ATLにATLENSURE_SUCCEEDEDというマクロがあります。これはHRESULT値を1つ引数に取り、その値が失敗を表すものだったら例外を投げるというものです(例外を投げるはデフォルトの挙動であり、変更可能)。

HRESULT hr = CoInitializeEx(
    nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
ATLENSURE_SUCCEEDED(hr);

さて、以前はこのマクロに副作用のある式を置けませんでした。具体的には、Visual C++ 2010までがダメで、2012からOKになりました。それぞれ以下のように定義されています (atldef.h)。

Visual C++ 2005~2010
#define ATLENSURE_SUCCEEDED(hr) ATLENSURE_THROW(SUCCEEDED(hr), hr)
Visual C++ 2012
#define ATLENSURE_SUCCEEDED(hrExpr)								\
do {															\
	HRESULT __atl_hresult = (hrExpr);							\
	ATLENSURE_THROW(SUCCEEDED(__atl_hresult), __atl_hresult);   \
} while (0)
Visual C++ 2013
#define ATLENSURE_SUCCEEDED(hrExpr)								\
do {															\
	HRESULT __atl_hresult = (hrExpr);							\
	ATLENSURE_THROW(SUCCEEDED(__atl_hresult), __atl_hresult);   \
} __pragma(warning(suppress:4127)) while (0)

(注:このpragmaでは、条件式が定数であることの警告を抑制しています: コンパイラの警告 (レベル 4) C4127

このように、Visual C++ 2012から1度変数に代入することで、1度きりの評価で済まされるようになりました。なお、いずれのバージョンでも、ATLENSURE_THROWで各実引数の評価は1度だけです。

つまり、Visual C++ 2012からはこのように書いても問題ありません。逆に言えば、それ以前ではこのように書いてはいけません。

ATLENSURE_SUCCEEDED(CoInitializeEx(
    nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE));

スポンサード リンク

この記事のカテゴリ

  • ⇒ ATLENSURE_SUCCEEDEDにはVC++ 2012から副作用のある式も置ける