Search code examples
c++overloadingreturn-type

Function return type overloading C++


i've read that you can only overload functions by argument type and not by return type.

Recently i tried to learn how to use the <filesystem>.

Here i found that the current_path(); function has a return type of path, but if you call it like this current_path(path('path/to/a/directory')); it changes your CWD and returns void

QUESTIONS

  • is it possible to do that, or is it just the website that gives false information?
  • if it is possible, how can i do it myself?
  • i'm new in C++ so explain in a way a beginner can understand.

Solution

  • You cannot overload based on return type alone. In a nutshell, the compiler figures out what overload to call based on the arguments. Hence, you cannot distinguish two overloads based only on return type:

    int f() { return 42; }
    double f() { return 3.14; }       // error redeclaration of f()
    
    f();   // calls what function ?!?
    

    When parameter types differ, two overloads can have different return types:

     int g() { return 42; }          // (1)
     double g(int) { return 3.14; }  // (2)
    
     g();  // calls (1)
     g(1); // calls (2)
    

    While vanilla overloading does not let you overload based only on the return type, there is a neat trick that can emulate it. Bear with me.

    The above f overloads cause a compiler error, because they arent a valid overload set (differ only by return type). But we can define two seperate functions:

    int f_int(){ return 42; }    
    double f_double() { return 3.14; }
    

    We can define a type whose purpose is nothing but to be convertible to either an int or a double. During that conversion we can call the respective f_x:

    struct foo {
        operator int() { return f_int(); }
        operator double() { return f_double(); }
    };
    

    Now these two lines:

    int x = foo{};
    double y = foo{};
    

    call f_int or f_double, respectively, based on what we assign it too.

    live demo

    However, take this with a grain of salt. It is rare that you actually need to overload based on return type only. Those two lines can be rather obscure when it isnt clear from context what is happening. Implicit conversions are always a source of confusion. Last but least, it also doesn't go well with "almost always auto".