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.
Related
How can I in C++ make a function accept every Object, so I can give it numbers, String or other Objects. I am not very well in C++, I hope it's not a totally stupid question...
Edit: Ok, an example: if you want to try to wrap the std::cout streams into normal functions, that funtion should be able to accept everything - from Integers over Floats to complex Objects. I hope it's more clear now!
You can overload your function for different types, i.e.
size_t func(int);
size_t func(std::string);
Alternatively and/or additionally, you can provide a function template, which is a way to tell the compiler how to generate your function for any particular type, for example
template<typename T>
size_t func(T const&) { return sizeof(T); }
You may use more advanced techniques such as SFINAE to effectively overload those template functions, i.e. to use different templates for different kind of types T (i.e. integral types, pointer, built-in types, pod, etc). The compiler will then pick the best-fitting func() (if any) for any function call it encounters and, if this is a template, generate an appropriate function.
This requires no re-coding.
A completely different approach is to use a generic erasure type, such as boost::any, when the function will need to resolve the expected types at coding-time (as opposed to compile-time):
size_t func(boost::any const&x)
{
auto i = boost::any_cast<const int*>(x);
if(i) return func(*i);
// etc for other types, but this must be done at coding time!
}
You can use templates for this purpose:
template <typename T>
void foo(T const & value)
{
// value is of some type T, which can be any type at all.
}
What you can actually do with the value may be rather limited without knowing its type -- it depends on the goal of your function. (If someone attempts to call the function with an argument type that causes that function specialization to be ill-formed then your template function will fail to instantiate and it will be a compile-time error.)
I'm not sure what you're trying to accomplish, but you can pass a void pointer as a parameter.
void foo(void* bar);
If I understood you correctly you might wanna try using templates http://en.cppreference.com/w/cpp/language/function_template
You are probably looking for templates.
I suggest you read this.
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").
Am I able to implement the following function in C++?
I would like to keep the myInstance variable unspecified until the callback method is called, instead of containing it in a boost::bind instance.
MyClass *myInstance;
void call(/* boost::mem_fn */ callback)
{
// Somewhere in this function, the operator()() method
// is called on the callback instance
callback(myInstance);
}
call(boost::mem_fn(&MyClass::myMethod));
I understand that boost::mem_fn is a function which returns a particular object, but I'm unsure of its type. The documentation says unspecified as its return type. One of the boost::bind constructors takes this type as a parameter, but I'm unable to find the actual declaration in its implementation. Also, am I even allowed to store my own instance of this particular type, or is this strictly for use by boost functions?
This is one of those cases where it seems that the compiler is doing some very magic stuff.
The reason there isn't really a well defined type is that the type returned from bosst::mem_fn is always assumed to be a template parameter of the function it's passed to. Let me show you an example:
std::for_each has a signature like this:
template <class InputIterator, class Function>
Function for_each (InputIterator first, InputIterator last, Function f);
This little slice of magic has two template parameters, an InputIterator and a Function. These could have been called anything, but the names given to them describe how they will be used, really, are more self-documenting names than a real type. The type of InputIterator may well be something like std::vector<foo>::iterator - the point is that the compiler will automatically resolve what an "InputIterator" is at compile time. It can figure this type out for you.
The same is true of Function. As long as you pass it something that can be called - that is, has a version of operator() that is compatible with what gets called in for_each, then you never need to know what Function is.
So the short answer is, make your call function take a template parameter:
template<typename SomeSortOfFunction>
void call(SomeSortOfFunction callback)
and then the compiler should resolve SomeSortOfFunction to be whatever the type is that is returned from boost::mem_fn
The return type of boost::mem_fn is unspecified. You should use either Matt's approach (i.e. pass it as a template), or if separate compilation is important to you, use type erasure:
MyClass *myInstance;
void call(boost::function<void(MyClass*)> callback)
{
callback(myInstance);
}
call(boost::mem_fn(&MyClass::myMethod));
The return type of mem_fn is not something you should ever explicitly type or store. It is generated at compile time via the types of the arguments.
It can, however, be stored via std::function (or boost::function).
The operator() signature of men_fn is the original method arguments with a possibly const pointer to the class prepended, and the same return value type. Just create a std::function with that signature, and it can take the men_fn type and store it.
In short if you have a zero argument method for class foo that returns void try storing the men_fun in a std::function<void(foo *)>.
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().
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.