- PR -

C++/CLI のテンプレートのインスタンス化について

1
投稿者投稿内容
はいあっと
会議室デビュー日: 2008/06/05
投稿数: 3
投稿日時: 2008-06-05 20:40
初めまして、初めて投稿します。
よろしくお願いします。

さっそくお聞きしたいことがあるのですが、

VC2005のテンプレートクラスで以下のようなコードを書いてクラスライブラリとします。

namespace ABC {

template<class T> public ref class Base1
{
public:
T abcdefg(){return 0;}
};

public ref class Class1 : public Base1<int>
{
public:
};

void func()
{
Class1^ aa = gcnew Class1();
//aa->abcdefg();
}
}

それを、

int main(array<System::String ^> ^args)
{
ABC::Class1^ aaa = gcnew ABC::Class1();
aaa->abcdefg();
}

このように使用しようとすると、abcdefg() が存在しないとエラーになってしまいます。

いろいろ悩んだ結果、実は上のソースで既にコメントアウトしてあった、

void func()
{
Class1^ aa = gcnew Class1();
//aa->abcdefg(); ←
}

←の部分をコンパイルすれば、エラーにならない事はわかりました。
インスタンス化されないと、外から見えないのだろうかというのは、なんとなく想像できたのですが、これを、ダミーの関数を書かずに簡単にインスタンス化させる方法ってなにか無いでしょうか?

あと・・・
多分無理なのかなと諦めかけているのですが、

typedef Base1<int> Base1int;

みたいな形で、typedef したものを外部に公開する方法は存在しないでしょうか?
そもそも、typedef したものは、たとえ int とかであっても外から使えなかったので、無理なのかなーと思っています。
代替の方法でもよいので何かご存知無いでしょうか?

なお、上記ソースには書いてない今回の目的だったりするのですが、C++のテンプレートクラスをラップしたかった(具体的にはスマートポインタをCLIのクラスに変えたかった)ので、generic は静的に型を決めないとかの理由で対象外となっている状況です。

よろしくお願いいたします。
Azulean
大ベテラン
会議室デビュー日: 2008/01/04
投稿数: 123
お住まい・勤務地: 大阪府
投稿日時: 2008-06-05 23:21
引用:

はいあっとさんの書き込み (2008-06-05 20:40) より:
typedef Base1<int> Base1int;

みたいな形で、typedef したものを外部に公開する方法は存在しないでしょうか?


typedefってC++のコード内にしか効かないと思います。
その型のマネージなエイリアスを作りたいのか、その場限りの別名にしたいのか判別しようがないですし。
また、マネージ型にはメタデータ等の要素があるので、単なる別名というのは向かないような気がします。

引用:

はいあっとさんの書き込み (2008-06-05 20:40) より:
なお、上記ソースには書いてない今回の目的だったりするのですが、C++のテンプレートクラスをラップしたかった(具体的にはスマートポインタをCLIのクラスに変えたかった)ので、generic は静的に型を決めないとかの理由で対象外となっている状況です。


そのスマートポインタのCLI版をどこで利用するんでしょうか?

C++のマネージクラスのメンバーとして持たせたいのでしょうか?
(ネイティブのメンバーがポインタでない、メンバー変数として持てないから?)
この場合、思ったように自動で解放はしてくれないと思います。
なぜなら、結局gcnew/deleteのお世話になるので、スマートポインタらしさが失われるためです。
(マネージクラスのメンバーは自動でデストラクタが走るということはないはず。ファイナライザはそのうち走るかもしれない。)


C#等の他の言語に公開したいのでしょうか?
この場合の状況が想像できません。もうちょっと例を示して頂けますか?
IDisposableを実装して、usingステートメントを使えば済むという可能性もなきにしもあらず。
※C++のスマートポインタの形をC#/VB.NETで実現するにはIDisposableとusingの組み合わせとなるでしょう。ファイナライザ任せだと、スコープを抜けてもすぐには実行されません。

[ メッセージ編集済み 編集者: Azulean 編集日時 2008-06-05 23:26 ]
はいあっと
会議室デビュー日: 2008/06/05
投稿数: 3
投稿日時: 2008-06-06 13:45
Azuleanさん返信ありがとうございます。

具体的に現在やっていることとしては、ユーザーコントロールを作成して
C++の既存のライブラリで管理されたデータを表示したり、編集したりするような
ツールの作成をやっていたりします。

大きな規模のものではなく、かなり小規模な内製ツールみたいなものなので、
とりあえずC++のデータと密に連携できると便利だと思って、C++/CLIのみでGUIを作成していたりします。

ユーザーコントロールを作成する際に、プロジェクトが分かれていないと何かと不便なようなので、別プロジェクトに分けて片方をクラスライブラリとしているのですが、
その際に、typedefで作った別名が、相手に伝わらないので、不便だなーと思ったことがtypedefに関する質問の動機でした。
専用のヘッダを作ればいいだけかもしれなかったのですが、どうせクラスライブラリに分けるのだから、とりあえずC#とかからも参照できたりしたらいいな、とかちょっと欲が出たので、よい方法無いかなと探していました。

スマートポインタについては、C++側の関数に渡すのに必要なので保存して、ついでにある程度管理できれば良いかなぐらいの気持ちなので、完全再現は求めていない状態です。
ただ、せめてテンプレート引数に型を渡して中身のC++のスマートポインタ型を自動で生成するぐらいはやりたかったのですが、クラスライブラリ間ではテンプレートは伝わらず、じゃあせめてtypedefしたものを・・・と思ったら駄目で、それじゃあせめて継承したクラスを予め作っておいて・・・と思ったら、使わない限りインスタンス化されず、ダミー関数を作ることになってしまって、せめてそこのインスタンスを自動で作る方法くらいは無いだろうか・・・と、探し始めたのが今回の動機でした。

自分の中ではつながっていた出来事だったのですが読み返してみると唐突な感じの質問になってしまっていました。すみません・・・。
Azulean
大ベテラン
会議室デビュー日: 2008/01/04
投稿数: 123
お住まい・勤務地: 大阪府
投稿日時: 2008-06-07 01:14
クラスライブラリとして型を公開する以上は、マネージ型であることが前提となるので、スマートポインタを見せたい、間接的に使わせたいという要求は無理とみられます。
(ジェネリック + IDisposableで似たような存在は作れますが、テンプレートとは型解決のタイミングが異なるので、同じにはなりません)

クラスライブラリとして別プロジェクトに分けた以上は、ネイティブC++のやり方でデータを共有する考えは捨て去るべきでしょう。
面倒でもマネージ型に仕立て上げるしかありません。

クラスライブラリはC#、VB他でも参照できるため、C++独自の文化は通用しないということで認識すべきところですね。
はいあっと
会議室デビュー日: 2008/06/05
投稿数: 3
投稿日時: 2008-06-09 11:39
なるほど・・・
たとえC++/CLIを使ったとしても.netの仕様上でそれらしく再現できないし、
静的なテンプレート的な事が出来るようには作られていないので、基本的に代替手段はないということですね・・・

今回の場合はC++側の関数にスマートポインタの形で値を受け渡さないとならないので、必ずインスタンス化されたC++テンプレートの型が必要になってしまう関係で、マネージ型には出来ないので素直にマクロ等の記述方法で対処することにします。

・・・C言語にどっぶり浸かっている自分の悪い癖で、実はちょっとだけジェネリックで作った型のメタ情報からメモリ内容を自分で操作してネイティブな型に変換できないかとか、ダーティーな手段が頭をよぎりましたが建設的じゃないのと深そうなので考えないことにしました。

単なる別名はマネージ型には向いていないとか、いろいろなるほどと思うことがありました。
お答えいただき、ありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)