C++ C++;lambda不';t推断函数重载

C++ C++;lambda不';t推断函数重载,c++,lambda,overloading,C++,Lambda,Overloading,我定义了这样一个类: class foo { public: // I define const and non-const versions of the 'visit' function // nb. the lambda is passed by reference virtual void visitWith(std::function<void(foo&)>&); virtual void visitWith(std::function<

我定义了这样一个类:

class foo {
public:
  // I define const and non-const versions of the 'visit' function
  // nb. the lambda is passed by reference
  virtual void visitWith(std::function<void(foo&)>&);
  virtual void visitWith(std::function<void(const foo&)>&) const;
};
foo f;
f.visitWith([&](const foo&) {
  // Do something here
});
foo f;
f.visitWith( (std::function<void(const foo&)>) [&](const foo&) {
  // Do something here
});
class foo {
public:
  // Use typedefs so that all the code that comes after these two functions is neater
  typedef std::function<void(Branch&)>visitor;
  typedef std::function<void(const Branch&)>const_visitor;
  
  virtual void visitWith(const visitor&);
  virtual void visitWith(const const_visitor&) const;

  // This is to thunk the third case that can happen when you start
  // a const visit from a non-const foo.
  void visitWith(const const_visitor& v) {
    static_cast<const foo*>(this)->visitWith(v);  // Add const-ness
  }

};
我得到编译器错误。编译器不知道该做什么

我可以通过添加这样的类型转换使其工作:

class foo {
public:
  // I define const and non-const versions of the 'visit' function
  // nb. the lambda is passed by reference
  virtual void visitWith(std::function<void(foo&)>&);
  virtual void visitWith(std::function<void(const foo&)>&) const;
};
foo f;
f.visitWith([&](const foo&) {
  // Do something here
});
foo f;
f.visitWith( (std::function<void(const foo&)>) [&](const foo&) {
  // Do something here
});
class foo {
public:
  // Use typedefs so that all the code that comes after these two functions is neater
  typedef std::function<void(Branch&)>visitor;
  typedef std::function<void(const Branch&)>const_visitor;
  
  virtual void visitWith(const visitor&);
  virtual void visitWith(const const_visitor&) const;

  // This is to thunk the third case that can happen when you start
  // a const visit from a non-const foo.
  void visitWith(const const_visitor& v) {
    static_cast<const foo*>(this)->visitWith(v);  // Add const-ness
  }

};
foof;
f、 visitWith((std::function)[&](constfoo&){
//在这里做点什么
});
但那太可怕了

我怎样才能让它干净利落地工作呢

编辑:

这可能是VisualC++中的一个问题,它拒绝编译这里给出的代码:

我尝试编译时的VC++输出是:


<2> Edt2:不,Visual C++是正确的,代码是模糊的。请参阅下面的我的解决方案…

lambda是编译器生成的类型,它不是
std::function
的实例,但可以分配给一个实例

您的
visitWith()
方法通过非常量引用获取
std::function
,这意味着它需要一个预先存在的
std::function
对象,例如:

std::function func=[&](const foo&){
//在这里做点什么
};
福福;
f、 visitWith(func);
将lambda直接传递给
visitWith()
需要编译器创建一个临时
std::function
对象,但非常量引用不能绑定到临时对象。这就是原始代码无法编译的原因

对于您正在尝试的内容,您必须通过值或常量引用传递
std::function

class-foo{
公众:
void visitWith(std::function);
void visitWith(std::function)const;
};

class-foo{
公众:
void visitWith(const std::function&);
void visitWith(const std::function&)const;
};

我向微软报告了这个“错误”,并得到了回复,如下所示:

短版本:VisualC++是正确处理的,IDENON是错误的。 最后,我通过向foo添加第三个重载来解决这个问题,该重载可以向对象添加常量,如下所示:

class foo {
public:
  // I define const and non-const versions of the 'visit' function
  // nb. the lambda is passed by reference
  virtual void visitWith(std::function<void(foo&)>&);
  virtual void visitWith(std::function<void(const foo&)>&) const;
};
foo f;
f.visitWith([&](const foo&) {
  // Do something here
});
foo f;
f.visitWith( (std::function<void(const foo&)>) [&](const foo&) {
  // Do something here
});
class foo {
public:
  // Use typedefs so that all the code that comes after these two functions is neater
  typedef std::function<void(Branch&)>visitor;
  typedef std::function<void(const Branch&)>const_visitor;
  
  virtual void visitWith(const visitor&);
  virtual void visitWith(const const_visitor&) const;

  // This is to thunk the third case that can happen when you start
  // a const visit from a non-const foo.
  void visitWith(const const_visitor& v) {
    static_cast<const foo*>(this)->visitWith(v);  // Add const-ness
  }

};
class-foo{
公众:
//使用typedefs以便这两个函数后面的所有代码都更整洁
typedef std::functionvisitor;
typedef std::functionconst_访问者;
虚拟无效访问(const visitor&);
虚拟无效访问(const const_visitor&)const;
//这是第三种情况,当你开始时可能会发生
//来自非康斯特福的康斯特访问。
无效访问(const const_访问者&v){
静态(this)->visitWith(v);//添加常量
}
};
现在代码开始工作,例如:

foo f;
f.visitWith([](const foo& f) {
    std::cout << "visited a const foo!" << std::endl;
});

foof;
f、 visitWith([])(const foo&f){

std::我认为通过值传递的lambda会在每次函数调用时复制该对象,这可能会很昂贵吗?(取决于lambda捕获的内容),或者lambda更像是廉价的复制函数指针吗?通过值传递的lambda确实可以进行复制,是的。可以将lambda视为一个匿名结构,并实现了
运算符()
。但是您的
visitWith
并没有获取/传递lambda本身(
visitWith
必须使用模板参数才能做到这一点)这是一个关于lambda的代码< St::Stult。这可能是VisualC++中的一个问题,它拒绝编译下面所示的代码,即使它在该网站上编译并运行:Edg:在初始问题^ ^中添加了编译器错误的图像。w lambda已通过。这与您的原始代码没有什么不同,只是使用了typedef,这是不必要的。请参阅我刚才添加到答案中的演示链接,其中显示了我的示例的工作情况。