Get a reference to the lambda's captured value - c++

I am using a function (not mine, from a library I don't control) with a signature similar to this:
template<typename T, typename F>
void do_async(T const&, F); // the second parameter is a callable
and it usually used like this
do_async(obj, [this](){ ... });
I wrote a function similar to this that always uses the same callback lambda:
template<typename T>
void do_async_wrapper(T obj) {
do_async(obj, [this](){ ... });
}
My problems stem from the fact that since the obj is passed as a reference, it has to be kept alive until the callback is called. My function is supposed to take care of that so the caller doesn't have to worry about object lifetime. That is why it accepts by value.
I would like to do something like this in order to keep it alive:
template<typename T>
void do_async_wrapper(T obj) {
do_async(obj, [this, obj{std::move(obj)}](){ ... });
}
Obviously this wont (always) work as-is since the reference points to the function-local one which doesn't exist anymore, while the one kept alive is a (move-)copy of it.
Any suggestions?

As the functor is taken by value, you cannot store the object directly in the functor and pass a reference to it.
You may work-around that by using smart pointer as shared_ptr:
template<typename T>
void do_async_wrapper(T obj) {
auto ptr = std::make_shared<T>(std::move(obj));
do_async(*ptr, [this, ptr](){ /*...*/ });
}

Related

Passing a mutable lambda with unique_ptr into a const& std::function

I have got a dispatch function which executes a given lambda in a main thread. For the sake of this question, suppose it looks like the following:
void dispatch(const std::function<void()>& fn) {
fn();
}
I need to load a new object in a new thread without interrupting the main thread. So I do the following: 1) start a new thread and create a new unique pointer inside the thread, 2) call dispatch and propagate the new unique pointer where it belongs.
std::unique_ptr<std::string> foo; // nullptr
// do the loading in a new thread:
std::thread t([&](){
// in the new thread, load new value "Blah" and store it temporarily
auto bar = std::make_unique<std::string>("Blah");
dispatch([bar2 = std::move(bar), &foo]() mutable {
foo = std::move(bar2); // propagate the loaded value to foo
});
});
t.join(); // for the sake of this example
std::cout << "foo = " << *foo << std::endl; // this should say: foo = Blah
Run example online: http://cpp.sh/5zjvm
This code does not compile because the inner lambda in dispatch is mutable and so does not fit into dispatch(const std::function<void()>& fn) which requires a const&.
The lambda, however, needs to be mutable because it needs to call std::move on the unique pointers.
This code could be fixed for example by changing dispatch to:
template <typename Fn>
void dispatch(Fn fn) {
fn();
}
Unfortunately, the dispatch function is an API of a library and I cannot change it.
Is there a way out of this problem without getting rid of unique pointers?
No, that isn't your problem.
Your problem is that your lambda cannot be copied, as it has a unique ptr captured by value in it.
std::function<Sig> type erases down to
Invoke with Sig
Destroy
Copy (and sometimes move)
Cast-back-to-original-type
Your lambda cannot be copied, so cannot be stored in a std::function.
The lazy-coder's solution is:
dispatch([bar2 = std::make_shared<decltype(bar)>(std::move(bar)), &foo]() mutable {
foo = std::move(*bar2);
});
where we shove the non-copyable state into a shared_ptr.

Prevent copy-construction with make_shared

I have a manager class that allow clients to add components through two methods: one with no argument that default-construct the component and another one that takes an rvalue (which should allow client to use a custom constructor of the component).
Here's the code I came up with:
template <class TComponent>
std::shared_ptr<TComponent> AddComponent()
{
return AddComponent(TComponent{ this });
}
template <class TComponent>
std::shared_ptr<TComponent> AddComponent(const TComponent &&obj)
{
auto ptr = std::make_shared<TComponent>(obj);
vec.push_back(ptr);
return ptr;
}
The problem I have is that std::make_shared always copy-constructs the object. Is there a way to prevent this behavior?
I read about perfect forwarding but it doesn't seem to help here.
I read about perfect forwarding but it doesn't seem to help here.
I don't see why it wouldn't.
Simply remove the const to make move construction possible, and add std::forward:
template <class TComponent>
std::shared_ptr<TComponent> AddComponent(TComponent &&obj)
{
auto ptr = std::make_shared<TComponent>(std::forward<TComponent>(obj));
vec.push_back(ptr);
return ptr;
}
Now, rvalues will be moved. Lvalues will be copied which you cannot avoid.

return lambda by rvalue ref?

#include <iostream>
#include <functional>
template <typename... Args>
std::function<void(Args...)> pushToEventLoop(std::function<void(Args...)> && p_function)
{
auto func = [p_function](Args... args) ->void
{
// This is what i would do here, but requires too much source code
//ThreadPool::enque(std::bind(p_function, args...));
// This is what i'll do for the sake of the example.
p_function(args...);
};
return func;
}
int main()
{
auto function(pushToEventLoop(std::function<void(char const *)>(std::bind(std::printf, std::placeholders::_1))));
auto function2 = std::bind(function, "Hello World!\n");
function2();
return 0;
}
Is it possible and how, to return the "func" variable by rvalue ref?
I have a feeling that this is somehow totally insane, but I'd like to know why, so I can restore my sanity.
I have no idea if i have done something horribly wrong. Please provide feedback.
I built this thing so that I can make callbacks that are actually just posted to the treadpool for processing, without the caller or the target knowing anything about this. The middleman that binds them together makes the choice of how to connect them.
https://ideone.com/4Wfhb1
EDIT
Ok, so I thought that there is copying going on when I return the func variable. But apparently it's dealt with by RVO, so no copying takes place. I have not verified this, but now that I think about it, that would make sense.
If your question is how to return a lamba in the most eficient way, then just return it by value and use automatic return typ deduction:
//this will actually return a lmabda and not a std::function
template <typename... Args>
auto pushToEventLoop(std::function<void(Args...)> && p_function)
{
return [f = std::move(p_function)](Args... args)
{
f(args...);
};
}
This will leverage RVO and avoid any dynamic memory allocations that std::function might have to perform.
Also having an r-value reference parameter usually doesn't gain you anything, if you don't move from it (unless you require that specific interface for another reason). In order to do so here you can leverage c++14's generalized lambda capture (the compiler can't perform that optimization by itself, as p_function itself is an l-value).
Now, if your question on the other hand was, if/how you can return a (r- or l-value) reference to a non-static local variable from a function, then the answer is simply:
NEVER DO THAT!
I think what you're trying to do is to move p_function into your lambda while avoiding copies? Presumably this is for performance reasons?
In which case you probably want to write it like this:
template <typename... Args>
// return by value - because RVO will elide copies for us
std::function<void(Args...)>
// passing by r-value reference... ok no problem there
pushToEventLoop(std::function<void(Args...)> && p_function)
{
// but I want to MOVE my p_function into func
// this will require at least c++1y (c++14)
auto func = [p_function = std::move(p_function)](Args... args) ->void
{
// p_function has now been moved into the lambda ...
};
// ... p_function passed to us is now in a valid but undefined state
// so don't use it here
// allow RVO to do its thing
return func;
}

Extending lifetime of temporary - proper way

Say I have:
f(T& t){ ... }
which I sometimes want to provide argument for from a function call
T GetT() { ... }
like this:
f(GetT())
Which won't compile even though I'm convinced that the lifetime of T is guaranteed to last until the end of expression, I also cannot change the T& to const T& because I need to modify the object inside f.
I thought about using T&& but then when I happen to have lvalue of T I would need to move() it, which would make it awkward because I sometimes need to use T after the call to f. In my case T is plain old data so I guess it would work but it doesn't feel right to move an object and use it afterwards.
Is there an elegant way to allow function to take both rval and lval refs to mutable object?
ATM I'm just doing
T t = GetT();
f(t);
Which I feel is at least one useless line and one useless copy of T.
How about using universal references.
Not sure if you would consider it elegant but it would look something like this:
struct MyStruct
{
int i;
};
template<class T>
void foo(T&& t)
{
static_assert(std::is_base_of<MyStruct,
typename std::remove_reference<T>::type>::value, "ERROR");
t.i = 1024;
}
MyStruct GetMyStruct()
{
return MyStruct();
}
int main()
{
foo(GetMyStruct());
MyStruct ms;
foo(ms);
return 0;
}
The way that you're currently doing, i.e. storing the object in a variable, is a proper way to extend the lifetime of the returned object and allow non-const references to bind to it. If GetT is implemented so that (N)RVO is possible, then no useless copy need to be made because it can be elided.
I came up with a solution to my problem with simple overload:
f(T& t) { ... }
f(T&& t) { f(t); }
But there still has to be a better way.
You cannot bind a reference to a temporany: only const reference can do that.
I suggesto you to look this link C++11 binding rules for const &&

Using C++11 lambdas asynchronously, safely

I've come to C++11 from an Objective-C background, and one thing I'm struggling to come to terms with is the different capturing semantics of C++11 lambdas vs Objective-C "blocks". (See here for a comparison).
In Objective-C, like C++, the self/this pointer is implicitly captured if you refer to a member variable. But because all objects in Objective-C are effectively "shared pointers", to use the C++ terminology, you can do this:
doSomethingAsynchronously(^{
someMember_ = 42;
});
... and you're guaranteed that the object whose member you're accessing will be alive when the block executes. You don't have to think about it. The equivalent in C++ seems to be something like:
// I'm assuming here that `this` derives from std::enable_shared_from_this and
// is already owned by some shared_ptr.
auto strongThis = shared_from_this();
doSomethingAsynchronously([strongThis, this] {
someMember_ = 42; // safe, as the lambda holds a reference to this
// via shared_ptr.
});
Here, you need to remember to capture the shared_ptr in addition to the this pointer. Is there some less error-prone way of achieving this?
One of the founding principles of C++ is that you don't pay for what you don't use. That means in this case that contexts where taking a shared_ptr to this is unnecessary shouldn't incur any reference counting overhead. This also means that it shouldn't happen automatically even e.g. as a feature of enable_shared_from_this, since you might want to pass a short-lived lambda to an algorithm (for_each, etc.) in which case the lambda doesn't outlive its scope.
I'd suggest adapting the lambda-wrapper pattern; in that case it's used for move capture of a large object (How to capture std::unique_ptr "by move" for a lambda in std::for_each), but it can equally be used for shared capture of this:
template<typename T, typename F>
class shared_this_lambda {
std::shared_ptr<T> t; // just for lifetime
F f;
public:
shared_this_lambda(std::shared_ptr<T> t, F f): t(t), f(f) {}
template<class... Args>
auto operator()(Args &&...args)
-> decltype(this->f(std::forward<Args>(args)...)) {
return f(std::forward<Args>(args)...);
}
};
template<typename T>
struct enable_shared_this_lambda {
static_assert(std::is_base_of<std::enable_shared_from_this<T>, T>::value,
"T must inherit enable_shared_from_this<T>");
template<typename F>
auto make_shared_this_lambda(F f) -> shared_this_lambda<T, F> {
return shared_this_lambda<T, F>(
static_cast<T *>(this)->shared_from_this(), f);
}
template<typename F>
auto make_shared_this_lambda(F f) const -> shared_this_lambda<const T, F> {
return shared_this_lambda<const T, F>(
static_cast<const T *>(this)->shared_from_this(), f);
}
};
Use by inheriting enable_shared_this_lambda in addition to enable_shared_from_this; you can then explicitly request that any long-lived lambdas take a shared this:
doSomethingAsynchronously(make_shared_this_lambda([this] {
someMember_ = 42;
}));
Boost uses:
auto self(shared_from_this());
auto l = [this, self] { do(); };
Mentioned here: What's the reason of using auto self(shared_from_this()) variable in lambda function?
Actually, there's one right answer to this problem. The answer has the exact same effect of binding with shared_from_this() (like when you do it with boost::asio::io_service). Think about it; what does binding with shared_from_this() do? It simple replaces this. So what prevents you from replacing this with shared_from_this() totally?
Following your example, which I updated to make the difference clearer, instead of this:
auto strongThis = shared_from_this();
doSomethingAsynchronously([strongThis, this] () {
this->someMember_ = 42; //here, you're using `this`... that's wrong!
});
Do this:
auto strongThis = shared_from_this();
doSomethingAsynchronously([strongThis] () //notice, you're not passing `this`!
{
strongThis->someMember_ = 42;
});
The only cost here is that you're gonna have to prefix everything with strongThis->. But this is the most meaningful way to do it.