Search code examples
c++functionc++11methodsbind

std::bind won't accept an std::cref of a bind-placeholder - why?


I try to pass a method as a parameter function, which itself takes a parameter, by using std::cref, but somehow I cannot get it right. What is wrong?

struct node 
{
    void get(int &i){ 
        i = x; 
    }

    int x, z;
    void foo(std::function<void(int&)>t){ 
        t(z); 
    }

    void bar(){
        x = 7;
        z = 10;
        foo(std::bind(&node::get, this, std::cref(_1)));

        cout<< "z:" << z << std::endl; //Here is expected that z is changed to 7
    }
};

Solution

  • std::bind can only process placeholders directly as parameters: std::bind(…, _1, …).

    std::cref(_1) wraps the placeholder in a std::reference_wrapper. bind doesn't recognize it as a placeholder anymore, and tries to pass it directly to the bound function, as it would do with any other non-placeholder parameter.

    To work around this and other limitations of bind, use a lambda:

    foo([this](int &x){return get(std::ref(x));});
    

    I've replaced cref with ref here, because get() expects a non-const reference. You can't use cref here, with or without the lambda. (Note that std::ref(x) is equivalent to x here, and is used instead of x for demonstration purposes only.)