Compilation error: no unique final overrider for 'virtual void Looper::Setup()'

Hello everyone,

I am getting this single error when trying to compile with multi_prop while using saber_Fett263_buttons.h & blaster_BC_buttons.h but I do not know what it means (or how to solve it):

In file included from C:\..\ProffieOS\config\olicomplex1.6.03.3_BT_newerStyles.h:489,
                 from C:\..\ProffieOS\ProffieOS.ino:690:
C:\..\ProffieOS\props\multi_prop.h: In instantiation of 'class MultiProp<SaberFett263Buttons, BlasterBCButtons, Detonator, Jetpack>':
C:\..\ProffieOS\ProffieOS.ino:697:11:   required from here
  697 | PROP_TYPE prop;
      |           ^~~~
C:\..\ProffieOS\props\multi_prop.h:225:7: error: no unique final overrider for 'virtual void Looper::Setup()' in 'MultiProp<SaberFett263Buttons, BlasterBCButtons, Detonator, Jetpack>'
  225 | class MultiProp : public virtual Saber, public virtual Blaster, public virtual Detonator, public virtual Jetpack {
      |       ^~~~~~~~~

exit status 1

Compilation error: no unique final overrider for 'virtual void Looper::Setup()' in 'MultiProp<SaberFett263Buttons, BlasterBCButtons, Detonator, Jetpack,>'

As always, thank you for any help.

Cheers

It means that your inherited Props have more than one Setup(), and you must create an override which decides which one(s) to call.

1 Like

I am getting the same error with dual_prop.h when both props have Setup().

I also found a partial fix for dual_prop.h:

  // This works for saber_BC_buttons.h & blaster_BC_buttons,
  // but it doesn't work for saber_BC_buttons.h & blaster.h because there is no Setup() in blaster.h
  // or for any saber/blaster combination where one or both doesn't have a Setup() function.
  void Setup() override {
    Saber::Setup();
    Blaster::Setup();
  }

But then when I switch one or both props to one (or both) that doesn’t have Setup(), I get these errors:

In file included from C:\..\ProffieOS\config\olicomplex1.6.03.3_BT_newerStyles.h:488,
                 from C:\..\ProffieOS\ProffieOS.ino:690:
C:\..\ProffieOS\props\dual_prop.h: In instantiation of 'void SaberBlasterProp<Saber, Blaster>::Setup() [with Saber = SaberSA22CButtons; Blaster = Blaster]':
C:\..\ProffieOS\props\dual_prop.h:176:8:   required from here
  176 |   void Setup() override {
      |        ^~~~~
C:\..\ProffieOS\props\dual_prop.h:177:17: error: 'virtual void Looper::Setup()' is private within this context
  177 |     Saber::Setup();
      |     ~~~~~~~~~~~~^~
In file included from C:\..\ProffieOS\props\dual_prop.h:57:
C:\..\ProffieOS\props\prop_base.h:71:7: note: declared private here
   71 | class PropBase : CommandParser, Looper, protected SaberBase, public ModeInterface {
      |       ^~~~~~~~
C:\..\ProffieOS\props\dual_prop.h:177:17: error: 'Looper' is not an accessible base of 'SaberBlasterProp<SaberSA22CButtons, Blaster>'
  177 |     Saber::Setup();
      |     ~~~~~~~~~~~~^~
C:\..\ProffieOS\props\dual_prop.h:178:19: error: 'virtual void Looper::Setup()' is private within this context
  178 |     Blaster::Setup();
      |     ~~~~~~~~~~~~~~^~
C:\..\ProffieOS\props\prop_base.h:71:7: note: declared private here
   71 | class PropBase : CommandParser, Looper, protected SaberBase, public ModeInterface {
      |       ^~~~~~~~
C:\..\ProffieOS\props\dual_prop.h:178:19: error: 'Looper' is not an accessible base of 'SaberBlasterProp<SaberSA22CButtons, Blaster>'
  178 |     Blaster::Setup();
      |     ~~~~~~~~~~~~~~^~

exit status 1

Compilation error: 'virtual void Looper::Setup()' is private within this context

So how do I code for “if propX has a Setup(), use propX’s Setup() when propX is in use”

It “who shall not be named” suggested this SFINAE solution:

template <typename T>
struct has_setup {
  template <typename U, void (U::*)() = &U::Setup>
  static constexpr bool check(int) { return true; }

  template <typename>
  static constexpr bool check(...) { return false; }

  static constexpr bool value = check<T>(0);
};

void Setup() override {
  if constexpr (has_setup<Saber>::value && !std::is_base_of<Looper, Saber>::value) {
    Saber::Setup();
  }
  if constexpr (has_setup<Blaster>::value && !std::is_base_of<Looper, Blaster>::value) {
    Blaster::Setup();
  }
}

Is this a hack or an acceptable solution for dual/multi_prop?

Edit: it compiles.

They all have Setup, the problem is that some of them seem to be private.
Try changing the inherit in PropBase to “protected Looper” (line 71 in prop_base.h) and see if that helps.

1 Like

Thank you, yes that solves the problem.