The following code works, but I feel that the line worker([this](int a, long b, int* c){receiver(a, b, c);}); is sort of redundant because it is repeating the signature of receiver. Instead of passing a lambda function that in turn calls the member function, can I somehow pass the member function directly?
using callback = std::function<void(int, long, int*)>;
void worker(callback c)
{
c(1,2L,(int*)3);
}
class Caller
{
public:
Caller()
{
worker([this](int a, long b, int* c){receiver(a, b, c);});
}
void receiver(int a, long b, int* c)
{
}
};
If you have access to C++20, use bolov's answer. If not…
Though this still uses a lambda, you can take advantage of an argument pack to avoid duplicating the signature:
worker([this](auto... params) { receiver(params...); });
This requires C++14 or newer.
Perfect forwarding can be added if you have more complex types and want to avoid copies:
worker([this](auto&&... params) {
receiver(std::forward<decltype(params)>(params)...);
});
std::bind is the classical approach, that avoids the need to explicitly spell out the forwarding signature:
using namespace std::placeholders;
// ...
worker(std::bind(&Caller::receiver, this, _1, _2, _3));
C++20 also has std::bind_front; it reduces this verbiage, somewhat.
You cannot pass a pointer to a member function "directly". This is because a member function requires a specific instance of an object whose member function should get invoked. So, in some form of fashion, in some way, you cannot avoid this, or some other instance of the object, to be involved in the process. This is fundamental to C++. The only thing that can be done here is to find some syntactic sugar, which is basically all this is, here.
The cleanest way is C++20's std::bind_front:
worker(std::bind_front(&Caller::receiver, this));
Why use `std::bind_front` over lambdas in C++20?
Related
I have the following scenario quite often in my c++17 code.
Generic example:
class Receiver{
public:
typedef std::function<void(const std::vector<uint8_t>& payload)> PROCESS_PACKET;
PROCESS_PACKET m_callback;
void run(){
while(){
// do stuff, then call callback:
m_callback(data);
}
}
};
class UsesReceiver{
public:
UsesReceiver(){
receiver.m_callback=std::bind(&UsesReceiver::processData, this, std::placeholders::_1);
receiver.run();
}
private:
void processData(const std::vector<uint8_t>& payload){
// here do something implementation specific
}
Receiver receiver;
};
What always bugs me is this part:
receiver.m_callback=std::bind(&UsesReceiver::processData, this, std::placeholders::_1);
For this example it is quite simple, since the function only takes one parameter, but as soon as you have more parameters this part is a lot of boilerplate in my opinion.
Because I am thinking:
If there is a member function whoese definition is exactly the same as the declared function pointer (e.g. arguments and function type match) there should be a simple one-liner that checks these preconditions at compile time and looks basically like this:
receiver.m_callback=std::bind_quick(&UsesReceiver::processData,this);
Where std::bind_quick, is "just like std::bind" but without placeholders if both function declarations match (checked at compile time).
Since the first couple of comments were "use lambdas instead":
This doesn't really solve the problem, because with lambdas you still have to declare "placeholders" for your function arguments:
receiver.m_callback=[this](auto && PH1) {
processData(std::forward<decltype(PH1)>(PH1));
};
As pointed out in the comments you should generally prefer lambdas over std::bind, even if it doesn't solve your issue.
It's fairly easy to create your quick_bind function using lambdas though.
template <typename Func, typename Obj>
auto quick_bind(Func f, Obj* obj) {
return [=](auto&&... args) {
return (obj->*f)(std::forward<decltype(args)>(args)...);
};
}
Then use it like so
receiver.m_callback=quick_bind(&UsesReceiver::processData, this);
It returns a lambda with a templated operator, so if your assigning it to a std::function it will work as long as there's not a mismatch in function signature.
I am of the position that you should have stopped using std::bind in c++14.
Lambdas solve 99.9% of std::bind problems cleaner and in a way more likely to be understood, and you shouldn't even write the remaining 0.1% of std::bind code (which involves passing std::binds to std::bind and the madness that results).
In the raw we get:
receiver.m_callback=[this](auto&payload){processData(payload);};
this is already simpler and clearer in my opinion. Just language primitives, no library functions involved.
If you want a helper function
In c++20, use std::bind_front or in c++17:
template<class F, class...Args>
auto bind_front( F&& f, Args&&...args ) {
return [f = std::forward<F>(f), tup=std::make_tuple(std::forward<Args>(args)...)](auto&&... more_args)
->decltype(auto)
{
return std::apply([&](auto&&...args)->decltype(auto){
return std::invoke( f, decltype(args)(args)..., decltype(more_args)(more_args)... );
}, tup);
};
}
a bit of a mess, but gives you
receiver.m_callback=notstd::bind_front(&UsesReceiver::processData, this);
Live example.
Since I also got a really good solution in one of the comments, I am going to sum it up here:
If you are lucky enough to work with c++20, you can use std::bind_front as suggested by #StoryTeller.
For the example above, that would look like this:
receiver.m_callback=std::bind_front(&UsesReceiver::processData, this);
If you do not have c++20 support, you can also use absl::bind_front.
Excerpt:
The simpler syntax of absl::bind_front() allows you to avoid known
misuses with std::bind()
Else,you can also write your own macro or function, as suggested in the answer above or in the comment by #NathanOliver.
You can convert Lambdas to function pointers. What are the practical use cases for this? Why do we need this?
Play with it
int main() {
auto test = []() -> int { return 1; };
using func_point = int (*)();
func_point fp = test;
return test();
}
First, you can only convert lambdas with empty closure. Such lambdas are effectively stateless, which makes the conversion possible.
As for the use cases, one important use case is integration with C. There are plenty C APIs, which allow registration of user callbacks, usually taking one or more arguments, like this:
// Registers callback to be called with the specified state pointer
void register_callback(void (*callback)(void* state), void* state);
You can associate the state with a C++ class instance and translate the callback invokation to a method call:
class Foo
{
public:
void method();
};
Foo foo;
register_callback([](void* p) { static_cast< Foo* >(p)->method(); }, &foo);
Alternatives to function pointers are std::function and template parameters / generic functors. All of those impact your code in different ways.
You can pass lambdas to code that expects either std::function, generic functors or function pointers. It is convenient to have a single concept in the calling code that supports all those different interface concepts so consistently and after all, convenience is all, lambdas are about.
Just to make this complete:
function pointers are the least universal concept of the ones above, so not every lambda can be turned into a function pointer. The capture clause must be empty.
Prefixing lambdas with a + explicitly casts them to a function pointer, if possible, i.e. in the following snippet, f has the type int (*)( int ): auto f = +[]( int x ) { return x; };
I'd like to reduce amount of syntax required to refer to a function and was wondering if there was a way to do something like:
(NOT COMPILABLE)
using pushToLastUsed = mSomeLongStackFIFOObject.push_back;
// or
auto pushToLastUsed = mSomeLongStackFIFOObject.push_back;
then I could to something like:
pushToLastUsed(10);
instead of:
mSomeLongStackFIFOObject.push_back(10);
Of course I could make a macro like:
#define pushToLastUsed mSomeLongStackFIFOObject.push_back
// some code using it here
#undef pushToLastUsed
but I'd prefer not to use macros.
One solution might be to use a lambda expression to capture the function call into a callable object :
#include <vector>
void foo(std::vector<int> & bar)
{
auto pushToLastUsed = [&bar](int index) {
bar.push_back(index);
};
pushToLastUsed(10);
}
Though in my opinion there is very little to gain from doing this, even if you replace bar with a very long identifier.
My first idea was something along the line of the other answer. On a second read of your question I understand that it is mainly the long name of the object that you want to avoid to repeat. Hiding a call to a standard function should be done with care as its main effect is to obfuscate your code. Everybody knows what push_back does, but even you will likely forget what exactly pushToLastUse does. A different option is to alias only the mSomeLongStackFIFOObject with a shorter name as in
auto& short_name = mSomeLongStackFIFIObject;
short_name.push_back(10);
When you're writing mSomeLongStackFIFOObject.push_back(10); you're actually calling SomeLongStackFIFOClass::push_back(&mSomeLongStackFIFOObject, 10);
One option is to do:
auto& m= mSomeLongStackFIFOObject;
And then:
m.push_back(10);
It will shorten it and still let you use any variable you like.
If the variable is global, you can always do:
static inline void pushBack(int n) { mSomeLongStackFIFOObject.push_back(n); }
If you're trying to shorten the access, I can guess that you're using the variable more than once; then it could make sense to try to put all the accesses in a function that belongs to the class.
You can achieve the desired behaviour by binding the object mSomeLongStackFIFOObject to the member function push_back and using a placeholder for its argument. This requires at least a C++11 compiler.
Consider the following example:
#include <functional>
#include <iostream>
struct A {
void push_back(const int& n) { std::cout << "push_back(" << n << ")\n"; }
};
int main() {
A mSomeLongStackFIFOObject;
std::function<void(const int&)> pushToLastUsed = std::bind(
&A::push_back,
&mSomeLongStackFIFOObject,
std::placeholders::_1
);
pushToLastUsed(10); // push_back(10)
}
Some notes about this:
As Mirko already mentioned correctly, calling a non-static member function is basically the same as calling a static member function with this as implicit first parameter. The binding of an instance of struct A as first parameter makes use of this fact.
Type inference using auto does work for member functions without any parameters but not in the case above.
If the non-static member function is overloaded (e.g. std::vector<T>::push_back) you have to explicitly state the template parameters for the function template std::bind. See Using std::tr1::bind with std::vector::push_back
or Are there boost::bind issues with VS2010? for further information.
Is it possible to create a functor from a lambda function in C++?
If not, why not?
It's giving me a surprising bit of trouble to do.
Practical Use Case:
Another function requires making a functor like so:
Class::OnCallBack::MakeFunctor(this, &thisclass::function);
Typically in order to use this, I have to make a function within thisclass which means adding to the header file.
After a lot of uses, there's a good bit of bloat.
I want to avoid this bloat by doing something like:
Class::OnCallBack::MakeFunctor(this,
void callback()
{ []() { dosomething; } });
What goes wrong is compilation errors for starters.
Even if it did compile, is it possible to do something like this?
If you want to store the lambda function you could do it like this for a void() function
std::function< void() > callback = [](){ dosomething };
Or, for a function with a return type and parameters,
std::function< int( int ) > callback = []( int i ){ return dosomething(i);}
You'll need to include this file to use std::function though.
#include <functional>
You haven't specified a signature of Class::OnCallBack::MakeFunctor so I guess it's something like:
template<typename T>
Functor<T> MakeFunctor(T*, doesnt_matter (T::*)(doesnt_matter));
just because this is passed explicitly in your example.
In this case it's not a problem of C++ but of your MakeFunctor. If it would be:
template<typename F>
Functor<F> MakeFunctor(F f);
you could call it as:
Class::OnCallBack::MakeFunctor([]() { dosomething; });
There are no lambda functions in C++. The "lambda" structure in C++ defines a class with an operator(). A functor, in some. It also defines an instance of that class.
I don't know what your actual problem is, but I would guess that it has something to do with the fact that you cannot name the type of the lambda. You can usually work around this by using decltype, e.g.:
auto f = [](...) { ... };
typedef decltype( f ) LambdaType;
The other problem might be that every instance of a lambda, even identical instances, have different, unrelated types. Again, the solution is probably to create a named variable with a single instance of the lambda, using auto.
I have this problem where a C++ function pointer is saved, together with a set of arguments to call it on, such that it can be called later. The calling code is unaware of the type and arguments of the functions. Saving and calling function pointers and arguments is extremely performance critical in my application. The interface should look something like this:
void func( int a, char * b );
call_this_later( func, 5, "abc" );
A straightforward solution is to put all of this information in a functor, requiring a different typedef per called function. C++11 would allow me to do that using a variadic template, so that is ok.
Since the type of the functor is not known at the point of call, it seems necessary to create a virtual base class for these functors and to invoke the functors using virtual function calls. The performance overhead of virtual function calls + heap allocation is too high (I am pushing the boundaries of implementing this idiom with as few assembly instructions as possible). So I need a different solution.
Any ideas?
You could do this with a lambda expression which captures the types.
template <typename Func, typename Arg1, typename Arg2>
std::function<void(void)> call_this_later(Func f, Arg1 a1, Arg2 a2) {
return [=]() { f(a1, a2); }; // Capture arguments by value
}
A few things to note:
I don't think you can use perfect forwarding here since you have to capture the arguments
Since C++ is not garbage collected, if the arguments are pointers they may point to something that isn't alive later on. For example if your argument is const char* then it's OK if you use it with a string literal but not if you pass someStdString.c_str() and the string is going to die any-time soon.
I gave the example with two arguments, if your compiler supports variadic templates you can use those otherwise just create an overload for each number of arguments.
What about a solution using boost::function / boost::bind:
void func( int a, char * b );
boost::function<void ()> my_proc =
boost::bind(&func, 5, "abc");
// then later...
my_proc(); // calls func(5, "abc");
You're going to need a custom allocator to match your allocation pattern. Alternatively, use compile-time polymorphism to pass the type of the functor in to the call site.