I'm trying to use function pointers to a class member function and then use std::bind to call that function on an object of that class in a separate function. Within this separate function, I can bind the object and function pointer once, and then a second time in Xcode, but not with MSVS2015...
Here is some basic code that reproduces the issue I'm having. Everything compiles and runs fine on Xcode:
class AClass
{
public:
bool isNumber1()
{
return num == 1 ? true : false;
}
private:
int num;
};
typedef bool (AClass::*isFunction)();
bool checkIsFunc (AClass& object, isFunction function)
{
auto f = std::bind(function, object);
f = std::bind(function, object); // Error occurs here
return f();
}
int main (int argc, char* argv[])
{
AClass obj;
bool outcome = checkIsFunc(obj, &AClass::isNumber1);
return 0;
}
However, with MSVS2015, I get the following error:
error C2280: 'std::_Bind<true,bool,std::_Pmf_wrap<bool (__thiscall AClass::* )(void),bool,AClass,>,AClass &> &std::_Bind<true,bool,std::_Pmf_wrap<bool (__thiscall AClass::* )(void),bool,AClass,>,AClass &>::operator =(const std::_Bind<true,bool,std::_Pmf_wrap<bool (__thiscall AClass::* )(void),bool,AClass,>,AClass &> &)': attempting to reference a deleted function
Any ideas what I am doing wrong here or why this works in Xcode but not VS?
Thanks!
Jim
std::bind
does not return a std::function
object but one of an implementation-defined binder type. Here, then:
auto f = std::bind(function, object);
f
is deduced to be this binder type, and this binder type doesn't have to be assignable, only CopyConstructible and MoveConstructible. Quoth the standard, [func.bind.bind]/5:
Remarks: The return type [of std::bind] shall satifsy the requirements of
MoveConstructible
. If all ofFD
andTiD
satisfy the requirements ofCopyConstructible
, then the return type shall satisfy the requirements ofCopyConstructible
.
FD
and TiD
are the bound function type and the argument types, respectively. Note that it says nothing about MoveAssignable
and CopyAssignable
, which means1 that the binder isn't required to satisfy them. And that means that the assignment
f = std::bind(function, object); // Error occurs here
is not required by the standard to work.
It appears that MSVC's implementation of std::bind
sticks to this, while libc++ (which I believe comes with Xcode, but I don't develop for Mac OS X) is more lenient.
If you want f
to be a std::function
, you have to declare it as one explicitly:
std::function<bool()> f = std::bind(function, object);
And then the reassignment will work as well because std::function
is assignable.
1 along with the fact that such a requirement is not mentioned anywhere else