2

std::count など、STL を使用して関数または関数オブジェクトをパラメーターとして渡す例がウェブ上にたくさんあります。

そのような引数を取る独自の関数を作成するにはどうすればよいですか?

簡単な例として、私のクラスは次のとおりです。

struct Foo{
 int val=0;
 int methodinc()const{return val+1};
 }

次のような関数 funcall を定義したいと思います。

int funcall (foo arg, function f) 
  {return f(arg); }

ここで、宣言「機能」は、とりわけ、私が確信していないものです。「funcall」という用語は Lisp に由来し、引数 ab cに(funcall f a b c)のみ適用されます。f

次に、次のようなものが機能するはずです。

Foo ff;

funcall(ff,Foo::methodinc); // should return 1
funcall(ff, [](Foo x) {return x.val+1;}) // should return 1

これを達成するための簡単な方法は何ですか?

私はこれらをデバッグ ヘルパーとして作成しています。「funcall」は、count、remove-if、transform など、関数の引数を取る STL 関数のような、独自のデータ構造のアナログのような独自の実装の一部として使用されます。しかし、複雑なテンプレート式を記述してコードを定義したくありません。


この質問に対する最初の回答は、少なくとも私にとっては、関数の引数を宣言して使用するという概念全体が少し曖昧であることを示唆しています。おそらく funcall に対処する前に、関数の引数を別の関数に渡すだけで、それを使用しない方が簡単な作業になるかもしれません。たとえば、C++ でベクトル v を数えるには、次のように書く必要があります。

std::count(v.begin, v.end(), [](int j){return j>3})

次のように、常にベクトル全体をカウントするカウントをどのように書くことができますか?

 mycount(v,[](int j){return j>3})

上と同じですか?そして、この「mycount」は、ラムダの代わりにメンバー関数ポインターに対して機能しますか?

この質問は基本的に「funcall」の質問と同じですが、渡された関数オブジェクトを実際に呼び出す必要はありません。

4

2 に答える 2

1

C++ は非常に強力で複雑な言語です。その中で、Lisp を自分で実装することを含め、Lisp でできることは何でもできます。問題は、そこにたどり着くには、言語とその機能についてかなり多くを学ばなければならないことです。残念ながら、関数をオブジェクトとして使用することは、C++ の最も複雑な部分の 1 つです。

問題を解決する方法は複数あります。@Kerrekの回答は優れたものですが、明らかに準備ができているものを超えています. 編集で提供されるコードはラムダ用であり、必ずしも物事が簡単になるとは限りません。

基本的に、C++ の関数オブジェクトは単なるポインターです。彼らはこのように見えます。

typedef int (*func)(int a, char b);

int f(int aa, char bb) {
  return aa + bb;
}

int main(void) {
  func fv = f;
  int ret = fv(10, ' ');
  printf ("ret=%d", ret);
  return 0;
}

ここで、func は関数呼び出しを表す型、f は実際の関数、fv は関数呼び出し変数です。

この構造から、他のすべてが構築されます。テンプレートを使用すると、コンパイラが型の一致を行い、ラムダを使用すると、nmes を考える必要がなくなります。その下にある C/C++ 関数は単なるポインターです。

したがって、答えは、関数を引数として取る独自の関数を作成できるということです。これらの引数は、上記のように宣言された適切な型の関数への単なるポインターであることがわかっている場合です。

于 2014-05-19T04:10:58.597 に答える