【问题标题】:Give a closure as a «class method pointer»?将闭包作为«类方法指针»?
【发布时间】:2015-02-18 03:05:31
【问题描述】:

好的,应该很简单,基本上下面的例子应该可以工作(至少可以编译)

class Foo {
public:
    void DoNothing( void(Foo::*funcptr)() ){}
    void CallDoNothing();
};

void Foo::CallDoNothing(){
    auto closure = [this](){};
    DoNothing(closure);
}

int main(){
    return 0;
}

但由于某种原因会触发编译错误

test.cpp: In member function ‘void Foo::CallDoNothing()’:
test.cpp:9:19: error: no matching function for call to ‘Foo::DoNothing(Foo::CallDoNothing()::__lambda0&)’
  DoNothing(closure);
                   ^
test.cpp:9:19: note: candidate is:
test.cpp:3:7: note: void Foo::DoNothing(void (Foo::*)())
  void DoNothing( void(Foo::*funcptr)() ){}
       ^
test.cpp:3:7: note:   no known conversion for argument 1 from ‘Foo::CallDoNothing()::__lambda0’ to ‘void (Foo::*)()’

我什至已经尝试过转换:DoNothing(reinterpret_cast< void(Foo::*funcptr)() >(closure));DoNothing(( void(Foo::*funcptr)() )closure);,以及对此的一些变体——这些都只是触发了编译错误!

【问题讨论】:

  • 无法将带有捕获的 Lambda 转换为函数指针,更不用说成员函数指针了。
  • @user657267 好吧,如果确实如此,那就太可悲了……好吧,那我如何声明一个接受闭包的参数(即捕获局部变量的 lambda)?
  • std::function<void()>

标签: c++ c++11 lambda closures function-pointers


【解决方案1】:

为什么你认为一个 lambda 函数可以赋值给一个成员函数指针? lambda 函数属于某种匿名类型。只有当它有一个空捕获时,它才可以分配给函数指针,但即使这样也与您的示例中的成员函数指针不兼容。

您可以使用std::function<void ()> 或将DoNothing 设为模板函数。

【讨论】:

  • 我之所以这么想,是因为编译器可以将没有闭包的 lambda 隐式转换为简单的函数指针。接下来我们问自己:闭包和这个简单的 lambda 有什么区别?接下来我们记住类函数指针与通常的函数指针不同,因为它们隐式接受«this»作为第一个参数。因此,很明显,闭包只能转换为«类方法指针»。这是一个扣除:Ь
  • @Hi-Angel 如果您知道只能将具有空捕获的 lambda 函数分配给函数指针,并且该语言没有为具有捕获的 lambda 定义任何内容,我觉得假设这一点很勇敢以 this 作为捕获的 lambda 与成员函数指针之间存在关系。这在语义层面上听起来很合理,但编译器必须遵守语言定义。由于这没有说出来,我不明白为什么你应该假设它有效。逻辑论点和语言标准有时非常不同:-)
  • 好吧,我不知道语言标准没有为闭包定义任何强制转换,这就是为什么我尝试在真实程序中编写类似 lisp 的函数,最后,问了这个问题☺
  • @Hi-Angel 您可以在 isocpp.org 上查找该标准的最新草案。它的可读性不是很高,但作为参考很好。您也可以在那边的一个论坛中询问为什么省略了转换,也许您甚至可以说服他们考虑将其作为未来的标准。
猜你喜欢
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
  • 2012-10-22
  • 2021-12-10
  • 2017-10-10
  • 1970-01-01
相关资源
最近更新 更多