web-dev-qa-db-ja.com

std :: functionの使用法と構文

std::functionを使用する必要がありますが、次の構文の意味がわかりません。

std::function<void()> f_name = []() { FNAME(); };

std::functionを使用する目的は何ですか?関数へのポインタを作ることですか?

23
user2982229

_std::function_は型消去オブジェクトです。つまり、一部の操作の詳細が消去され、操作に対する統一されたランタイムインターフェイスが提供されます。 _std::function_の場合、プライマリ1 操作は、コピー/移動、破棄、およびoperator()を使用した「呼び出し」-「コールオペレーターのような関数」です。

難解な英語では、それは_std::function_が、それを呼び出す方法で関数ポインターのように機能するほとんどすべてのオブジェクトを含むことができることを意味します。

それがサポートするシグネチャは山かっこで囲みます:std::function<void()>は引数を取りません。 std::function< double( int, int ) >は2つのint引数を取り、doubleを返します。一般に、_std::function_は、引数を引数リストから変換でき、戻り値を戻り値に変換できる関数のようなオブジェクトの格納をサポートします。

_std::function_とラムダは、互換性がある場合、獣とは異なることを知ることが重要です。

行の次の部分はラムダです。これはC++ 11の新しい構文で、単純な関数のようなオブジェクト(_()_で呼び出すことができるオブジェクト)を書き込む機能を追加します。このようなオブジェクトはタイプイレースして_std::function_に格納できますが、実行時のオーバーヘッドが多少犠牲になります。

特に[](){ code }は本当に単純なラムダです。これに対応します:

_struct some_anonymous_type {
  some_anonymous_type() {}
  void operator()const{
    code
  }
};
_

上記の単純な疑似関数型のインスタンス。上記のような実際のクラスは、実装によって定義された一意の名前(多くの場合、ユーザー定義型に含めることができない記号を含む)で、コンパイラーによって「発明」されます(発明せずに標準に従うことができるかどうかはわかりません)そのようなクラスですが、私が知っているすべてのコンパイラが実際にクラスを作成します)。

完全なラムダ構文は次のようになります。

_[ capture_list ]( argument_list )
-> return_type optional_mutable
{
  code
}
_

ただし、多くの部分は省略したり、空のままにしたりできます。 capture_listは、結果の匿名型とそのメンバー変数のコンストラクター、argument_listはoperator()の引数、戻り型は戻り型の両方に対応します。ラムダインスタンスのコンストラクタは、インスタンスがcapture_listで作成されるときにも魔法のように呼び出されます。

_[ capture_list ]( argument_list ) -> return_type { code }
_

基本的になる

_struct some_anonymous_type {
  // capture_list turned into member variables
  some_anonymous_type( /* capture_list turned into arguments */ ):
    /* member variables initialized */
  {}
  return_type operator()( argument_list ) const {
    code
  }
};
_

1 さらに、RTTIが格納され(typeid)、元の型へのキャストバック操作が含まれます。

行をバラバラにしましょう:

std :: function

これは、パラメーターを取らず、値を返さない関数の宣言です。関数がintを返した場合、次のようになります。

_std::function<int()>
_

同様に、それがintパラメータも取る場合:

_std::function<int(int)>
_

あなたの主な混乱は次の部分だと思います。

_[]() { FNAME(); };
_

_[]_の部分はキャプチャ句と呼ばれます。ここでは、ラムダの宣言に対してローカルであり、使用可能にする変数withinラムダ関数自体を配置します。これは「何も捕らえられたくない」ということです。これがクラス定義内にあり、クラスをラムダで使用できるようにしたい場合は、次のようにします。

_[this]() { FNAME(); };
_

次の部分は、ラムダに渡されるパラメーターです通常の関数とまったく同じ。先に述べたように、std::function<void()>は、パラメーターを取らないメソッドを指すシグニチャーであるため、これも空です。

残りは通常の関数のようにラムダ自体の本体であり、関数FNAMEを呼び出すだけです。

別の例

次の署名があるとします。これは、2つの数値を合計できるもののためのものです。

_std::function<int(int, int)> sumFunc;
_

これでラムダを次のように宣言できます:

_sumFunc = [](int a, int b) { return a + b; };
_

MSVCを使用しているかどうかはわかりませんが、ラムダ式の構文へのリンクを次に示します。

http://msdn.Microsoft.com/en-us/library/dd293603.aspx

26
Moo-Juice