0

Suppose I have a function like this:

vector<double> compute(const vector<double>& x, vector<double> dx = boost::none) const{
    if (dx)
        dx = getDerivative();
    // do operations on x and return result
}

and I have two use cases for this function, one where I just need the result of the computation, and another where I need the result and the derivative, e.g.:

vector<double> J;
vector<double> y = compute(x);
vector<double> y = compute(x, J);

When I call the second version (passing in J), the values of J are not updated, though dx gets updated inside compute. I would guess this is an issue regarding a pass by reference, but when I update the function signature to vector<double>& dx, I get the following error:

error: cannot bind non-const lvalue reference of type ‘vector<double>&’ to an rvalue of type ‘vector<double>’

Any suggestions how I can tackle this?

varagrawal
  • 2,909
  • 3
  • 26
  • 36

3 Answers3

3

Here, you could use overloading instead of default argument.

From your code, the best approach would be:

vector<double> compute(const vector<double>& x) const
{
    // do operations on x and return result
}

vector<double> compute(const vector<double>& x, vector<double> &dx) const
{
    dx = getDerivative();

    compute(x);
}

Written that way, you avoid useless overhead when you don't need the derivative and still reuse common code.

If some other cases, it might make sense to do it the other way if the extra data is not hard to compute but you want simplest code at the caller site. It would look like:

vector<double> compute(const vector<double>& x, vector<double> &dx) const
{
    dx = getDerivative();

    // do operations on x and return result
}

vector<double> compute(const vector<double>& x) const
{
    vector<double> unused_dx;
    compute(x, unused_dx);        
}

However, it has more overhead as you construct a vector and compute the derivative even though you don't need them. Thus that solution is only appropriate when extra code is negligible.

Phil1970
  • 2,605
  • 2
  • 14
  • 15
0
vector<double> compute(const vector<double>& x, vector<double> *dx = nullptr) const{
    if (dx)
        *dx = getDerivative();
    // do operations on x and return result
}
vector<double> y = compute(x);
vector<double> J;
vector<double> y = compute(x, &J);
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0

Sounds like you want to use a pointer, rather than a reference. For example:

vector<double> compute(const vector<double>& x, vector<double> * const dx = nullptr) const{
    if (dx != nullptr)
        *dx = getDerivative();
    // do operations on x and return result
}

From there, you just need to adjust your calls a little bit:

vector<double> J;
vector<double> y = compute(x);
vector<double> y = compute(x, &J);
//                            ^ Note passing address here.
Karl Nicoll
  • 16,090
  • 3
  • 51
  • 65