Ignoring a return-by-reference result from a function
Asked Answered
F

6

6

Suppose i have a function that returns an important result and several unimportant results. I declared it so that the unimportant results are returned by reference:

int CalculateStuff(int param1, int param2, int& result1, int& result2);

I would like to call this function to calculate some stuff, but at call site i want to ignore the unimportant results. I could do it as follows:

...
int dummy1, dummy2;
int result = CalculateStuff(100, 42, dummy1, dummy2);
... // do something with the result

I would like to consider another way to do the same without declaring dummy variables:

int result = CalculateStuff(100, 42, *new int, *new int);

This has a memory leak (unacceptable), but has an advantage of showing my intent (ignoring the results) more clearly than the "dummy" names.

So, what would happen if i wrote it as follows:

int result = CalculateStuff(100, 42, auto_ptr(new int).get(), auto_ptr(new int).get());

Is it legal? Will the temporary integers still exist when the function's code is executed? Should i use unique_ptr instead of auto_ptr?

(Please don't suggest refactoring my code; i probably will - but first i want to understand how this stuff works)

Frunze answered 17/10, 2011 at 11:56 Comment(1)
Added as a comment as it doesn't actually answer your question - but I usually declare a temporary called _ and pass that if this comes up. "CalculateStuff(100, 42, _, _); seems reasonably clear.Marque
C
4

It is legal; auto_ptr objects will remain alive until the end of expression (i.e. function call). But it is ugly as hell.

Just overload your function:

int CalculateStuff(int param1, int param2, int& result1, int& result2);
int CalculateStuff(int param1, int param2) { 
    int r1=0, r2=0; 
    return CalculateStuff(param1, param2, r1, r2);
}
Cronyism answered 17/10, 2011 at 12:0 Comment(3)
That still begs the same question, how are you going to implement the second overload? Are you going to use dummy variables, or *new int or auto_ptr, or what, so that you could call the first overload from the second?Erny
@Nawaz for example, by creating two temporary variables, or calling some third implementation (e.g. the one with pointers that you suggested).Cronyism
But that is exactly the question.Erny
E
4

According to Bjarne Stroustrup, if some parameters are optional, it is an ideal case for making them pointer type, so that you can pass NULL when you don't need to pass arguments for them:

int CalculateStuff(int param1, int param2, int * result1, int * result2);

And use:

int result = CalculateStuff(100, 42, NULL, NULL);

All other alternatives would not be as good as this one, or at least not better than this.

Of course, the implementation of CalculateStuff has to check the parameters if they're NULL or not.

Erny answered 17/10, 2011 at 12:2 Comment(0)
A
3

A recommended approach if you have control over the function would be: return a std::tuple (or boost::tuple) with all results or write an overload that doesn't need the extra variables.

Amputee answered 17/10, 2011 at 12:0 Comment(0)
A
3

Here is my advice: if you have to ask on SO to figure out the correctness of the code and its semantics, then the code fails at clearly expressing your intent.

I think the first version (with dummy1 and dummy2) is the most transparent, and is obviously correct.

If you find yourself repeatedly calling the function and not wanting the optional results, you could provide an overload:

int CalculateStuff(int param1, int param2, int& result1, int& result2) {}

int CalculateStuff(int param1, int param2) {
  int unwanted1, unwanted2;
  return CalculateStuff(param1, param2, unwanted1, unwanted2);
}
Arriviste answered 17/10, 2011 at 12:2 Comment(0)
N
3

You could make a class that provides implicit (or explicit) conversion to int&.

struct ignored
{
   int n;
   operator int&() { return n; }
};

n = CalculateStuff(a, b, ignored(), ignored());

You can further make this a template and add const overloads.

Niello answered 17/10, 2011 at 12:17 Comment(2)
won't the type of ignored be const and give you trouble?Psychophysiology
@WinstonEwert: Why? A temporary cannot bind to a non-const reference directly. However, one can call non-const methods of a temporary object. That's what this is taking advantage of.Trebizond
C
2

It's legal, but it's not guaranteed not to leak memory, see question 3 here for example.

The correct and idiomatic way of implementing optional output is to pass a pointer, passing NULL when you don't want the results, and testing for NULL in the function before writing through the pointer.

Corlisscorly answered 17/10, 2011 at 13:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.