170

ラムダのタイプは関数ポインターであるという認識がありました。次のテストを実行したところ、間違っていることがわかりました(デモ)。

#define LAMBDA [] (int i) -> long { return 0; }
int main ()
{
  long (*pFptr)(int) = LAMBDA;  // ok
  auto pAuto = LAMBDA;  // ok
  assert(typeid(pFptr) == typeid(pAuto));  // assertion fails !
}

上記のコードにはポイントがありませんか?そうでない場合、キーワードtypeofで推定されたときのラムダ式は何ですか?auto

4

7 に答える 7

175

ラムダ式のタイプは指定されていません。

しかし、それらは一般的にファンクターの単なる構文糖衣です。ラムダはファンクターに直接変換されます。内部の[]すべてはコンストラクターパラメーターとファンクターオブジェクトのメンバーに変換され、内部のパラメーター()はファンクターのパラメーターに変換されますoperator()

変数をキャプチャしない([]'s内に何もない)ラムダは、関数ポインターに変換できます(MSVC2010は、コンパイラーの場合、これをサポートしていませんが、この変換は標準の一部です)。

ただし、ラムダの実際の型は関数ポインターではありません。不特定のファンクタータイプです。

于 2011-10-31T08:43:34.033 に答える
126

これは、関数呼び出し演算子をオーバーロードする一意の名前のない構造です。ラムダのすべてのインスタンスは新しいタイプを導入します。

非キャプチャラムダの特殊なケースでは、構造体はさらに関数ポインタへの暗黙の変換を行います。

于 2011-10-31T08:44:12.323 に答える
29

[C++11: 5.1.2/3]: ラムダ式の型(クロージャオブジェクトの型でもあります)は、一意の名前のない非ユニオンクラス型(クロージャ型と呼ばれます)であり、そのプロパティについて以下で説明します。このクラスタイプは集合体ではありません(8.5.1)。クロージャタイプは、対応するラムダ式を含む最小のブロックスコープ、クラススコープ、または名前空間スコープで宣言されます。[..]

この句は、このタイプのさまざまなプロパティを一覧表示します。ここにいくつかのハイライトがあります:

[C++11: 5.1.2/5]:ラムダ式のクロージャ型には、パブリックinline関数呼び出し演算子(13.5.4)があり、そのパラメーターと戻り型は、それぞれラムダ式parameter-declaration-clausetrailing-return-typeによって記述されます。[..]

[C++11: 5.1.2/6]:ラムダキャプチャのないラムダのクロージャ型には、クロージャ型の関数呼び出し演算子と同じパラメータと戻り型を持つ関数へのポインタへのパブリック非仮想非明示的const変換関数があります。この変換関数によって返される値は、呼び出されたときに、クロージャ型の関数呼び出し演算子を呼び出すのと同じ効果を持つ関数のアドレスでなければなりません。

この最後のパッセージの結果は、変換を使用した場合、に割り当てることができるということLAMBDAですpFptr

于 2013-12-29T13:15:10.973 に答える
7
#include <iostream>
#include <typeinfo>

#define LAMBDA [] (int i)->long { return 0l; }
int main ()
{
  long (*pFptr)(int) = LAMBDA;  // ok
  auto pAuto = LAMBDA;  // ok

  std::cout<<typeid( *pAuto ).name() << std::endl;
  std::cout<<typeid( *pFptr ).name() << std::endl;

  std::cout<<typeid( pAuto ).name() << std::endl;
  std::cout<<typeid( pFptr ).name() << std::endl;
}

関数型は確かに同じですが、ラムダは新しい型(ファンクターのような)を導入します。

于 2011-10-31T08:49:53.713 に答える
1

また、ラムダは関数ポインタに変換可能であることに注意してください。ただし、typeid <>は、ラムダからジェネリック関数ポインターとは異なる非trvialオブジェクトを返します。したがって、typeid<>のテストは有効な仮定ではありません。一般に、C ++ 11は型の指定について心配する必要はありません。特定の型がターゲット型に変換可能であるかどうかは、すべて重要です。

于 2017-05-19T19:51:07.823 に答える
0

どうすればboost::bindオブジェクトをクラスメンバーとして保存できますか?からの実用的な解決策 、試してみてboost::function<void(int)>くださいstd::function<void(int)>

于 2011-11-08T13:01:09.740 に答える
-8

これはうまくいくかもしれません:

    h1 {
        font-size:20px;
      }
    h2{
        font-size:18px;
      }
    p {
        font-size: 16px;
      }
    exmp{
        font-size:16px;
        color:#000077;
        /*font-style: oblique;*/
        font-family: Lucida Console;
      }
<h1>If you truly insist in defining a datatype other then auto for your lambda variable then I would recommend the following</h1>

    <h2>Step 1: </h2>
    <p>Typedef a function pointer</p>
    <exmp> typedef void(*FuncPointerType)();</exmp>
    <p>Note the empty parentheses, this will need to be the same as the arguments later of your lambda <br> Now create a function pointer as you would normaly do.</p>
<exmp>/void (**MyFunction)() = new FuncPointerType([](){});</exmp>
<p>Note that the you will have to go and manually delete the pointer as it is created on the heap<br>Finally call the function pointer, it can be called one of 2 ways:</p>
<exmp>(*(*MyFunction))();</exmp>
<p>OR</p>
<exmp>(*MyFunction)();</exmp>
<p>Note the importance that it should be returnd for a function pointer pointer to just a function pointer.</p>

于 2020-11-15T00:00:27.447 に答える