マクロだと思っていませんか?実は、結構前からインライン関数なんです。

MSDNライブラリの該当ページのタイトルはHRESULT_FROM_WIN32 macro (COM)で、マクロのままです。しかし、その中には「こう定義されている」と、C/C++の場合はインライン関数として定義される箇所がばっちり抜粋されています。

#define __HRESULT_FROM_WIN32(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000)))
 
#if !defined(_HRESULT_DEFINED) && !defined(__midl)
#define _HRESULT_DEFINED
typedef __success(return >= 0) long HRESULT;
#endif
 
#ifndef __midl
FORCEINLINE HRESULT HRESULT_FROM_WIN32(unsigned long x) { return (HRESULT)(x) <= 0 ? (HRESULT)(x) : (HRESULT) (((x) & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000);}
#else
#define HRESULT_FROM_WIN32(x) __HRESULT_FROM_WIN32(x)
#endif

インライン関数として定義されることで、HRESULT_FROM_WIN32(GetLastError())というコードを書いても心配ありません。GetLastError()は1回しか評価されません。

逆に、マクロでないと困るときには、__HRESULT_FROM_WIN32を使います。こちらはマクロです。たとえば、switch caseのように、定数式が要求される場面です。

#include <iostream>
#include <windows.h>
#include <shlwapi.h>
#include <comdef.h>
 
int main()
{
  IStreamPtr s;
  HRESULT hr = SHCreateStreamOnFileEx(
    LR"(C:\)",
    STGM_READ,
    0,
    FALSE,
    nullptr,
    &s);
  switch (hr)
  {
  case S_OK:
    std::cout << "S_OK" << std::endl;
    break;
  case __HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND):
    std::cout << "ERROR_PATH_NOT_FOUND" << std::endl;
    break;
  default:
    std::cout << std::hex << hr << std::endl;
  }
}

軽く調べたところ、Visual Studio 2008付属のWindows SDK 6.0Aでは、このインライン関数による定義でした。一方、Visual Studio 2005付属のPlatfrom SDKでは、まだマクロによる定義がデフォルトでした。ただし、INLINE_HRESULT_FROM_WIN32を定義すると、インライン関数で定義されるようになっていました。


スポンサード リンク

この記事のカテゴリ

  • ⇒ HRESULT_FROM_WIN32は関数である
  • ⇒ HRESULT_FROM_WIN32は関数である