gpt4 book ai didi

C++/Arduino 将函数作为参数传递

转载 作者:可可西里 更新时间:2023-11-01 17:53:18 31 4
gpt4 key购买 nike

我正在尝试创建一个回调风格的 API,我对 C++ 还很陌生。我不断收到错误 error: invalid use of non-static member function但我不确定接下来的步骤。我希望能够将成员函数作为参数传递给另一个类。

代码是这样的

class Button {
int buttonDownTime = 0;
int debounceTime = 2000;

...

template<typename Callback>
void debounce(Callback func) {
if (millis() - buttonDownTime > debounceTime) {
func();
}
}
}

class Player {
int playerCount = 0;

void incriment() {
playerCount++;
}
}

void loop() {

...

button.debounce(player.incriment);
}

编辑:

所以我要感谢大家到目前为止的精彩回答,但自发布以来我学到了一些东西。 Arduino 的 AVR 不包括 C++ 的 <functional> .如果没有该库,这是否可行?

再次感谢!

最佳答案

非静态成员函数需要一个对象才能工作,因此不能像普通函数指针那样传递和调用。

让您的debounce 方法工作的最简单方法是使用捕获您的player 对象并对其调用increment 的lambda :

class Button {
//...
template<typename Callback>
void debounce(Callback&& func) { // <<-- Note the && here, without
// it func would need to be
// copied
if (millis() - buttonDownTime > debounceTime) {
func();
}
}
}

void loop() {
//...
button.debounce([&player](){ player.incriment(); });
}

通过一些额外的努力,您可以实现类似于 C++17 的 std::invoke 的东西来统一调用任何类型的可调用对象。由于您使用的是 Arduino,无法访问 C++ 标准库,因此您还需要自己实现 std::remove_referencestd::forward :

template <typename T>
struct remove_reference
{
using type = T;
};

template <typename T>
struct remove_reference<T&>
{
using type = T;
};

template <typename T>
struct remove_reference<T&&>
{
using type = T;
};

template <typename T>
constexpr T&& forward(typename remove_reference<T>::type& t)
{
return static_cast<T&&>(t);
}

template <typename T>
constexpr T&& forward(typename remove_reference<T>::type&& t)
{
return static_cast<T&&>(t);
}

template <typename Callable, typename... Args>
auto invoke(Callable&& func, Args&&... args)
-> decltype(forward<Callable>(func)(forward<Args>(args)...))
{
return forward<Callable>(func)(forward<Args>(args)...);
}

template <typename Callable, typename Class, typename... Args>
auto invoke(Callable&& method, Class&& obj, Args&&... args)
-> decltype((forward<Class>(obj).*method)(forward<Args>(args)...))
{
return (forward<Class>(obj).*method)(forward<Args>(args)...);
}

class Button {
//...
template<typename Callback, typename... Args>
void debounce(Callback&& func, Args&&... args) {
if (millis() - buttonDownTime > debounceTime) {
invoke(forward<Callback>(func),
forward<Args>(args)...);
}
}
}

void loop() {
//...
button.debounce(&Player::increment, player);
}

这并不能完全完成 C++17 的 std::invoke 所做的所有事情,但它已经足够接近以实现一个基本的回调。它还为您提供了额外的灵 active ,因为您可以将额外的参数传递给 debounce,它们将被传递给您的回调:

void foo(int num) { /*...*/ }

void loop() {
Button b;
b.debounce(foo, 42);
}

如果您需要保存回调并稍后调用它,这实际上不起作用,但看起来这并不是您想要做的。

关于C++/Arduino 将函数作为参数传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44638938/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com