Function Overloading

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;
}

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.