我正在尝试创建一个回调样式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);
}
Run Code Online (Sandbox Code Playgroud)
编辑:
所以我想感谢大家到目前为止所有的答案,但是自从发布以来我学到了一些东西.Arduino的AVR不包括C++ <functional>
.没有那个图书馆,这可能是一件事吗?
再次感谢你!
非静态成员函数需要一个对象来工作,因此不能像普通函数指针一样传递和调用。
让你的debounce
方法工作的最简单方法是使用 lambda 来捕获你的player
对象并调用increment
它:
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(); });
}
Run Code Online (Sandbox Code Playgroud)
通过一点额外的努力,您可以实现类似于 C++17 的东西std::invoke
来统一调用任何类型的可调用对象。由于您使用的是 Arduino 并且无法访问 C++ 标准库,因此您还需要std::remove_reference
自己实现std::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);
}
Run Code Online (Sandbox Code Playgroud)
这并不能完全完成 C++17std::invoke
所做的所有事情,但它足以实现基本回调。它还为您提供了额外的灵活性,您可以传递其他参数debounce
,并且它们将传递给您的回调:
void foo(int num) { /*...*/ }
void loop() {
Button b;
b.debounce(foo, 42);
}
Run Code Online (Sandbox Code Playgroud)
如果您需要保存回调并稍后调用它,那么这实际上不起作用,但看起来这并不是您想要做的。
归档时间: |
|
查看次数: |
2965 次 |
最近记录: |