Search code examples
c++vectorvariant

Pass either a double or a vector<double>& to a function


I have a function which calculates the first derivative dy/dx for discrete values y(x) stroed as std::vector:

vector<double> CalcDerivative(vector<double>&y, vector<double>&x) {...}

Often the spacing dx is constant so it would be more efficient to pass a double to this function instead of vector<double> as argument x.

I tried to accomplish this with std::variant. The drawback with std::variant is however, that it cannot handle references so the vector x has to be copied while being passed as a variant to the function.

For now I solved the problem by defining two functions with overloaded arguments. But I wonder whether there is a more elegant solution which won't duplicate the code for the two cases (x as double or as vector<double>).


Solution

  • One possible solution might be to define the "worker" function such that it is independent of the "number of passed doubles". For this purpose, std::span is suitable. The exemplary solution might look like:

    std::vector<double> CalcDWorker(
      std::span<const double> y, std::span<const double> x)
    {
      ... // x.size() == 1 indicates uniform spacing
    }
    
    std::vector<double> CalcDerivative(
      const std::vector<double>& y, const std::vector<double>& x)
    {
      return CaclDWorker({y.begin(), y.end()}, {x.begin(), x.end()});
    }
    
    std::vector<double> CalcDerivative(
      const std::vector<double>& y, double x)
    {
      return CaclDWorker({y.begin(), y.end()}, {&x, 1});
    }
    

    It requires C++20, but there are third-party span implementations available also for earlier C++ versions (such as the one provided by Boost).

    Live demo: https://godbolt.org/z/n6adEKWes