最終更新日時: 2026年04月06日 09時53分12秒 (JST)
Akira Takahashi が更新

履歴 編集

# main関数をグローバルモジュールに関連付けることを許可 [P3618R0](C++26)

このページはC++26に採用される見込みの言語機能の変更を解説しています。

のちのC++規格でさらに変更される場合があるため関連項目を参照してください。

## 概要

C++20でモジュールが導入されたが、`main()`関数は名前付きモジュールに属することが禁止されていた。

C++26では、モジュール内で`extern "C++"`言語リンケージ指定を付けて`main()`関数を定義することで、`main()`関数をグローバルモジュールに関連付けることが許可される。

    // mymodule.cpp
    module mymodule;

    extern "C++" int main() {
      // グローバルモジュールに関連付けられる
      // モジュール内の非エクスポートな実体にアクセスできる
    }

これにより、モジュール内の非エクスポートな実体をテストするために、テストコードをモジュール内に置くことが可能になる。

## 仕様

- `main()`関数に`extern "C++"`言語リンケージ指定を付けることが許可される
- `extern "C++"`言語リンケージ指定を付けた`main()`関数は、名前付きモジュール内で定義されていてもグローバルモジュールに関連付けられる
- `extern "C++"`言語リンケージ指定なしで`main()`関数を名前付きモジュールに属するように宣言することは、依然として不適格 (ill-formed) である

## 例

    module;

    #include <cassert>

    export module mylib;

    // エクスポートされる関数
    export int add(int a, int b) {
      return a + b;
    }

    // エクスポートされない内部関数
    int internal_helper(int x) {
      return x * 2;
    }

    // extern "C++"を付けることで、main関数をグローバルモジュールに関連付ける
    // モジュール内の非エクスポートな実体にもアクセスできる
    extern "C++" int main() {
      assert(add(1, 2) == 3);
      assert(internal_helper(5) == 10);
    }

### 出力

## この機能が必要になった背景・経緯

モジュール内の非エクスポートな実体をユニットテストする場合、テストコードはそのモジュールに属する必要がある。しかしC++20およびC++23では、`main()`関数は名前付きモジュールに属することが禁止されていたため、モジュール内にテスト用の`main()`関数を直接書くことができなかった。

この問題に対して、P3422R1は「モジュール内の`main()`を自動的にグローバルモジュールに関連付ける」という特別扱いを追加するアプローチを提案していた。一方、本提案 (P3618R0) は、既存の`extern "C++"`メカニズムを利用して明示的にグローバルモジュールへの関連付けを行うアプローチをとった。本提案は`main()`への特別扱いを追加するのではなく、既存の特別扱い（`main()`に言語リンケージ指定を禁止していたこと）を削除するという、より一貫性のある設計となっている。

## 検討されたほかの選択肢

P3422R1では、モジュール内で定義された`main()`関数を暗黙的にグローバルモジュールに関連付けるアプローチが提案されていた。これは`main()`への新たな特別扱いの追加であり、本提案 (P3618R0) は既存の`extern "C++"`を利用する明示的なアプローチの方が言語の一貫性を保てるとして、こちらが採用された。

## 関連項目

- C++20 モジュール

## 参照

- P3618R0 Allow attaching main to the global module