It's just a failing of the Arduino build process to generate prototypes (function declarations) for functions that have default argument values. There's otherwise nothing wrong with what you're doing. Not in my opinion anyway. The build process sometimes chokes on function or class templates as well. The answer to these sorts of problems is probably that these features are not considered part of the Arduino "language".
Just a reminder: In C++ a function declaration needs to have been seen in order to generate a call to it. A definition will serve as a declaration. In either case, one must have been seen before the call site. Generating declarations where needed is, perhaps, the greater part of what the Arduino build process does that can be said to make the Arduino "language" different from plain C++.
The following were generated by working out of /tmp/default-param with the "input" being default-param.ino, running:
arduino-cli -b arduino:avr:uno build --build-path /tmp/build
and inspecting /tmp/build/sketch/default-param.ino.cpp which I'm calling "output". You can use the same process if you want to see exactly what the build process is doing to your code.
Non-default argument
This input:
void setup() {
func(11);
}
void loop() {}
void func(int xyzzy) {}
generates:
#include <Arduino.h>
#line 1 "/tmp/default-param/default-param.ino"
#line 1 "/tmp/default-param/default-param.ino"
void setup();
#line 4 "/tmp/default-param/default-param.ino"
void loop();
#line 5 "/tmp/default-param/default-param.ino"
void func(int xyzzy);
#line 1 "/tmp/default-param/default-param.ino"
void setup() {
func(11);
}
void loop() {}
void func(int xyzzy) {}
The build process has inserted a valid C++ function declaration prior to the call site, so the compiler is happy.
With default argument
But this input:
void setup() {
func(11);
}
void loop() {}
void func(int xyzzy = 7) {}
generates:
#include <Arduino.h>
#line 1 "/tmp/default-param/default-param.ino"
#line 1 "/tmp/default-param/default-param.ino"
void setup();
#line 4 "/tmp/default-param/default-param.ino"
void loop();
#line 1 "/tmp/default-param/default-param.ino"
void setup() {
func(11);
}
void loop() {}
void func(int xyzzy = 7) {}
No declaration prior to the call site this time, so the compiler is not happy with this generated code.
Build process
The build process is a rather ugly... process... that scrapes the output of the compiler and generated ctags to build include paths and to try to generate forward references for things. Sometimes, it just gets it wrong. I'm not sure what the exact error is in the build process, but it is probably just a failure to match the error caused by calling an undeclared function with its matching entry in the ctags. You can try reading through the build process documentation to make sense of this. Ultimately though, you may have to read the source to arduino-cli/arduino-builder to get to exact cause.
Non-.ino (and non-.pde) files more or less go through the build process unscathed. So, if you really want default arguments, you can make use of and .h file for your function prototype/declaration and a .cpp file for its body and follow the normal rules of C++.
Using your own declaration
You can just make your own declaration for it. Doing so makes it not detect an error on that line.
void func(int xyzzy = 7);
void setup() {
func(11);
}
void loop() {}
void func(int xyzzy) {}
Output:
#include <Arduino.h>
#line 1 "/tmp/default-param/default-param.ino"
void func(int xyzzy = 7);
#line 3 "/tmp/default-param/default-param.ino"
void setup();
#line 6 "/tmp/default-param/default-param.ino"
void loop();
#line 7 "/tmp/default-param/default-param.ino"
void func(int xyzzy);
#line 3 "/tmp/default-param/default-param.ino"
void setup() {
func(11);
}
void loop() {}
void func(int xyzzy) {}
As you can see it generates a proto type for whatever reason. But not one that conflicts with your own.
It is probably better if you want to make use of default arguments to just use headers and .cpp file for those functions that have them so that you're not subject to changes in the ability of arudino-cli/arduino-builder to handle them.