简体   繁体   中英

Pointer to member function using C++ lambda

I'm trying to find a way to provide pointers to a member functions between different class instances. For the moment I'm able to provide pointers to member function that takes no arguments but cannot manage to do so when the function to point to has an argument.

A sample code to illustrate my problem :

#include <iostream>

class Event
{
public:
    std::string type;
    Event(std::string type):type(type){}
};

class EventDispatcherBase
{
public:

    void addEventListener(std::function<void(Event &event)> listener)
    {
        Event myEvent("Type of the myEvent object");
        listener(myEvent);
    }
};

class EventDispatcherClass:public EventDispatcherBase
{
public:
    EventDispatcherClass()
    {
        addEventListener([](Event &event){std::cout << event.type << std::endl;});
        //addEventListener([this]{listener(Event event);});
    };

    void listener(Event &event)
    {
        std::cout << event.type << std::endl;
    }
};

int main()
{
    EventDispatcherClass eventDispatcherClass;

    return 0;
}

This code works with an anonymous lambda expression and output "Type of the myEvent object" in the console. But if I uncomment the line

addEventListener([this]{listener(Event event);});

in the constructor of the EventDispatcherClass in order to transmit a pointer to the void listener(Event &event) member function, the compiler throw the following error :

no viable conversion from '(lambda at .../main.cpp:27:26)' to 'std::function'

I don't understand why.

but cannot manage to do so when the function to point to has an argument.

The lambda should take an argument of type Event& , which will be forwarded to the member function inside the lambda. So change it to

addEventListener([this](Event &event){listener(event);});
//                     ^^^^^^^^^^^^^^

LIVE

The working line:

addEventListener([](Event &event){std::cout << event.type << std::endl;});

looks nothing like the broken one:

//addEventListener([this]{listener(Event event);});

so start by changing the working line bit by bit.

  1. add the capture expression you will want, and it still works

     addEventListener([this](Event &event){std::cout << event.type << std::endl;}); 
  2. change the body to the one you want, and it still works

     addEventListener([this](Event &event){ this->listener(event); }); 

If you're having trouble seeing what's different between the two versions - which is actually pretty common when you wrote them yourself and you're seeing what you intended to type instead of what's there - try changing the layout to line everything up (so you'd see the missing (Event &event) ), or transforming one into the other step-by-step as above, or just replace one with the other and diff the file versions.

just change it to addEventListener(listener);

and make the function itself static as static void listener(Event &event)

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