|
| 1 | +# main関数をグローバルモジュールに関連付けることを許可 [P3618R0] |
| 2 | +* cpp26[meta cpp] |
| 3 | + |
| 4 | +<!-- start lang caution --> |
| 5 | + |
| 6 | +このページはC++26に採用される見込みの言語機能の変更を解説しています。 |
| 7 | + |
| 8 | +のちのC++規格でさらに変更される場合があるため[関連項目](#relative-page)を参照してください。 |
| 9 | + |
| 10 | +<!-- last lang caution --> |
| 11 | + |
| 12 | +## 概要 |
| 13 | +C++20でモジュールが導入されたが、`main()`関数は名前付きモジュールに属することが禁止されていた。 |
| 14 | + |
| 15 | +C++26では、モジュール内で`extern "C++"`言語リンケージ指定を付けて`main()`関数を定義することで、`main()`関数をグローバルモジュールに関連付けることが許可される。 |
| 16 | + |
| 17 | +```cpp |
| 18 | +// mymodule.cpp |
| 19 | +module mymodule; |
| 20 | + |
| 21 | +extern "C++" int main() { |
| 22 | + // グローバルモジュールに関連付けられる |
| 23 | + // モジュール内の非エクスポートな実体にアクセスできる |
| 24 | +} |
| 25 | +``` |
| 26 | +
|
| 27 | +これにより、モジュール内の非エクスポートな実体をテストするために、テストコードをモジュール内に置くことが可能になる。 |
| 28 | +
|
| 29 | +
|
| 30 | +## 仕様 |
| 31 | +- `main()`関数に`extern "C++"`言語リンケージ指定を付けることが許可される |
| 32 | +- `extern "C++"`言語リンケージ指定を付けた`main()`関数は、名前付きモジュール内で定義されていてもグローバルモジュールに関連付けられる |
| 33 | +- `extern "C++"`言語リンケージ指定なしで`main()`関数を名前付きモジュールに属するように宣言することは、依然として不適格 (ill-formed) である |
| 34 | +
|
| 35 | +
|
| 36 | +## 例 |
| 37 | +```cpp example |
| 38 | +module; |
| 39 | +
|
| 40 | +#include <cassert> |
| 41 | +
|
| 42 | +export module mylib; |
| 43 | +
|
| 44 | +// エクスポートされる関数 |
| 45 | +export int add(int a, int b) { |
| 46 | + return a + b; |
| 47 | +} |
| 48 | +
|
| 49 | +// エクスポートされない内部関数 |
| 50 | +int internal_helper(int x) { |
| 51 | + return x * 2; |
| 52 | +} |
| 53 | +
|
| 54 | +// extern "C++"を付けることで、main関数をグローバルモジュールに関連付ける |
| 55 | +// モジュール内の非エクスポートな実体にもアクセスできる |
| 56 | +extern "C++" int main() { |
| 57 | + assert(add(1, 2) == 3); |
| 58 | + assert(internal_helper(5) == 10); |
| 59 | +} |
| 60 | +``` |
| 61 | + |
| 62 | +### 出力 |
| 63 | +``` |
| 64 | +``` |
| 65 | + |
| 66 | + |
| 67 | +## この機能が必要になった背景・経緯 |
| 68 | +モジュール内の非エクスポートな実体をユニットテストする場合、テストコードはそのモジュールに属する必要がある。しかしC++20およびC++23では、`main()`関数は名前付きモジュールに属することが禁止されていたため、モジュール内にテスト用の`main()`関数を直接書くことができなかった。 |
| 69 | + |
| 70 | +この問題に対して、P3422R1は「モジュール内の`main()`を自動的にグローバルモジュールに関連付ける」という特別扱いを追加するアプローチを提案していた。一方、本提案 (P3618R0) は、既存の`extern "C++"`メカニズムを利用して明示的にグローバルモジュールへの関連付けを行うアプローチをとった。本提案は`main()`への特別扱いを追加するのではなく、既存の特別扱い(`main()`に言語リンケージ指定を禁止していたこと)を削除するという、より一貫性のある設計となっている。 |
| 71 | + |
| 72 | + |
| 73 | +## 検討されたほかの選択肢 |
| 74 | +P3422R1では、モジュール内で定義された`main()`関数を暗黙的にグローバルモジュールに関連付けるアプローチが提案されていた。これは`main()`への新たな特別扱いの追加であり、本提案 (P3618R0) は既存の`extern "C++"`を利用する明示的なアプローチの方が言語の一貫性を保てるとして、こちらが採用された。 |
| 75 | + |
| 76 | + |
| 77 | +## <a id="relative-page" href="#relative-page">関連項目</a> |
| 78 | +- [C++20 モジュール](/lang/cpp20/modules.md) |
| 79 | + |
| 80 | + |
| 81 | +## 参照 |
| 82 | +- [P3618R0 Allow attaching main to the global module](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3618r0.html) |
| 83 | +- [P3422R1 Fixing Modules for Test](https://open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3422r1.html) |
0 commit comments