int fooVar = 10;
std::function<void()> fooFunction = [=]() {
fooVar = 12;
};
Trying to modify foorVar in that lambda results in an error, because its not an lvaue.
Why is the copied value made constant?!
int fooVar = 10;
std::function<void()> fooFunction = [=]() {
fooVar = 12;
};
Trying to modify foorVar in that lambda results in an error, because its not an lvaue.
Why is the copied value made constant?!
It makes sense if you want to do something like:
int counter = 10;
std::function<void()> fooFunction = [=]() {
while(counter--) {
// do important things
}
}
With = you are capturing variables by value not reference if you use & in the [] it will capture that variable as a reference and you should see the change outside of the lambda.
But in your example, there is no reason for counter to exist outside the lambda. It always starts at 10 and always ends at 0. So counter could always exist entirely in the lambda.It makes sense if you want to do something like:
But in your example, there is no reason for counter to exist outside the lambda. It always starts at 10 and always ends at 0.
Assuming counter isn't defined as int counter = 10; but is something dynamic. Does your argument still hold?
In a sense, yes. You're not actually manipulating counter, but a copy of counter. The type is irrelevant. It doesn't need to be captured by the lambda, just passed as a parameter. Which for readability would make more sense (in my mind), since that defines it as an input affecting the function.Assuming counter isn't defined as int counter = 10; but is something dynamic. Does your argument still hold?
int fooVar = 10;
struct __lambda
{
int fooVar;
__lambda(int fooVar) : fooVar{fooVar} {}
void operator()() const
{
fooVar = 12;
}
};
std::function<void()> fooFunction = __lambda{fooVar};int fooVar = 10;
std::function<void()> fooFunction = [=]()mutable {
fooVar = 12; // totally fine now!
};
If you mark the lambda is mutable, the operator() will not be marked const, so you can modify the fooVar member.
int fooVar = 10; std::function<void()> fooFunction = [=]()mutable { fooVar = 12; // totally fine now! };
fooFunction();
assert(fooVar == 12, "Huh?"); // this fires - function didn't modify this variable
If you mark the lambda is mutable, the operator() will not be marked const, so you can modify the fooVar member.
But also note that if you do this, you'll need to be very careful about how many times fooFunction is invoked (since the second invocation won't behave identically to the first), as well as if the functor itself it is ever copied, or only ever referenced (and if copied, whether the copy happens before or after any invocations).
Also, it's advisable not to store lambdas in std::function objects. It might cost extra memory allocation.
The type of each different lambda is known only to the compiler, so use auto instead.
Also, it's advisable not to store lambdas in std::function objects.
As you saying, don't store lambdas in std::function unless you need to (i.e. passing a lambda into a function that takes std::function as a parameter), or are you saying never use std::function to store a lambda?
I store lambdas in std::function all the time. Ofcourse if the lambda doesn't need to be stored for later calling, I just use auto, but since I still use std::function alot, I'd like to know if there's a problem with that that I'm not aware of.
Are you saying that std::function's member vars takes a few extra bytes to hold the object, which requires a separate allocation (definitely worth pointing out), or are you warning about something more dangerous? ![]()
Using std::function for lambdas is like using std::vector for arrays. I tend to use both heavily (except in cases where I don't).
The advice is to know what you are doing and to know what it will cost you (but that's true for everything in C++!!).
Also, it's advisable not to store lambdas in std::function objects.
As you saying, don't store lambdas in std::function unless you need to (i.e. passing a lambda into a function that takes std::function as a parameter), or are you saying never use std::function to store a lambda?
I store lambdas in std::function all the time. Ofcourse if the lambda doesn't need to be stored for later calling, I just use auto, but since I still use std::function alot, I'd like to know if there's a problem with that that I'm not aware of.
Are you saying that std::function's member vars takes a few extra bytes to hold the object, which requires a separate allocation (definitely worth pointing out), or are you warning about something more dangerous?
You are right I didn't put that correctly. It's totally fine storing them in std::function objects if there is no alternative to the task at hand.
The problem with std::function is that its the same size for every kind of function it could store, so it does extra allocations if its memory is not enough to store bookkeeping information about the lambda.
Imagine having a game with tons of those small allocations each frame because you just define and store some lambdas. It could hinder performance.
class IDelegate
{
public:
virtual ~IDelegate() {}
virtual bool operator()() const = 0;
};
namespace Internal
{
template<typename T>
class DelegateImpl: public IDelegate
{
public:
DelegateImpl(const T& aFunctor): Functor(aFunctor) {}
virtual bool operator()() const final {return Functor();}
private:
T Functor;
};
void DoSomeStuffImpl(const IDelegate& aDelegate); // does the real work
}
template<typename T>
void DoSomeStuff(const T& aFunctor)
{
DoSomeStuffImpl(Internal::DelegateImpl<T>(aFunctor));
}
You are right I didn't put that correctly. It's totally fine storing them in std::function objects if there is no alternative to the task at hand.
The problem with std::function is that its the same size for every kind of function it could store, so it does extra allocations if its memory is not enough to store bookkeeping information about the lambda.
Imagine having a game with tons of those small allocations each frame because you just define and store some lambdas. It could hinder performance.
Thanks, wasn't trying to derail the thread, just wasn't sure if I was walking on thin ice with std::function.
I'm not using millions of lambdas per second, so a small amount of overhead is perfectly fine for me. Thanks for the clarification.
In practical terms, all decent implementations of std::function have a small-object optimization. If your stored functor/lambda is small, it won't incur an allocation.
You can provide the std::function a custom allocator that fails on all allocations to ensure that you're within your implementation's small-object size, or that it has one at all.
The std::function replacement I usually write/use actually enforces the small object requirement, as in it's a compile error to assign a lambda larger than X*sizeof(void*) where X is usually something like 3-4 (in one implementation, I made it a template parameter, so an API could decide if it allowed larger functors, which I happened to need in that project in a handful of cases).
This topic has been locked by a moderator. New replies are not allowed.
With your permission, GameDev.net uses analytics cookies to understand how people use the platform. You can accept analytics or continue with necessary cookies only. Learn more