Указатель на функцию-член с использованием C ++ лямбда - PullRequest
2 голосов
/ 28 мая 2019

Я пытаюсь найти способ предоставления указателей на функции-члены между различными экземплярами классов.На данный момент я могу предоставить указатели на функцию-член, которая не принимает аргументов, но не может это сделать, когда у функции, на которую указывает указатель, есть аргумент.

Пример кода, иллюстрирующий мою проблему:

#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;
}

Этот код работает с анонимным лямбда-выражением и выводит «Тип объекта myEvent» в консоли.Но если я раскомментирую строку

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

в конструкторе EventDispatcherClass для передачи указателя на функцию-член void listener(Event &event), компилятор выдаст следующую ошибку:

нет жизнеспособного преобразования из '(лямбда в ... / main.cpp: 27: 26)' в 'std :: function'

Я не понимаю, почему.

Ответы [ 3 ]

4 голосов
/ 28 мая 2019

, но не может сделать это, когда у функции, на которую указывает указатель, есть аргумент.

Лямбда должна принимать аргумент типа Event&, который будет перенаправлен функции-члену внутри лямбды. Так что измените его на

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

ЖИТЬ

3 голосов
/ 28 мая 2019

Рабочая строка:

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

не похожа на ломаную:

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

, поэтому начните с изменения рабочей строки по битам.

  1. добавьте выражение захвата, которое вам нужно, и оно все еще работает

    addEventListener([this](Event &event){std::cout << event.type << std::endl;});
    
  2. измените тело на то, что вы хотите, и оно все еще работаетработает

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

Если у вас возникли проблемы с различием между двумя версиями - что довольно часто встречается, когда вы пишете их сами и видите, что вы намеревался печатать вместо того, что там есть - попробуйте изменить раскладку, чтобы выстроить все в ряд (чтобы вы увидели недостающий (Event &event)), или преобразовать один в другой шаг за шагом, как указано выше, или просто заменить одинс другой и отличайтесь от версии файла.

0 голосов
/ 28 мая 2019

просто измените его на addEventListener(listener);

и сделайте саму функцию статической как static void listener(Event &event)

...