【问题标题】:How to pass lambda to overridden method with boost::function parameter?如何使用 boost::function 参数将 lambda 传递给被覆盖的方法?
【发布时间】:2013-03-27 15:53:06
【问题描述】:

我有一个类,其构造函数定义如下:

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>)'

是否可以像这样将 lambda 作为参数传递给重写的构造函数?如果是这样,我做错了什么,我应该如何更改代码以使其工作?我正在使用 Visual Studio 2010。

谢谢

【问题讨论】:

  • 简单示例运行良好liveworkspace.org/code/9YSdj$5
  • 是的,我想知道这是否是 VS2010 特定的问题,只是出于兴趣,我尝试更改构造函数签名以将 const refs 用于函数以匹配您的示例,但我得到了同样的错误。

标签: c++ visual-studio-2010 boost c++11 lambda


【解决方案1】:

只有在有派生类型Example 时它才能工作,这可以通过创建对象并将其转换为正确的类型来解决,例如

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&) {});

Example

【讨论】:

  • 根据您必须从 lambdas 创建访问者的频率,请考虑我的回答中的“第一步” - 它可以缩短通话时间。
【解决方案2】:

使用一些粘合代码,您可以让编译器找出 lambda 的参数类型并调用相应的构造函数,而无需显式强制转换。但是,您唯一需要的是至少为您的访问者提供一个移动构造函数。

第一步:创建一个“模板化”构造函数。我想,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

第二步:创建一个模板元编程函数,确定 lambda 的参数类型并将其显式传递给第一个函数。例子可以找到here:

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,那么只给它一个模板化的构造函数,然后在里面做lambda的参数类型推导。

【讨论】:

  • 谢谢,我没有考虑元编程。这是一个非常干净的解决方案,而且由于 LJV 是在很多地方创建的,我认为在构造函数中增加额外的复杂性绝对值得(我可以修改 LJV,所以我会这样做)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-30
  • 2011-08-09
  • 2017-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多