В последнее время я узнал о лямбдах и указателях функций и хотел использовать их в простой системе обратного вызова. Карта, которая хранит событие и все обратные вызовы, которые должны быть вызваны при его срабатывании, выглядит следующим образом:
std::unordered_map< sf::Event::EventType , std::vector< Callback > > eventMap;
.
Я определил Callback таким образом typedef void(*Callback)(sf::Event const&);
. Моя registerEvent()
функция принимает событие и обратный вызов в качестве аргументов.
registerEvent()
может быть вызван следующим образом:
inputHandler.registerEvent(/*Any event type*/, [](sf::Event const&)
{
//do something
});
Это прекрасно работает, но когда я хочу захватить объект, я получаюошибка компиляции: error: no matching function for call to ‘InputHandler::registerEvent(sf::Event::EventType, Button::Button(ID, Callback, InputHandler&)::<lambda(const sf::Event&)>)’
Код, который выдает эту ошибку, выглядит следующим образом:
class Button
{
//
public:
Button(ID id, Callback callback, InputHandler& inputhandler)
{
inputhandler.registerEvent(sf::Event::MouseButtonPressed, [this](sf::Event const&)
{
{
getTextureRect();
}
});
}
};
Кажется, что захват this
изменяет тип лямбда-выражения, что делает его несовместимым с registerEvent()
функция. Но так как множество разных классов должны иметь возможность создавать такие лямбды, а также лямбды без захвата должны содержаться в векторе, я не знаю, как определить, какого типа должен быть вектор. Я слышал о std::function
, но (это может звучать глупо), я хотел бы использовать способ в стиле C, чтобы лучше понять. Я думаю, что этот пост говорит кое-что об этом, но я не совсем понимаю это хорошо. Я думал о создании двух карт, одна для всех лямбд без захвата и одна для других. Тогда я мог бы позволить каждому классу наследовать от базового класса и сделать тип захвата в векторе указателем на базовый класс, хотя это довольно сложно и добавляет ненужные накладные расходы, и я даже не знаю, сработает ли это. Каково общее решение для подобной ситуации?
Спасибо за все ответы и с наилучшими пожеланиями,
Даниэль Шрайбер Мендес:)
Редактировать:
Обратный вызов теперь выглядит следующим образом: typedef std::function< void(sf::Event const&) > Callback;
И когда я хочу его использовать:
//inside the Button Constructor
inputhandler.registerEvent(sf::Event::MouseButtonPressed, Callback([this](sf::Event const& event)
{
//memberFunc();
}));
Это не дало мне ошибку, но вел себя неправильно. Он действительно выполнял лямбду, но не изменял класс, в котором он был определен. Поэтому я добавил строку в конструктор, которая просто печатает адрес только что созданного объекта. Я создаю только одну кнопку, поэтому должен быть напечатан только один адрес. Но было два разных. Это означает, что при вставке лямбда-выражения, обернутого в std :: function, в вектор создается новый объект Button. Как это может быть? Неявное создание объекта?
Спасибо за ваши ответы:)