c++stdbind

Why can std::function bind functions of different types?


I saw a special usage about std::bind(), just like the following code:

using namespace std::placeholders;
class Test {
public:
    Test() {
        _state_function_map[0] = std::bind(&Test::state_function, _1, _2);
    }
    void test_function() {
        auto it = _state_function_map.find(0);
        int result = it->second(this, 0.0);
    }
private:
    int state_function(const double value) const {
        // do someting
    }
private:
    using func_type = std::function<int(Test* const, const double)>;
    std::unordered_map<int, func_type> _state_function_map;
};

What I can't understand is, func_type and Test::state_function are not the same type, func_type has two parameters, and Test::state_function only has one parameter, so why can they bind Test::state_function in _state_function_map?


Solution

  • func_type has two parameters, and Test::state_function only has one parameter,I can't understand how it works.

    For binding purposes, the non-static member function state_function has an additional first implicit object parameter of type const Test&.

    Now, when we define a std::function object, we specify the function type that is the signature of the callable object that object can represent. When the callable is a member function, the signature’s first parameter represent the (normally implicit) object on which the member function will be called on. Now, there are two ways to specify the signature in case of a member function:

    Method 1

    Here we say that the object on which the member function will be called will be passed as a pointer.

    //----------------------------------vvvvv-------------------------->pointer here means a pointer to the object of type `Test` will be passed
    using func_type = std::function<int(Test* const, const double)>;
    

    This method 1 is what you used in your example. It means that the member function was being called using a pointer to an object of type Test.

    Method 2

    But there is another way of passing the object. In particular, you can sepcify that the object will be passed as a reference as shown below:

    //----------------------------------------vvvvv------------------>note the reference here which says that here an object of type `Test` will be passed instead of a pointer 
    using func_type = std::function<int(const Test&, const double)>;
    

    Note also that for the above to work you will have to modify it->second(this, 0.0); to

    //---------vvvvv-------------->note the * used here to dereference 
    it->second(*this, 0.0);
    

    Demo