The textbook functional programming introduction example "return a function with a curried parameter" in C does not compile for me:
// return a function x(v) parameterized with b, which tells if v > b
bool (*greater(int))(int b)
{
return [b](int v) { return v > b; };
}
It says that identifier b
in the capture [b]
is undefined. I know that I'm being naive here, but where is my error?
CodePudding user response:
You say that greater
is a function taking an unnamed (anonymous) int
argument, and return a pointer to a function taking an int
argument with the name b
.
The part (int b)
is the argument list for the returned function pointer.
To solve that specific problem use
bool (*greater(int b))(int)
instead.
Because function pointers are so complicated, they are usually hidden behind type-aliases:
using greater_function_type = bool(int);
greater_function_type* greater(int b) { ... }
As for the problem that lambdas with captures can't be used as C-style function pointers, use std::function
as return type instead:
using greater_function_type = std::function<bool(int)>;
greater_function_type greater(int b) { ... }
Note that it's not returning a pointer anymore.
Since the C 14 standard you can use automatic return-type deduction with the keyword auto
:
auto greater(int b) { ... }
If you need to store the returned objects, for example as a class member variable, you need to use std::function<bool(int)>
for that.
Also be careful when using names like greater
in conjunction with using namespace std;
(which is a bad habit), because of std::greater
.
CodePudding user response:
Lambda is capturing [b]
, which cannot be converted to a function pointer. It requires std::function
:
std::function<bool(int)> greater (int b) { ... }
If the function is expected to be inline
then you may use simple auto
as well:
auto greater (int b) { ... }
BTW, if b
is not expected to change within the scope of greater()
, then accept it as const int b
instead f int b
to be more expressive.
CodePudding user response:
Only lambdas without capture can be cast into a C style function pointer.
Lambdas with capture are actually classes with data members (one for each capture).
In your case you have one capture (b
).
In order to return a curried function (which require a capture) you should use std::function
:
#include <functional>
#include <iostream>
std::function<bool(int)> greater(int b)
{
auto l = [b](int v) { return v > b; };
return l;
}
int main()
{
auto g5 = greater(5);
std::cout << g5(2) << std::endl;
std::cout << g5(7) << std::endl;
}
Output:
0
1