AlexTemina
AlexTemina

Reputation: 159

Best way of calling a function with different arguments passed by reference when you only need one of these arguments

this is a simple question:

If I have to call a method like this, for instance:

void getBounds(float &xmin, float &ymin, float &zmin,
             float &xmax, float &ymax, float &zmax)

What is the proper way to call the method, if I just need the information stored in xmax? I don't want to create variables that I'm not going to use.

Is there a way to do this? Let's say that the incorrect way of doing what I want would be something like:

float xmax;
getBounds(nullptr, nullptr, nullptr, xmax, nullptr, nullptr);

Now I'm using dummy-trash variables, but maybe there is another way.

Thanks in advance.

EDIT: Sorry, I forgot to mention that I cannot edit the method, is from a third-party library.

Upvotes: 4

Views: 285

Answers (6)

Tomek
Tomek

Reputation: 4659

If you can rewrite getBounds and can use C++11 consider using tuple, tie and ignore:

std::tuple<float, float, float, float, float, float> getBounds()
{
  std::tuple<float, float, float, float, float, float> r;
  :
  std::get<3>(r) = ...;
  :
  return(r);
}
:
float xmax;
std::tie(std::ignore, std::ignore, std::ignore, xmax, std::ignore, std::ignore> = getBounds();

--EDIT--

As you cannot change it you may overload it. Parameterless version would just wrap around the original one, pack everything in a tuple and return it.

Upvotes: 0

Ralph Tandetzky
Ralph Tandetzky

Reputation: 23650

If you wrote that method, just change the function's signature to

void getBounds( float*, float*, float*, float*, float*, float* )

so that you can pass nullptrs if you want to ignore a parameter. Otherwise you might want to write a wrapper function.

void getBounds( float*a, float*b, float*c, float*d, float*e, float*f )
{
    float dummy;
    getBounds( 
        a ? *a : dummy, 
        b ? *b : dummy, 
        c ? *c : dummy, 
        d ? *d : dummy, 
        e ? *e : dummy, 
        f ? *f : dummy );
}

If your situation doesn't occur regularly then another way of handling this could be to write

float xmax; // in outer scope
{
    float dummy; // in inner scope. Will be thrown away afterwards
    getBounds( dummy, dummy, dummy, xmax, dummy, dummy );
}

so you don't litter your scope.

I would prefer the first variant.

Upvotes: 0

Alexis
Alexis

Reputation: 2179

You can't send nullptr if the function is waiting for a reference

But if you change your function signature for a pointer the you can go for something like: void getBounds(float *xmax, float *xmin = nullptr, float *ymin = nullptr, float *zmin = nullptr, float *ymax = nullptr, float *zmax = nullptr) { }

and call it: getBounds( &xmax); but then you must check in your function if the variable is nullptr or no

but as said in the comment it will only work in one case

Upvotes: 0

Bathsheba
Bathsheba

Reputation: 234865

Acknowledge to Mats Petersson: you can't pass nullptr as the function requires references.

If the function has no warranty attached to it, then you should create temporary variables and pass them all in. It would be unsafe to pass the same variable; in case it's used in internal computation.

Even if the function works with the same variable passed, there is no guarantee that someone won't change the implementation of that function in a way that causes your code to break. You could be opening yourself up to nasty bugs in the future.

Upvotes: 0

James Kanze
James Kanze

Reputation: 154027

Can you modify getBounds or not? If you can, and calculating each of the values is expensive, it might be worth changing it to pass pointers, and only do the relevant calculation if the pointer is non-null. Otherwise, you'll need to pass an lvalue (variable) to each. And theoretically, if you pass the same variable to more than one argument, you could get undefined behavior in the function (say because the function starts with something along the lines of xmin = ymin = 0.0;).

Finally, unless the calculation of each value is expensive, and the function skips it if it gets a null pointer, creating and passing the extra variables is unlikely to have any impact on performance.

Upvotes: 2

Mats Petersson
Mats Petersson

Reputation: 129524

Something like:

float dummy;
float xmax;

getBounds(dummy, dummy, dummy, xmax, dummy, dummy);

This will only create one variable on the stack, thus saving space - creating more of them won't have any side-effect other than taking up another 4 bytes each [assuming "nornal" sized floats, standard does not specify exact size of float] - it takes the same amount of time to create one or five (or a hundred) stack based, uninitialized variables.

Using pointers would allow you to pass in a nullptr, however, that will also add an extra check in the getBounds, so

void getBounds(....)
{
    xmin = the_getXmin_function();
    ...
}

becomes:

void getBounds(....)
{
    if (xmin != nullptr)
        *xmin = the_getXmin_function();
    ...
}

assuming the_getXmin_function is trivial, this will slow the code down. If the function is complex, then having an if, and "I don't want this" option would help performance quite a bit.

Upvotes: 1

Related Questions