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 \"bl
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
class shared_this_lambda {
std::shared_ptr t; // just for lifetime
F f;
public:
shared_this_lambda(std::shared_ptr t, F f): t(t), f(f) {}
template
auto operator()(Args &&...args)
-> decltype(this->f(std::forward(args)...)) {
return f(std::forward(args)...);
}
};
template
struct enable_shared_this_lambda {
static_assert(std::is_base_of, T>::value,
"T must inherit enable_shared_from_this");
template
auto make_shared_this_lambda(F f) -> shared_this_lambda {
return shared_this_lambda(
static_cast(this)->shared_from_this(), f);
}
template
auto make_shared_this_lambda(F f) const -> shared_this_lambda {
return shared_this_lambda(
static_cast(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;
}));