11

重複の可能性:
std::functions を取る関数の呼び出しを明確にする std::function
のテンプレート引数 (シグネチャ) はその型の一部ではありませんか?

関数をオーバーロードして、さまざまな異なるラムダ (通常は多かれ少なかれ引数を使用) で自然に呼び出すことができるようにしたいと考えています。私が試した明らかなことは次のとおりです。

#include <functional>
#include <iostream>

extern void fn(std::function<void(int)>);
extern void fn(std::function<void(int, int)>);

void test()
{
    fn([](int a) { std::cout << "lambda with 1 arg " << a << std::endl; });
}

ただし、これは g++ (v4.6.2 および v4.7.1 を試行) で失敗し、次のエラーが表示されます。

test.cc: In function ‘void test()’:
test.cc:9:74: error: call of overloaded ‘fn(test()::<lambda(int)>)’ is ambiguous
test.cc:9:74: note: candidates are:
test.cc:4:13: note: void fn(std::function<void(int)>)
test.cc:5:13: note: void fn(std::function<void(int, int)>)

ここここで別の (そしてはるかに複雑な) アプローチを見つけましたが、私の質問は、上記のコードが失敗するのはなぜですか? それが機能しないという標準の何かがありますか、それともこれは単にg ++のバグ/制限ですか?

4

2 に答える 2

5

すべてのラムダ[](int a) { std::cout << "lambda with 1 arg " << a << std::endl; } には一意の型がありますが、上記と同じ別のラムダでも、メンバーを持つ異なるラムダ型になりますoperator()(int a)

の実装にstd::functionは、 と の両方で使用できるテンプレート化された変換が std::function<void(int)>ありstd::function<void(int, int)>ます。インスタンス化されたときにコンパイルされるのは 1 つだけですが、両方ともオーバーロード解決の対象と見なされるため、あいまいさが生じます。望ましい結果を得るには、ライブラリは SFINAE を使用して、エラーのあるものをオーバーロード候補セットから除外する必要があります (libc++ の最近のバージョンではそうしています)。

于 2012-08-18T18:58:03.583 に答える
0

質問は裏返しに聞こえます。を使用してタイプを定義し、std::functionそのタイプのオブジェクトを呼び出す方法とその戻り値を記述します。次に、の特殊化を使用してstd::function、ラムダを含む、異なる引数タイプまたは異なるリターンタイプを持つさまざまな呼び出し可能オブジェクトをラップできます。

于 2012-08-18T19:19:43.137 に答える