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.
Related
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.
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.
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.
What is the best practice to use when one needs to store a lambda as a class member so that its invocation can be deferred? More specifically, is it safe to store the lambda passed to the class deferred_lambda in the code listing below as a reference? If not, would it be safe if I were to store the the lambda in deferred_lambda as a value instead of as a reference?
Finally, can I expect to incur a performance penalty in comparison to a regular function call with g++ for storing the lambda as a class member in this way? That is, would using deferred_lambda.invoke() be slower than a call to operator() on some dummy struct that would implement the same operations?
With g++, I noticed that the size of the lambda increases as I use more captured variables. I suppose that this is to be expected, since to my understanding, the compiler internally generates a struct for the lambda that contains the necessary captured variables as members. This observation is what led to the question that I am now asking, since storing lambdas by value may be more expensive in terms of time and memory than storing references to them would.
template <class Func>
class deferred_lambda
{
Func& func_;
public:
deferred_lambda(Func func) : func_(func) {}
void invoke() { func_(); }
};
template <class Func>
deferred_lambda<Func> defer_lambda(Func func)
{
return deferred_lambda(func);
}
void foo()
{
int a, b, c;
auto x = defer_lambda([&]() { a = 1; b = 2; c = 3; });
}
I believe the way to store a lambda for later execution is to use a std::function object. Depending on the library implementation the function class should have the necessary constructors and convertors to have a lambda, or any other sort of functor or function, assigned to it for later execution.
More specifically, is it safe to store the lambda passed to the class deferred_lambda in the code listing below as a reference?
No. That would be a dangling reference after defereed_lambda() has finished.
If not, would it be safe if I were to store the the lambda in deferred_lambda as a value instead of as a reference?
Yes. But you still have to ensure variables captured by reference still live when executing the lambda.
That is, would using deferred_lambda.invoke() be slower than a call to operator() on some dummy struct that would implement the same operations?
Probably not, there's no reason for it.
This observation is what led to the question that I am now asking, since storing lambdas by value may be more expensive in terms of time and memory than storing references to them would.
It still has to be stored somewhere...
I am trying to store pointers to memberfunctions of different Classes in C++. What are the possibilities in C++?
I would like to do this:
class A {
T0 f(T1,T2);
};
class B {
T0 g(T1,T2);
T0 h(T1,T2); //interfaces cant be used since the number of functions per class differs.
};
typedef WHATTOPUTHERE type;
type x;
x = A::f;
x = B::h;
Update: Another Problem is that the code should be continueable like this:
B myB;
myB::x(a,b); //not sure about the syntax, should result in myB::h(a,b) being called
This means that I can not bind at the time I store the pointer, since the instance does not exist (yet).
Function objects to encapsulate your function pointers should work.
boost::function is one option, maybe something like this:
class SomeObj
{
public:
void SetInt(int i);
};
SomeObj myObject;
std::vector<boost::function> memberFuncs;
// in the template arg to boost::bind specify the function type
// _1 here denotes late binding so you can pass whatever value you want when invoked
// you could simply bind a parameter as a variable or literal instead
memberFuncs.push_back(boost::bind<void(int)>(&SomeObj::SetInt, &myObject, _1));
memberFuncs[0](42); // myObject->SetInt(42);
Untested/uncompiled code disclaimer this is just for a general idea.
One possible implementation (using C++11) can easily be done using std::function and a lambda like this:
typedef std::function<void(int)> FunctionType;
SomeClass someClass;
FunctionType func = [&someClass](int argument)
{
someClass.SomeMemberFunction(argument);
};
To have a pointer to Fred::f(char, float) you need this sort of pointer:
int (Fred::*)(char,float)
http://www.parashift.com/c++-faq-lite/pointers-to-members.html
The answer to your particular question is that there is no type that you can add to the typedef and make the code compile. The reason is that member function pointers take a hidden argument of the type of the class form which they are obtained. The type of that hidden argument will be different when you take the address of a member function from A or B.
The next question is whether it makes sense or not from a design perspective, considering that you cannot apply the function pointer A::f to an instance of type B, what is the point of considering member pointers of A and B together?
Now, there are possible workarounds for this particular problem (if it makes sense in your case, but I would first review the design) that involve performing type-erasure on the function pointer to remove the hidden argument and generate an object that is callable with the given set of arguments and return type that is common to all of the member functions. This is already done inside std::function (alternatively boost::function if your compiler does not support C++11), as has been suggested before:
A a_instance;
std::function< T0 (T1,T2) > f( std::bind( &A::f, &a_instance, _1, _2 ) );
T0 r = f( T1(), T2() );
Note that part of the trick is that std::bind binds the member function pointer with the pointer to the instance, filling in the hidden argument, while leaving the other two arguments unbound. At this point, because the result of bind does no longer depend on the type of the first argument, type-erasure can be applied removing A from the type of the resulting object.