モジュールは、通常はヘッダーにはないものの定義を提供できると期待しています。
このモジュールを想像してください:
export module hello;
export inline auto say_hello() -> char const* {
return "hello world";
}
ご覧のとおり、関数はインラインです。インターフェースにもあります。ヘッダーを使用すると、実装を配置する場所がありません。インライン関数を可能にするために、言語では複数の定義を見つけることができます。したがって、各 TU はオブジェクト ファイルに独自の定義を出力します。
それは、モジュールを使用して回避できる繰り返し作業です。ご覧のとおり、モジュール インターフェイスは他の cpp ファイルと同様に TU です。インライン関数をエクスポートする場合、実装は他の TU で使用できますが、すべての TU が実装を提供する必要はありません。これは、インライン関数を含む TU という 1 つの場所に配置できるためです。
constexpr 変数でも同じことが期待されます。また、それらへの参照またはアドレスを取得する可能性があるため、定義も必要です。たとえば、次のようにします。
export module foo;
import <tuple>;
export constexpr auto tup = std::tuple{1, 'a', 5.6f};
import foo;
int a = std::get<0>(tup);
このstd::get
関数は、タプルへの参照を取ります。これは constexpr 変数ですが、一部のコンテキスト (特に最適化がない場合) では、変数を ODR で使用する必要がある場合があります。
したがって、私の例では、モジュールfoo
は constexpr 変数のみをエクスポートしますが、cpp ファイルが定義を含むオブジェクト ファイルにコンパイルされることを期待しています。
オブジェクト ファイル内に何もない場合もあります。また、今日は空の TU のように動作することも期待しています。
// I'm empty
cpp
このようなファイルを問題なくプロジェクトに追加し、実行可能ファイルにリンクできます。ツールがモジュールと同じように動作することを期待しています。