2016-02-10 18 views
6

メンバ関数のアドレスをクラス外に渡す際の基本的な問題を理解しています。私はmem_fn()が解決策であるかもしれないという気持ちを持っていますが、詳細については問題があります。関数宣言でC++のmem_fn(member_function)を宣言するにはどうすればよいですか?

私は

pInstance->valNamedFlags(operand, "Statement types", statementsSubscripts, statementsNames, std::mem_fn(&e::setStatement)); 

でvalNamedFlagsを呼び出すようにしようとしているクラスEでは、現在

typedef void (*valNamedFlagsCallback)(const int, const bool); 
bool valNamedFlags(const OptBlk *operand, const char *description_of_value_or_NULL, const int subscripts[], const char *names[], valNamedFlagsCallback callBack); 

として宣言されたクラスpのメンバ関数を持っている(私は)(mem_fnのなしでスタートしましたもちろん、それは古典的な "メンバ関数へのポインタ"の問題です。私は& e :: setStatementを試してみました。& setStatementを参照してください)

FWIW、setStatementは私がmem_fnのを排除する場合

void setStatement(const int ifcid, const bool isAffirmative); 

すべての作品として(プロトタイプ宣言)と静的としてsetStatementを宣言しています。私は他のすべての可能性のある問題をすべて排除したと言っていることを指摘しています。私の唯一の問題は、 "メンバー関数へのポインタ"の問題です。残念ながら、setStatement()は静的関数ではなくメンバ関数である必要があります。

私はMS VS 2010で取得しています特定のエラーが

ブールP :: valNamedFlags(定数OptBlkの*、constのchar型*、constのint型[]、constのCHAR * []、P :: valNamedFlagsCallbackです)」:からパラメータ5は変換できません 'のstd :: tr1を:: _ Mem_fn3 < _Rx、_Pmf、_Arg0、_Arg1、_Arg2> P' に ':: valNamedFlagsCallback'

私は独立したコールバックの宣言を維持したいと思いますクラスeの;つまり、私はそれ以上の一般化をしたいので、

に行きたいので、私は行きたくありません。

mem_fn()は適切な解決法ですか、私は基本的にオフですか?もしそうなら、私はどのようにvalNamedFlags()プロトタイプのコールバックを宣言するべきですか?

私は別のアプローチをとるべきですか?

+0

[std :: bind'](http://en.cppreference.com/w/cpp/utility/functional/bind) – StoryTeller

+0

^...と 'std :: function'を見てくださいもうすでにそれがあります。 –

+1

ありがとうございます。私は多くのWebページを見て、私の頭は泳いでいます。私はいくつかの詳細が必要です。だから私はこの質問にここに来たのです。 – Charles

答えて

6

あなたのコールバックは、簡単な関数ポインタとして定義され、呼び出すことはできませんので、いくつかは、提案として実際に、あなたはバインドのようなものをやって問題を持っています。

あなたがそれを行うには余裕がある場合は、あなたが

typedef std::function<void(int, bool)> valNamedFlagsCallback 

ような何かにあなたの

typedef void (*valNamedFlagsCallback)(const int, const bool); 

を変更することができます(また、値パラメータのconstは、関数のシグネチャには影響しないことに注意)を使用すると、std::bind()

using namespace std::placeholders; 

pInstance->valNamedFlags(operand, 
     "Statement types", 
     statementsSubscripts, 
     statementsNames, 
     std::bind(&E::setStatement, e, _1, _2)); 

またはyoあなたは単純な関数としてそれを維持しなければならないなら、あなたは、静的/グローバル変数として権利オブジェクトを参照1を送信する必要があります、

pInstance->valNamedFlags(operand, 
    "Statement types", 
    statementsSubscripts, 
    statementsNames, 
    [&](int i, bool b) { e->setStatement(i, b); }); 

:uがラムダを使用することができます。

+0

ありがとう!これは私が必要とする助けのレベルです。一つの問題は、Web上でmem_fn()とbind()の例が多く見つかりましたが、関数プロトタイプのものはなく、私自身はその飛躍を遂げることができませんでした。なぜ私はあなたのstd :: function typedefに行きたくないのかわかりません。呼び出し中の参照を現在どのように指定するか正確にはわかりません。試してみました:: bind (&e :: setStatement)と私はMSのテンプレートで何十もの奇妙なエラーが発生しています... – Charles

+0

また、私はMS VS 2010のアルファテストを行っていますが、私の究極の環境は、部分的なC++ 11のサポートと私はラムダを使用することはできません。 – Charles

+0

@Charles私は誤字があったので、それはあなたのせいではありません。改訂されたコードでもう一度お試しください。もう何が必要なのかわかります。 –

5

bindメンバ関数ポインタ経由で呼び出すインスタンスが必要です。 (std::bind(&e::setStatement, eInstance, _1, _2)eInstanceがクラスeのオブジェクトへのポインタであるとします)。

using namespace std::placeholders; // for _1, _2, _3... 
pInstance->valNamedFlags(operand, "Statement types", statementsSubscripts, statementsNames, std::bind(&e::setStatement, eInstance, _1, _2)); 

(指定されていない)std::bindの戻り値は、溶液の一つはstd::functionを使用することで、自由な関数ポインタ型valNamedFlagsCallbackと一致しないことに留意されたいです。

typedef std::function<void(const int, const bool)> valNamedFlagsCallback; 

Simplified demo

+1

実際には、 'bind()'は単純な関数ポインタに変換可能なものを返します。 –

+2

@YamMarcovic - 良い点。 'valNamedFlags'は最後の引数としてバインド式の結果を取る必要があります。実際には、それはテンプレートであるか、 'valNamedFlagsCallback'を取る' std :: function 'を取るべきであることを意味します。 –

+0

@YamMarcovicあなたが正しいです。 – songyuanyao

0

皆さんありがとう!!!

プロトタイプ:

bool valNamedFlags(const OptBlk *operand, const char *description_of_value_or_NULL, const int subscripts[], const char *names[], std::function<void(int,bool)> callBack); 

コール:

valNamedFlags(..., std::bind(&e::setStatement, this, _1, _2)); 

が実際に実行され、適切な引数を持つsetStatementを呼び出します。

+0

完全性のために、MS VS 2010はstd :: bindなどを問題なく使用しますが、他のコンパイラは標準準拠の構文上の完全性を保証するものですが、std :: tr1 :: bind()とそうです。 – Charles

関連する問題