Nicholas - 10 months ago 64

C++ Question

I attempt to try my snippet of Newton's method on a multivariate function and used

`std::bind`

`std::function`

error: conversion from 'std::_Bind_helper&, int>::type {aka

std::_Bind, int))(double, double,

double)>}' to non-scalar type 'std::function'

requested

What does this error message mean and how should I fix my current code?

`#include <iostream>`

#include<functional>

#include<cmath>

double newton(std::function<double(double)> F, std::function<double(double)> f,

double x=0, int maxiter=1000, double epsilon=0.001)

{

int n = 0;

while((n < maxiter) && (fabs(F(x)) > epsilon))

{

x = x - F(x) / f(x);

n++;

}

return x;

}

// I'd like to fix x and z at 1 and 2 and find root for y

double ftest(double x, double y, double z)

{

return x * x + (y * y - 2 * y - 4) + z * z;

}

// Partial derivative of ftest with regards to y

double ftest1(double y)

{

return 2 * y - 2;

}

int main()

{

using namespace std::placeholders;

std::function<double(double)> F = std::bind(ftest, 1, _2, 2);

std::function<double(double)> f = ftest1;

std::cout << newton(F, f);

return 0;

}

Answer Source

The problem here:

```
std::function<double(double)> F = std::bind(ftest, 1, _2, 2);
```

is that `F`

is a function that takes a single argument of type `double`

, but your bind expression involves `_2`

- which refers to the second argument passed to the function object that `bind()`

returns. That is, the *second* argument. Basically, you're constructing this function object, roughly:

```
struct {
template <class T, class U>
auto operator()(T, U arg) {
return ftest(1, arg, 2);
}
};
```

That object takes two arguments. `std::function<double(double)>`

doesn't allow for that - it requires that your callable allow for a single argument.

The simple fix is to fix the placeholder:

```
std::function<double(double)> F = std::bind(ftest, 1, _1, 2);
```

or, better, just don't use `bind()`

at all and prefer a lambda:

```
std::function<double(double)> F = [](double y) { return ftest(1, y, 2); }
```