web-dev-qa-db-ja.com

プロジェクトで#include_nextを使用するのはなぜですか?

IOSを引用するには Wrapper Headersに関するドキュメント

#include_nextは、<file>と "file"の包含を区別しません。また、指定したファイルが現在のファイルと同じ名前であることを確認しません。現在のファイルが見つかった場所の後の検索パス内のディレクトリから始まる名前のファイルを単に検索します。

`#include_next 'を使用すると、大きな混乱を招く可能性があります。他に選択肢がない場合にのみ使用することをお勧めします。特に、特定のプログラムに属するヘッダーでは使用しないでください。 fixincludesの行に沿ってグローバルな修正を行うためにのみ使用してください。

それでは、2つの質問、#include_nextとは何ですか、なぜ使用する必要があるのでしょうか?

49
CodaFi

デフォルトのヘッダーを独自のヘッダーに置き換える場合に使用します。たとえば、「stdlib.h」を置き換えるとします。プロジェクトにstdlib.hというファイルを作成すると、デフォルトのヘッダーの代わりにそのファイルが含まれます。

#include_nextは、一部をstdlib.hに完全に置き換えるのではなく追加する場合に使用されます。次を含むstdlib.hという新しいファイルを作成します。

#include_next "stdlib.h"
int mystdlibfunc();

そして、コンパイラは、通常の#includeの場合のようにyour stdlib.hを再び再帰的にインクルードせず、「stdlib.h」という名前のファイルの他のディレクトリで続行します。

66
Hampus Nilsson

何かの複数のバージョンをサポートしている場合に便利です。たとえば、PostgreSQL 9.4および9.6をサポートするコードを書いています。多くの内部APIの変更が存在しますが、ほとんどは既存の関数の新しい引数です。

互換性ヘッダーとラッパー関数

すべての新しい名前を持つstatic inlineラッパー関数を使用して互換性ヘッダーを作成できます。基本的にはラッパーAPIで、コードのどこでもラッパー名を使用します。 something_compat.hと言う:

#include "something.h"

static inline something*
get_something_compat(int thingid, bool missing_ok)
{
    assert(!missing_ok);
    return get_something(thingid);
}

しかし、_compatまたはあらゆるサフィックスをどこにでも散らかすのはいです。

ラッパーヘッダー

代わりに、古いバージョンに対してビルドするときに、インクルードパスに互換性ヘッダーを挿入できます。 compat94/something.h

 #include_next "something.h"

 #define get_something(thingid, missing_ok) \
 ( \
     assert(!missing_ok), \
     get_something(thingid) \
 )

そのため、残りのコードでは9.6シグネチャのみを使用できます。 9.4に対してビルドする場合、ヘッダー検索パスの前に-Icompat94を付けます。

多重評価を防ぐには注意が必要ですが、#include_nextを使用している場合は、gccに依存することを明らかに気にしません。その場合、 ステートメント式 も使用できます。

このアプローチは、新しいバージョンが「プライマリ」ターゲットである場合に便利ですが、一定の期間、古いバージョンとの後方互換性が望まれます。そのため、古いバージョンを徐々に廃止し、現在のバージョンを参照してコードをクリーンに維持しようとしています。

代替案

または、賢明な人になり、C++を使用し、オーバーロードされた関数とテンプレートインライン関数を使用します:p

8
Craig Ringer