IRandomAccessIterator インターフェースを利用して要素を列挙する C# プログラム
次に、上で作成したライブラリから IRandomAccessIterator<int> 型としてオブジェクトを受け取り、イテレータを操作するプログラムを C# 言語で記述します。
using Microsoft.VisualC.StlClr.Generic; class Test { public static void Main(string[] args) { DataManager data = new DataManager(0, 10); IRandomAccessIterator<int> iterator = data.GetBegin(); IRandomAccessIterator<int> end = data.GetEnd(); for (; !iterator.equal_to(end) ; iterator.next() ) { int value = data.GetValue(iterator); System.Console.WriteLine(value); } } }
0 1 2 3 4 5 6 7 8 9
Sample06 は、Sample05 の DataManager クラスのインスタンスを生成し、C++/CLI 側の内部で作成したコンテナのイテレータを返します。C# コードでは GetBegin() メソッドと GetEnd() メソッドから IRandomAccessIterator インターフェイス型のオブジェクトを受け取り、先頭の要素から末尾までを for 文で取得して出力します。このとき、get_cref() や get_ref() メソッドが使えないため、事前に用意した DataManager クラスの GetValue() メソッドから値を取得しています。
このように、イテレータは他の言語でも扱えますが、他の言語からイテレータの指す要素へのアクセスが困難であるため、あまり実用的ではありません。C++/CLI 上であればイテレータをポインタのように扱うことができましたが、他の言語ではインターフェイスを介した操作が必須となります。通常、コンテナの要素へ純粋な .NET Framework アプリケーションからアクセスするには Sample02 の IEnumerable を通す方法が理想的です。
関数オブジェクト
STL 及び STL/CLR では、関数のように振る舞うことができる任意のオブジェクトを関数オブジェクトと呼び、アルゴリズムに組み込むことができました。C++/CLI のみで開発した場合は、STL/CLR で用意されている関数オブジェクトの他に、関数へのポインタやデリゲートも関数オブジェクトとして扱うことができます。C# や Visual Basic など、C++/CLI 以外の言語では STL/CLR の関数オブジェクトを直接利用することはできませんが、デリゲートを通すことでアクセスが可能になります。
STL における negate 関数オブジェクトのようなパラメータを 1 つ受け取り結果を返す関数は Microsoft.VisualC.StlClr.UnaryDelegate デリゲートを使います。STL/CLR では、同義のデリゲートで unary_delegate が cliext/functional ヘッダ内でも宣言されていますが、.NET Framework として他の言語とコラボレーションするには UnaryDelegate を使います。
public delegate TResult UnaryDelegate<TArg, TResult>( TArg )
TArg 型パラメータには受け取るパラメータの型、TResult 型パラメータには戻り値の型を指定します。
同様に、STL における plus 関数オブジェクトのような 2 つのパラメータを受け取る関数には Microsoft.VisualC.StlClr.BinaryDelegate デリゲートを使います。STL/CLR では、同じデリゲート型で binary_delegate も用意されています。
public delegate TResult BinaryDelegate<TArg1, TArg2, TResult>( TArg1 , TArg2 )
TArg1 と TArg2 型パラメータには受け取るパラメータの型、TResult には戻り値の型を指定します。
これらのデリゲートを利用するシナリオは、C++/CLI で開発したライブラリから STL/CLR や自作の関数オブジェクトを他の言語に渡す場合と、他の言語で作られたメソッドを C++/CLI のアルゴリズムなどに利用する関数オブジェクトとして使う場合などが考えられます。前者の場合、STL/CLR の関数オブジェクトは、関数オブジェクト自身を呼び出すデリゲートに変換する型キャスト演算子をオーバーロードしています。
operator delegate_type^();
ここの delegate_type^ 型は、関数オブジェクトのメンバとして定義されている型です。例えば negate 関数オブジェクトであれば UnaryDelegate 型、plus 関数オブジェクトであれば BinaryDelegate 型となります。
