1
#include <functional>

void foo(std::function<void()> f) { f(); }
void foo(void (*f)()) { f(); }

int main ()
{
  foo( [](){} );
}

VS コンパイル、gcc および clang は、あいまいなオーバーロードについて不平を言います。誰が正しいですか?ラムダはクラス型であると想定されているため、ラムダと関数ポインターの間で変換を行うべきではありません。したがって、VS はすべての可能性に反して正しいように見えます。しかし、おそらく私は何かを見逃しています。

ラムダをどちらかの型にキャストする以外に、呼び出しを明確にする簡単な方法はありますか?

4

2 に答える 2

4

ラムダは、呼び出すことができる匿名で未指定のオブジェクトを作成します。これは関数ポインターでもstd::functionオブジェクトでもありませんが、関数ポインターとオブジェクトの両方として使用できるためstd::function、あいまいなオーバーロード エラーが発生します。VSは間違っていると思います。

また、関数ポインターを使用してstd::functionオブジェクトを作成できるため、引数を取る関数が既にある場合は、関数ポインターを受け取るオーバーロードを使用する必要はありませんstd::function

于 2013-07-21T11:14:13.563 に答える
3

非キャプチャ ラムダには、同じシグネチャを持つ関数ポインターへの暗黙的な変換があります。これは、5.1.2 章の第 6 段落で指定されています。

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

于 2013-07-21T13:27:21.807 に答える