Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 没有可行的过载'=';用于将std::函数回调指定为成员函数_C++_C++11_Callback_Cocos2d X - Fatal编程技术网

C++ 没有可行的过载'=';用于将std::函数回调指定为成员函数

C++ 没有可行的过载'=';用于将std::函数回调指定为成员函数,c++,c++11,callback,cocos2d-x,C++,C++11,Callback,Cocos2d X,我试图将成员函数连接到std::function回调。回调类型为: std::function<void(Touch*, Event*)> 当我尝试使用以下命令分配回调时: listener->onTouchEnded = bind(&Game::onTouchEnded, this); 我得到了一个No-available重载'='错误,有几个候选者。以下是我认为最相关的一个项目的细节: Candidate function not viable: no know

我试图将成员函数连接到
std::function
回调。回调类型为:

std::function<void(Touch*, Event*)>
当我尝试使用以下命令分配回调时:

listener->onTouchEnded = bind(&Game::onTouchEnded, this);
我得到了一个
No-available重载'='
错误,有几个候选者。以下是我认为最相关的一个项目的细节:

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`
候选函数不可行:从
“绑定”
到
'std::_1::函数'
第一个论点`
我尝试了几种不同的bind()安排,但不确定错误是什么。这些类型在参数和返回值方面似乎都是正确的,所以我不确定它为什么不接受它?

试试看

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
必须被告知如何处理传递给其返回值的参数。默认情况下,它只是丢弃它们

当您将其传递到
std::函数
时,它会尝试键入擦除它<代码>标准::函数将
触摸*,事件*
传递给
绑定
bind
的返回值将丢弃它们,并根据请求调用
(this->*&Game::ontouched)(
)。这不是一个有效的呼叫,您会收到一个错误

解决这个问题的简单方法是添加占位符,上面写着“如何处理绑定返回值的参数”<代码>绑定将成员函数视为首先接受额外的
参数的函数。你想要:

(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
调用的替代。这里,我们自动将参数转发到我们调用的方法,而不必显式地列出它们。

尝试添加两个
std::placeholder
。您需要传递第二个参数parameter@LogicStuff@sunny1304不过我没有别的东西要绑。这些参数将在回调中传递给我。我只是把这个函数绑定到
这个
上,这样我就可以使用一个成员函数作为回调函数了。嗯,第一个函数真的可以用!我曾尝试过仅使用占位符绑定::1,但没有使用第二个占位符。那个绑定呼叫到底在干什么?!哦,lambda很好——我已经在使用它们了,但我想切换到一个成员函数。不过,这是一个很好的选择。在详细阅读bind()之后,我想我理解了它。这两个占位符用于触摸*和事件*参数。出于某种原因,我认为占位符定义了我传递的参数的位置--
this
。这就是为什么我在尝试时只包括一个。但现在我想我明白了@aardvarkk只是补充一句,这是一个长期的神奇和神话的东西:-)。。。但我很高兴你能理解now@aardvarkk
bind
只是写了一些与lambda几乎相同的东西,而如果您尝试递归地
bind
则会增加一些额外的恼人的魔力。这个递归的角落案例导致我避免使用
bind
,因为它很少比一个简单的lambda更短或更清晰,而且它有可能会咬到你。我实际上是在使用lambda,但内联代码开始变得相当冗长和分散注意力。您认为使用一行lambda将参数转发给成员函数优于直接调用bind吗?这就是我从你上面的其他评论中收集到的信息。@Aardvark是的。任何C++开发人员都应该至少理解基本的lambda,但是很少有C++开发者完全理解<代码>绑定< /COD>。短lambda至少和
绑定一样清晰。
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)