1

In the following code:

#include "Simple_window.h"
#include "Graph.h"

int fac(int n) // factorial(n); n!
{
    int r = 1;
    while(n>1) {
        r *= n;
        --n;
    }
    return r;
}

double term(double x,int n) { return pow(x,n)/fac(n); }

double expe(double x,int n) // sum of n terms for x
{
    double sum = 0;
    for(int i = 0; i<n; ++i) sum += term(x,i);
    return sum;
}

int main() {
    Simple_window win {Point{100,100},xmax,ymax,""};

    for(int n = 0; n<50; ++n) {
        ostringstream ss;
        ss << "exp approximation; n==" << n;
        win.set_label(ss.str());
        // get next approximation:
        Function e {[n](double x) { return expe(x,n); },
            -10,10,Point{300,300},200,30,30; // ***this line doesn't compile***
        win.attach(e);
        win.wait_for_button();
        win.detach(e);
    }
}

From the book "Principles and Practice using C++" by Stroustrup, the local variable n isn't taken when I try to compile it, and gives the error message:

No instance of the constructor Graph_lib::Function::Function coincides with the argument list

What is the problem?

By the way, the support code used for the books is https://web.archive.org/web/20191217104940/http://www.stroustrup.com/Programming/PPP2code

gian_
  • 95
  • 6
  • What is a `Function`? You appear to be asking about lambda argument capture in the title, yet your error and the line you point to have nothing to do with the argument capture of the lambda. Can you [edit] your question and clarify? Feel free to delete all tags except [tag:c++] as it's the only relevant one – Tas Aug 11 '20 at 05:26
  • @Tas the error is in the line I indicated in the first argument for the constructor of the Function e, and if I omit the local variable n in the lambda expression then the code compiles without complaint. – gian_ Aug 11 '20 at 14:04

1 Answers1

1

Your post is not close to a Minimal Reproducible Example

Here is an example for Minimal Reproducible Example.

In Graph.h Function takes a variable of Fct. Where Fct is typedef double Fct(double);.

According to this post, lambda expression doesn't translate to function automatically, unless it doesn't create closure object by capturing nothing.

Check this example

typedef double Fct ( double );

typedef double bct ( double, int );

struct Foo{
    Foo( Fct f ){};
};

struct bar{
    bar( bct f){};
};


int main(){
    int n(1);
    Foo f{ [](double x){ return x; } };
    //Foo f{ [n](double x){ return x*n; } };  // <=== this won't compile

    bar b{[](double x, int n){return x*n;}};

}

To pass the n into function f without closure, you may

  1. Change signature from typedef double Fct ( double ); to typedef double Fct ( double, int ); Like my example of bar

  2. Write a function with a constant n.

  3. (Strongly not suggested, unless you never maintain the code ) Global variable to make it possible to change n outside the function.

Louis Go
  • 2,213
  • 2
  • 16
  • 29
  • Thanks for the link. There is any way to still make the code work using the lambda expression or a bigger change to the definition of Function would be required to make it work together? I ask because at this point of the book the concept of lambda expressions taking local variables is briefly introduced only with the purpose of solving the problem that arises from the fact the first argument of the Function constructor requires a mathematical function of only one double argument instead of the two that expe(double,int) actually has. – gian_ Aug 11 '20 at 14:17
  • Also, I must add that after reading the sample code that comes with the book, I'm surprised to see that the solution is different. It doesn't use lambda expressions, and instead uses the global variable solution that appears mentioned in the link you provided. I believe that this implies that there must be a mistake in what it is explained in the book, but as I said above I still wonder if there is any way to bypass the problem and make the code work. – gian_ Aug 11 '20 at 14:33
  • @gian_ There are multiple ways. 1. Most common way: changing `Fct`'s signature to take `x` and `n` 2. Global variable, but not suggested because it would shoot in your foot one day. Because global variables imply [bad smell](https://stackoverflow.com/a/19158418/4123703). – Louis Go Aug 11 '20 at 23:56
  • @gian_ I read your edit version but it's not enough to be a minimum reproducible example, because the code includes multiple _non-standard_ headers "Simple_window.h" "Graph.h". You may learn to read headers and reduce your code. Your final question would be smilar to my posted code. – Louis Go Aug 12 '20 at 00:00
  • @Louis Go : when I try to compile your code I get this error: undefined reference to `Foo::Foo(double (*)(double))' – Theodore May 24 '21 at 13:03
  • 1
    @Theodore Hi, I'm not sure why it was compiled but I fixed it with adding body to ctor of `Foo` – Louis Go May 25 '21 at 02:44
  • @Louis Go: thanks! now it compiles, but when I change to your solution 1 with typedef double Fct ( double, int ); and Foo f{ [n](double x){ return x*n; } }; still doesn't compile - I get this: no instance of constructor "Foo::Foo" matches the argument list -- argument types are: (lambda []double (double x)->double) – Theodore May 25 '21 at 07:55
  • @Louis Go: thanks Louis, this works, but how to do it if you want to use the n from the capture list - [n]? – Theodore May 26 '21 at 11:07
  • 1
    @Theodore According to this [post](https://stackoverflow.com/a/45565056/4123703), lambda expression doesn't translate to function automatically, unless it doesn't create closure object by capturing nothing. – Louis Go May 27 '21 at 01:24