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.
Related
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?
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.
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.
Say that I have:
template <typename T>
struct Foo {
T& func();
};
And I implement a Foo: Foo<int> bar Now I want to get the return type of bar.func(). I've been trying to force result_of to work with me but to no avail.
What I'd really like is to just be able to do result_of_t<foo.func> and be done with it but I imagine it's significantly more difficult? How should I go about getting this return type?
EDIT:
I was hoping to accomplish this without without respect to how bar was declared. That is to say, I want to just be able to pass bar.func into result_of or similar and gt out the return type.
std::result_of is pretty annoying to use actually. Its syntax is:
result_of<F(ArgTypes...)>
Where F is something invokable, and everything here is a type. In your case, you want to invoke a member function: &Foo<int>::func. But it's not the value of the pointer-to-member that you need, but the type. So we want decltype(&Foo<int>::func). The way to invoke a member function is to pass an instance of the object as the first argument.
Put it all together and we get:
using T = std::result_of_t<decltype(&Foo<int>::func)(Foo<int>&)>;
static_assert(std::is_same<T, int&>::value, "!");
Or we could just use decltype:
using T = decltype(std::declval<Foo<int>&>().func());
which is much more natural.
Given bar, that's just:
using T = decltype(bar.func());
as opposed to:
using T = std::result_of_t<decltype(&decltype(bar)::func)(decltype(bar))>;
I have to create objects of three-four classes, all inherited from one base class, but some of the objects need to have different behavior - like complete change of one function; I can do this through more inheritance and polymorphism, but it doesn't seem like a good idea.
My first solution was to use specialized templates(for every nonstandard case), but then I have though about lambdas as template parameter(like here: Can we use a lambda-expression as the default value for a function argument? ) and use them instead class method(like here: C++11 lambda and template specialization ) - for me it's much better solution, because I only have to pass lambda for every weird situation:
auto default_lambda = [&]() -> int {return this->Sth;};
template<typename functor = decltype(default_lambda)>
class SomeClass{
...
Problem is with this pointer - method which I want to change need access to non-static methods and lambda is defined outside of non-static method. Moreover, I can't pass reference to class to lambda, because it's a template class(or maybe I'm wrong?).
Of course, I can use specialized template or just function pointers, but I really like solution with lambdas and I consider it much more fine than my other ideas.
Is there any way to "avoid" this problem? Or maybe my idea was bad all along?
There are at least three obvious problems with your approach:
The class SomeClass won't get access to private members, i.e. use of this is out of question.
You attempt to bind this from the context but there is no context i.e. nothing bind to. You will have to pass the object to dealt with a function parameter.
You only specified a type of the function object but no instance, i.e. you won't be able to use it later.
That said, it seems you could just use the type of a custom function object type rather than some lambda function (sure, this is absolutely unsexy but in return it actually works):
struct default_lambda {
template <typename T>
int operator()(T const& o) const { return o.x(); }
};
template <typename F = default_lambda>
class SomeClass {
...
};
If you need complete change of one function, you have two choices:
One virtual function, using perhaps local classes + type erasure if you have many such objects and you don't want to create many namespace scope types:
std::function, which can be rebound later if you wish.
Example code for the first solution (you can even make this a template):
std::unique_ptr<my_base2> get_an_object()
{
class impl : public my_base2
{
void my_virtual_function() { blah blah; }
};
return std::unique_ptr<my_base2>(new impl);
}
Both are generally superior to templates in this situation (but without context it is hard to tell).