Использование лямбд в качестве функций обратного вызова

Используя библиотеку Ticker для ESP32, как я могу использовать лямбду в качестве аргумента метода attach?

tickerSystemManager.attach(1000, [&](){
  systemManager->sync();
});

Пытаясь использовать вышесказанное, я получаю следующую ошибку:

Matrx.cpp:11:4: error: no matching function for call to 'Ticker::attach(int, Matrx::setup()::<lambda()>)'
...
Ticker.h:40:8: note: candidate: void Ticker::attach(float, Ticker::callback_t)

Как я могу вставить лямбду в этот метод?

, 👍1

Обсуждение

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

Итак, что я могу сделать, чтобы вызвать метод _sync_ моего объекта? Кажется, что каждая попытка сделать это дает мне ту или иную ошибку., @Matt Clark

Если SystemManager является глобальным, просто удалите & из захвата., @Mat


1 ответ


Лучший ответ:

3

Как объясняет @timemage в комментарии, вы не можете передать лямбду захвата функции, которая ожидает, что простой указатель будет функционировать. Однако есть выход из этого: класс Ticker обеспечивает перегрузку метода attach (), который позволяет предоставить параметр любого типа для обратного вызова:

template<typename TArg>
void attach(float seconds, void (*callback)(TArg), TArg arg)

Вы можете использовать эту версию attach() и предоставить ее как

  • не захватывающая лямбда,которая получает указатель на SystemManager
  • этот указатель является третьим аргументом.

Edit: я сделал несколько тестов, и кажется, что мой компилятор не может правильно выполнить вывод аргументов шаблона в этом случае, но подход работает , если вы явно специализируете шаблон. А именно:

tickerSystemManager.attach<typeof systemManager>(
    1000,
    [](typeof systemManager p){ p->sync(); },
    systemManager);
,

Вам удалось сделать это по теме. С таким же успехом можно пойти еще дальше и показать перегрузку пользовательских данных в контексте лямбда-выражения., @timemage

@timemage: Хорошее предложение. Я обновил ответ., @Edgar Bonet

Я очень ценю ответ, он скомпилирован и, кажется, работает так, как ожидалось! Я все еще пытаюсь изучить Cpp во время создания проекта ESP, и вы определенно даете мне больше информации!, @Matt Clark