STL/CLR の仕組み

επιστημη氏が STL/CLR ネタを書かれています.

便乗して軽く STL/CLR の仕組みでも紹介と.

generics と template の違い

よく generics と template は似ていると言われますが,細部に宿る本質は全くの別物で,その一例を (id:NyaRuRu:20060731#p1) でも紹介しました.
C++ の template は,C# の文脈で言えば partial クラスによるコンパイル時合成処理とよく似ています.
「template では可能だが generics ではできないこと」のいくつかは,「partial クラスでは可能だが,generics クラスではできないこと」として説明することができます.

cliext containers

cliext 名前空間直下に定義されたコンテナクラスは,generics ではなく template を使用しており,コンパイル時に型引数 T を用いてクラス定義が作成されます.例えば,2 つの C++/CLI プロジェクトでそれぞれ cliext::vector を使用すると,各アセンブリに個別の cliext::vector クラスが作成されます.これらのクラスは .NET の型システム上は同名の別クラスとして扱われ,代入互換性を持ちません.
このような事情を反映してか,コンパイル時に生成された cliext::vector 型は C# で言うところの internal class となり,外部のアセンブリから直接アクセスはできないようになっています.

cliext generic enumerators, cliext generic iterators

cliext に定義された template container class は,アセンブリごとに実装クラスを生成し,かつアセンブリ間で互換性がないという discomunication を引き起こします.では,STL/CLR を用いて作られたクラスを異なるアセンブリや異なる言語で連携させるにはどうすればいいのでしょうか?
その鍵となるのが Microsoft.VisualC.STLCLR.dll に定義された generic class / interface です.
STL/CLR のコンテナクラスは Microsoft.VisualC.STLCLR.dll に定義された generic interface を実装しています.例えば cliext::vector は,インターフェイス cliext::vector_interface も実装しており,このインターフェイスを介して vector クラスの機能を外部に公開することができます.
同様に,cliext::vector は cliext::vector_enumerator も実装しており,Enumerator パターンを使用した既存のクラスと容易に連携させることが可能になっています.
また,C++Iterator パターンを表す,cliext::IForwardIterator や,cliext::IRandomAccessIterator なども実装されており,Iterator パターンを使用したアルゴリズムと組み合わせることも可能です.

STL/CLR の仕組み - まとめ

従来, C++ の template のようなコンパイル時合成技術と,DLL のような実行時リンクの仕組みは,非常に相性の悪いものでした.
STL/CLR は,コンパイル時合成技術を用いてコンテナクラス実装の効果的な再利用を実現する一方で,Microsoft.VisualC.STLCLR.dll に定義された generic 型を経由することで他アセンブリ / 他言語との連携を可能にした,C++ .NET の利点をそれぞれ生かした興味深い実装だと思います.