Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to call std::transform with a function with multiple arguments

Tags:

c++

Hello I have a function which signature is

std::string f(double x, double param1, double param2, double param3);

I would like to call it on a std::vector xvalues for the parameter x using something like std::transform for a particular value of param1, param2 and param3.

It would be the equivalent of:

double param1(1.);
double param2(1.1);
double param3(1.2);
std::vector<std::string> results();
for (std::vector<double>::const_iterator it = xvalues.begin() ; it != xvalues.end() ; ++xvalues)
{
  results.push_back(f(*it, param1, param2, param3);
}

How can this be done in a more elegant manner ?

Kind regards Tony

like image 561
BlueTrin Avatar asked Nov 15 '10 10:11

BlueTrin


3 Answers

You should look into boost::bind which will allow you, as the name indicates, to 'bind' arguments to your function f :

 std::transform([...], boost::bind(&f, _1, param1, param2, param3));

The result of this bind is an unary function (_1 being a placeholder for the argument which it should be called with) : all other parameters will have fixed values param1, param2, param3.

like image 167
icecrime Avatar answered Oct 20 '22 12:10

icecrime


And for completeness' sake, the C++0x version, or what is all the fuss about lambdas ?

std::transform([...], [=](double i){ return f(i, param1, param2, param3); });
like image 24
Matthieu M. Avatar answered Oct 20 '22 11:10

Matthieu M.


As icecrime suggested boost::bind will be the best option here. However, if you can not use boost for some reason you can always do it with user defined functor like this:

using namespace std;

string f(double x, double param1, double param2, double param3)
{
    return string();
}

struct Caller
{
    Caller(vector<string>& results) : m_res(results)
    {

    }
    void operator()(double x)
    {
        m_res.push_back(f(x, 1.0,2.0,3.0));
    }

private:
    vector<string>& m_res;
};

int main()
{
    vector<double> d;
    vector<string> r;

    d.push_back(1.0);
    d.push_back(2.0);

    Caller c(r);
    for_each(d.begin(), d.end(), c);

}
like image 3
Naveen Avatar answered Oct 20 '22 10:10

Naveen