C++ Lambda capture by reference - c++

As far I know, after running the following code myString should have got the value "Inside lambda3.secondLambda". Instead it will still have the value "Initialized".
std::string myString("Initialized");
auto lambda3 = [&]() { [&myString]() { myString = "Inside lambda3.secondLambda"; }; };
The first lambda captures all variables by reference and the sencond captures only myString by reference. Why does it not behave as I have expected?

By specifying the body of the lambda, you specify code that would be called when the lambda's operator() is called.
So you need to actually call the lambdas, otherwise it's simply code inside the definition of functions which never get called. You can do:
auto lambda3 = [&] {
auto l = [&myString] {
myString = "Inside lambda3.secondLambda";
};
l();
};
lambda3();
To take it one step further, you can return the inner lambda and then execute it like this:
auto lambda3 = [&] {
return [&myString] {
myString = "Inside lambda3.secondLambda";
};
};
lambda3()();

You have defined a closure, but not actually run the function. You must actually run it like lambda3() if you want to execute its body.
However, you have nested lambdas, so you need to run what's in the lambda as well. It's not clear why you are doing this. Your inner lambda is neither assigned inside the outer lambda's scope (so you can run it inside the lambda using the same syntax), or returned (so the caller of this lambda can run what it returns).
If you returned it, you could do lambda3()():
auto lambda3 = [&]() { return [&myString]() { myString = "Inside
lambda3.secondLambda"; }; };
Note: only the word return was added to allow lambda3()() to work.
In this particular example, you are better served with just:
auto lambda3 = [&myString]() {
myString = "Inside lambda3.secondLambda"; };

Related

How to assign a unique_ptr value from within a lambda

I have a situation where I need to assign a unique ptr value from within a lambda function.
std::unique_ptr<SomeType> unique_ptr_obj;
// Lambda below has fixed return type.
bool var = ()[unique_ptr_obj=std::move(unique_ptr_obj)]-> bool {
unique_ptr_obj = GetUniqueObject();
return true
} ();
// Should be able to use unique_ptr_obj
UseUniqueObject(unique_ptr_obj.get());
However, as expected unique_ptr_obj is nullptr as it was moved into lambda. Is there a way I can populate unique_ptr_obj from within a lambda and be able to reuse it later ?
Any suggestions on how to accomplish this ? Should I convert unique_ptr_obj to shared_ptr ?
You should change the declaration of your lambda to capture unique_ptr_obj by reference:
bool var = [&unique_ptr_obj]() -> bool {
// Whatever the next line does, now it changes that variable by reference.
// Otherwise you were changing a local copy.
unique_ptr_obj = GetUniqueObject();
return true;
} ();
You don't want to share ownership. Or maybe you do, but it won't help with the lambda assigning something to unique_ptr_obj, hence using a shared_ptr is not the solution.
You also do not want to move from unique_ptr_obj. Sloppy speaking, moving from something means leaving it in an empty state.
If you want a function to modify its argument then you pass by reference. If you want a lambda to modify something in the outer scope you let it capture it by reference.
This is the same whether its an int or a unique_ptr:
int x = 0;
bool value = [&x]() { x = 42; return true; } ();
// ^^ capture x by reference
assert(x == 42);

How to use packaged_task correctly?

I have a regular method that sometimes takes too long. There is a request to implement this method differently and to exit on timeout. Unfortunately the procedure cannot be interrupted, so it has to be finished, but I can return from the function leaving the procedure running in a separate thread. I've implemented it using a packaged_task pattern:
int mayTakeTooLong() {
auto asyncProcedure = []() -> int {
// Old code is here
};
std::packaged_task<int()> task(std::move(asyncProcedure));
auto future = task.get_future();
std::thread workerThread(task);
switch (future.wait_for(std::chrono::seconds(1))) {
case std::future_status::ready:
workerThread.join();
return future.get();
case std::future_status::timeout:
workerThread.detach();
return 0;
}
}
Disregard for now the fact that I'm detaching the thread in case of a timeout: in actual implementation trickier.
Now imagine that there is a parameter of the function that is passed by reference:
int mayTakeTooLong(const std::vector<SomeClass> &values);
Due to the fact the asyncProcedure may run longer than the lifetime of the vector, I need to copy it somewhere. My first implementation [I guess] was incorrect. I was passing the vector by value to the lambda itself:
int mayTakeTooLong() {
auto asyncProcedure = [](std::vector<SomeClass> values) -> int {
// Old code is here
};
std::packaged_task<int(std::vector<SomeClass>)> task(std::move(asyncProcedure));
auto future = task.get_future();
std::thread workerThread(task, values);
// ...
}
The problem with this code is that the values are copied asynchronously and not in the constructor of the thread, being synchronized with the beginning of the invocation of the lambda. So the first question is whether my understanding is correct.
A more safe idea is to capture the object into the lambda:
int mayTakeTooLong(const std::vector<SomeClass> &values) {
auto asyncProcedure = [values]() -> int {
// Old code is here
};
// ...
}
The values are being copied by value and become the part of the lambda. But in this case each time the lambda is being copied itself the vector would be copied as well. I'm trying to prevent the copying be moving the lambda:
int mayTakeTooLong(const std::vector<SomeClass> &values) {
auto asyncProcedure = [values]() -> int {
// Old code is here
};
std::packaged_task<int()> task(std::move(asyncProcedure));
// ...
}
As I can see, the lambda is never copied, but is that guaranteed by the standard? What could be a better option to implement this pattern?

auto variable declaration without definition

I was wondering if there's an elegant solution for the following issue:
Let's say I'd like to have a variable holding a value with a pretty complex type and would the compiler to automatically infer it's type, but declare first and give value later in the code because of initialization in an if statement.
For example:
{
auto a;
if (some predicate)
a = init_a(1);
else
a = init_a(2);
}
Obviously this code doesn't compile, but the I think that the compiler has all the information it needs to infer the type.
If 'a' was just an int, this was not a problem, but if the type is a complex template, I don't want to have to write it (or in some cases even know it).
Also, i wouldn't want to call the default constructor of a and then write over it.
Possible solutions:
Template the type of 'a'.
initialize 'a' using a lambda and move the predicate into the lambda.
Just write the type of 'a' instead auto.
Use a void pointer/shared_ptr and then init 'a' on the heap.
Each of these has its own drawbacks.
Is there a more elegant solution for it?
The compiler doesn't have infinite lookahead what is happening further on in the code. It only knows what's happening at the current statement. Therefore it can't deduce any types without an initializer.
If you don't know the return-type of init_a then you could use decltype:
decltype(init_a(1)) a;
You can also use a lambda call to initialize the variable:
auto a = [ /* Captures needed for the condition... */ ]()
{
if (some_condition)
return init_a(1);
else
return init_a(2);
}(); // Call the lambda immediately
Or, as mentioned in many comments, use the ternary conditional expression:
auto a = some_condition ? init_a(1) : init_a(2);
There's a technique called "Immediately Invoked Lambda Expression" that is using lambda to initialize a variable in a complex way. Using this approach your a can be const which improves const-correctness. More details here.
For a simple binary predicate, consider just using the ternary operator:
struct A { int a; };
A initA(int a) { return A{a}; }
bool somePredicate(int input) { return input == 42; }
int main() {
const auto input = 42;
const auto a = somePredicate(input) ? initA(1) : initA(2);
}
for more complex initialization logic (beyond a binary case), wrap the initialization logic in a lambda:
struct A { int a; };
A initA(int a) { return A{a}; }
bool somePredicate(int input) { return input == 42; }
int main() {
const auto input = 42;
const auto a = []() {
if (somePredicate(input)) { return initA(1); }
else if (input == 100) { return initA(100); }
else { return initA(2); }}();
}
Both these approaches come with additional possibility of making the variable to be initialized const.
If the return types of your lambda are different but convertible to some type then you can force the return type (note the -> is mandatory when specifying a return type):
auto a = [=]() -> ConvertedType {
if (some_predicate) {
return CovertibleType1(1);
} else if (other_predicate) {
return ConvertibleType2(2);
}
return ConvertibleType3(3);
}();
Though I realize this basically defeats the auto declaration...

Passing a locally-created lambda for use in a callback, then going out of scope

I'm using some (somewhat C-ish) library which involves a callback mechanism. The callback functions I can provide it take a void* as a parameter so you can pass arbitrary stuff to them. For the sake of this question let's assume the lambda doesn't take any parameters, but it does capture stuff.
Now, I need to have my callback function invoke a lambda - and it must get this lambda somehow via the void *, i.e. we have
void my_callback(void * arbitrary_stuff) {
/* magic... and somehow the lambda passed */
/* through `arbitrary_stuff` is invoked. */
}
// ...
template <T>
void adapted_add_callback(MagicTypeInvolvingT actual_callback) {
/* more magic */
libFooAddCallback(my_callback, something_based_on_actual_callback);
}
// ...
void baz();
void bar() {
int x;
adapted_add_callback([x]() { /* do something with x */ });
adapted_add_callback(baz);
}
and I want to know what to replace magic, more_magic and MagicTypeInvolvingT with.
Other than the typing challenge here, what I'm worried about, obviously, is how to make sure the data the lambda encapsulates is available on the stack for eventual use, as otherwise I should probably get some kind of segmentation fault.
Notes:
my_callback() should be synchronous, in the sense that it'll execute the lambda on whatever thread it is on and return when it returns. It's either the fooLibrary or the lambda itself which do asynchronicity.
the most straightforward way might be ( assuming the C function is guaranteed to invoke the callback exactly once, and that the lambda is valid at callback point )
void my_callback(void * arbitrary_stuff) {
(*std::unique_ptr{ static_cast<std::function<void()>*>(arbitrary_stuff) })();
}
void adapted_add_callback( std::function<void()> actual_callback ) {
libFooAddCallback(my_callback, new auto( std::move(actual_callback) ) );
}
if you don't want the function<> overhead you'll need to implement your own type erasure ...
You have a couple of issues here.
One is that you can't depend on passing the lambda itself as a void *, so you'll pretty much need to pass a pointer to the lambda (well, the closure created from the lambda, if you want to be precise). That means you'll need to ensure that the lambda remains valid until the callback completes.
The second is a question about how those captures happen - capture by value, or by reference? If you capture by value, everything's fine. If you capture by reference, you also need to ensure that anything you've captured remains valid until the callback completes. If you capture a global by reference, that should normally be fine--but if you capture a local by reference, then the local (even potentially) goes out of scope before the lambda is invoked, using the reference will cause undefined behavior.
I went in a way similar to Massimiliano Janes', but without the overhead of std::function. You have to ensure that the callback is called only once by the library.
using Callback = void(*)(void*);
// Probes the type of the argument and generates a suitable cast & invoke stub
// Caution: self-destructs after use!
template <class F>
Callback cbkWrap(F &) {
return [](void *data) {
std::unique_ptr<F> retrieved(static_cast<F*>(data));
(*retrieved)();
};
}
// Moves the functor into a dynamically-allocated one
template <class F>
void *cbkFunc(F &f) {
return new F{std::move(f)};
}
int main() {
int x = 42;
auto lambda = [&x] { std::cout << x << '\n'; };
libFooAddCallback(cbkWrap(lambda), cbkFunc(lambda));
}
See it live on Coliru
If you can ensure that the lambda outlives the potential calls, you can get rid of the dynamic memory allocations and simply pas a pointer to it as data:
// Probes the type of the argument and generates a suitable cast & invoke stub
template <class F>
Callback cbkWrap(F &) {
return [](void *data) {
auto retrieved = static_cast<F*>(data);
(*retrieved)();
};
}
int main() {
int x = 42;
auto lambda = [&x] { std::cout << x << '\n'; };
libFooAddCallback(cbkWrap(lambda), &lambda);
}
See it live on Coliru
There is unfortunately no way to give ownership of the lamba to the library without knowing exactly how many times it will be called.

Can I declare a variable inside a lambda capture clause?

I want to submit a handle but I only want it to be executed if a shared pointer is still valid:
// elsewhere in the class:
std::shared_ptr<int> node;
// later on:
const std::weak_ptr<int> slave(node); // can I do this in the capture clause somehow?
const auto hook = [=]()
{
if (!slave.expired())
//do something
else
// do nothing; the class has been destroyed!
};
someService.Submit(hook); // this will be called later, and we don't know whether the class will still be alive
Can I declare slave within the capture clause of the lambda? Something like const auto hook = [std::weak_ptr<int> slave = node,=]().... but unfortunately this doesn't work. I would like to avoid declaring the variable and then copying it (not for performance reasons; I just think it would be clearer and neater if I could create whatever the lambda needs without polluting the enclosing scope).
You can do this using generalized lambda captures in C++14:
const auto hook = [=, slave = std::weak_ptr<int>(node)]()
{
...
};
Here's a live example. Note that since there are no parameters or explicit return type, the empty parameter list (()) can be left out.
As mentioned by chris this is possible in C++14.
If you are willing to modify the captured value simply add mutablespecifier.
Here is an example which fills a vector from zero to the length of the vector.
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> container(10);
std::generate(container.begin(), container.end(), [n = 0]() mutable { return n++; });
for (const auto & number : container)
{
std::cout << number << " ";
}
std::cin.ignore();
return 0;
}