4

デフォルトの引数を取るメンバー関数を持つクラスがあります。

struct Class
{
    void member(int n = 0)
    {}
};

std::tr1::mem_fn を使用して呼び出すことができます。

Class object;

std::tr1::mem_fn(&Class::member)(object,10);

そうは言っても、オブジェクトの呼び出し可能なメンバーをデフォルトの引数で呼び出したい場合、正しい構文は何ですか?

std::tr1::mem_fn(&Class::member)(object); // This does not work

g++ で次のエラーが発生します。

test.cc:17: error: no match for call to ‘(std::tr1::_Mem_fn<void (Class::*)(int)>) (Class&)’
/usr/include/c++/4.3/tr1_impl/functional:551: note: candidates are: _Res std::tr1::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Class&, _ArgTypes ...) const [with _Res = void, _Class = Class, _ArgTypes = int]
/usr/include/c++/4.3/tr1_impl/functional:556: note:                 _Res std::tr1::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Class*, _ArgTypes ...) const [with _Res = void, _Class = Class, _ArgTypes = int]

それでも、 Class::member が異なる引数を取るメンバーによってオーバーロードされている場合、同じ問題があります...

4

2 に答える 2

5

デフォルトの関数は呼び出し時にバインドされますが、実装方法が原因で、暗黙的に任意の種類のラッパーにバインドすることはできません。を渡す&Class::memberと、mem_fnのみが表示さvoid (Class::*)(int)れ、デフォルトの引数は表示されません。を使用tr1::bindすると、デフォルトの引数を明示的にバインドできます。std::tr1::bind(&Class::member, 0)または、そのまま使用することもできますがmem_fn、1 つのオブジェクトで両方を行うことはできません。そのためには、独自のラッパー クラスを作成する必要があります。

mem_fnオーバーロードに関しては、適切な関数ポインターが のように選択されるように、テンプレート引数を明示的に指定する必要がありますmem_fn<void(int)>(&Class::member)

于 2008-11-16T19:41:42.543 に答える
3

その理由は、デフォルト引数は関数の関数型を変更しないためです。

mem_fn関数が1つの引数しか必要としないこと、または関数の2番目の引数がオプションであることを知る方法はありませ&Class::membervoid(Class::*)(int). したがって、2 番目の引数として整数が必要です。

オーバーロードされたメンバー関数のアドレスを渡したい場合は、正しいメンバー関数ポインター型にキャストする必要があります。

static_cast<void(Class::*)()>(&Class::member) だけの代わりに&Class::member、コンパイラはどのアドレスを取得するかを判断するためのコンテキストを持っています。

編集:copproには、コンテキストを提供するためのより良いソリューションがあります:std::tr1::mem_fn<void()>(&Class::member)

于 2008-11-16T19:36:27.450 に答える