1

In order to explain my problem I used 3 classes: Actions, Triggers, and Combine.

Actions simulates an action function, that is defined externally.

Triggers has that function that needed to be executed.

Combine combines Actions and Triggers.

Now, void combine_funcs() is a member function of Combine class, when the match between Triggers and Actions happen -> passing a function to be executed.

Here void combine_funcs() is show with std::bind, but is was also tested straight foreward.

Error outsput is given below code.

class Actions
{
  typedef void (*cb_func)(uint8_t resaon);

private:
  cb_func exter_func;

public:
  void get_external_func(cb_func func)
  {
    exter_func = func;
  }
  void callAction(uint8_t i)
  {
    exter_func(i);
  }
};

class Triggers
{
public:
  void this_is_external_func(uint8_t i)
  {
    Serial.println(i);
  }
};

class Combine
{
public:
  Actions a;
  Triggers b;

  void combine_funcs()
  {
    a.get_external_func(std::bind(&Triggers::this_is_external_func, this,std::placeholders::_1));
  }
  void loop()
  {
    if (millis() > 10000)
    {
      a.callAction();
    }
  }
};

Combine combo;

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("Start!");
  combo.combine_funcs();
}

void loop()
{
  // put your main code here, to run repeatedly:
  combo.loop();
}

Compilation output:

/Users/guydvir/Dropbox/Arduino/sketch_jul26a/sketch_jul26a.ino: In member function 'void Combine::combine_funcs()':
    sketch_jul26a:36:34: error: cannot convert 'std::_Bind_helper<false, void (Triggers::*)(unsigned char), Combine*, const std::_Placeholder<1>&>::type' to 'Actions::cb_func' {aka 'void (*)(unsigned char)'}
       36 |     a.get_external_func(std::bind(&Triggers::this_is_external_func, this,std::placeholders::_1));
          |                         ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
          |                                  |
          |                                  std::_Bind_helper<false, void (Triggers::*)(unsigned char), Combine*, const std::_Placeholder<1>&>::type
    /Users/guydvir/Dropbox/Arduino/sketch_jul26a/sketch_jul26a.ino:9:34: note:   initializing argument 1 of 'void Actions::get_external_func(Actions::cb_func)'
        9 |   void get_external_func(cb_func func)
          |                          ~~~~~~~~^~~~
    /Users/guydvir/Dropbox/Arduino/sketch_jul26a/sketch_jul26a.ino: In member function 'void Combine::loop()':
    sketch_jul26a:42:20: error: no matching function for call to 'Actions::callAction()'
       42 |       a.callAction();
          |                    ^
    /Users/guydvir/Dropbox/Arduino/sketch_jul26a/sketch_jul26a.ino:13:8: note: candidate: 'void Actions::callAction(uint8_t)'
       13 |   void callAction(uint8_t i)
          |        ^~~~~~~~~~
    /Users/guydvir/Dropbox/Arduino/sketch_jul26a/sketch_jul26a.ino:13:8: note:   candidate expects 1 argument, 0 provided
    exit status 1
    cannot convert 'std::_Bind_helper<false, void (Triggers::*)(unsigned char), Combine*, const std::_Placeholder<1>&>::type' to 'Actions::cb_func' {aka 'void (*)(unsigned char)'}

EDIT_1 : Change Combine class to inherete other classes

class Combine : public Actions, Triggers
{
public:
  void combine_funcs()
  {
    get_external_func(this_is_external_func);
  }
  void loop()
  {
    if (millis() > 10000)
    {
      callAction(13);
    }
  }

yeilds same error:

/Users/guydvir/Dropbox/Arduino/sketch_jul26a/sketch_jul26a.ino: In member function 'void Combine::combine_funcs()':
sketch_jul26a:33:23: error: invalid use of non-static member function 'void Triggers::this_is_external_func(uint8_t)'
   33 |     get_external_func(this_is_external_func);
      |                       ^~~~~~~~~~~~~~~~~~~~~
/Users/guydvir/Dropbox/Arduino/sketch_jul26a/sketch_jul26a.ino:22:8: note: declared here
   22 |   void this_is_external_func(uint8_t i)
      |        ^~~~~~~~~~~~~~~~~~~~~
/Users/guydvir/Dropbox/Arduino/sketch_jul26a/sketch_jul26a.ino: At global scope:
sketch_jul26a:60:6: error: redefinition of 'void setup()'
   60 | void setup()
      |      ^~~~~
/Users/guydvir/Dropbox/Arduino/sketch_jul26a/sketch_jul26a.ino:46:6: note: 'void setup()' previously defined here
   46 | void setup()
      |      ^~~~~
sketch_jul26a:68:6: error: redefinition of 'void loop()'
   68 | void loop()
      |      ^~~~
/Users/guydvir/Dropbox/Arduino/sketch_jul26a/sketch_jul26a.ino:54:6: note: 'void loop()' previously defined here
   54 | void loop()
      |      ^~~~
exit status 1
invalid use of non-static member function 'void Triggers::this_is_external_func(uint8_t)'

};
16
  • Does this Q+A help? stackoverflow.com/a/72450270/10292145
    – VE7JRO
    Commented Jul 28, 2022 at 19:09
  • @VE7JRO can you explain why do I need a void* ?
    – guyd
    Commented Jul 28, 2022 at 19:17
  • why not set the object as a parameter?
    – Juraj
    Commented Jul 28, 2022 at 19:44
  • 1
    Why not using class inheritance, for example, class Combine public Action {}? However, solution aside, don't create classes for the sake of creating classes, all three of your classes are not necessary or should belong to somewhere else as methods.
    – hcheung
    Commented Jul 28, 2022 at 23:51
  • 1
    I changed your sketch with auto f = std:bind.... and a.get_external_func(f); and the error message is a little clearer.
    – Juraj
    Commented Jul 29, 2022 at 13:05

1 Answer 1

1

The problem is, that the return type of bind is not the same type as the type of the original function so you can't set it with void get_external_func(cb_func func).

But it looks like in X->Y problem. If you do OOP, use objects.

I take the sketch in the question as a test so I want comment on other parts and how to do them properly. I just made minimal changes to pass the object and call the method (member function) with the object.


class Triggers
{
public:
  void func(uint8_t i)
  {
    Serial.println(i);
  }
};

class Actions
{
  Triggers* trigers;
  
public:
  void set_triggers(Triggers* t)
  {
    trigers = t;
  }
  
  virtual void callAction(uint8_t i)
  {
    trigers->func(i);
  }
};

class Combine
{
public:
  Actions a;
  Triggers b;

  void combine_funcs()
  {
    a.set_triggers(&b);
  }
  void loop()
  {
    if (millis() < 10000)
    {
      a.callAction(1);
    }
  }
};

Combine combo;

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("Start!");
  combo.combine_funcs();
}

void loop()
{
  // put your main code here, to run repeatedly:
  combo.loop();
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.