This question already has answers here:
Should I use std::function or a function pointer in C++?
(6 answers)
Closed 5 years ago.
Whats the difference between std::function<> and a standard function pointer?
that is:
typedef std::function<int(int)> FUNCTION;
typedef int (*fn)(int);
Are they effectively the same thing?
A function pointer is the address of an actual function defined in C++. An std::function is a wrapper that can hold any type of callable object (objects that can be used like functions).
struct FooFunctor
{
void operator()(int i) {
std::cout << i;
}
};
// Since `FooFunctor` defines `operator()`, it can be used as a function
FooFunctor func;
std::function<void (int)> f(func);
Here, std::function allows you to abstract away exactly what kind of callable object it is you are dealing with — you don't know it's FooFunctor, you just know that it returns void and has one int parameter.
A real-world example where this abstraction is useful is when you are using C++ together with another scripting language. You might want to design an interface that can deal with both functions defined in C++, as well as functions defined in the scripting language, in a generic way.
Edit: Binding
Alongside std::function, you will also find std::bind. These two are very powerful tools when used together.
void func(int a, int b) {
// Do something important
}
// Consider the case when you want one of the parameters of `func` to be fixed
// You can used `std::bind` to set a fixed value for a parameter; `bind` will
// return a function-like object that you can place inside of `std::function`.
std::function<void (int)> f = std::bind(func, _1, 5);
In that example, the function object returned by bind takes the first parameter, _1, and passes it to func as the a parameter, and sets b to be the constant 5.
They are not the same at all. std::function is a complex, heavy, stateful, near-magic type that can hold any sort of callable entity, while a function pointer is really just a simple pointer. If you can get away with it, you should prefer either naked function pointers or auto-bind/auto-lambda types. Only use std::function if you really need a systematic way of organizing a heterogeneous collection of callable entities, such as functions, functors, capturing lambdas and bind expressions.
Update: A bit of explanation about auto types: Compare the following two functions:
void do_something_1(std::function<void(int)> f, int a) { f(a); }
template <typename F, typename A> void do_something_2(F f, A a) { f(a); }
Now imagine invoking them with a lambda or a bind expression:
do_something_X([foo, &bar](int n){ bar += n*foo; }, 12);
do_something_X(std::bind(X::bob, &jim, true, _1, Blue), 13);
The second version with the template is more efficient, because in both cases, the argument F is deduced to the actual, unknowable type of the expression. The first version, with std::function, isn't a template and may look simpler and more deliberate, but it always forces the construction of the std::function object, and quite possibly carries multiple type erasure and virtual dispatch costs.
A std::function has state. It can hold additional parameters "bound" into it.
These parameters can range from things like other classes, other functions, or even this pointers for member function calls.
The replacement function pointer is not typedef int (*fn)(int);
It is typedef int (*fn)(void*,int);, with the void* reperensting the state that would be hidden in the std::function.
No.
One is a function pointer; the other is an object that serves as a wrapper around a function pointer.
They pretty much represent the same thing, but std::function is far more powerful, allowing you to do make bindings and whatnot.
Related
In the past, when I wanted a callback as a function parameter, I usually decided to use std::function. In rare cases where I definitely never use captures, I used a typedef for a function declaration instead.
So, usually my declaration with a callback parameter looks something like this:
struct Socket
{
void on_receive(std::function<void(uint8_t*, unsigned long)> cb);
}
However, as far as I know, std::function is actually doing a little work at runtime due to having to resolve the lambda with it's captures to the std::function template and move/copy it's captures (?).
Reading about the new C++ 20 features I figured I might be able to make use of concepts to avoid using std::function and use a constrained parameter for any viable functor.
And this is where my problem comes up: Since I want to work with the callback functor objects sometime in the future, I have to store them. Since I have no definitive type for my callback, my initial thought was to copy (eventuallty move at some point) the functor to heap and use a std::vector<void*> to note where I left them.
template<typename Functor>
concept ReceiveCallback = std::is_invocable_v<Functor, uint8_t*, unsigned long>
&& std::is_same_v<typename std::invoke_result<Functor, uint8_t*, unsigned long>::type, void>
&& std::is_copy_constructible_v<Functor>;
struct Socket
{
std::vector<void*> callbacks;
template<ReceiveCallback TCallback>
void on_receive(TCallback const& callback)
{
callbacks.push_back(new TCallback(callback));
}
}
int main(int argc, char** argv)
{
Socket* sock;
// [...] inialize socket somehow
sock->on_receive([](uint8_t* data, unsigned long length)
{
// NOP for now
});
// [...]
}
While this works well enough, when implementing the method that is supposed to call the functor, I noticed that I have just postponed the issue of the unknown/missing type. As far as my understanding goes, casting a void* to a function pointer or some similar hack should yield UB - How would the compiler know, that I am actually trying to call operator() of a class that is completely unknown?
I thought about storing the (copied) functor along with the function pointer to it's operator() definition, however I have no idea how I could inject the functor as this inside the function, and without it I doubt that captures would work.
Another approach I had was to declare a pure virtual interface that declares the required operator() function. Unfortunately my compiler forbid me to cast my functor to the interface and I don't think there is a legal way to let the lambda derive from it either.
So, is there a way to work this out or am I possibly just misusing the template requirements/concepts feature?
Your initial version used std::function precisely because it erases the type. If you want type erasure (and you clearly do, since you want the user to be able to use any type without your code knowing explicitly what that type is), then you need some form of type erasure. And type erasure isn't free.
Constraints are for templates. You don't want a template function; you want a single function that deals with a type-erased callable.
And for callbacks which have to outlive the call stack of the provider, std::function's overhead is pretty much what you need. That is, the "overhead" is not pointless; it's what permits you to store objects of arbitrary, unknown types in your callback processor.
I am currently using a templated function to evaluate the derivatives of mathematical functions, like so
template <class func_type>
arma::mat matrixDerivative
(func_type func, const double x, double h, double b=1.4) {
// <implementation details>
}
The template parameter allows me to use either function pointers or functors to evaluate the right-hand side.
Is there an easy way to extend this to evaluate the derivatives of functions that are class methods? I wasn't able to wrap my head around the use of function pointers to member functions and I couldn't work out the details of having a functor as a class attribute that still had access to its parent's attributes and methods.
My questions usually aren't clear, so feel free to ask for clarifications in the comments before answering.
In C++11 simply use a lambda:
[&]( double x )->double {
return ptr->method(x);
}
which generates a function object that can be invoked with double. The above construct assumes that the lambda will be used and discarded before the end of the current scope ([&] is unsafe otherwise).
Note that ->double can be omitted for single-line and void returning lambdas in C++11, and omitted even on multi-line lambdas in C++1y if you are ok with the return type it deduces (based off the first return statement in your function).
In C++03, std::mem_fun can be used, or you can create a custom function object.
In C++1y:
[&](auto&&... x) {
return ptr->method(std::forward<decltype(x)>(x)...);/
}
creates a perfect-forwarding functor wrapper. I would rarely do that kind of thing, even in C++1y, outside of seriously industrial library code. Less verbose we get:
[&](auto&&... x) {
return ptr->method(x...);
}
which lets us imperfectly forward, and defer selection of the overload to the point of use of the lambda, not the point where the lambda was written, which can be nice. (if any of the methods use rvalue or by-value calls, going back to perfect forwarding becomes tempting)
In C++11, std::mem_fn requires that the method in question not be overloaded, or that the overload be manually resolved (with an arcane-looking cast). std::bind then wraps that with a perfect-forwarding function object. The main advantage this procedure is is that the type of the construct, while implementation defined, can be determined, so you can have a function that returns the type in question. However, that is a pretty esoteric advantage: I would go with the lambda.
Lambdas, while strange, are increasingly common in C++, and are easier to understand what they are doing than a chain bind mem_fun expression in my experience as they look more like "normal" code (after you get over the "magic").
There are a lot of examples on the web of using STL to pass in functions or function objects as parameters, for example in std::count .
How do I write my own functions that take such arguments?
As a simple example, say my class is:
struct Foo{
int val=0;
int methodinc()const{return val+1};
}
I would like to define a function funcall like:
int funcall (foo arg, function f)
{return f(arg); }
where the declaration “function” is what I am not sure of, among other things. The term “funcall” comes from Lisp, where (funcall f a b c) just applies f to the arguments a b c.
Then something like this should work:
Foo ff;
funcall(ff,Foo::methodinc); // should return 1
funcall(ff, [](Foo x) {return x.val+1;}) // should return 1
What are simple ways to accomplish this?
I am writing these as debugging helpers, the “funcall” would be used as part of the implementation of my own like my own data structure’s analogs of count, remove-if, transform and other like STL functions that take function arguments. But I do not want to write complicated template expressions to define my code.
The initial answers to this question suggest that the whole notion of declaring and using function arguments is a bit obscure, at least to me. Perhaps before addressing funcall, an even easier task might be just to pass a functional argument to another function, not use it. For example, in C++, to count a vector v I have to write
std::count(v.begin, v.end(), [](int j){return j>3})
How can one write a count that always counts the whole vector, so that:
mycount(v,[](int j){return j>3})
is the same as above? And could this "mycount" work for member function pointers instead of lambdas?
This question is basically the same as the "funcall" question but without the requirement actually to call the function object that is passed.
Typically a function template suits this sort of need for flexibility best:
template <typename F, typename T>
auto funcall(T && t, F f) -> decltype(f(std::forward<T>(t))
{
return f(std::forward<T>(t));
}
Instead of the trailing return type and decltype you can also use the result_of trait:
template <typename F, typename T>
typename std::result_of<F(T&&)>::type funcall(T && t, F f)
{
return f(std::forward<T>(t));
}
Or, in C++14, you can just say decltype(auto) funcall(T && t, F f) with no trailing return type, and it'll be deduced automatically.
The main reason for making F a deduced template argument rather than a fixed type (such as std::function<R(T)> is to allow you to call funcall directly with lambdas and bind/mem_fn expressions, which have unknowable types. Passing those directly allows efficient inlining opportunities, whereas creating of an std::function object is rather expensive by comparison.
C++ is an extraordinarily powerful and complex language. In it you can do anything you can do in Lisp, including implementing Lisp yourself. The problem is that to get there you will have to learn rather a lot about the language and what it can do. Using functions as objects is unfortunately one of the most complicated parts of C++.
There are multiple ways to solve your problem. The #Kerrek answer is an excellent one, but clearly beyond what you're ready for. The code provided in your edit is for a lambda, which will not necessarily make things simpler.
At its heart, function objects in C++ are just pointers. They look like this.
typedef int (*func)(int a, char b);
int f(int aa, char bb) {
return aa + bb;
}
int main(void) {
func fv = f;
int ret = fv(10, ' ');
printf ("ret=%d", ret);
return 0;
}
Here func is a type representing a function call, f is the actual function and fv is a functional call variable.
From this structure all else is built. With templates the compiler does the type matching and with lambdas you avoid having to think up nmes. Underneath it all, C/C++ functions are just pointers.
So the answer is that you can write your own functions that take functions as arguments when you know that those arguments are simply pointers to functions of a suitable type, declared as shown above.
I am playing around with the c++11 functional features. One thing I find odd is that the type of a lambda function is actually NOT a function<> type. What's more, lambda's do not seem to play really well with the type-inferencing mechanism.
Attached is a small example in which I tested flipping the two arguments of a function for adding two integers. (The compiler I used was gcc 4.6.2 under MinGW.) In the example, the type for addInt_f has been explicitly defined using function<> while addInt_l is a lambda whose type is type-inferenced with auto.
When I compiled the code, the flip function can accept the explicitly type-defined version of addInt but not the lambda version, giving an error saying that,
testCppBind.cpp:15:27: error: no matching function for call to 'flip(<lambda(int, int)>&)'
The next few lines show that the lambda version (as well as a 'raw' version) can be accepted if it's explicitly cast to the appropriate function<> type.
So my questions are:
Why is it that a lambda function does not have a function<> type in the first place? In the small example, why does not addInt_l have function<int (int,int)> as the type instead of having a different, lambda type? From the perspective of functional programming, what's the difference between a function/functional object and a lambda?
If there is a fundamental reason that these two have to be different. I heard that lambda's can be converted to function<> but they are different. Is this a design issue/defect of C++11, an implementation issue or is there a benefit in distinguishing the two as the way it is? It seems that the type-signature of addInt_l alone has provided enough information about the parameter and return types of the function.
Is there a way to write the lambda so that the above mentioned explicit type-casting can be avoided?
Thanks in advance.
//-- testCppBind.cpp --
#include <functional>
using namespace std;
using namespace std::placeholders;
template <typename T1,typename T2, typename T3>
function<T3 (T2, T1)> flip(function<T3 (T1, T2)> f) { return bind(f,_2,_1);}
function<int (int,int)> addInt_f = [](int a,int b) -> int { return a + b;};
auto addInt_l = [](int a,int b) -> int { return a + b;};
int addInt0(int a, int b) { return a+b;}
int main() {
auto ff = flip(addInt_f); //ok
auto ff1 = flip(addInt_l); //not ok
auto ff2 = flip((function<int (int,int)>)addInt_l); //ok
auto ff3 = flip((function<int (int,int)>)addInt0); //ok
return 0;
}
std::function is a tool useful to store any kind of callable object regardless of its type. In order to do this it needs to employ some type erasure technique, and that involves some overhead.
Any callable can be implicitly converted to a std::function, and that's why it usually works seamlessly.
I'll repeat to make sure it becomes clear: std::function is not something just for lambdas or function pointers: it's for any kind of callable. That includes things like struct some_callable { void operator()() {} };, for example. That is a simple one, but it could be something like this instead:
struct some_polymorphic_callable {
template <typename T>
void operator()(T);
};
A lambda is just yet another callable object, similar to instances of the some_callable object above. It can be stored in a std::function because it's callable, but it doesn't have the type erasure overhead of std::function.
And the committee plans to make lambdas polymorphic in the future, i.e., lambdas that look like some_polymorphic_callable above. Which std::function type would such a lambda be?
Now... Template parameter deduction, or implicit conversions. Pick one. That's a rule of C++ templates.
To pass a lambda as a std::function argument, it needs to be implicitly converted. Taking a std::function argument means that you're choosing implicit conversions over type deduction. But your function template needs the signature to be deduced or provided explicitly.
The solution? Don't restrict your callers to std::function. Accept any kind of callable.
template <typename Fun>
auto flip(Fun&& f) -> decltype(std::bind(std::forward<Fun>(f),_2,_1))
{ return std::bind(std::forward<Fun>(f),_2,_1); }
You may now be thinking why do we need std::function then. std::function provides type erasure for callables with a known signature. That essentially makes it useful to store type-erased callables and to write virtual interfaces.
Because function<> employs type erasure. This allows several different function-like types to be stored in a function<>, but incurs a small runtime penalty. Type erasure hides the actual type (your specific lambda) behind a virtual function interface.
There is a benefit to this: one of the C++ design "axioms" is to never add overhead unless it is really needed. Using this setup, you do not have any overhead when using type inference (use auto or pass as a template parameter), but you still have all the flexibility to interface with non-template code through function<>. Also note that function<> is not a language construct, but a component of the standard library that can be implemented using simple language features.
No, but you can write the function to just take the type of the function (language construct) instead of the specifics of the function<> (library construct). Of course, that makes it a lot harder to actually write down the return type, since it does not directly give you the parameter types. However, using some meta-programming a la Boost.FunctionTypes you can deduce these from the function you pass in. There are some cases where this is not possible though, for example with functors that have a templated operator().
int func(int x){return x;}
...
std::function<int(int)> x = std::bind(func, std::placeholders::_1);
x(123);
Does x(123) actually call the operator() of the functor which std::function generated which in turn calls the operator() of the functor which std::bind generated which finally calls func? Does this get optimized into something as optimal as calling func(123)?
Where does the functor live which std::bind generates? In what scope? And how does std::bind name it? (can there be name collisions)
Can lambdas replace all uses of std::bind?
Is std::bind as optimal as implementing it as a lambda instead?
What's up with the syntax of the template argument of std::function? How does that get parsed and how can I use that template argument syntax elsewhere?
Does x(123) actually call the operator() of the functor which std::function generated which in turn calls the operator() of the functor which std::bind generated which finally calls func? Does this get optimized into something as optimal as calling func(123)?
I wouldn't describe the operator() of std::function as 'generated' (it's a regular member), but otherwise that is a good description. Optimizations are up to your compiler, but be warned that to optimize the indirection of std::function (which requires the use of type erasure) a compiler may need to perform heroics.
Where does the functor live which std::bind generates? In what scope? And how does std::bind name it? (can there be name collisions)
The call to std::bind returns a functor of unspecified type, and a copy of that functor is stored inside the x object. This copy will live as long as x itself. There is no name involved so I'm not sure what you mean by that.
Can lambdas replace all uses of std::bind?
No. Consider auto bound = std::bind(functor, _1); where functor is a type with an overloaded operator(), let's say on long and int. Then bound(0L) doesn't have the same effect as bound(0) and you can't replicate that with a lambda.
Is std::bind as optimal as implementing it as a lambda instead?
This is up to the compiler. Measure yourself.
What's up with the syntax of the template argument of std::function? How does that get parsed and how can I use that template argument syntax elsewhere?
It's a function type. Perhaps you're already familiar with the syntax for pointers/references to functions: void(*)(), int(&)(double). Then just remove the pointer/reference out of the type, and you just have a function type: void(), int(double). You can use those like so:
typedef int* function_type(long);
function_type* p; // pointer to function
1 . Does x(123) actually call the operator() of the functor which std::function generated which in turn calls the operator() of the functor which std::bind generated which finally calls func? Does this get optimized into something as optimal as calling func(123)?
If you have optimizations enabled, the 'stuff' gets inlined and you can count on this being as optimal as calling func(123).
2 . Where does the functor live which std::bind generates? In what scope? And how does std::bind name it? (can there be name collisions)
Precising: bind generates a 'fleeting', implementation defined, bind expression, that is assignable to function<>. Function is just a class template (Thanks, Luc T.). And it lives in the standard library. However, the bind expressions are implementation defined.
The standard library does come with traits (std::is_bind_expression<>) to allow MPL detection of such expressions. One decisive feature of bind expressions over std::function is that they are (what I'd call) deferred callable objects (i.e. that they retain full call site semantics including the ability to select overloads at the actual application site). std::function<>, on the other hand, commits to a single prototype and internally stores the callable object by type erasure (think variant or any).
3 . Can lambdas replace all uses of std::bind?
4 . Is std::bind as optimal as implementing it as a lambda instead?
AFAICT lambdas should compile down to about the same as the bind expressions. One thing that I think lambdas can't do that bind expressions can is nested bind expressions
Edit While the specific idiom of nested bind expressions is not replicatable using lambdas, lambdas are of course able to express (nearly) the same much more naturally:
bind(f, bind(g, _1))(x);
// vs.
[](int x) { f(g(x)); };
5 . What's up with the syntax of the template argument of std::function? How does that get parsed and how can I use that template argument syntax elsewhere?
It is just a function signature (the type of a function), being passed as template parameter.
You can also use it as a function parameter type, which degrades to a function pointer(similar to how array by-value parameters degrade to pointers, Thanks David!).
In practice, most anywhere, as long as you don't have a need to name a variable/type:
void receiveFunction(void(int, double)); // spunky 'function<>'-style syntax
void sample(int, double) { }
int main()
{
receiveFunction(sample);
}
void receiveFunction(void (*f)(int, double)) // boring 'old' style syntax
// void ( f)(int, double) // ... also ok
{
// ..
}
Can lambdas replace all uses of std::bind?
C++14 will allow lambdas to mostly replace bind. Responding in particular to Luc Danton's answer, in C++14, you can write templated lambdas using auto such that bound(0) and bound(0L) behave differently.