この文書の現在のバージョンと選択したバージョンの差分を表示します。
cli:generics [2009/01/31 15:11] 192.168.0.63 作成 |
cli:generics [2013/12/23 09:08] |
||
---|---|---|---|
ライン 1: | ライン 1: | ||
- | ====== generics ====== | ||
- | |||
- | genericsはC++のテンプレートと同じようなものです。テンプレートの場合、型の解決は実際のコード中でそのテンプレートが利用されるときに行われますが、genericsではgenericを使ったクラスがあった場合、そのクラスを使うコードがなくてもコンパイルできなければなりません。実行時に動的にそのgenericsを利用可能にするためです。そのため以下のような問題があります。 | ||
- | |||
- | 以下のようなC++のテンプレートを考えます。 | ||
- | |||
- | <code cpp> | ||
- | class C { | ||
- | public: | ||
- | int func() { | ||
- | return 1; | ||
- | } | ||
- | }; | ||
- | template<typename T> class Caller { | ||
- | public: | ||
- | int DoFunc(T& t) { | ||
- | return t.func(); | ||
- | } | ||
- | }; | ||
- | int main() | ||
- | { | ||
- | C c; | ||
- | Caller<C> caller; | ||
- | int i = caller.DoFunc(c); | ||
- | return 0; | ||
- | } | ||
- | </code> | ||
- | |||
- | これをC++/CLIのgenericsを使って書くと以下のようになり、コンパイルエラーとなります。 | ||
- | |||
- | <code cpp> | ||
- | ref class C { | ||
- | public: | ||
- | int func() { | ||
- | return 1; | ||
- | } | ||
- | }; | ||
- | generic<typename T> ref class Caller { | ||
- | public: | ||
- | int DoFunc(T t) { | ||
- | return t->func(); // error | ||
- | } | ||
- | }; | ||
- | int main() | ||
- | { | ||
- | C^ c = gcnew C; | ||
- | Caller<C^>^ caller = gcnew Caller<C^>; | ||
- | int i = caller->DoFunc(c); | ||
- | return 0; | ||
- | } | ||
- | </code> | ||
- | |||
- | 型Tはコンパイル時に解決しないため、Object型としかみなせないためです。そのためgenericsでは以下のような方法を利用します。 | ||
- | |||
- | <code cpp> | ||
- | interface class I { | ||
- | int func(); | ||
- | }; | ||
- | ref class C : I { | ||
- | public: | ||
- | virtual int func() { | ||
- | return 1; | ||
- | } | ||
- | }; | ||
- | generic<typename T> where T : I ref class Caller { | ||
- | public: | ||
- | int DoFunc(T t) { | ||
- | return t->func(); | ||
- | } | ||
- | }; | ||
- | int main() | ||
- | { | ||
- | C^ c = gcnew C; | ||
- | Caller<C^>^ caller = gcnew Caller<C^>; | ||
- | int i = caller->DoFunc(c); | ||
- | return 0; | ||
- | } | ||
- | </code> | ||
- | インターフェースIを利用して、型Tに縛りをかけます。 | ||
- | |||
- | その他の注意点として、genericの型はハンドルか値型でなければなりません。 |