STL/CLR を使ってみる
C++/CLI で STL が使えるようなので試してみる。
2011-05-09 関数オブジェクト等を追記
2011-05-09 関数オブジェクト等を追記
準備
とりあえず新規で「 CLR コンソールアプリケーション 」。
stdafx.h には何も定義されていない、無視すればいい。
その前に DLL パスが私の環境 (Visual Studio 2008 professional) で定義されていなかった。
オプションを開いて

$(ProgramFiles)\Reference Assemblies\Microsoft\Framework\v3.5
を「参照ファイル」に追加。
こうしないと Microsoft.VisualC.STLCLR.dll が参照できません。
stdafx.h には何も定義されていない、無視すればいい。
その前に DLL パスが私の環境 (Visual Studio 2008 professional) で定義されていなかった。
オプションを開いて

$(ProgramFiles)\Reference Assemblies\Microsoft\Framework\v3.5
を「参照ファイル」に追加。
こうしないと Microsoft.VisualC.STLCLR.dll が参照できません。
とりあえず vector
MSDN を探しても何故かコンテナ関係しか見つからない。
ということで vector で実験してみる。
ハンドル型( ^ )がちょっとうっとうしいけどほとんど同じに書ける、これはなかなか。
しかしイテレータは ++ 演算子が定義されているはずなんだがエラーになるので next メソッドで。
とにかくマネージド環境でも同じように使えるというのは嬉しいですね。
ということで vector で実験してみる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | #include "stdafx.h" #include <iostream> #include <vector> #include <cliext/vector> #using <mscorlib.dll> //コレはネイティブコードを使う時に必要 using namespace System; #pragma managed //以下はマネージド void ManagedFunc() { cliext::vector<String ^> vec; vec.push_back( "あいうえお" ); vec.push_back( "かきくけこ" ); //iterator は IRandomAccessIterator になる cliext::vector<String ^>::iterator ^ it = vec.begin(); cliext::vector<String ^>::iterator ^ itend = vec.end(); int i = 0; for (; it != itend; it->next()) { Console::WriteLine(vec[i++]); //Console::WriteLine(it->get_cref()); //こっちのほうが簡単 } } #pragma unmanaged //以下ネイティブ void UnManagedFunc() { std::vector<std::string> vec; vec.push_back( "さしすせそ" ); vec.push_back( "たちつてと" ); std::vector<std::string>::iterator it = vec.begin(); std::vector<std::string>::iterator itend = vec.end(); int i = 0; for (; it != itend; it++) { std::cout << vec[i++].c_str() << std::endl; //std::cout << it->c_str() < std::endl; //解っているならコレで } } #pragma managed //以下はマネージド int main(array<System::String ^> ^args) { ManagedFunc(); UnManagedFunc(); Console::WriteLine( "終了するには何かキーを押してください" ); Console::ReadKey(); return 0; } |
ハンドル型( ^ )がちょっとうっとうしいけどほとんど同じに書ける、これはなかなか。
しかしイテレータは ++ 演算子が定義されているはずなんだがエラーになるので next メソッドで。
とにかくマネージド環境でも同じように使えるというのは嬉しいですね。
普通なテンプレート
とりあえず通常のテンプレートとしては使えるのか?
なるほど問題無いみたい。
template キーワードを generic キーワードに変更するとエラーになる。
generic とは少し違うようだ。
VC++ で T を typename 使うと TCHAR 関連かと少し戸惑ったり...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #include "stdafx.h" using namespace System; namespace me { // typename が正しいけど class と書いても通る template < class T, class T2> T2 calc(T a, T2 b) { return a + b; } } int wmain( int argc, wchar_t * argv[]) { Console::WriteLine( "20 + 1.5 = {0}" , me::calc(20, 1.5)); //=> 20 + 1.5 = 21.5 return 0; } |
なるほど問題無いみたい。
template キーワードを generic キーワードに変更するとエラーになる。
generic とは少し違うようだ。
1 2 3 4 5 6 | // error generic < typename T, typename T2> T2 calc(T a, T2 b) { return a + b; } |
VC++ で T を typename 使うと TCHAR 関連かと少し戸惑ったり...
関数オブジェクト
関数オブジェクトは使えるのだろうか?
何も問題無い、ref と gcnew キーワードを使う必要があるだけだ。
昔作った STL のコードを流用したい場合にはマジで使えそう。
とも感じるけど Generic の List で同じことをやってみる。
関数オブジェクトを用意する必要が無い。
新たに作るならどう考えたって Generic のほうが簡単だよなぁ...
ついでに Python でもやってみる。
桁違いに簡単...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | #include "stdafx.h" #include <cliext/vector> #include <cliext/algorithm> #include <cliext/functional> using namespace System; using namespace cliext; // 関数オブジェクトテスト // #include <functional> template < class T> ref struct print : public unary_function<T, void > { void operator()(T n) { Console::Write( "{0} " , n * 10); } }; ref class Test { public : Test() { vector< int > vec; for ( int i=0; i < 10; i++) { vec.push_back(i); } // for_each Test // #include <algorithm> for_each(vec.begin(), vec.end(), gcnew print< int >()); } }; int wmain( int argc, wchar_t * argv[]) { Test^ t = gcnew Test(); //=> 0 10 20 30 40 50 60 70 80 90 return 0; } |
昔作った STL のコードを流用したい場合にはマジで使えそう。
とも感じるけど Generic の List で同じことをやってみる。
関数オブジェクトを用意する必要が無い。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #include "stdafx.h" using namespace System; using namespace System::Collections::Generic; ref class Test { public : Test() { List< int > list ; for ( int i=0; i < 10; i++) { list.Add(i); } for each ( int n in list) { Console::Write( "{0} " , n * 10); } } }; int wmain( int argc, wchar_t * argv[]) { Test^ t = gcnew Test(); //=> 0 10 20 30 40 50 60 70 80 90 return 0; }</ int > |
ついでに Python でもやってみる。
1 2 3 4 5 6 7 8 9 10 | #!/usr/bin/env python3 import sys vector = [] for i in range ( 10 ): vector.append(i) for n in vector: sys.stdout.write( "{0} " . format (n * 10 )) #=> 0 10 20 30 40 50 60 70 80 90 |
Copyright(C) sasakima-nao All rights reserved 2002 --- 2025.