More C++ Idioms/inline ガードマクロ(Inline Guard Macro)

inline ガードマクロ(Inline Guard Macro)

編集

意図

編集

コンパイラのコマンドライン指定によるマクロ定義切り替えを利用して、関数を inline にするかどうかを簡単に制御する。

別名

編集

動機

編集

デバッグ目的のため、プログラム全体で関数の inline 化を止める必要がある場合が多い。 しかし、リリースバージョンでは、inline 関数が望ましい。 必要な時必要になり次第 inline の有効、無効を素早く切り替える方法が必要である。 その上、そのような関数は、inline 化される時にはヘッダファイル中で定義されるべきであり、inline 化されない時にはソースファイル(.cpp)中で定義されるべきである。 非 inline 関数がヘッダファイルにある場合、ほとんどいつでも、関数定義を複数作ってしまうことになる。一方、inline 関数がヘッダファイルにない場合、複数の翻訳単位で利用することができない。いずれの場合も、リンカがエラーを出力する。

そのため、柔軟な inline 化の方法が望ましい場合が多いが、C++ ではちょっとしたマクロの魔法なしには対応できない。inlineガードマクロイディオムは、これを実現する。

解法とサンプルコード

編集

全ての inline 関数を、.ipp ファイルという別のファイルに置き、各関数をマクロ INLINE で修飾することが解法となる。 ヘッダファイルと実装ファイルはいつも通り作成し、.ipp ファイルは、inline 化が望まれるかどうかに応じて、これら2つのうち1つのファイル(つまりヘッダファイルか実装ファイルか)内で選択的にインクルードされる。 下記はクラス Test の例である。

// test.ipp ファイル
INLINE void Test::func()
{}

// test.hpp ファイル
#ifndef __TEST_H // インクルードガード
#define __TEST_H 

class Test
{
  public:
    void func();
};

#ifdef _INLINE_
#define INLINE inline // INLINE を inline (キーワード)として定義する
#include "test.ipp"   // _INLINE_ が定義されている時のみインクルードされる
#endif

#endif  // __TEST_H

//test.cpp file
#include "test.hpp" // いつも通りヘッダファイルをインクルードする

#ifndef _INLINE_
#define INLINE      // INLINE は空文字列として定義される
#include "test.ipp" // _INLINE_ が定義されて「いない」時のみインクルードされる
#endif

inline ガードマクロの使用により、_INLINE_ が定義されているかどうかによって test.ipp が test.cpp か test.hpp のいずれかに組み込まれる。 test.cpp に組み込まれた場合、INLINE が空文字列として定義されるため関数は inline 化されない。一方、test.hpp に組み込まれた場合、INLINE が inline (キーワード)として定義される。今や残りは _INLINE_ マクロを定義することだけである。 一般的に、全ての現代的な C/C++ コンパイラはコマンドラインでマクロを定義することができる。例えば、上記プログラムを gcc で inline 有効でコンパイルする場合、-D _INLINE_ オプションを使用する。そのようなマクロが定義されていない場合、関数は自動的に非 inline として扱われ、プログラムがコンパイルされる。

既知の利用

編集
  • ACE (Adaptive Communication Environment)
  • TAO (The ACE ORB)

関連するイディオム

編集