C++'s evaluation strategy for function arguments is always "eager" and usually "by value". The short version of what that means is, a composed function call sequence such as
x = a(b(c(1)));
is exactly the same as
{
auto t0 = c(1);
auto t1 = b(t0);
x = a(t1);
}
(auto t0
means "give t0
whatever type is most appropriate"; it is a relatively new feature and may not work in your C++ compiler. The curly braces indicate that the temporary variables t0
and t1
are destroyed after the assignment to x
.)
I bring this up because you keep talking about functions "taking functions as input". There are programming languages, such as R, where writing a(b(1))
would pass the expression b(1)
to a
, and only actually call b
when a
asked for the expression to be evaluated. I thought MATLAB was not like that, but I could be wrong. Regardless, C++ is definitely not like that. In C++, a(b(1))
first evaluates b(1)
and then passes the result of that evaluation to a
; a
has no way of finding out that the result came from a call to b
. The only case in C++ that is correctly described as "a function taking another function as input" would correspond to your example using feval
.
Now: The most direct translation of the MATLAB code you've shown is
#include <stdio.h>
static double a(double x) { return 2*x; }
static double b(double y) { return 3*y; }
static double c(double p, double q) { return a(p) * b(q); }
static double d(double r) { return a(b(r)); }
static double f1(double (*arg1)(double))
{ return arg1(2.0); }
int main()
{
printf("%g\n", a(b(1))); // prints 6
printf("%g\n", c(1,2)); // prints 12
printf("%g\n", d(1)); // prints 6
printf("%g\n", f1(d)); // prints 12
printf("%g\n", f1(a)); // prints 4
return 0;
}
(C++ has no need for explicit syntax like feval
, because the typed parameter declaration, double (*arg1)(double)
tells the compiler that arg1(2.0)
is valid. In older code you may see (*arg1)(2.0)
but that's not required, and I think it makes the code less readable.)
(I have used printf
in this code, instead of C++'s iostreams, partly because I personally think printf
is much more ergonomic than iostreams, and partly because that makes this program also a valid C program with the same semantics. That may be useful, for instance, if the reason you are learning C++ is because you want to write MATLAB extensions, which, the last time I checked, was actually easier if you stuck to plain C.)
There are significant differences; for instance, the MATLAB functions accept vectors, whereas these C++ functions only take single values; if I'd wanted b
to call c
I would have had to swap them or write a "forward declaration" of c
above b
; and in C++, (with a few exceptions that you don't need to worry about right now,) all your code has to be inside one function or another. Learning these differences is part of learning C++, but you don't need to confuse yourself with templates and lambdas and classes and so on just yet. Stick to free functions with fixed type signatures at first.
Finally, I would be remiss if I didn't mention that in
static double c(double p, double q) { return a(p) * b(q); }
the calls to a
and b
might happen in either order. There is talk of changing this but it has not happened yet.