简体   繁体   中英

How to use std::bind with none static member function?

I'm trying to learn some basic c++11 concepts by implementing some well known design patterns. Currently I'm stuck at Callables while trying to implement the new Angular2 EventEmitter Pattern in C++. So here is the code if the comment stays all is ok:

class Controller {

public:

Controller() {
    const pattern::EventEmitter<SwitchEvent> listner;
    listner.subscribe([this](const SwitchEvent& event) {
        if(event.get_state()) {
            this->_count++;
            std::cout << "count: " << this->_count << std::endl;
        }
    });
    //listner.subscribe(std::bind(&Controller::track, this));
}

private:

int _count = 0;

void track(const SwitchEvent& event) {
    if(!event.get_state()) {
        this->_count++;
        std::cout << "count: " << this->_count << std::endl;
    }
}

};

and the output is as expected:

$ g++ -std=c++11 -Wall test.cc
$ ./a.out 
count: 1 

But when I remove the comment I get an Error:

test.cc: In constructor ‘Controller::Controller()’:
test.cc:50:62: error: no matching function for call to ‘pattern::EventEmitter<SwitchEvent>::subscribe(std::_Bind_helper<false, void (Controller::*)(const SwitchEvent&), Controller*>::type) const’
     listner.subscribe(std::bind(&Controller::track, this));
                                                          ^
test.cc:50:62: note: candidate is:
In file included from test.cc:1:0:
EventEmitter.hh:16:6: note: void pattern::EventEmitter<T>::subscribe(const std::function<void(const T&)>&) const [with T = SwitchEvent]
void subscribe(const std::function<void(const T&)>& listener) const {
  ^
EventEmitter.hh:16:6: note:   no known conversion for argument 1 from ‘std::_Bind_helper<false, void (Controller::*)(const SwitchEvent&), Controller*>::type {aka std::_Bind<std::_Mem_fn<void (Controller::*)(const SwitchEvent&)>(Controller*)>}’ to ‘const std::function<void(const SwitchEvent&)>&’

You need to provide bind a placeholder so it knows that it takes an argument:

listner.subscribe(std::bind(&Controller::track, this, std::placeholders::_1));

Otherwise, it will give you a nullary function object, which you cannot construct your std::function with.

You need to pass through the "second" argument to track() , which is the event. The first argument you bind to this , but the second is missing. So you need something like this:

using namespace std::placeholders;
listner.subscribe(std::bind(&Controller::track, this, _1));

Since you tagged it as C++11 then you would be better of using a lambda:

listner.subscribe([this](const SwitchEvent& event) {
  if(!event.get_state()) {
    _count++;
    std::cout << "count: " << _count << std::endl;
}});

Otherwise use a placeholder for the track parameter, event :

listner.subscribe(std::bind(&Controller::track, this, std::placeholders::_1));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM