Function overloading is a powerful and useful technique for simplifying your code. It does have a few pitfalls though. Here are a few examples.
The Constness of Pointers
This is a perfectly valid overload because a pointer and a pointer to const are different types. It will compile and run just fine. The same applies to references.
int max(int* a, int* b) {
return (*a > *b) ? *a : *b;
}
int max(const int* a, const int* b) {
return (*a > *b) ? *a : *b;
}
int main() {
int x {5};
int y {10};
int m = max(&x, &y);
return 0;
}
However, the “constness” of pointers in function parameters does not affect the type of the parameter, therefore, it is not a valid overload. These will be seen as the same and give an compiler error when built.
int max(int* a, int* b) {
return (*a > *b) ? *a : *b;
}
int max(int* const a, int* const b) {
return (*a > *b) ? *a : *b;
}
int main() {
int x {5};
int y {10};
int m = max(&x, &y);
return 0;
error: redefinition of ‘int max(int*, int*)’
The sameness of default parameters
You need to be careful when overloading with default parameters. It is perfectly valid to have two functions overloaded with default parameters but the example won’t compile.
#include <iostream>
int max(int a = 10, int b = 12.0) {
std::cout << "(int, int) overload called" << std::endl;
return (a > b) ? a : b;
}
double max(double a = 10.0, double b = 12.0) {
std::cout << "(double, double) overload called" << std::endl;
return (a > b) ? a : b;
}
int main() {
auto m = max();
return 0;
}
error: call of overloaded ‘max()’ is ambiguous
The surprising thing about references
The following code has valid function overloading and as such, it will compile and run. The runtime behaviour is a little surprising though. The overload called is (double, double). This is because when passing arguments by reference with implicit conversion, a copy of the argument is made and that is passed. Therefore you can’t pass by reference when implicit conversion happens. The solution to this issue is mark you reference parameters as const.
#include <iostream>
#include <string>
double max(double a, double b){
std::cout<< "(double, double) max called" << std::endl;
return (a > b) ? a : b;
}
int& max(int& a, int& b){
std::cout << "(int, int) max called" << std::endl;
return (a > b) ? a : b;
}
int main(){
char a{6};
char b{9};
auto result = max(a,b);
return 0;
}