Overload operators in a function without writing body 2 times

Viewed 71

Currently, i have this code:

void writeLog(__FlashStringHelper* mes){

  Serial.println(mes);

  if(!logfile){
    logfile = SD.open(logpath,FILE_WRITE);
    if(!logfile) return;
  }

  logfile.write(mes);

}

void writeLog(char* mes){

  Serial.println(mes);

  if(!logfile){
    logfile = SD.open(logpath,FILE_WRITE);
    if(!logfile) return;
  }

  logfile.write(mes);

}

Is there a way to overload a function to accept char* and __FlashStringHelper* without writing the body 2 times?

Thanks!

3 Answers

If you can use templates try this:

template <typename T>
void writeLog(T mes) {

    Serial.println(mes);

    if (!logfile) {
        logfile = SD.open(logpath, FILE_WRITE);
        if (!logfile) return;
    }

    logfile.write(mes);

}

This is pretty much exactly what template functions are for! You need only write one template function in your case, as follows:

template<typename T>
void writeLog(T mes)
{
    Serial.println(mes);
    if (!logfile) {
        logfile = SD.open(logpath, FILE_WRITE);
        if (!logfile) return;
    }
    logfile.write(mes);
}

Then you can call this with an argument of any valid type. If you try to call it with an argument type for which there is no compatible version of the Serial.println or logfile.write calls, then the compiler will give an error. Otherwise, the compiler will generate code for the appropriate real function as and when you make a valid call. Thus, your main could look something like this:

int main()
{
    char text[256];
    writeLog(text); // OK: Compiler will generate the code equivalent to your second function
    __FlashStringHelper fsh;
    writeLog(&fsh); // OK: Compiler will generate the code equivalent to your first function
    int p;
//    writeLog(p);  //Error: No suitable versions of "Serial.println()" and "logfile.write()" with an int parameter
    return 1;
}

EDIT: If you know that all calls to your function will be made using a pointer type as the argument, you could make your template more specific (and thus better detect mis-uses) by specifying the argument as a pointer:

template<typename T>
void writeLog(T* mes)
{
//...

Thanks everyone, i found a solution! There is a class that is shipped with Arduino IDE called String. It supports implicit casts from __FlashStringHelper* and char*.

void writeLog(String mes){

  Serial.println(mes);

  if(!logfile){
    logfile = SD.open(logpath,FILE_WRITE);
    if(!logfile) return;
  }

  logfile.println(mes);

}

writeLog("A string from RAM");
writeLog(F("A string from flash memory"));
Related