没有可行的重载 '=' 用于将 std::function 回调分配为成员函数
No viable overloaded '=' for assigning std::function callback as member function
我正在尝试将成员函数挂接到 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() 安排,但我不确定错误告诉我什么。这些类型在参数和 return 值方面似乎都是正确的,所以我不确定为什么它不接受它?
尝试
listener->onTouchEnded = bind(&Game::onTouchEnded, this, std::placeholders::_1, std::placeholders::_2);
或尝试 lambda 函数
listener->onTouchEnded = [this](Touch* touch, Event* event){ this->onTouchEnded(touch, event); };
bind
必须被告知如何处理传递给其 return 值的参数。默认情况下,它只是丢弃它们。
当您将它传递给 std::function
时,它会尝试对其进行类型擦除。 std::function
将 Touch*, Event*
传递给 bind
。 bind
的 return 值丢弃它们,并按照您的要求调用 (this->*&Game::onTouchEnded)()
。这不是一个有效的调用,您会得到一个错误。
解决此问题的简单方法是添加 "what do do with arguments to the bind return value" 占位符。 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
的直接替代品。在这里,我们自动将参数转发给我们调用的方法,而不必显式列出它们。
我正在尝试将成员函数挂接到 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() 安排,但我不确定错误告诉我什么。这些类型在参数和 return 值方面似乎都是正确的,所以我不确定为什么它不接受它?
尝试
listener->onTouchEnded = bind(&Game::onTouchEnded, this, std::placeholders::_1, std::placeholders::_2);
或尝试 lambda 函数
listener->onTouchEnded = [this](Touch* touch, Event* event){ this->onTouchEnded(touch, event); };
bind
必须被告知如何处理传递给其 return 值的参数。默认情况下,它只是丢弃它们。
当您将它传递给 std::function
时,它会尝试对其进行类型擦除。 std::function
将 Touch*, Event*
传递给 bind
。 bind
的 return 值丢弃它们,并按照您的要求调用 (this->*&Game::onTouchEnded)()
。这不是一个有效的调用,您会得到一个错误。
解决此问题的简单方法是添加 "what do do with arguments to the bind return value" 占位符。 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
的直接替代品。在这里,我们自动将参数转发给我们调用的方法,而不必显式列出它们。