I have a base function
int base(const int i, const double &x)
In this function, I consider i to be a "parameter" (which can take predefined values from 0 to N-1), while x I consider to be the actual "argument" (which can take any arbitrary value).
What I need is to create an array of function pointers int (*pointers[N])(const double &x). Each member of the array corresponds to a different value for the parameter i and thus each call pointers[n](x) should be equivalent to a call base(n, x).
Is there a way to achieve this functionality?
I have been trying to educate myself about functors (is this a way to go?) and recently also looked into std::bind but my understanding is that it only works with C++11 (which I currently cannot use).
Any advice or code snippet would be really helpful. Thanks!
You can use non-capturing lambdas for that:
typedef int (*fp)(double);
fp p1 = [](double x) -> int { return base(1, x); };
fp p2 = [](double x) -> int { return base(2, x); };
fp p3 = [](double x) -> int { return base(3, x); };
This doesn't work for capturing lambdas, and so you can't generate those programatically. There's essentially no difference between this and spelling out one function for each value in C:
int f1(double x) { return base(1, x); }
fp p = f1;
Related
This question already has answers here:
Passing capturing lambda as function pointer
(10 answers)
Closed 4 months ago.
The community reviewed whether to reopen this question 4 months ago and left it closed:
Original close reason(s) were not resolved
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?
EDIT: as #some-programmer-dude pointed out correctly, the function signature is wrong.
greater is a function accepting an int b returning ( a pointer * to a function accepting an (int) returning a bool ).
// return a function x(v) parameterized with b, which tells if v > b
bool (*greater(int b))(int)
{
return [b](int v) { return v > b; };
}
This of course does not remove the original question which all three replies answered correctly.
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.
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.
In order to implement function currying, you need to use the computer-science concept of closure. One of the ways to achieve it in C++ is using capturing lambdas (like you did in your code).
But only C++ lambdas without capture can be cast into a C style function pointer (as you attempted).
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
I am using a library for an optimizer (Brent's method) that has a function "local_min".
Its prototype is defined roughly as follows:
double local_min ( double f ( double x ) );
The function accepts a function pointer (?) as a parameter. Suppose f(x) is the function... the optimizer will test various values for x to find a minimum value for f(x).
The local_min function is called such as:
double f(double x){
return .5 + x * x;
}
int main(){
double fx = local_min(f);
return 0;
}
The trouble I am having is that I want to define the .5 as a scalar for the function, but I do not want to use global values. Ideally, I would have everything in a single class. But everything I try, I change the function signature of f(x) and it will no longer be accepted by local_min().
For example:
int main(){
double value = 0.5;
auto lambda = [](double x) {
return value + x * x;
};
double fx = local_min(f);
return 0;
}
does not work because value is not accessible. Similarly,
int main(){
double value = 0.5;
auto lambda = [&](double x) {
return value + x * x;
};
double fx = local_min(f);
return 0;
}
changes the function signature and is no longer accepted by local_min().
Instead of a function pointer, make local_min accept an arbitrary type. This will let you pass it a lambda with captures as desired
template<typename F>
double local_min(F f)
{
// ... same usage as before
}
The callable f will still behave the same way as before, i.e. like a function that takes a double and returns a double. If you call local_min with an incompatible type, it will fail to compile. You can check for this with a static_assert to give the user a nice error message if you want.
I would like to compute the function composition -- f ( g (param) ). Here is what I tried:
auto fComposition(auto&& f, auto&& g, auto&&... params)
{
/* some stuff */
auto result = std::forward<decltype(f)>(f)(
std::forward<decltype(g)>(g)(
std::forward<decltype(params)>(param)
)
);
/* other stuff */
return result;
};
Compiling with
g++ -std=c++17 src.cpp
basic test
#include <random>
#include <math.h>
int main()
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<double> distr(-1.0, 1.0);
auto xx = fComposition(round, distr, gen);
return 0;
}
I've got the message that it doesn't recognize the type of first function .
BTW, is this really your code? You're not expanding params so it should not compile.
I. The way you define composition, it is indistinguishable from a simple invocation: your fComposition(f, g, arg) is the same as f(g(arg)) except for extra characters typing. The real composition is usually a combinator that accepts two functions and returns a closure that, when invoked on actual arguments, applies them in succession. Something like:
template<class F, class G> auto comp(F f, G g) {
return [f, g](auto &&... args) {
return f(g(std::forward<decltype(args)>(args)...));
};
}
(Note by-values bindings. In C++17, they are more advanced than twenty years ago. :) You can add std::moves and std::forwards by taste.)
This way you compose two functions:
auto fg = comp(f, g);
and later invoke the result on arguments:
auto x = fg(arg1, arg2);
II. But really, why limit ourselves with two operands? In Haskell, (.) is a single binary function. In C++, we can have a whole tree of overloads:
template<class Root, class... Branches> auto comp(Root &&root, Branches &&... branches) {
return [root, branches...](auto &&...args) {
return root(branches(std::forward<decltype(args)>(args)...)...);
};
}
Now you can encapsulate any AST in a single callable:
int f(int x, int y) { return x + y; }
int g(int x) { return x * 19; }
int h(int x) { return x + 2; }
#include <iostream>
int main() {
auto fgh = comp(f, g, h);
std::cout << fgh(2) << '\n';
}
A similar technique was the only way known to me to have anonymous closures in C++ prior to 11 standard.
III. But wait, is there a library solution? In fact, yes. From std::bind's description
If the stored argument arg is of type T for which std::is_bind_expression<T>::value == true (for example, another bind expression was passed directly into the initial call to bind), then bind performs function composition: instead of passing the function object that the bind subexpression would return, the subexpression is invoked eagerly, and its return value is passed to the outer invokable object. If the bind subexpression has any placeholder arguments, they are shared with the outer bind (picked out of u1, u2, ...). Specifically, the argument vn in the std::invoke call above is arg(std::forward<Uj>(uj)...) and the type Vn in the same call is std::result_of_t<T cv &(Uj&&...)>&& (cv qualification is the same as that of g).
Sorry, no examples here at this moment. >_<
P.S. And yes, std::round is an overloaded function so you should typecast it to specify which exactly overload you need to be composed.
The include of random includes cmath, which in libstdc++ also defines several of the math operators (including round) in the default namespace as well as in the std namespace. (See this answer for the rationale.) And C++'s round has multiple overloads. As a result, you have several versions of round available, and your function doesn't know which round you want to use, thus the error message about ambiguity. The correct solution is to disambiguate which round you mean. You can do this with a static cast:
static_cast<double(*)(double)>(round)
Since you have to go through the trouble anyway, you may as well also use the cmath header instead of math.h and use std::round instead. At least then you know that it's going to be overloaded up front.
What is the underlying rationale (technical or conceptual) that C++ does not allow defining array of function type? E.g.
using fn_t = int(int);
fn_t ary[2]; // ERROR (ref: ISO/IEC-14882 [dcl.array])
Given two random functions I just made up:
int a( int x, int y )
{
return x * y;
}
int b( int x, int y )
{
int result = 0;
for (int xi = 1; xi <= x; xi++)
for (int yi = y; yi > 0; yi--)
result += xi * xi;
return result;
}
How do you suggest I put them in an array?
I could compile them, I suppose, then just have an array of max( sizeof(a’s bytecode), sizeof(b’s bytecode) ). But now I have some additional considerations:
Where does this array go?
Some processors can run code from anywhere in memory. Some cannot.
What about security attributes for the code?
What about relocation considerations?
How do I call this function?
Can I use the processor’s usual calling conventions?
Or will this require extra behind-the-scenes magic?
What happens when I want a pointer to the array?
What happens if I move the array and then call the pointer?
What about exceptions and other abnormal signal considerations?
This is just the tip of the iceberg. There are a lot of technical considerations to doing this kind of thing.
Which leads to the main consideration:
What advantage would this give over pointers to functions?
With a pointer to a function, I can do everything I otherwise wanted to do:
int (*fs)(int,int)[] = { a, b };
int x = fs[0]( 10, 10 );
int y = fs[1]( 10, 10 );
The language is designed with several goals — two of the most important being simplicity and flexibility.
Doing what you would reduces both simplicity and flexibility for everyone: compiler writers, compilers themselves, runtime management, speed, safety, etc.
EDIT:
tl;dr Because it offers no advantage over pointers or references to functions, but plenty of drawbacks.
What is the underlying rationale (technical or conceptual) that C++ does not allow defining array of function type?
What is a function? It's just some code at an address. Conceptually it's a singleton, since there is no reasonable way to copy one or allocate one on the heap. Why would you? It already exists. It has a name, and that name yields a function pointer - the address of the code.
There is a concept of a 'function object', which is more equivalent to the 'first class function' of high level languages like python or javascript.
But under the hood it's modelled as a structure containing the address of code (a function pointer) and some state.
There are a few ways to create an array of functions: (this code is c++14)
#include <functional>
#include <iostream>
int a(int i) {
std::cout << "called a with " << i << std::endl;
return i;
}
int b(int i) {
std::cout << "called b with " << i << std::endl;
return i + 1;
}
int c(int i) {
std::cout << "called c with " << i << std::endl;
return i + 2;
}
int main()
{
// make life easier by creating a typedef
using raw_fptr = int (*)(int);
// an array of function pointers
raw_fptr raw_ptrs[] =
{
a, b, c
};
// a typedef of a std::function object
using fobject = std::function<int(int)>;
// an array of function objects
fobject fobjects [] = {
&a, // can capture a function pointer
[](int i) -> int { // or a lambda
return b(i);
},
std::bind(&c, std::placeholders::_1) // or a binder
};
for (auto&& f : raw_ptrs)
f(0);
for (auto&& f : fobjects)
f(1);
}
I have a long algorithm that should process some instruction described from more than one #define in order to reduce drastically my source-code. For example:
#define LongFunction(x, y, alg) return alg(x, y)
#define Alg1(x, y) ((x)+(y))
#define Alg2(x, y) ((x)^((x)-(y)))
And all I need to do is
LongFunction(x, y, Alg1);
LongFunction(x, y, Alg2);
I'd like to not pass a function as parameter because LongFunction is full of loops and I want that the code will be as fast as possible. How can I accomplish this task smartly?
There are many ways to parameterize on function.
Using macros might seem simple, but macros don't respect scopes, and there are problems with parameter substitution and side-effects, so they're Evil™.
In C++11 and later the most natural alternative is to use std::function and lambdas, like this:
#include <functional> // std::function
#include <math.h> // pow
using std::function;
auto long_function(
double const x,
double const y,
function<auto(double, double) -> double> alg
)
-> double
{
// Whatever.
return alg( x, y ); // Combined with earlier results.
}
auto alg1(double const x, double const y)
-> double
{ return x + y; }
auto alg2(double const x, double const y)
-> double
{ return pow( x, x - y ); }
#include <iostream>
using namespace std;
auto main() -> int
{
cout << long_function( 3, 5, alg1 ) << endl;
}
Regarding “fast as possible”, with a modern compiler the macro code is not likely to be faster. But since this is important, do measure. Only measurements, for release build and in the typical execution environment, can tell you what's fastest and whether the speed is relevant to the end user.
Of old, and formally, you could use the inline specifier to hint to the compiler that it should machine code inline calls to a function. Modern compilers are likely to just ignore inline for this (it has another more guaranteed meaning wrt. ODR). But it probably won't hurt to apply it. Again, it's important to measure. And note that results can vary with compilers.
One alternative to the above is to pass a simple function pointer. That might be faster than std::function, but is less general. However, in the other direction, you can templatize on a type, with a member function, and that gives the compiler more information, more opportunity to inline, at the cost of not being able to e.g. select operations from array at runtime. I believe that when you measure, if this is important enough, you'll find that templatization yields fastest code. Or at least as fast as the above.
Example of templatizing on a type that provides the operation:
#include <math.h> // pow
template< class Op >
auto long_function( double const x, double const y )
-> double
{
// Whatever.
return Op()( x, y ); // Combined with earlier results.
}
struct Alg1
{
auto operator()(double const x, double const y)
-> double
{ return x + y; }
};
struct Alg2
{
auto operator()(double const x, double const y)
-> double
{ return pow( x, x - y ); }
};
#include <iostream>
using namespace std;
auto main() -> int
{
cout << long_function<Alg1>( 3, 5 ) << endl;
}
By the way, note that ^ is not an exponentiation operator in C++ (it is in e.g. Visual Basic). In C and C++ it's a bitlevel XOR operator. In the code above I've assumed that you really meant exponentiation, and used the pow function from <math.h>.
If, instead, you really meant bitlevel XOR, then the arguments would need to be integers (preferably unsigned integers), which then would indicate that you want argument types for long_function depending on the argument types for the specified operation. That's more thorny issue, but involves either overloading or templating, or both. If that's what you really want then please do elaborate on that.