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 で実験してみる。
#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 関連かと少し戸惑ったり...
#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 とは少し違うようだ。
// error
generic <typename T, typename T2>
T2 calc(T a, T2 b)
{
	return a + b;
}
VC++ で T を typename 使うと TCHAR 関連かと少し戸惑ったり...
関数オブジェクト
関数オブジェクトは使えるのだろうか?
昔作った STL のコードを流用したい場合にはマジで使えそう。
とも感じるけど Generic の List で同じことをやってみる。
関数オブジェクトを用意する必要が無い。
ついでに Python でもやってみる。
#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;
}
何も問題無い、ref と gcnew キーワードを使う必要があるだけだ。昔作った STL のコードを流用したい場合にはマジで使えそう。
とも感じるけど Generic の List で同じことをやってみる。
関数オブジェクトを用意する必要が無い。
#include "stdafx.h"
using namespace System;
using namespace System::Collections::Generic;
ref class Test
{
public:
	Test()
	{
		List 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;
} 
新たに作るならどう考えたって Generic のほうが簡単だよなぁ...ついでに Python でもやってみる。
#!/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.