2

次のように定義されたコンストラクターを持つクラスがあります。

LambdaJSONVisitor();
LambdaJSONVisitor(boost::function<void (const Value &)> f);
LambdaJSONVisitor(boost::function<void (const Object &)> f);
LambdaJSONVisitor(boost::function<void (const KeyValuePair &)> f);
LambdaJSONVisitor(boost::function<void (const Array &)> f);

そして、私はこのようなオブジェクトを構築しようとしています:

LambdaJSONVisitor setNodeIDVisitor([&](const JSONAPI::Value &val) -> void
{
    ...
});

コンパイルしようとすると、次のコンパイラ エラーが発生します。

4>netmodel\CNetworkAlarmBuilder.cpp(60): error C2668: 'JSONAPI::LambdaJSONVisitor::LambdaJSONVisitor' : ambiguous call to overloaded function
4>          C:\workspace\client\projects\JSONParser\API/LambdaJSONVisitor.h(21): could be 'JSONAPI::LambdaJSONVisitor::LambdaJSONVisitor(boost::function<Signature>)'
4>          with
4>          [
4>              Signature=void (const JSONAPI::Array &)
4>          ]
4>          C:\workspace\client\projects\JSONParser\API/LambdaJSONVisitor.h(20): or       'JSONAPI::LambdaJSONVisitor::LambdaJSONVisitor(boost::function<Signature>)'
4>          with
4>          [
4>              Signature=void (const JSONAPI::KeyValuePair &)
4>          ]
4>          C:\workspace\client\projects\JSONParser\API/LambdaJSONVisitor.h(19): or       'JSONAPI::LambdaJSONVisitor::LambdaJSONVisitor(boost::function<Signature>)'
4>          with
4>          [
4>              Signature=void (const JSONAPI::Object &)
4>          ]
4>          C:\workspace\client\projects\JSONParser\API/LambdaJSONVisitor.h(18): or       'JSONAPI::LambdaJSONVisitor::LambdaJSONVisitor(boost::function<Signature>)'
4>          with
4>          [
4>              Signature=void (const JSONAPI::Value &)
4>          ]
4>          while trying to match the argument list '(`anonymous-namespace'::<lambda1>)'

このようなオーバーライドされたコンストラクターにパラメーターとしてラムダを渡すことは可能ですか? もしそうなら、私は何を間違っていますか? また、コードを変更して機能させるにはどうすればよいですか? Visual Studio 2010 を使用しています。

ありがとう

4

2 に答える 2

3

派生型がある場合にのみ機能しませんこれは、オブジェクトを作成して正しい型にキャストすることで修正できます。

auto lambda = [&](const C&) {};
Func f(static_cast<std::function<void(const C&)>>(lambda));

または次のようなオブジェクトを作成せずに

Func f(static_cast<std::function<void(const C&)>>(
[&](const C&) {});

于 2013-04-05T09:42:58.353 に答える
2

いくつかのグルー コードを使用すると、明示的なキャストを行わなくても、コンパイラにラムダの引数の型を認識させ、対応するコンストラクターを呼び出させることができます。ただし、必要なのは、少なくとも Visitor のムーブ コンストラクターだけです。

最初のステップ: 「テンプレート化された」コンストラクターを作成します。LambdaJSONVisitor は変更できないので、ヘルパー関数が必要になると思います。

template <class Arg>
LambdaJSONVisitor createLJV_Arg(std::function<void(const Arg&)> f)
{ return LambdaJSONVisitor(f); }

テンプレート パラメーターを明示的に指定することで、その関数を呼び出すことができるようになりました。

LambdaJSONVisitor v = createLJV_Arg<Value>( [](Value const&){} );
                                 // ^-- explicitly state the type

2 番目のステップ: ラムダの引数の型を決定し、最初の関数に明示的に渡すテンプレート メタプログラミング関数を作成します。例はここにあります:

template <class F>
LambdaJSONVisitor createLJV(F&& f)
{
   typedef boost::function_types::parameter_types<decltype(&F::operator())>::type args_t;
   typedef boost::mpl::at<args_t, boost::mpl::int_<1>>::type arg1_t;

   return createLJV_Arg<arg1_t>(std::forward<F>(f));
}

そして、ちょうど

LambdaJSONVisitor v = createLJV( [](Value const&){} );

もちろん、を変更できるLambdaJSONVisitor場合は、テンプレート化されたコンストラクターを 1 つだけ指定し、その中でラムダの引数の型推定を行います。

于 2013-04-05T10:21:56.210 に答える