2

I am fairly new to C++ and I would like to do the following but can't figure out how.

I want to define a function based on a template with some parameters. Lets say we have f(x)=a*x+b, but the parameters a and b will be passed as parameters.

I would like to define a function create_function(double a, double b) that returns a*x+b with a and b evaluated to whatever the parameters are passed so that I can use another function func( double x ) to evaluate it.

The goal is to just create the function once with given parameters so that it can then be repeatedly called by another routine as just f(x). The real function is much more complex than this but I'll be able to adapt it.

I've been looking at this post and it would be something similar to this but I don't know how to adapt it to returning a function that still depends on x.

Jesús Ros
  • 480
  • 2
  • 6
  • 19

4 Answers4

11

You can do this with lambdas:

auto create_function(double a, double b)
{
  return [a, b](double x) { return a * x + b; };
}

void test()
{
  auto func = create_function(2.0, 3.0);
  double y = func(4.0); // y is now 11
}

Demo (shows that the compiler already knows func(4.0) will always return 11)

Max Langhof
  • 23,383
  • 5
  • 39
  • 72
3

You can do use a lambda function for this purpose:

auto f = [a, b](auto x) { return a * x + b; };

... or, to actually wrap it into a function:

auto create_function(double a, double b) {
    return [=](auto x) { return a * x + b; };
}

Effectively, lambda functions are just a [more] convenient way to create function objects.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
2

You can use std::bind:

#include <functional>
#include <iostream>

double f(double a, double b, double x) { return a * x + b; }

std::function<double(double)> create_function(double a, double b) {
    using std::placeholders::_1;
    return std::bind(f, a, b, _1);
}

int main() {
    auto func(create_function(1, 2));
    std::cout << func(4) << std::endl;
    return 0;
}
Thomas Sablik
  • 16,127
  • 7
  • 34
  • 62
  • 2
    i am on the edge of downvoting, imho since there are lambdas it is only rarely necessary to use `std::bind` anymore. However, maybe its just my personal dislike of `std::bind` ;) – 463035818_is_not_an_ai Aug 20 '18 at 08:20
  • 4
    In the day and age of [tag:c++14], there is no reason to use `std::bind`. It's a fine tool, but for a time when lambda's didn't exist. – StoryTeller - Unslander Monica Aug 20 '18 at 08:20
  • In c++11 bind has some features, that lambdas don't have like moving arguments. I'm currently working with a c++ compiler that doesn't support c++14. With c++14 you don't need bind anymore. – Thomas Sablik Aug 20 '18 at 08:25
2

The goal is to just create the function once with given parameters so that it can then be repeatedly called by another routine as just f(x). The real function is much more complex than this but I'll be able to adapt it.

If you need to store more than one implementation to be called later, consider storing the result in a std::function (otherwise, because each lambda has a unique type, you will be unable to store the function).

I've been looking at this post and it would be something similar to this but I don't know how to adapt it to returning a function that still depends on x.

auto create_function(double a, double b)
{
    return [a, b](double x) { return a*x + b; };
}

client code:

std::function<double(double)> computation = create_function(3., 4.);
double y1 = computation(1.0);
double y2 = computation(2.0);

computation = another_lambda_implementation(/*arguments here*/);
double y3 = computation(2.0);
utnapistim
  • 26,809
  • 3
  • 46
  • 82