Passing forwarding reference as lambda capture

Consider following code:

template <typename C>
void boo (C&& c) {
    c ();
}

template <typename T>
void foo (T&& v) { // (X)
    boo ([&v] () { some_func (std::forward<T> (v)); }); // (Y)
}

As far as I am concerned v in (X) is a forwarding reference. Is v also a forwarding reference in (Y) if it was captured by reference? Or should I write it differently to take advantage of forwarding?

Answer

As far as I am concerned v in (X) is a forwarding reference.

Correct.


Is v also a forwarding reference in (Y) if it was captured by reference?

No, v inside the body of the lambda refers to the anonymous closure instance’s member variable v. Read

some_func (std::forward<T> (v));

as

some_func (std::forward<T> (this_closure->v));

Regardless, your use of std::forward here is correct – it will propagate temporariness if the v passed to foo was an rvalue.

This is because std::forward<X>(x) does this:

  • If X is a value type or an rvalue reference type, it casts x to X&&.

  • If X is an lvalue reference type, it casts x to X&.

v inside the lambda body is always an lvalue, but std::forward<T> depends on the type of the original type passed to foo.

If you are sure that the lambda will be invoked once in the same call stack as the foo invocation, it is safe to capture by reference and forward in the body.

Otherwise, you might want to “capture by perfect-forwarding”.

Leave a Reply

Your email address will not be published. Required fields are marked *