- PR -

C++/CLI nativeメンバへのbind1st, mem_funでエラー

1
投稿者投稿内容
やっぷ
会議室デビュー日: 2007/05/07
投稿数: 17
投稿日時: 2008-05-06 00:51
やっぷと申します。VS2005にて、C++/CLIです。
マネージクラスのメンバにネイティブクラスを持たせているのですが、このネイティブクラスのメソッドを、mem_fun1, bind1stを用いて呼び出そうとすると、エラーになってしまい、困っています。現象の本質を再現する最小コードは以下の通りです。空のCLRプロジェクトとして作成しています。
コード:
// main.cpp
#include <iostream>
#include <functional>
using namespace std;

class UnManaged
{ 
public: 
  void Hi( int i ){ cout<< "Hi "<< i << endl; } 
};

public ref class Managed
{
public:
  void Hi( void ){
    this->m_u = new UnManaged();
    bind1st( std::mem_fun1( &UnManaged::Hi ), this->m_u )( 11 ); // ★C2664
  }
public:
  UnManaged* m_u;
};

void main( void )
{
  Managed^ man = gcnew Managed;
  man->Hi();
  return;
}


エラーコードは以下のようなものです。
引用:

main.cpp
.\\\\\\\\main.cpp(17) : error C2664: 'std::bind1st' : 2 番目の引数を 'UnManaged *' から
'UnManaged *const &' に変換できません。(新しい機能 ; ヘルプを参照)
gc ヒープ (マネージ クラスのメンバ) からのオブジェクトをネイティブ参照に変換できません


上記の、m_uにあたる、UnManagedなインスタンスが、例えばグローバルなポインタだったら、エラーは出ず、ちゃんと動作するのですが、Managedクラスのメンバとして作成した場合のみ、エラーとなります。
やはりこの場合(つまりUnManagedのメソッドを、bind1st, mem_fun1を使って呼び出したい場合)、UnManagedなインスタンスを格納するポインタは、Managedのメンバとして持ってはいけないのでしょうか?
よろしくお願いします。
Blue
大ベテラン
会議室デビュー日: 2005/09/12
投稿数: 230
お住まい・勤務地: 知っている人は知っている
投稿日時: 2008-05-06 01:32
問題はSTLの関数を使うからではなく、アンマネージドの関数で
マネージドの領域を(constでも)参照渡ししてしまうことなんでしょう。

引用:
'UnManaged *' から
'UnManaged *const &' に変換できません。


からもっと簡単な例にすると
コード:

#pragma unmanaged
void Test(int* const& p)
{
*p = 0;
}
#pragma managed

public ref class Foo
{
private:
int* p;
public:
void Bar()
{
this->p = new int;
*this->p = 1;
Test(this->p); // error C2664: 'Test' : 1 番目の引数を 'int *' から 'int *const &' に変換できません。
// gc ヒープ (マネージ クラスのメンバ) からのオブジェクトをネイティブ参照に変換できません
//int* pp = this->p;
//Test(pp);
}
};

int main()
{
Foo f;
f.Bar();
return 0;
}


で、コメント部分のように"constであれば"一時変数を使えばできそうな感じ。

[ メッセージ編集済み 編集者: Blue 編集日時 2008-05-06 02:11 ]
やっぷ
会議室デビュー日: 2007/05/07
投稿数: 17
投稿日時: 2008-05-07 00:08
Blueさん、理解&解決できました。
Managedクラスの中におけるNativeポインタなメンバは、その指し示すアドレスはNativeヒープであっても、ポインタの値そのもの、つまりポインタメンバ自体はManaged領域に格納されているものであるが故に、一時変数に代入しなおせば問題ないということなのですねと理解しました。
先の拙ソースにて、bind1st の行を、下記の如く書き直してみると、エラーC2664は出なくなりました。
コード:
  //bind1st( std::mem_fun1( &UnManaged::Hi ), this->m_u )( 11 );
  um = this->m_u;
  bind1st( std::mem_fun1( &UnManaged::Hi ), um )( 11 );


大変助かりました。ありがとうございました。
1

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