Skip to content

Commit 18aae7e

Browse files
committed
C++26: 「main関数をグローバルモジュールに関連付けることを許可」を追加 (close #1492)
1 parent 7e4e769 commit 18aae7e

File tree

4 files changed

+86
-2
lines changed

4 files changed

+86
-2
lines changed

implementation-status.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@
325325
| P2900R14: [契約プログラミングをサポートする](/lang/cpp26/contracts.md) | 関数の事前条件、事後条件、不変条件を記述できるようにする | | | | |
326326
| P2841R7: [コンセプトと変数テンプレートにテンプレートテンプレートパラメータのサポートを追加](/lang/cpp26/concept_and_variable-template_template-parameters.md.nolink) | テンプレート引数をあとで指定するテンプレートテンプレートパラメータを、コンセプトと変数テンプレートでも使用できるようにする | | | | |
327327
| P1967R14: [ファイルを読み込む`#embed`命令を追加](/lang/cpp26/embed.md) | バイナリファイルをインクルードするメカニズム。`#include`とちがって読み出しサイズなどの柔軟な指定ができる | 15 | | | |
328-
| P3618R0: [`main`関数をグローバルモジュールに含められるようにする](/lang/cpp26/allow_attaching_main_to_the_global_module.md.nolink) | `main`関数に`extern "C++"`を指定できるようにすることで名前付きモジュールに含められるようにする | 16 | 21 | | | |
328+
| P3618R0: [`main`関数をグローバルモジュールに含められるようにする](/lang/cpp26/allow_attaching_main_to_the_global_module.md) | `main`関数に`extern "C++"`を指定できるようにすることで名前付きモジュールに含められるようにする | 16 | 21 | | | |
329329
| P2996R13: [静的リフレクション](/lang/cpp26/reflection.md.nolink) | リフレクション演算子`^^``std::meta::info`型によりコンパイル時にさまざまな情報を取得できる | | | | |
330330
| P1306R5: [コンパイル時のタプルやリストを展開処理する`template for`](/lang/cpp26/expansion_statements.md.nolink) | クラス・タプル・Range・パラメータパックなどを展開してすべての要素をコンパイル時の処理する`template for`文を追加 | 16 | | | |
331331
| P3533R2: [`constexpr`仮想継承を許可](/lang/cpp26/constexpr_virtual_inheritance.md.nolink) | 定数式の文脈での仮想継承を許可 | 16 | | | |

lang/cpp20/modules.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,7 @@ int main() {
493493
## <a id="relative-page" href="#relative-page">関連項目</a>
494494
- [C++23 無意味なexport宣言を禁止する](/lang/cpp23/meaningful_exports.md)
495495
- [C++26 モジュール宣言でのモジュール名のマクロ展開を禁止する](/lang/cpp26/module_declarations_shouldnt_be_macros.md)
496+
- [C++26 `main`関数をグローバルモジュールに関連付けることを許可](/lang/cpp26/allow_attaching_main_to_the_global_module.md)
496497

497498

498499
## 参照

lang/cpp26.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ C++26とは、2026年中に改訂される予定の、C++バージョンの通
104104
| 言語機能 | 説明 |
105105
|----------|------|
106106
| [モジュール宣言でのモジュール名のマクロ展開を禁止する](/lang/cpp26/module_declarations_shouldnt_be_macros.md) | `export module MACRO_NAME;`を禁止 |
107-
| [`main`関数をグローバルモジュールに含められるようにする](/lang/cpp26/allow_attaching_main_to_the_global_module.md.nolink) | `main`関数に`extern "C++"`を指定できるようにすることで名前付きモジュールに含められるようにする |
107+
| [`main`関数をグローバルモジュールに含められるようにする](/lang/cpp26/allow_attaching_main_to_the_global_module.md) | `main`関数に`extern "C++"`を指定できるようにすることで名前付きモジュールに含められるようにする |
108108
| [モジュール宣言より前での`#line`ディレクティブの使用を許可する](/lang/cpp26/allow_line_before_module_declarations.md.nolink) | モジュール宣言より前での`#line`ディレクティブの使用を禁止していたのは過度な制限だった |
109109

110110

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
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

Comments
 (0)