Problems with #ifdef AKA Passing differnt parameter types to a function

I'm writing a program where I want to easily switch at compile time between outputting results to the Serial monitor or an LCD.

I hope to use a generic print routine that prints to either Serial and/or LCD depending on something like #define LCD_ENABLE or #define UART_ENABLE in the beginning of the sketch. The problem is how do I pass the multitude of data types .print can have to a single function.
The function would be something like...
Output(string/integer/float, row = 0, column = 0)
and it would print to Serial (ignoring the row/column) and/or LCD using the row/column optional parameters the string/integer/float. The types I expect to pass would be F("string"), unsigned long, int, byte, binary & float number.
Is this an easy thing to do without writing separate programs.

I type this without testing, so there might be an errors in it.

// comment this line out, if you don't want to override the lcd
#define USE_UART

#ifdef USE_UART
#define Output(a) Serial.println(a)
#else
#define Output(a) lcd.print(a)
#endif

This might look simple, but you can extend it a lot, with empty functions, multiple parameters, multi-line macros and so on.

Caltoa:
This might look simple, but you can extend it a lot, with empty functions, multiple parameters, multi-line macros and so on.

Thanks for the idea, just a couple of questions though...
How would I be able to print to both Serial and LCD at same time?
How would I use the example given with extra optional parameters to position cursor for LCD and ignore for serial.
Output(a, row = 0, column = 0)

The number of overloaded methods you're dealing with is actually not that big, and you could easily just created your own overloaded functions that accept the same sets of parameters and calls whichever of the underlying methods you choose to enable.

void Output(char *v, int row, int column)
{
    do LCD output
    do serial output
}

void Output(int v, int row, int column)
{
    do LCD output
    do serial output
}

void Output(float v, int row, int column)
{
    do LCD output
    do serial output
}

etc

If you want to be able to select between serial and/or lcd output at compile time or runtime then you can put the appropriate logic in these wrapper functions to select which of the underlying methods to call.

Thanks for the info. I will hopefully get time to test this out tomorrow.

Using overloading and functions is another approach.

You can drop a few parameters with a macro like this:
#define Output(a,b,c) Serial.prinln(c)

I would not mix the functions with overloading and the macros, select the one you feel most comfortable with.

I decided to go down the overload route as it makes printing to both lcd and serial easier (or so I thought).
Foolishly I left my LCD at work so cannot confirm if data is printing to it but thankfully I still have the serial monitor with me XD
The attached code compiles and displays as expected in the serial monitor and if I rem out '#define isSerial' the code compiles and nothing is displayed in serial monitor as expected (cannot check LCD). The problem is if I rem out the '#define isLCD' I would expect it to not print to the lcd just the serial but it fails to compile with ''Serial' was not declared in this scope' along with a bucket load of other errors.
Any ideas why please.

sketch_mar09a_Print_Overloads.ino (9.28 KB)

Adding #include <Arduino.h> resolves the "Serial is not defined in this scope" message, but you have a lot of other errors that are not possible for us to resolve for you.

PaulS:
Adding #include <Arduino.h> resolves the "Serial is not defined in this scope" message, but you have a lot of other errors that are not possible for us to resolve for you.

Thanks Paul, any idea why the code compiles and works (LCD display not tested yet) until I change line to //#define isLCD and then it falls flat on it's face complaining about stuff that worked fine prior to that? Is it something I'm missing or an arduino funny, hence the you have a lot of other errors that are not possible for us to resolve for you. statement.

Is it something I'm missing or an arduino funny, hence the you have a lot of other errors that are not possible for us to resolve for you. statement.

The Arduino adds stuff to your sketch, like the #include statement. Where it adds it is critical to proper compilation. Adding it yourself forces it to be in a known position.

There are functions that you are calling that are not defined in the code you posted, and calls that do not match the functions you have defined. That was the reason for the note about other errors.

PaulS:
There are functions that you are calling that are not defined in the code you posted, and calls that do not match the functions you have defined. That was the reason for the note about other errors.

I assumed that the #ifdef wrapped code was not included and compiled if the test condition was false. Does this mean the code is still included in the object file no matter what the condition and is removed later when the files are linked (as you can probably guess C++ is not my best language)

The problem is that the Arduino IDE is mucking about with your code before it compiles it, and the implementation is not very good. In particular, the logic to decide where to put the results of its half-baked mucking about is hopelessly naive and routinely puts it in the wrong place resulting in compilation errors not caused by your code or anything you have done wrong.

The solution is to fudge your code to trick the IDE into putting its inserted code into the right place, as PaulS suggested.

No, it doesn't make sense, it's just something you have to put up with if you want to continue using the Arduino IDE. On the plus side, it's free.

The solution is to fudge your code to trick the IDE into putting its inserted code into the right place, as PaulS suggested.

Just in case you are wondering how, add this as the FIRST line of your sketch:

byte meYouDumbIDE;

The IDE will then diddle with your code immediately after that line, which is where you want it to.

You can, using verbose mode during compiling, see where the IDE creates the cpp file it makes from your ino file, and see what that cpp file looks like.

Alternatively, you can (properly) put all your #define statements in a header file that the IDE won't even look in.