没有可行的重载'='用于将std :: function回调赋值为成员函数

时间:2016-02-08 16:36:46

标签: c++ c++11 callback cocos2d-x

我正在尝试将成员函数挂钩到std::function回调。回调类型是:

std::function<void(Touch*, Event*)>

我的会员功能是:

void Game::onTouchEnded(Touch* touch, Event* event)

当我尝试使用以下内容分配回调时:

listener->onTouchEnded = bind(&Game::onTouchEnded, this);

我与几位候选人发生No viable overloaded '='错误。以下是我认为最相关的细节:

Candidate function not viable: no known conversion from 
'__bind<void (Game::*)(cocos2d::Touch *, cocos2d::Event *), Game *>'
to
'std::__1::function<void (cocos2d::Touch *, cocos2d::Event *)>'
for 1st argument`

我尝试了几种不同的bind()安排,但我不确定错误告诉我的是什么。这些类型在参数和返回值方面似乎都是正确的,所以我不确定它为什么不接受它?

2 个答案:

答案 0 :(得分:2)

尝试

listener->onTouchEnded = bind(&Game::onTouchEnded, this, std::placeholders::_1, std::placeholders::_2);

或尝试lambda函数

listener->onTouchEnded = [this](Touch* touch, Event* event){ this->onTouchEnded(touch, event); };

答案 1 :(得分:2)

必须告诉

bind如何处理传递给其返回值的参数。默认情况下,它只是丢弃它们。

当您将其传递给std::function时,会尝试键入 - 删除它。 std::functionTouch*, Event*传递给bindbind的返回值会丢弃它们,并根据您的请求调用(this->*&Game::onTouchEnded)()。这不是有效的通话,而且您收到错误。

解决此问题的简单方法是添加占位符,说明“如何处理绑定返回值的参数”。 bind将成员函数视为首先采用额外this参数的函数。你想要:

(this->*&Game::onTouchEnded)(_1, _2)

对应于:

std::bind(&Game::onTouchEnded, this, _1, _2)

现在这一切都很好,但实际上你应该避免std::bind。完全理解它是很棘手的:当你递归地调用它时,它有一些奇怪的角落情况可以咬你,或强迫你不必要地进行类型擦除。

相反,使用lambda。在C ++ 11中,它看起来像:

[this](Touch* touch, Event* event){return this->onTouchEnded(touch, event);}

在C ++ 14中,另一种选择是:

[this](auto&&args)->decltype(auto){return this->onTouchEnded(decltype(args)(args)...);}

甚至:

template<class T, class M>
auto bind_method( T* t, M* m ) {
  return [t, m](auto&&...args)->decltype(auto){
    return (t->*m)(decltype(args)(args)...);
  };
}

可以这样使用:

bind_method(this, &Game::onTouchEnded)

是您拨打bind的替代品。在这里,我们将参数自动转发给我们调用的方法,而不是必须明确地列出它们。