Search code examples
c++xcodevisual-studiostd-functionstdbind

attempting to reassign std::function with std::bind and getting error "attempting to reference a deleted function"


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


Solution

  • 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 of FD and TiD satisfy the requirements of CopyConstructible, then the return type shall satisfy the requirements of CopyConstructible.

    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