4

関数オブジェクトを渡す次の小さなプログラムの何が問題になっていますか?

#include <iostream>
#include <functional>

void foo(const std::unary_function<const std::string&, void>& fct) {
  const std::string str = "test";
  fct(str); // error
}

class MyFct : public std::unary_function<const std::string&, void> {
public:
  void operator()(const std::string& str) const {
    std::cout << str << std::endl;
  }
};

int main(int argc, char** argv){
  MyFct f;
  foo(f);
  return 0;
}

6 行目で次のエラーが表示されます。

 no match for call to 
`(const std::unary_function<const std::string&, void>) (const std::string&)'
4

1 に答える 1

12

よくある間違い。typedef を追加する 2 つの構造体にすぎませunary_functionbinary_function

argument_type
result_type

そしてそれぞれ

first_argument_type
second_argument_type
result_type

それ以上ではありません。これらは、関数オブジェクト型の作成者の便宜のためのものであるため、自分で行う必要はありません。しかし、それらはポリモーフィックに動作しません。必要なのは、関数オブジェクト ラッパーです。boost::function頭に浮かぶ:

void foo(boost::function<void(const std::string&)> const& fct) {
  const std::string str = "test";
  fct(str); // no error anymore
}

もしくはテンプレにする

template<typename FunctionObject>
void foo(FunctionObject const& fct) {
  const std::string str = "test";
  fct(str); // no error anymore
}

値で取得し、それfooを使用してシーケンスに適用する場合はコピーを返すことができます。これにより、関数オブジェクトがそのメンバー間でいくつかの状態変数を更新できるようになります。for_eachそのようにする例です。とにかく、通常は小さく、コピーすると柔軟性が高まるため、値で受け入れます。私もです

template<typename FunctionObject>
void foo(FunctionObject fct) {
  const std::string str = "test";
  fct(str); // no error anymore
}

その後、fct のコピーを取得してどこかに保存することができます。また、fctの operator() を非 const にして、一部のメンバーを更新することができます (これは のポイント全体の一部ですoperator())。const 参照によって関数オブジェクトを取得する場合、ユーザーが関数を渡した可能性があるため、通常はコピーできません。それをコピーすると、ローカル関数ポインターの代わりに関数をローカルに宣言しようとします。ただし、値渡しを受け入れると、関数が渡されたときに代わりに関数ポインターが受け入れられ、安全にコピーできます。

于 2009-03-29T01:21:20.753 に答える