13

I use a function which use 2 reference parameters to return values, only one of this value interess me. Is there a proper way to do it in one line.

I'll explain myself with the code

Function code

void Limits (double& min, double &max)
{
    min = MIN;
    max = MAX;
}

using the function

double min;
double unused;

Limits(min, unused);

// using myDouble but not unused

What i would like to write is something like

double min;

Limits(min, double());

I can't find a way without previously properly declare the object. Is there an elegant solution?

I can't modify the function.

Giacogiac
  • 189
  • 1
  • 11
  • In your posted code, you are not calling `Limits` using an object. It's a little unclear where you are calling it from. If it is being called inside another member function of the class, you can just use `this->_min`. I don't understand why you need to worry about using `unused` and calling `Limits`. – R Sahu Nov 18 '14 at 17:01
  • 1
    I corrected the code, this is just example code, I must use this function, I can't modify this function and I don't care about the second parameter, I'm just trying to find an elegant solution – Giacogiac Nov 19 '14 at 08:35

5 Answers5

4

I'm not sure why having to declare an additional variable is a problem. Regardless, if you can't modify the function, make a wrapper:

void MyLimits(double& min) {
  double unused;
  Limits(min, unused);
}

Or you could do something funky like this:

double min;

Limits(min, *std::unique_ptr<double>(new double));
glank
  • 371
  • 2
  • 10
  • The second solution is c++11 only but it answer my question. – Giacogiac Nov 19 '14 at 08:53
  • 1
    Replace `unique_ptr` with `auto_ptr`, and the second solution is also pre-C++11. On the other hand, it is horribly inefficient: dynamically allocating an object only to immediately throw it out. It's also not exception safe if `min` is a more complicated expression which may throw. – James Kanze Nov 19 '14 at 10:05
  • @James Indeed, I do not recommend anyone actually doing this. – glank Nov 19 '14 at 16:58
3

I think, with C++11 and its rvalue references, you can implement the requested one-liner. It reads as follows:

template<class T> T& make_dummy_out(T&& t) { return t; }

Then you can call your Limit function as follows:

double min;
Limits(min, make_dummy_out(double()));

This is safe, because the lifetime of the ad-hoc-created double() will be until the end of the statement, which is after the Limits() call has been completed.

Note, that make_dummy_out() is basically the opposite of std::move(): While std::move() turns an lvalue reference explicitely into an rvalue reference, make_dummy_out() converts an rvalue reference explicitely into an lvalue reference. Of course, you need to declare the template function only once, and then can use it to create dummy output parameters whereever you need it.

Kai Petzke
  • 2,150
  • 21
  • 29
2

What nullable reference. So you're stuck with pointers.

void Limits(double* min, double* max)
{
    if (min) *min = this->min_;
    if (max) *max = this->max_;
}

int min;
Limits(&min, NULL);

I know I know, you're going to say "Pointers Bad!". Pointers are not bad, but if you really don't like it, I suggest looking into boost::optional. Personally, I feel like this unnecessarily adds code complexity.

IdeaHat
  • 7,641
  • 1
  • 22
  • 53
1

The most obvious solution would be to use pointers:

void
Limits( double* min, double* max )
{
    if ( min != nullptr ) {
        *min = myMin;
    }
    if ( max != nullptr ) {
        *max = myMax;
    }
}

//  ...
double min;
Limits( &min, nullptr );

Alternatively, you could just define separate functions:

void Limits( double& min, double& max );
void UpperLimit( double& max );
void LowerLimit( double& min );

EDIT:

Since the orginal poster has since indicated that he cannot modify the function, he should wrap it with one which uses pointers:

void myLimits( double* min, double* max )
{
    double ignore;
    Limits( min == nullptr ? ignore : *min,
            max == nullptr ? ignore : *max );
}
James Kanze
  • 150,581
  • 18
  • 184
  • 329
1

No but you can have a macro that simply do this for you. My following example shows you how to do this.

#define LIMITS(min) do { double unused; Limits(min, unused); } while (0)
...
// Later in your code:
double min;
LIMITS(min);

Note that I added do { ... } while (0) in my macro. This is to create a local scope for the unused variable. You can then use the macro from within the same function.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • @James: you assumes that he can change the way his Limits function is declared. I agree that if it's the case, it could switch over pointer then. But what if such a function is from a library. You have to use an alternative and macro is a good one. This is the way I understood his problem. – Richard Pearson Nov 18 '14 at 19:36
  • Even if the function is from a library, he could wrap it with a function which takes pointers (and passes a reference to a local variable if the pointer is null). – James Kanze Nov 19 '14 at 09:59