c++ combining function pointers with best possible performance - c++

I want to have a type describing a function that would allow creating new functions of the same type by combining existing functions, something like this:
FuncType f;
FuncType g;
FuncType h = f(g);
FuncType e = f + g;
I tried the using function pointers and assigning lambdas to them as follows:
typedef double(*FunPtr)(double);
double Fun1(double a) { return 2 * a; }
double Fun2(double a) { return a * a; }
int main{
auto Fun3 = [](double a){return -a;};
FuncType F1 = Fun1;
FuncType F2 = Fun2;
FuncType F3 = Fun3;
auto HFun = [](double a){return (*F1)(a);} // does not work, requires capturing F1
auto HFun = [F1](double a){return (*F1)(a);} // works
FunPtr H = HFun; //Does not work, I suppose because of capturing F1.
}
Replacing
typedef double(*FunPtr)(double);
with
typedef std::function FunPtr;
solves the issue, but the function calls are going to happen inside very large nested loops, hence performance can be an issue and I have read here and there that using std::function comes with an overhead.
1- Is there a way to make this possible in a way that has a better performance compared to std::function?
2- Does using function pointers have a better performance in the first place?
3- Which of normal functions or lambdas is a better choice to start with? (F3 vs F1)
Thanks a lot!

1- Is there a way to make this possible in a way that has a better performance compared to std::function?
std::function is very flexible, but it is indeed slow. In order to be so flexible it performs type erasure and that has a cost. I would guess that probably all other options are faster than std::function (always benchmark).
2- Does using function pointers have a better performance in the first place?
Function pointers are very direct and the overhead should be negligible, but they are not very flexible.
3- Which of normal functions or lambdas is a better choice to start with? (F3 vs F1)
Lambda functions are much easier to use than than function pointers and they are efficient. But each lambda function is is "own type", which causes difficulties when you want to create an array of them.
Lambda functions can be converted to function pointers, but only if they do not capture, but you need to capture to do the f(g) you want. Therefore, in your case they don't seem to be an option
My suggestion is that you try to keep using function pointers and if you can't for some reason then change to using virtual classes.
In the past I had a need to store an array of functions and I started using an array of std::function which proved to be slow. In the end I changed to an array of base class pointers where the base class had a pure virtual method with the actual function to be implemented in subclasses. Benchmark showed that this solution was faster than using std::function. Even though virtual methods also have some overhead it was less than the overhead in std::function.

Related

Explanation of std::function

What is the purpose of std::function? As far as I understand, std::function turns a function, functor, or lambda into a function object.
I don't quite understand the purpose of this... Both Lambdas and Functors are function objects already and I do believe that they can be used as predicates for algorithms like sort and transform. As a side note, Lambdas are actually Functors (internally). So the only thing I can see std::function being useful for is to turn regular functions into function objects.
And I don't quite see why I would want to turn a regular function into a function object either. If I wanted to use a function object I would have made one in the first place as a functor or lambda... rather than code a function and then convert it with std::function and then pass it in as predicate...
I'm guessing that there is much more to std::function... something that isn't quite obvious at first glance.
An explanation of std::function would be much appreciated.
What is the purpose of std::function? As far as I understand, std::function turns a function, functor, or lambda into a function object.
std::function is an example of a broader concept called Type Erasure. The description you have isn't quite accurate. What std::function<void()> does, to pick a specific specialization, is represent any callable that can be invoked with no arguments. It could be a function pointer or a function object that has a concrete type, or a closure built from a lambda. It doesn't matter what the source type is, as long as it fits the contract - it just works. Instead of using the concrete source type, we "erase" it - and we just deal with std::function.
Now, why would we ever use type erasure? After all, don't we have templates so that we can use the concrete types directly? And wouldn't that be more efficient and isn't C++ all about efficiency?!
Sometimes, you cannot use the concrete types. An example that might be more familiar is regular object-oriented polymorphism. Why would we ever store a Base* when we could instead store a Derived*? Well, maybe we can't store a Derived*. Maybe we have lots of different Derived*s that different users use. Maybe we're writing a library that doesn't even know about Derived. This is also type erasure, just a different technique for it than the one std::function uses.
A non-exhaust list of use-cases:
Need to store a potentially heterogenous list of objects, when we only care about them satisfying a concrete interface. For std::function, maybe I just have a std::vector<std::function<void()>> callbacks - which might all have different concrete types, but I don't care, I just need to call them.
Need to use across an API boundary (e.g. I can have a virtual function taking a std::function<void()>, but I can't have a virtual function template).
Returning from a factory function - we just need some object that satisfies some concept, we don't need a concrete thing (again, quite common in OO polymorphism, which is also type erasure).
Could potentially actually use templates everywhere, but the performance gain isn't worth the compilation hit.
Consider a simple use case:
/* Unspecified */ f = [](int x, int y){ return x + y; };
f = [](int x, int y){ return x - y; };
int a = 42;
f = [&a](int x, int y){ return a * x * y; };
How would you specify /* Unspecified */?
Furthermore,
std::queue<of what?> jobs;
jobs.push_back([]{ std::cout << "Hi!\n"; });
jobs.push_back([]{ std::cout << "Bye!\n"; });
for(auto const &j: jobs) j();
What value_type should be kept in jobs?
Finally,
myButton.onClick(f);
What type does f have? A template parameter? Okay, but how is it registered internally?
In most uses that I've seen, std::function was overkill. But it serves two purposes.
First, it gives you a uniform syntax for calling function objects. For example, you can use an std::function instantiation to wrap an ordinary function that takes a single argument of a class type or a member function and the class object that it should be applied to without worrying about the different calling syntax.
struct S {
void f();
};
void g(const S&);
S obj;
typedef std::function<void()> functor1(&S::f, obj);
typedef std::function<void()> functor2(&g, obj);
functor1(); // calls obj.f()
functor2(); // calls g(obj);
Note that both functors here are called with the same syntax. That's a big benefit when you're writing generic code. The decision of how to call the underlying function is made within the std::function template, and you don't have to figure it out in your code.
The other big benefit is that you can reassign the function object that a std::function object holds:
functor1 = std::function<void>()>(&g, obj);
This changes the behavior of functor1:
functor1() // calls g(obj)
Sometimes that matters.
As far as I understand, std::function turns a function, functor, or lambda into a function object.
You pretty much summed it up, you can turn any of these into the same thing, an std::function, that you can then store and use as you wish.
When you are designing a class or an API in general you usually don't have a reason to restrict your features to just one of these, so using std::function gives the liberty of choice to the user of your API, as opposed to forcing users to one specific type.
You can even store different forms of these together, it's basically an abstraction of callable types with a given signature and a clearly defined semantic.
One example of where std::function can be very useful is in implementing an "observer pattern". So, for example, say you want to implement a simple "expression evaluator" calculator GUI. To give a somewhat abstract idea of the kind of code you might write against a GUI library using the observer pattern:
class ExprEvalForm : public GuiEditorGenerated::ExprEvalForm {
public:
ExprEvalForm() {
calculateButton.onClicked([] {
auto exprStr = exprInputBox.get();
auto value = ExprEvaluator::evaluate(exprStr);
evalOutputLabel.set(std::to_string(value));
});
}
};
Now, how would the GUI library's button class store the function that's passed to onClicked? Here, an onClicked method (even if it were templated) would still need to store somewhere into a member variable, which needs to be of a predetermined type. That's exactly where the type erasure of std::function can come into play. So, a skeleton of the button class implementation might look like:
class PushButton : public Widget {
public:
using ButtonClickedCallback = std::function<void()>;
void onClicked(ButtonClickedCallback cb) {
m_buttonClickedCallback = std::move(cb);
}
protected:
void mouseUpEvent(int x, int y) override {
...
if (mouseWasInButtonArea(x, y))
notifyClicked();
...
}
private:
void notifyClicked() {
if (m_buttonClickedCallback)
m_buttonClickedCallback();
}
ButtonClickedCallback m_buttonClickedCallback;
};
Using function object is helpful when implementing thread pool. You can keep no of available workers as threads and work to do as queue of function objects. It is easier to keep work to be done as function object than function pointers for example as you can just pass anything thats callable. Each time new function object appear in queue, worker thread can just pop it and execute by calling () operator on it.

modern c++ alternative to function pointers

I've been using function pointers till now, like this format in c++. I do have some uses now and then and I'm wondering is there anything else introduced in c++11/14 as their alternative.
#include <iostream>
using namespace std;
void sayHello();
void someFunction(void f());
int main() {
someFunction(sayHello);
return 0;
}
void sayHello(){
std::cout<<"\n Hello World";
}
void someFunction(void f()){
f();
}
I did take a look at this question but couldn't understand any advantages over traditional use of function pointers. Also I would like to ask , is there anything wrong (not recommended) thing with using function pointers since I never see anyone using them. Or any other alternative present.
The question you mention suggest std::function but does not emphasize (or mentions at all) its value when combined with std::bind.
Your example is the simplest possible, but suppose you have a
std::function<void (int, int)> f ;
A function pointer can do more or less the same things. But suppose that you need a function g(int) which is f with second parameter bound to 0. With function pointers you can't do much, with std::function you can do this:
std::function<void(int)> g = std::bind(f, _1, 0) ;
As an alternative to traditional function pointers, C++11 introduced template alias which combined with variadic templates could simplify the function pointer sintax. below, an example of how to create a "template" function pointer:
template <typename R, typename ...ARGS> using function = R(*)(ARGS...);
It can be used this way:
void foo() { ... }
int bar(int) { ... }
double baz(double, float) { ... }
int main()
{
function<void> f1 = foo;
function<int, int> f2 = bar;
function<double, double, float> f3 = baz;
f1(); f2({}); f3({}, {});
return 0;
}
Also, it can deal neatly with function overloads:
void overloaded(int) { std::cout << "int version\n"; }
void overloaded(double) { std::cout << "double version\n"; }
int main()
{
function<void, int> f4 = overloaded;
function<void, double> f5 = overloaded;
f4({}); // int version
f5({}); // double version
return 0;
}
And can be used as a pretty neat way to declare function-pointers parameters:
void callCallback(function<int, int> callback, int value)
{
std::cout << "Calling\n";
std::cout << "v: " << callback(value) << '\n';
std::cout << "Called\n";
}
int main()
{
function<int, int> f2 = bar;
callCallback(f2, {});
return 0;
}
This template alias could be used as an alternative of std::function which doesn't have its drawbacks nor its advantages (good explanation here).
Live demo
As a brief, I think that template alias combined with variadic templates is a good, nice, neat and modern C++ alternative to raw function pointers (this alias still are function pointers after all) but std::function is good, nice, neat and modern C++ as well with good advantages to take into account. To stick in function pointers (or alias) or to choose std::function is up to your implementation needs.
Also I would like to ask , is there anything wrong (not recommended)
thing with using function pointers since I never see anyone using
them.
Yes. Function pointers are terrible, awful things. Firstly, they do not support being generic- so you cannot take a function pointer that, say, takes std::vector<T> for any T. Secondly, they do not support having bound state, so if at any time in the future, anybody, ever, wishes to refer to other state, they are completely screwed. This is especially bad since this includes this for member functions.
There are two approaches to taking functions in C++11. The first is to use a template. The second is to use std::function.
The template kinda looks like this:
template<typename T> void func(F f) {
f();
}
The main advantages here are that it accepts any kind of function object, including function pointer, lambda, functor, bind-result, whatever, and F can have any number of function call overloads with any signature, including templates, and it may have any size with any bound state. So it's super-duper flexible. It's also maximally efficient as the compiler can inline the operator and pass the state directly in the object.
int main() {
int x = 5;
func([=] { std::cout << x; });
}
The main downside here is the usual downsides of templates- it doesn't work for virtual functions and has to be defined in the header.
The other approach is std::function. std::function has many of the same advantages- it can be any size, bind to any state, and be anything callable, but trades a couple off. Mainly, the signature is fixed at type definition time, so you can't have a std::function<void(std::vector<T>)> for some yet-to-be-known T, and there may also be some dynamic indirection/allocation involved (if you can't SBO). The advantage of this is that since std::function is a real concrete type, you can pass it around as with any other object, so it can be used as a virtual function parameter and such things.
Basically, function pointers are just incredibly limited and can't really do anything interesting, and make the API incredibly unflexible. Their abominable syntax is a piss in the ocean and reducing it with a template alias is hilarious but pointless.
I did take a look at this question but couldn't understand any
advantages over traditional use of function pointers. Also I would
like to ask , is there anything wrong (not recommended) thing with
using function pointers since I never see anyone using them.
Normal "global" functions typically don't/can't have state. While it's not necessarily good to have state during traversal in functional programming paradigm, sometimes state might come in handy when it relates orthogonally to what has been changed (heuristics as example). Here functors (or function objects) have the advantage.
Normal functions don't compose very well (creating higher level functions of lower level functions.
Normal functions don't allow for binding additional parameters on the fly.
Sometimes normal functions can act as replacement for lambdas, and visa versa, depending on the context. Often one wouldn't want to write a special function just because you have some very local/specific requirement during "container traversal".

How to store boost::bind object as member variable?

I am using boost::bind to create composed functions on-the-fly, and hope to store the object as some class member variable for later usage. For example we have two functors:
struct add{double operator()(double x, double y) const{return x+y;};};
struct multiply{double operator()(double x, double y) const{return x*y;};};
Then to create a function f(x,y,z) = (x+y)*z, I can do this:
auto f = boost::bind<double>(multiply(), boost::bind<double>(add(), _1, _2), _3);
And calling f(x,y,z) works perfectly. Now I want to save f as a class member variable, something like the following:
struct F
{
auto func;
double operator(const std::vector<double>& args) const
{
return func(args[0],args[1],args[2]); //Skipping boundary check
}
}
F f_obj;
f_obj.func = f;
f_obj(args);
But of course I cannot declare an auto variable. Is there any way to get around this?
Note that I am not using boost::function, as it will dramatically impact the performance, which is important to me.
Thanks for any advice.
Two options: use boost::function, and measure whether it actually affects performance.
Alternatively make F a template taking the type of func as parameter and deduce it from the type of the bind expression.
EDIT: The problem with the second option is it doesn't get rid of the awkward type. You can do that by defining a base class with a pure virtual function which the template overrides. But then you have dynamic memory to manage and the cost of a virtual function to pay - so you might as well go back to boost::function (or std::function) which does much the same thing for you.
The type returned from bind() is specific to each combination of function objects and arguments. If you want to store the result, you will need to erase the type in some way. The obvious approach is to use function<..>.
When the resulting function object is invoked frequently, the overhead introduced by function<...> effectively doing a virtual dispatch may be too high. One approach to counter the problem is to bundle the function object with suitable bulk operations and instead of storing the function object to store a suitable application. That won't help when individual calls are needed but when lots of calls are required the virtual dispatch is paid just once.

Modifying a function passed as input

I'm passing a function, f, to another function, SInf, but the 20+ times I call f in SInf, I call f(1./x)/(x*x).
Is there a way to have another function, say g(x)=f(1./x)/(x*x)? Though I guess not necessary to complete what I need to do, it would dramatically improve readability of the code.
I would rather not have a class or struct external to SInf, since I want it to be able to replace similar functions.
double SInf(double (*f)(double), int N, double aa, double bb, bool closed=true)
{
struct functions{
double fi(double x){return f(1./x)/(x*x);}
};
//bla bla lots of code
}
gives me
error: use of parameter from containing function
You can do things like this easily with std::function and lambda functions. It will be difficult otherwise, as you'll have no way to pass additional arguments.
If you are writing an uncomplicated single-threaded app, you can still use regular function pointers and pass the extra state via globals, but that breaks down in a hurry when programs get complicated.
StilesCrisis is correct that lambdas are a good (if not the best) way of solving this. Here's what you can do:
//define a function g
auto g = [&f] (double _x) {return f(1./_x)/(_x*_x);};
//call g
g(x);
If you are unfamiliar with this syntax, I suggest you read this article first. In particular, take a look at the "variable capture with lambdas" section.

C++11 lambdas to Function Pointer

I'm starting to develop applications using C++11 lambdas, and need to convert some types to function pointers. This works perfectly in GCC 4.6.0:
void (* test)() = []()
{
puts("Test!");
};
test();
My problem is when I need to use function or method local variables within the lambda:
const char * text = "test!";
void (* test)() = [&]()
{
puts(text);
};
test();
G++ 4.6.0 gives the cast error code:
main.cpp: In function 'void init(int)':
main.cpp:10:2: error: cannot convert 'main(int argc, char ** argv)::<lambda()>' to 'void (*)()' in initialization
If use auto, it works ok:
const char * text = "Test!";
auto test = [&]()
{
puts(text);
};
test();
My question is: how can I create a type for a lambda with [&]? In my case, I can not use the STL std::function (because my program does not use C++ RTTI and EXCEPTIONS runtime), and It has a simple implementation of function to solve this problem?
I can not use the STL std::function (because my program does not use C++ RTTI and EXCEPTIONS runtime)
Then you may need to write your own equivalent to std::function.
The usual implementation of type erasure for std::function doesn't need RTTI for most of its functionality; it works through regular virtual function calls. So writing your own version is doable.
Indeed, the only things in std::function that need RTTI are the target_type and target functions, which are not the most useful functions in the world. You might be able to just use std::function without calling these functions, assuming that the implementation you're using doesn't need RTTI for its usual business.
Typically, when you disable exception handling, the program simply shuts down and errors out when encountering a throw statement. And since most of the exceptions that a std::function would emit aren't the kind of thing you would be able to recover from (calling an empty function, running out of memory, etc), you can probably just use std::function as is.
Only lambdas with no capture can be converted to a function pointer. This is an extension of lambdas for only this particular case [*]. In general, lambdas are function objects, and you cannot convert a function object to a function.
The alternative for lambdas that have state (capture) is to use std::function rather than a plain function pointer.
[*]: If the lambda that holds state could be converted to function pointer, where would the state be maintained? (Note that there might be multiple instances of this particular lambda, each one with it's own state that needs to be maintained separately)
As has been mentioned, only lambdas that capture nothing can be converted to function pointers.
If you don't want to use or write something like std::function then another alternative is to pass as parameters the things you would otherwise capture. You can even create a struct to hold them.
#include <iostream>
struct captures { int x; };
int (*func)(captures *c) = [](captures *c){ return c->x; };
int main() {
captures c = {10};
std::cout << func(&c) << '\n';
}
Another alternative is to use global/static/thread_local/constexpr variables which do not require capturing.
You can use std::function, it doesn't need any "runtime". Otherwise, look here for a sketch how to implement std::function yourself.