はじめに~ Visual C++ 2008の注目すべき機能「 STL/CLR 」
Windows Presentation Foundation や LINQ、Silverlight など、Visual Studio 2008 世代で追加された多くのリッチな機能が華々しく紹介される中、C++ 言語に関連した新機能の報道やイベントでの話題は、ほとんど聞かなくなりました。ASP .NET AJAX、Web サービス、新しいユーザー・エクスペリエンス、こうした最新の話題とともに使われるコードの多くは Visual Basic か C# ばかりです。
Visual C++ 2005 で登場した C++/CLI は、.NET Framework アプリケーション開発用言語としての C++ としては大きな変革でした。ところが、Visual C++ 2008 では、大規模な拡張や追加は行われていないため、C# 3.0 などの話題に埋もれてしまいがちです。C++/CLI の言語仕様に変更はないものの、Visual C++ 2008 にも新しい機能が加えられています。その中でも、特筆するべきは STL/CLR でしょう。
C++/CLI は、他の .NET Framework アプリケーション開発用言語にはないマネージ型のテンプレートが使えます。テンプレートは、ジェネリックとは異なりコンパイル時にテキストレベルで展開されるものです。そのため、中間言語にコンパイルされた時には、型パラメータに指定された型に変換されています。この機能を使って C++ 言語の標準ライブラリである STL (Standard Template Library) をマネージ環境でも使えるように、マネージ型のテンプレートでそのまま STL を実装したのが STL/CLR です。
テンプレートを使う STL/CLR は、ソースコードをコンパイル時に展開します。中間言語を用いている .NET Framework のライブラリは、多くのプログラミング言語で共有することができますが、STL/CLR を使える言語は C++/CLI だけです。STL/CLR の基礎となっている STL は非常に強力なライブラリであり、標準 C++ で長年積み重ねられた経験を .NET で応用できるのは大きな利点ですが、現実的に .NET アプリケーション開発用言語として広く採用されているのは C# と Visual Basic です。STL/CLR を使ったとしても C# や Visual Basic で作られた .NET アプリケーションと連携できなければ、再利用できません。
確かに、STL/CLR を使ったプログラミングは C++/CLI だけのものですが、STL/CLR は .NET Framework との互換性も十分に考慮して設計されています。C++/CLI で作ったライブラリから STL/CLR オブジェクトを提供し、他の .NET Framework アプリケーションからインターフェイス型を通して利用することができます。これによって、C# 言語や Visual Basic から、コンテナやイテレータを操作することができ、STL の強力な機能を応用したプログラミングと、既存の .NET Framework アプリケーションを連携させられます。
本稿では、C++/CLI で STL/CLR を使ったライブラリを開発し、C# 言語から C++/CLI で開発したライブラリの STL/CLR オブジェクトにアクセスする様子を、実際のコードを通してご確認いただきます。
対象読者
本稿では、C++/CLI と C# 言語を用いて STL/CLR オブジェクトを操作します。C++/CLI と C# 言語での開発経験があり、標準 C++ の STL を理解していることを前提とさせていただきます。本稿のサンプルは Visual Studio 2008 で開発し、動作確認を行っています。本稿のサンプルを実行するには、バージョン 2.0 以降の .NET Framework が必要になります。
コンテナ
STL のコンテナは、.NET Framework におけるコレクションと同じ、複数の要素を管理するための機能を提供します。動的配列の vector
や、双方向リストの list
など、コンパイル時に要素の数を確定できない動的な要素の処理に適しています。.NET Framework では、要素を Object
型で管理する System.Collections
名前空間と、ジェネリックを使った System.Collections.Generic
名前空間の機能を使って、任意の数の要素を管理することができます。.NET Framework アプリケーション開発では、特別な理由がない限り .NET Framework の標準機能であるコレクションを選択するべきですが、既存の C++ 言語の資産を .NET Framework に移植するような場合には、STL/CLR を使うといった選択が考えられます。
STL/CLR のコンテナは、すべて .NET Framework のコレクションとして使えるようにインタフェースが実装されています。よって、コンテナを IEnumerable
型として C# 言語などで作られた .NET Framework アプリケーションから操作することが可能です。コンテナを IEnumerable
として操作する場合、既存の .NET Framework アプリケーション側に変更は必要ありません。他のコレクションと同じように STL/CLR コンテナを操作できます。
cliext::vector 型
例として、動的配列を提供する cliext::vector
型を見てみましょう。この型は、標準 C++ の STL における std::vector
クラスに相当します。STL/CLR のクラスや関数は cliext
名前空間内に配置されています。また、STL/CLR を利用するソースでは cliext/vector ヘッダをインクルードしてください。
template<typename Value> ref class vector : public System::ICloneable, System::Collections::IEnumerable, System::Collections::ICollection, System::Collections::Generic::IEnumerable<GValue>, System::Collections::Generic::ICollection<GValue>, System::Collections::Generic::IList<GValue>, Microsoft::VisualC::StlClr::IVector<GValue> { ..... };
従来の STL に比べると、型パラメータに指定するアロケータが消えていることが分かります。当然、STL/CLR はマネージ環境で動作するため、アプリケーションによるメモリ管理は不要です。
vector
型の宣言を見ると、多くのインターフェイスが実装されています。ここで特に重要なのは、IEnumerable
インターフェイスを実装している点です。IEnumerable
は、.NET Framework の列挙子を表すインターフェイスで、型に依存しないコレクションの要素を処理するコードは、必ず IEnumerable
を通すように作られているはずです。例えば foreach
文で反復処理を行う場合にも IEnumerable
が実装されていることが条件となります。