最終更新日時:
が更新

履歴 編集

__has_include(C++17)

概要

__has_includeはインクルードするファイルが存在するかどうかを返す述語である。

処理系によって異なるヘッダファイルをインクルードする場合、従来はコンパイラのみでヘッダファイルの有無を確認する方法がなく、下記例のように外部ツールにより補助する方法を取ることが多かった。

  • 外部ツールでヘッダファイルの存在を確認し、ヘッダファイルの有無を表すマクロ (例: #define HAS_STDIO_H 1など) を生成
  • 生成されたマクロは固有のコンフィグヘッダ (例: config.hなど) に出力
  • プログラマはコンフィグヘッダのマクロに応じて#if .. #include .. #endifを記述

C++17では標準的な方法でコンパイラがヘッダファイルの有無を確認できるため、ヘッダファイルの有無を確認するために外部ツールやコンフィグヘッダが不要となる。

ただし外部ツールの機能はヘッダファイルの有無を確認する以外にも、ライブラリのリンク可否、テストプログラムの実行結果取得など多くの機能を持つため、__has_includeにより外部ツールやコンフィグヘッダが完全に不要になるわけではない。

仕様

__has_includeに指定されたインクルードファイルが存在する場合は 1 として評価され、インクルードファイルが存在しない場合は 0 として評価される。

詳細な文法は下記の通り。

defined-macro-expression:
  defined identifier
  defined ( identifier )

h-preprocessing-token:
  any preprocessing-token other than >

h-pp-tokens:
  h-preprocessing-token
  h-pp-tokens h-preprocessing-token

has-include-expression:
  __has_include ( <h-char-sequence> )
  __has_include ( "q-char-sequence" )
  __has_include ( string-literal )
  __has_include ( < h-pp-tokens > )

誤解を恐れず言えば#includeの後に指定できるトークンと、同様のトークンが__has_includeにも指定できる。

#if __has_include(<has_include.hpp>)
#  warning <has_include.hpp> is found
#else
#  warning <has_include.hpp> is not found
#endif

#if __has_include("has_include.hpp")
#  warning "has_include.hpp" is found
#else
#  warning "has_include.hpp" is not found
#endif

#if __has_include(<fuga>)
#  warning <fuga> is found
#else
#  warning <fuga> is not found
#endif

#if __has_include("fuga")
#  warning "fuga" is found
#else
#  warning "fuga" is not found
#endif

出力

カレントディレクトリに has_include.hpp ファイルが存在する状態で、clang++ 5.0.0 にてコンパイルした場合。

has_include.cpp:5:4: warning: <has_include.hpp> is not found [-W#warnings]
#  warning <has_include.hpp> is not found
   ^
has_include.cpp:9:4: warning: "has_include.hpp" is found [-W#warnings]
#  warning "has_include.hpp" is found
   ^
has_include.cpp:17:4: warning: <fuga> is not found [-W#warnings]
#  warning <fuga> is not found
   ^
has_include.cpp:23:4: warning: "fuga" is not found [-W#warnings]
#  warning "fuga" is not found
   ^
4 warnings generated.

参照