Share via


チュートリアル: STL ライブラリをヘッダ ーユニットとしてインポートする

このチュートリアルでは、Visual Studio で C++ 標準テンプレート ライブラリ (STL) のライブラリをヘッダー ユニットとしてインポートする方法を示します。 標準ライブラリをより迅速かつ堅牢にインポートする方法については、「チュートリアル: モジュールを使用して C++ 標準ライブラリをインポートする」を参照してください

STL ヘッダーをヘッダー ユニットとしてインポートする方が、プリコンパイル済みヘッダー ファイルを使用するよりも簡単です。 ヘッダー ユニットは、セットアップと使用が簡単で、ディスク上で大幅に小さく、同様のパフォーマンス上の利点を提供し、共有 PCH よりも柔軟です。

ヘッダー ユニットとその利点の詳細については、「ヘッダー ユニットとは」を参照してください。 ヘッダーユニットと標準ライブラリをインポートする他の方法を比較するには、「ヘッダーユニット、モジュール、プリコンパイル済みヘッダーの比較」を参照してください

前提条件

ヘッダー ユニットを使用するには、Visual Studio 2022 以降、または Visual Studio 2019 バージョン 16.11 以降を使用します。 ヘッダー ユニットを /std:c++20 使用するには、オプション (またはそれ以降) が必要です。

ヘッダーユニットとして STL ヘッダーをインポートする 2 つの方法

STL ヘッダーの場合は、インポートする前に、ヘッダー ユニットにコンパイルする必要があります。 ヘッダー ユニットは、ヘッダー ファイルのバイナリ表現です。 .ifc 拡張子を持ちます。

使用する STL ヘッダーのビルド済みヘッダー ユニットを含むスタティック ライブラリを作成する方法をお勧めします。 その後、そのライブラリを参照し、そのヘッダー ユニットに対して import を使用します。 この方法により、ビルドの高速化と再利用が向上する可能性があります。 この方法を試す場合は、「方法 1: STL ライブラリ ヘッダー ユニットのスタティック ライブラリを作成する」を参照してください。

もう 1 つの方法は、Visual Studio を使い、プロジェクトで #include を使用した STL ヘッダーをスキャンし、ヘッダー ユニットにコンパイルし、それらのヘッダーに対して #include ではなく、import を使用することです。 この方法は、ソース コードを変更する必要がないため、大規模なコードベースがある場合に便利です。 この方法は、ビルドされたヘッダー ユニットを他のプロジェクトで再利用する目的には適していないため、スタティック ライブラリ アプローチよりも柔軟性が低くなります。 ただし、個々の STL ライブラリをヘッダー ユニットとしてインポートする場合のパフォーマンス上の利点は引き続き得られます。 この方法を試す場合は、「方法 2: インポートする STL ヘッダーについて include をスキャンする」を参照してください。

方法 1: STL ライブラリ ヘッダー ユニットのスタティック ライブラリを作成する

STL ライブラリをヘッダー ユニットとして使用する場合は、1 つ以上のスタティック ライブラリ プロジェクトを作成することをお勧めします。 これらのプロジェクトは、使用する STL ライブラリ ヘッダー ユニットで構成されている必要があります。 次に、ライブラリ プロジェクトを参照して、これらの STL ヘッダー ユニットを使用します。 これは、共有プリコンパイル済みヘッダーを使用するのと似ていますが、それより簡単です。

スタティック ライブラリ プロジェクトでビルドされたヘッダー ユニット (およびモジュール) は、参照元のプロジェクトで自動的に使用できるようになります。これは、参照元のプロジェクトがヘッダー ユニットをインポートできるように、プロジェクト システムによって適切な /headerUnit コマンドライン オプションがコンパイラに自動的に追加されるためです。

この方法では確実に、特定のヘッダーのヘッダー ユニットが 1 回だけビルドされます。 これにより、ヘッダー ユニットの一部またはすべてをインポートできます (PCH ではできません)。 ヘッダー ユニットは任意の順序で含めることができます。

次の例では、<iostream> および <vector> ヘッダー ユニットで構成されるスタティック ライブラリ プロジェクトを作成します。 ソリューションがビルドされると、この共有ヘッダー ユニット プロジェクトを別の C++ プロジェクトから参照します。 import <iostream>; または import <vector>; が検出されたすべての場所で、ヘッダーをプリプロセッサで変換するのではなく、そのライブラリのビルド済みヘッダー ユニットが使用されます。 同じヘッダーが複数のファイルに含まれている場合、PCH ファイルのようにビルドパフォーマンスが向上します。 ヘッダーで、それが含まれるファイルによって何度も処理される必要がなくなります。 代わりに、既に処理されているコンパイル済みヘッダー ユニットがインポートされます。

STL ライブラリ <iostream><vector> を含むスタティック ライブラリを作成するには、これらの手順に従います。

  1. 空の C++ プロジェクトを作成します。 SharedPrj という名前を 付けます
    [新しいプロジェクトの作成] ウィンドウで使用可能なプロジェクトの種類から、C++ 用の空のプロジェクトを選択します。Screenshot that shows creating a new empty C++ project.

  2. 新しい C++ ファイルをプロジェクトに追加します。 ファイルの内容を次のように変更します。

    import <iostream>;
    import <vector>;
    

プロジェクト プロパティを設定する

このプロジェクトからヘッダー ユニットを共有するように、プロジェクトのプロパティを設定します。

  1. Visual Studio の [メイン] メニューの [Project>SharedPrj プロパティ] を選択して、プロジェクトの [プロパティ ページ] ダイアログを開きます。Screenshot that shows settings for Configuration Type and C++ Language Standard.
  2. [構成] ドロップダウン リストで [すべての構成] を選択し、[プラットフォーム] ドロップダウン リストで [すべてのプラットフォーム] を選択します。 これらの設定により、デバッグまたはリリース用にビルドするかどうかにかかわらず、変更が確実に適用されます。
  3. プロジェクトの [プロパティ ページ] ダイアログの左側のウィンドウで、[構成プロパティ>全般] を選択します。
  4. [構成の種類] オプションを [スタティック ライブラリ (.lib)] に変更します。
  5. C++ 言語標準ISO C++20 Standard (/std:c++20) (またはそれ以降) に変更します。
  6. プロジェクトの [プロパティ ページ] ダイアログの左側のウィンドウで、[構成プロパティ>C/C++>全般] を選択します。
  7. [Scan Sources for Module Dependencies]\(モジュールの依存関係のスキャン ソース\) ドロップダウン リストで、[はい] を選択します。 (このオプションにより、コンパイラはコードをスキャンして、ヘッダー ユニットに組み込むことができる依存関係を探します)。 Screenshot that shows the scan module dependencies property setting.
  8. [OK] を選択してプロジェクトの [プロパティ ページ] ダイアログを閉じます。 メイン メニューの [ビルド]>[ソリューションのビルド] を選択して、ソリューションをビルドします。

ヘッダー ユニット ライブラリを参照する

<iostream><vector> をスタティック ライブラリからヘッダー ユニットとしてインポートするには、次のようにスタティック ライブラリを参照するプロジェクトを作成します。

  1. 現在のソリューションを開いたまま、Visual Studio のメニューで、[ファイル]>[追加]>[新しいプロジェクト] を選択します。

  2. 新しいプロジェクトの作成ウィザードで、C++ コンソール アプリ テンプレートを選択し、[次へ] を選択します

  3. 新しいプロジェクト に「チュートリアル」という名前を付けます。 [ソリューション] ドロップダウンを [ソリューションに追加] に変更します。 [作成] を選択してプロジェクトを作成し、ソリューションに追加します。

  4. Walkthrough.cpp ソース ファイルの内容を次のように変更します。

    import <iostream>;
    import <vector>;
    
    int main()
    {
        std::vector<int> numbers = {0, 1, 2};
        std::cout << numbers[1];
    }
    

ヘッダー ユニットには、オプション (またはそれ以降) が /std:c++20 必要です。 以下の手順を使用して、言語標準を設定します。

  1. ソリューション エクスプローラーで、チュートリアル プロジェクトを右クリックし、[プロパティ] を選択してプロジェクトの [プロパティ ページ] ダイアログを開きます。Screenshot that shows setting the language standard to the preview version.
  2. [チュートリアル プロジェクトのプロパティ ページ] ダイアログの左側のウィンドウで、[構成プロパティ>全般] を選択します。
  3. [C++ 言語標準] ドロップダウンで、ISO C++20 Standard (/std:c++20) (またはそれ以降) を選択します。
  4. [OK] を選択してプロジェクトの [プロパティ ページ] ダイアログを閉じます。

Walkthrough プロジェクトで、次の手順で SharedPrj プロジェクトへの参照を追加します。

  1. Walkthrough プロジェクトで [参照] ノードを選択し、[参照の追加] を選択します。 プロジェクトの一覧で [SharedPrj] を選択します。Screenshot that shows the Add Reference dialog. It's used to add a reference to the Walkthrough project.この参照を追加すると、Walkthrough プロジェクト内のヘッダー ユニットが SharedPrj 内のいずれかのビルド ヘッダー ユニットと一致するたびにimport、ビルド システムは SharedPrj によってビルドされたヘッダー ユニットを使用します
  2. [OK] を選択して [参照の追加] ダイアログを閉じます。
  3. Walkthrough プロジェクトを右クリックし、[スタートアップ プロジェクトに設定] を選択します。
  4. ソリューションをビルドします。 (使用[メイン] メニューの [Build Solution]\(ソリューションのビルド>\))これを実行して、期待される出力が生成されることを確認します。1

この方法の利点は、任意のプロジェクトからスタティック ライブラリ プロジェクトを参照して、ヘッダー ユニットを再利用できることです。 この例では、スタティック ライブラリに <vector> および <iostream> ヘッダー ユニットが含まれています。

さまざまなプロジェクトからインポートする、一般的に使用されるすべての STL ヘッダーを含めたモノリシックなスタティック ライブラリ プロジェクトを作成できます。 または、ヘッダー ユニットとしてインポートする STL ライブラリの異なるグループ用に、より小さな共有ライブラリ プロジェクトを作成することもできます。 その後、必要に応じて、それらの共有ヘッダー ユニット プロジェクトを参照します。

結果として、ヘッダー ユニットをインポートすると、コンパイラで行う必要のある作業が大幅に減るため、ビルドのスループットが向上します。

この方法をご自分のプロジェクトで使用する場合は、それを参照するプロジェクトと互換性のあるコンパイラ オプションを使って、スタティック ライブラリ プロジェクトをビルドします。 たとえば、STL プロジェクトは例外処理を有効にするために /EHsc コンパイラ オプションを使用してビルドする必要があるため、スタティック ライブラリ プロジェクトを参照するプロジェクトでもそれが必要になります。

/translateInclude を使用します

/translateIncludeコンパイラ オプション (C/C++>General>Translate Includes to Imports のプロジェクト プロパティ ページ ダイアログで使用可能) を使用すると、STL ライブラリである以前のプロジェクト#includeでヘッダー ユニット ライブラリを簡単に使用できます。 プロジェクト内の #include ディレクティブを import に変更する必要はなくなりますが、ヘッダー ユニットを含めるのではなく、インポートするという利点は引き続き得られます。

たとえば、プロジェクトに #include <vector> があり、<vector> 用のヘッダー ユニットが含まれるスタティック ライブラリを参照する場合、手動でソース コードの #include <vector>import <vector>; に変更する必要はありません。 代わりに、コンパイラは自動的#include <vector>import <vector>;に . この方法の詳細については、「方法 2: インポートする STL ヘッダーのスキャンインクルード」を参照してください。 すべての STL ヘッダー ファイルをヘッダー ユニットにコンパイルできるわけではありません。 Visual Studio に付属の header-units.json には、ヘッダー ユニットにコンパイルできる STL ヘッダー ファイルが一覧表示されています。 その動作を指定するためにマクロに依存するヘッダーは、多くの場合、ヘッダー ユニットにコンパイルできません。

ヘッダー ユニットを参照しない #include ステートメントは、通常の #include として扱われます。

プロジェクト間でヘッダー ユニットを再利用する

スタティック ライブラリ プロジェクトによってビルドされたヘッダー ユニットは、直接的または間接的に参照しているすべてのプロジェクトで自動的に使用できるようになります。 参照しているすべてのプロジェクトで自動的に使用できるようにする必要があるヘッダー ユニットを選択できプロジェクト設定があります。 この設定は、プロジェクトの設定の [VC++ ディレクトリ] にあります。

  1. ソリューション エクスプローラーで、プロジェクトを右クリックし、[プロパティ] を選択してプロジェクトの [プロパティ ページ] ダイアログを開きます。
  2. ダイアログの左側のウィンドウで、[構成プロパティ>VC++ ディレクトリ] を選択します。Screenshot that shows public project content properties, like Public Include Directories and All Header Files are Public.

次のプロパティは、ビルド システムに対するヘッダー ユニットの可視性を制御します。

  • [パブリック インクルード ディレクトリ] では、参照元プロジェクトのインクルード パスに自動的に追加する必要があるヘッダー ユニット用プロジェクト ディレクトリを指定します。
  • [パブリック C++ モジュール ディレクトリ] では、参照元プロジェクトで使用できるようにする必要があるヘッダー ユニットが含まれるプロジェクト ディレクトリを指定します。 このプロパティを使用すると、一部のヘッダー ユニットをパブリックにすることができます。 他のプロジェクトに表示されるので、ここで共有するヘッダー ユニットを配置します。 この設定を使用する場合は、便宜上、パブリックインクルードディレクトリを指定して、参照元プロジェクトのインクルードパスにパブリックヘッダーを自動的に追加します。
  • すべてのモジュールがパブリックである: DLL プロジェクトの一部としてビルドされたヘッダー ユニットを使用する場合は、シンボルを DLL からエクスポートする必要があります。 モジュール シンボルを自動的にエクスポートするには、このプロパティを [はい] に設定します。

ビルド済みのモジュール ファイルを使用する

通常、ソリューション間でヘッダー ユニットを再利用する最も簡単な方法は、各ソリューションから共有ヘッダー ユニット プロジェクトを参照することです。

プロジェクトがないビルド済みヘッダー ユニットを使用する必要がある場合は、ソリューションにインポートできるように、ビルド済みの .ifc ファイルの場所を指定できます。 この設定にアクセスするには:

  1. [メイン] メニューの [プロジェクト>のプロパティ] を選択して、[プロジェクトのプロパティ ページ] ダイアログを開きます。
  2. ダイアログの左側のウィンドウで、[構成プロパティ>C/C++>全般] を選択します。
  3. [追加のモジュールの依存関係]、参照するモジュールをセミコロンで区切って追加します。 追加のモジュール依存関係に使用する形式の例を次に示します。ModuleName1=Path\To\ModuleName1.ifc; ModuleName2=Path\To\ModuleName2.ifcScreenshot showing project Property Pages properties under Configuration Properties, C/C++, General, with Additional Module Dependencies selected.

ヘッダー ユニットの複数のコピーから選択する

同じ名前または同じヘッダー ファイルに対して複数のヘッダー ユニットをビルドするプロジェクトを参照する場合は、使用するプロジェクトを指定する必要があります。 たとえば、異なるコンパイラ設定でビルドされたヘッダー ユニットのバージョンが異なる場合があり、プロジェクト設定に一致するものを指定する必要があります。

プロジェクト の Additional Header Unit Dependencies プロパティを使用して、使用するヘッダー ユニットを指定して競合を解決します。 そうしないと、どれが選択されるかを予測できません。

[Additional Header Unit Dependencies]\(追加ヘッダー ユニットの 依存関係 \) プロパティを設定するには:

  1. [メイン] メニューの [プロジェクト>のプロパティ] を選択して、[プロジェクトのプロパティ ページ] ダイアログを開きます。
  2. ダイアログの左側のウィンドウで、[構成プロパティ>C/C++>全般] を選択します。
  3. 競合を解決するために追加のヘッダー ユニットの依存関係使用するモジュールまたはヘッダー ユニット ファイルを指定します。 追加のヘッダー ユニットの依存関係には、次の 形式を使用しますPath\To\Header1.h= Path\To\HeaderUnit1.ifc;Path\To\Header2.h= Path\To\ HeaderUnit2.ifcScreenshot that shows the Additional Header Unit Dependencies setting in the project Property Pages dialog.

重要

ヘッダー ユニットを共有するプロジェクトが、互換性のあるコンパイル オプションを使用してビルドされていることを確認します。 作成時に使用したものとは異なるヘッダー ユニットを実装するときにコンパイル オプションを使用すると、コンパイラから警告が発行されます。

Note

DLL プロジェクトの一部として組み込まれているヘッダー ユニットを使用するには、[All Modules are Public]\(すべてのモジュールがパブリック\)[はい] に設定します。

方法 2: インポートする STL ヘッダーについて include をスキャンする

STL ライブラリをインポートするもう 1 つの方法は、Visual Studio を使い、プロジェクトで #include を使用した STL ヘッダーをスキャンし、ヘッダー ユニットにコンパイルすることです。 その後、コンパイラによって、これらのヘッダーが含まれるのではなく、インポートされます。

このオプションは、プロジェクトに多くのファイルにわたって多くの STL ヘッダー ファイルが含まれる場合や、ビルド スループットが重要ではない場合に便利です。 このオプションでは、特定のヘッダー ファイルのヘッダー ユニットが 1 回だけビルドされることは保証されません。 ただし、大規模なコードベースがある場合は便利です。使用する多くの STL ライブラリのヘッダー ユニットの利点を利用するためにソース コードを変更する必要はありません。

この方法は、ビルドされたヘッダー ユニットを他のプロジェクトで再利用する目的には適していないため、スタティック ライブラリ アプローチよりも柔軟性が低くなります。 この方法は、大規模なプロジェクトには適していない可能性があります。すべてのソースでステートメントをスキャンする必要があるため、最適なビルド時間は #include 保証されません。

すべてのヘッダー ファイルをヘッダー ユニットに自動的に変換できるわけではありません。 たとえば、マクロを使用した条件付きコンパイルに依存するヘッダーは、ヘッダー ユニットに変換できません。 /translateInclude が指定されている場合に、コンパイラによって使用される STL ヘッダーの header-units.json ファイル形式の許可リストがあります。 これにより、ヘッダー ユニットにコンパイルできる STL ヘッダーが決まります。 header-units.json ファイルは、Visual Studio のインストール ディレクトリにあります。 たとえば、「 %ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.30.30705\include\header-units.json 」のように入力します。 STL ヘッダー ファイルがリストにない場合、ヘッダー ユニットとしてインポートするのではなく、通常の #include ファイルとして扱われます。 header-units.json ファイルのもう 1 つの利点は、ビルド済みヘッダー ユニットでのシンボルの重複を防ぐことです。 つまり、ヘッダー ユニットをコンパイルすると、別のライブラリ ヘッダーが複数回取り込まれても、シンボルは重複しません。

この方法を試すには、2 つの STL ライブラリを含むプロジェクトを作成します。 次に、次のセクションで説明するように、ライブラリを含めるのではなく、ヘッダー ユニットとしてインポートするようにプロジェクトのプロパティを変更します。

C++ コンソール アプリ プロジェクトを作成する

これらの手順に従って、<iostream><vector> の 2 つの STL ライブラリを含むプロジェクトを作成します。

  1. Visual Studio で、新しい C++ コンソール アプリ プロジェクトを作成します。

  2. ソース ファイルの内容を次のように置き換えます。

    #include <iostream>;
    #include <vector>;
    
    int main()
    {
        std::vector<int> numbers = {0, 1, 2};
        std::cout << numbers[1];
    }
    

プロジェクトのオプションを設定してプロジェクトを実行する

次の手順では、含まれているヘッダーをコンパイラでスキャンし、ヘッダー ユニットに変換するようにオプションを設定します。 また、ヘッダー ユニットとして扱えるヘッダー ファイルに対して import を記述した場合と同様に、コンパイラで #include を扱うようにするオプションも設定します。

  1. [メイン] メニューの [プロジェクト>のプロパティ] を選択して、[プロジェクトのプロパティ ページ] ダイアログを開きます。
  2. [構成] ドロップダウン リストで [すべての構成] を選択し、[プラットフォーム] ドロップダウン リストで [すべてのプラットフォーム] を選択します。 これらの設定により、デバッグ用またはリリース用のビルド、およびその他の構成に関係なく、変更が確実に適用されます。
  3. ダイアログの左側のウィンドウで、[構成プロパティ>C/C++>全般] を選択します。
  4. [モジュール依存関係のソースをスキャンする][はい] に設定します。 この設定により、互換性のあるすべてのヘッダー ファイルがヘッダー ユニットにコンパイルされます。
  5. [含む変換] を [インポート] に設定して、[はい] に設定します。 この設定により、ファイルに一覧表示されている STL ヘッダー ファイルが header-unit.json ヘッダー ユニットとしてコンパイルされ、プリプロセッサ #include を使用する代わりにインポートされます。 Screenshot that shows the scan module dependencies property setting in the project Property Pages.
  6. [OK] を選択して変更を保存し、プロジェクトの [プロパティ ページ] ダイアログを閉じます。

/std:c++20ヘッダー ユニットを使用するには、オプション以降が必要です。 コンパイラで使用される C++ 言語標準を変更するには:

  1. [メイン] メニューの [プロジェクト>のプロパティ] を選択して、[プロジェクトのプロパティ ページ] ダイアログを開きます。
  2. [構成] ドロップダウン リストで [すべての構成] を選択し、[プラットフォーム] ドロップダウン リストで [すべてのプラットフォーム] を選択します。 これらの設定により、デバッグ用またはリリース用のビルド、およびその他の構成に関係なく、変更が確実に適用されます。
  3. プロジェクトの [プロパティ ページ] ダイアログの左側のウィンドウで、[構成プロパティ>全般] を選択します。
  4. [C++ 言語標準] ドロップダウン リストで、ISO C++20 Standard (/std:c++20) (またはそれ以降) を選択します。
  5. [OK] を選択して変更を保存し、プロジェクトの [プロパティ ページ] ダイアログを閉じます。
  6. メイン メニューから [ビルド]>[ソリューションのビルド] の順に選択して、ソリューションをビルドします。

ソリューションを実行して、予想される出力 1 が生成されることを確認します。

この方法を使用するかどうかの主な考慮事項は、利便性と、ヘッダー ユニットとしてビルドするヘッダー ファイルを決定するためにすべてのファイルをスキャンするコストの間のバランスを取ることです。

関連項目

ヘッダー ユニット、モジュール、プリコンパイル済みヘッダーを比較する
チュートリアル: モジュールを使用して C++ 標準ライブラリをインポートする
チュートリアル: Visual C++ プロジェクトでヘッダー ユニットをビルドしてインポートする
/translateInclude