ATLにATLENSURE_SUCCEEDEDというマクロがあります。これはHRESULT値を1つ引数に取り、その値が失敗を表すものだったら例外を投げるというものです(例外を投げるはデフォルトの挙動であり、変更可能)。
HRESULT hr = CoInitializeEx(
nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
ATLENSURE_SUCCEEDED(hr); |
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) |
#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) |
#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) |
#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(CoInitializeEx(
nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE));
この記事のカテゴリ
- VC++ ⇒ ATLENSURE_SUCCEEDEDにはVC++ 2012から副作用のある式も置ける