なぜstd::mem_fn
が必要です。
呼び出し可能な関数(ラムダ、関数ポインターなど)を取り込んで、それを引数にバインドする関数があります。
例えば:
template<class T>
void Class::DoBinding(T callable) {
m_callable = std::bind(callable, _1, 4);
}
//somewhere else
Item item;
m_callable(item);
私が見たすべてのコードサンプルは次のことを行います。
//some defined member function
Item::Foo(int n);
DoBinding(std::mem_fn(&Item::Foo));
なぜそれは単純にできないのですか?
DoBinding(&Item::Foo);
後者はstd :: mem_fnを使用せずに呼び出すことができるようですが、なぜそれが必要なのですか?
これは、UnaryFunction
またはBinaryFunction
を予期するジェネリックコードが、通常の呼び出し構文で直接呼び出すためです。したがって、 _for_each
_ のような任意のアルゴリズムを選択するには、次のように実装できます。
_template<class InputIt, class UnaryFunction>
UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f)
{
for (; first != last; ++first) {
f(*first); // <== N.B. f(*first)
}
return f;
}
_
_&Item::Foo
_を指定してfor_each()
を呼び出した場合、コードは_(&Item::Foo)(x)
_を呼び出そうとします。これは、メンバーへのポインターについては_(x.*&Item::Foo)()
_を記述する必要があるため、形式が正しくありません。 _mem_fn
_が解決することを意図しているのは、構文上の違いです。_mem_fn
_は、メンバーへのポインターの呼び出し構文を処理するため、メンバーへのポインター、関数、および関数オブジェクトですべてのアルゴリズムを使用できます。 for_each(v.begin(), v.end(), &Item::Foo)
を持つことはできませんが、for_each(v.begin(), v.end(), mem_fn(&Item::Foo))
を持つことはできます。
これは、std::bind()
(および_std::thread
_および_std::function
_および...)でネイティブに正常に機能します。これらはすべて、メンバーへのポインターを個別に明示的に処理するためです。また、DoBinding()
自体がstd::bind()
を呼び出すため、この場合は_std::mem_fn
_の理由はありません 。
そこ です この構文上の違いを取り除くための提案でした: P0312 。うまくいきませんでした。
これは通常、DoBinding(std::mem_fn(&Item::Foo))
を作成する人が、DoBinding
がメンバーポインタを直接取得できることを知らないために行われます。
注意:std::sort(..., &Item::Foo)
はfailになります。これは、sort
が値が直接呼び出し可能な関数オブジェクトであることを想定しているためです。そしてメンバーポインタそうではない。実際、C++標準ライブラリのほとんどすべてのアルゴリズムは、直接呼び出すことができる型の代わりにメンバーポインターを指定すると、失敗します。 DoBinding
が機能するのは、メンバーポインター用に特別なオーバーロードがあるstd::bind
を使用しているためです。 DoBinding
の呼び出し元は、必ずしもあなたがそうしていることを知っているとは限りません。
テンプレートパラメータによって呼び出し可能オブジェクトを受け取るほとんどのコードは、メンバーポインタでチョークします。したがって、安全のために、直接呼び出すことができるオブジェクトとしてメンバーポインタを渡さないでください。 mem_fn
を使用して、そのようなオブジェクトに変換します。