Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I add an output parameter to a function without breaking existing code?

I am assuming that the function already has a return value so that cannot be added.

What I came up with to solve this problem is to add extra pointer parameters which default to nullptr.

Before:

bool fun(double a, std::vector<std::randomexample> const & b)

After:

bool fun(double a, std::vector<std::randomexample> const & b, int* extraoutput = nullptr)

and use it like this

if(extraoutput)
  *extraoutput = whatever;

But that's just what I came up with. I would like to know if there is a better way to do this. Note that "whatever" is already in the function.

like image 211
Sarien Avatar asked Nov 08 '12 17:11

Sarien


2 Answers

If for some reason you need binary as well as (mostly) source compatibility[*]:

Before:

bool fun(double a, std::vector<std::randomexample> const & b) {
    // do stuff
    return true;
}

After:

bool fun(double a, std::vector<std::randomexample> const & b, int* extraoutput) {
    // do stuff
    if(extraoutput)
        *extraoutput = whatever;
    return true;
}
bool fun(double a, std::vector<std::randomexample> const & b) {
    return fun(a, b, nullptr);
}

If you don't want function overloading (for example if fun is part of an extern "C" interface), then you don't actually have to call the new function fun. It could just as well be fun2.

[*] As AndreyT points out, the source compatibility of your solution is limited. Calls to your old function will call your new function fine, but some other things that you might do with the old function will not work fine (since you have changed its type).

There's actually a source incompatibility in my code too. void(*foo)() = (void(*)()) fun; is allowed before the overload is added, but afterwards it's ambiguous. If you want to support code that does that, then that's a second reason not to want function overloading.

like image 74
Steve Jessop Avatar answered Sep 30 '22 17:09

Steve Jessop


Normally, I add a method with the extra parameter, and call that one with a default value from the former method:

//foo v1
void foo( S s ) {
   ... stuff with s;
};

//codeA_v1:
S s;
foo(s);

//codeB_v1
S s2;
foo(s2);

Then, I add a method with an extra parameter:

void foo(S s){ foo(s, default_value_for_T); }
void foo(S s, T t){
   ... stuff with s and t
}

//codeA_v1 == codeA_v2
S s;
foo(s);

//codeB_v2
S s;
T t;
foo(s,t);
like image 33
xtofl Avatar answered Sep 30 '22 17:09

xtofl