C ++ / Arduino Passing a function as an argument

I am trying to create a callback style API and quite new to C ++. I keep getting the error error: invalid use of non-static member function, but not sure about the next steps. I would like to be able to pass a member function as an argument to another class.

The code is similar to

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

EDIT:

So, I want to thank everyone for the amazing answers, but I have learned something from the time of publication. Arduino AVR does not include C ++ <functional>. Is it possible to do this without this library?

Thanks again!

+4
source share
4 answers

std::bind. () - this. std::bind, - , this "", .

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

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

class Player {
  int playerCount = 0;
public:
  void incriment() {
    playerCount++;
  }
}

void loop() {

    ...
    Player player;
    button.debounce( std::bind( &Player::incriment, &player ) );
}

Coliru.

+2

- , , .

debounce - , 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(); });
}

++ 17 std::invoke . Arduino ++, 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);
}

, ++ 17 std::invoke, , . , debounce, :

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

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

, , , .

+1

++ (Player) , . , , Boost ( ), ( ).

, .

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

  public:
  template<typename CallbackClass>
  void debounce(CallbackClass* po) {
    if (millis() - buttonDownTime > debounceTime) {
      po->increment();
    }
  }
};

class Player {
  int playerCount = 0;

  public:
  void increment() {
    playerCount++;
  }
};

int main() {
  Button button;
  Player player;
  button.debounce(&player);
}
+1

- pure virtual func(), debounce() func().

class YourInterface {
public:
  virtual void func() = 0;
};

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

  ...

  void debounce(YourInterface yourInterface) {
    if (millis() - buttonDownTime > debounceTime) {
      yourInterface->func();
    }
  }
}

class Player {
public:
  int playerCount = 0;

  void increment() {
    playerCount++;
  }
}

void loop() {

  ...

  button.debounce(player.increment);
}
+1

Source: https://habr.com/ru/post/1679669/


All Articles