Use a function argument to call a different class member

I am attempting to add a new argument to a function that allows for me to change the class member that is being called.

I have a project that uses five different OLED displays, and the pack I bought included displays with mixed controllers (SSD1306 and SH1106). They displays still function, but when running it on the wrong driver I get some slight graphical errors.

I am using these two constructors from the U8G2 library and would like to be able to call either SSD1306 or SH1106 in the function argument, currently my function works and performs like this:

U8G2_SSD1306_128X64_NONAME_F_HW_I2C SSD1306(U8G2_R0, U8X8_PIN_NONE , SCL, SDA);
U8G2_SH1106_128X64_NONAME_F_HW_I2C SH1106(U8G2_R0, U8X8_PIN_NONE , SCL, SDA);

//more code//

//oled select channel, select data, select rotation, select frequency update in ms
void panel::oled(int i, float data, int freq,  int rotate)
{
  unsigned long currms = millis();
  if (currms - prevms[i] >= freq)
  {
    ch(i);
    SSD1306.clearBuffer();
    SSD1306.setCursor(0, 5);
    if (rotate == 90)
    {
      SSD1306.setDisplayRotation(U8G2_R1);
    }
    else if (rotate == 180)
    {
      SSD1306.setDisplayRotation(U8G2_R2);
    }
    else if (rotate == 270)
    {
      SSD1306.setDisplayRotation(U8G2_R3);
    }
    else
    {
      SSD1306.setDisplayRotation(U8G2_R0);
    }
    if (data >= 0.00 && data <= 9.99)
    {
      SSD1306.print(data, 2);
    }
    else if (data >= 10.0 && data <= 99.9)
    {
      SSD1306.print(data, 1);
    }
    else if (data >= 100 && data <= 999)
    {
      SSD1306.print(data, 0);
    }
    else if (data > 999)
    {
      SSD1306.drawStr(0, 5, "O/L");
    }
    else
    {
      SSD1306.print(data, 1);
      //SSD1306.drawStr(0, 5, "U/L");
    }
    SSD1306.sendBuffer();
    prevms[i] = currms;
  }
}

I would like to have the function work something like this where I can choose the SH1106 or SSD1306 drivers to be run when the function is called, otherwise it seems I would need an duplicate function strictly for the different driver.

void panel::oled(int i, float data, int freq,  int rotate, int driver)
{
  unsigned long currms = millis();
  if (currms - prevms[i] >= freq)
  {
    ch(i);
    driver.clearBuffer();
    driver.setCursor(0, 5);
    if (rotate == 90)
    {
      driver.setDisplayRotation(U8G2_R1);
    }

Attempting to add something like that results in an error:

" request for member 'clearBuffer' in 'driver', which is of non-class type 'int' "

Is there a way I can cheese around this with a #define or something?

Actually SSD1306 and SH1106 are class instances. Class members would be: clearBuffer() and setCursor().

It is possible to pass in a multiple class instance's using a reference;

void someFunction (className &var)

Unfortunately SSD1306 and SH1106 are from 2 different classes(in the same library) so this will not work in this case.

So I believe that function overloading(your duplicate function) is your only choice.
but this will at least bump you back to the top in case someone else knows better than I (most do ::slight_smile: ).

Maybe a template<>. On phone now, can't type example.

You didn't bother to tell us anything about the "panel" class. So, I'm assuming you can modify it as required. I'm not that experienced using templates, but this compiles and works as intended.

You can use it as a template (pun intended) and adapt for your applicant.

class panel {
  public:
  template <class T>
  void callPrint(T &anObject) {
    anObject.printName();
  }
};

class ClassA {
  public:
  void printName() {
    Serial.println("ClassA-type Object");
  }
};

class ClassB {
  public:
  void printName() {
    Serial.println("ClassB-type Object");
  }
};

panel panelObject;
ClassA objectA;
ClassB objectB;

void setup() {
  Serial.begin(115200);
  delay(1000);

  panelObject.callPrint(objectA);
  panelObject.callPrint(objectB);
}

void loop() {}