0

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?

user438383
  • 5,716
  • 8
  • 28
  • 43
tanghz
  • 13
  • 2
  • 3
    It is difficult to answer your question without knowing what you already know. Do you know what `std::function` is, why it is needed, how it is different from say a function pointer etc? – n. m. could be an AI Jun 13 '22 at 06:27
  • `std::bind` is unnecessary, you can insert `&Test::state_function` directly. – HolyBlackCat Jun 13 '22 at 06:46
  • you can write a functor that encapsulates a member function pointer and has an operator `()` that when called uses the `Test*` passed to its operator `()` to call the member function. Thats what `std::function` is in a nutshell, and much more – 463035818_is_not_an_ai Jun 13 '22 at 08:06
  • why not? Please try to be more specific about what you do not understand – 463035818_is_not_an_ai Jun 13 '22 at 08:09
  • func_type has two parameters, and Test::state_function only has one parameter,I can't understand how it works. – tanghz Jun 13 '22 at 10:44
  • Part of the confusion might be because you're mixing `std::bind` and `std::function`. The `std::bind` clearly states that it creates a function with two arguments, `_1` and `_2`. That matches the number expected by `std::function`. The surprise really is that you can use `_2` when binding `&Test::state_function` – MSalters Jun 13 '22 at 11:21
  • Does this answer your question? [How std::bind works with member functions](https://stackoverflow.com/questions/37636373/how-stdbind-works-with-member-functions) – JaMiT Jun 13 '22 at 14:01

1 Answers1

2

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

Jason
  • 36,170
  • 5
  • 26
  • 60
  • "For the purposes of overload resolution" - there's no overload resolution here. I know where the quote comes from: for purposes of overload resolution, even **static** functions have an implicit argument. But for **binding purposes**, only non-static members have such an implicit parameter. – MSalters Jun 13 '22 at 11:18
  • @MSalters Yeah, for overload resolution purposes both static and non-static member functions have implicit object parameter as i quoted [here](https://stackoverflow.com/a/72486959/12002570). I have updated my answer to say for binding purpose instead of overload resolution. – Jason Jun 13 '22 at 11:24