C++と色々

主にC++やプログラムに関する記事を投稿します。

Visual C++ 2015 Update 1でC++にmoduleが試験的に実装された

要約

12月1日のUpdate1でVisual C++にmoduleが試験的に実装されました channel9.msdn.com

このmoduleの文法はおおよそ

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4214.pdf

と近いものになっています。

moduleとは

javaのpackage/importや、C#のnamesoace/usingのような、他の高級言語ではポピュラーな機能です。関連するコンポーネント群を公開範囲を調整して外部へ公開できる機能といったところでしょうか。これにより、ライブラリごとの名前衝突を防げたり実装を遮蔽して疎結合にできる恩恵があります。

2015年時点のC++にはモジュール機能はありません。もっと原始的な、Cの時代から存在するヘッダをincludeするコピペ機能で誤魔化してきました。この方法ではincludeするヘッダの順序によって振る舞いが変わる恐れが存在したり、コンパイル時間の増大の原因となっていました。そういったことに対処する意味でも、module機能は必須といえます。

使い方

本当に試験的な実装で、まだVisual Studio上で快適に利用できる、というレベルには達してません。moduleの詳しい文法は

本の虫: 2014-10-pre-UrbanaのC++標準化委員会文書のレビュー: N4210-N4219

を参照して下さい。コマンドプロンプトを使う方法と、Visual Studioを使う方法を紹介します。

コマンドプロンプトを使う

cmdでもできなくはないですが、パスが通って楽に使える「開発者用コマンドプロンプトforVS2015」を使うと良いでしょう。VS2015インストール時に一緒に入っているので探してみてください。 任意のフォルダで、moduleを宣言しクラスや関数などをexportするファイルを作成します。このファイルの拡張子.ixxである必要があります。今回はcalc.ixxという名前で作成しました。 次に以下のように記述します:

module calc;

export
{
    int add(int x, int y);
    int sub(int x, int y);
}

int add(int x, int y) { return x + y; }
int sub(int x, int y) { return x - y; }

module calc;で、この宣言以下のクラスや関数などがそのmoduleに所属します。exportブロックの中に、外部に公開したいクラスや関数を宣言します。これは、

module calc;

export int add(int x, int y) { return x + y; }
export int sub(int x, int y) { return x - y; }

のように個別に書くこともできます。そして、ファイルを作成したフォルダで

cl.exe /c /experimental:module calc.ixx

とclを実行します。すると同じフォルダにcalc.objcalc.ifcというファイルが作成されます。 (自分の実行結果例)

C:\Users\takuya\dev\ModuleTest_>cl.exe /c /experimental:module calc.ixx
Microsoft(R) C/C++ Optimizing Compiler Version 19.00.23506 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

Experimental features are provided as a preview of proposed language features,
and we're eager to hear about bugs and suggestions for improvements. However,
note that these experimental features are non-standard, provided as-is without
support, and subject to breaking changes or removal without notice. See
http://go.microsoft.com/fwlink/?LinkID=691081 for details.

calc.ixx

C:\Users\takuya\dev\ModuleTest_>dir
 ドライブ C のボリューム ラベルがありません。
 ボリューム シリアル番号は E24A-3B05 です

 C:\Users\takuya\dev\ModuleTest_ のディレクトリ

2015/12/02  06:38    <DIR>          .
2015/12/02  06:38    <DIR>          ..
2015/12/02  06:38             1,499 calc.ifc
2015/12/02  06:35               170 calc.ixx
2015/12/02  06:38               550 calc.obj
               3 個のファイル               2,219 バイト
               2 個のディレクトリ  806,601,965,568 バイトの空き領域

C:\Users\takuya\dev\ModuleTest_>

calc.ixxと同じフォルダにmain.cppを作成し、次のように書いてください:

#include <iostream>
import calc;

int main()
{
    std::cout << add(1, 2) << std::endl;
    std::cout << sub(1, 2) << std::endl;
}

そうしたらcalc.ixxと同じように

cl.exe /c /experimental:module main.cpp

と実行します。あとはobjをリンクすれば実行ファイルができます。

link *.obj

今回はcalc.exeが作成されたと思います。実行して

3
-1

と表示されたら成功です!

Visual Studioを使う

適宜、ソリューション、プロジェクトファイルを作成します。次にコマンドプロンプトを使う方法と同じファイルをプロジェクトに作成していくのですが、 calc.ixxというファイル名でファイルを作成するとプロジェクトのコンパイルを行うファイルに含まれないようになってしまいます。つまり、objが生成されずリンクエラーになってしまいます。

ixxファイルをコンパイルに追加するには、calc.ixxを右クリックし、プロパティを開きます。構成プパティ > 全般から、項目の種類C/C++ コンパイラを選択します。これでcalc.ixxがコンパイルされるようになりました。(srz_zumixさんご指摘ありがとうございます)

f:id:nekko1119:20151203021256p:plain

calc.ixxとmain.cppの中身はコマンドプロンプトを使う方法と同じになりますのでそちらのサンプルコードを参考にしてください。

f:id:nekko1119:20151202054227p:plain

プロジェクトのプロパティを開き、構成プロパティ > C/C++ > コマンドライン/experimental:moduleを追記します。

f:id:nekko1119:20151202054752p:plain

適用(A)を押して閉じます。

次にixxファイルそれぞれをソリューションエクスプローラー上から右クリックし、プロパティを選択します。構成プロパティ > C/C++ > コマンドライン/cを追記します。

f:id:nekko1119:20151203021044p:plain

適用(A)を押して閉じます。

後は普段Visual Stuido上で開発を行うようにCtrl + F5なり、Ctrl + Shift + Bなり、F5なり押してビルドが成功、実行できるはずです。上手くいかない場合はプロジェクトのリビルドを試してみてください。ixxファイルを更新するたびにリビルドが必要な点が注意です。

f:id:nekko1119:20151202065620p:plain

まとめ

この記事で触れたことをまとめます。

  • Visual Studio 2015でC++にmoduleが試験的に実装された
  • moduleとは何か
  • まだIDEのサポートは弱い
  • 実際にmoduleを含んだコードをビルドする方法(CUIGUIそれぞれ)

私もまだ試したいことをが色々ある(templateはできるのか、exportはネストできるのか(=com.hoge.util.func(1, 2)のようなことができるのか)等)ので、いじって遊んでみたいと思います。

参考

channel9.msdn.com

本の虫: 2014-10-pre-UrbanaのC++標準化委員会文書のレビュー: N4210-N4219

stackoverflow.com