Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lifetime of a temporary captured by reference in a closure stored in a class

Consider the following code snippet:

struct foo { };

template <typename F>
struct impl : F
{
    impl(F&& f) : F{std::move(f)} { }
    auto get() { return (*this)(); }
};

template <typename X>
auto returner(X&& x)
{
    return impl{[&x]{ return x; }};
//               ^~
}

int main()
{
    auto x = returner(foo{}).get();
}

live example on wandbox.org


  • Is it guaranteed that foo{} will be alive for the entire duration of the returner(foo{}).get() expression?

  • Or is foo{} going to be alive only for returner(foo{}), thus causing undefined behavior when invoking impl::get()?


The Standard says in [class.temporary]:

Temporary objects are destroyed as the last step in evaluating the full-expression that (lexically) contains the point where they were created.

In [intro.execution]

A full-expression is

  • an unevaluated operand,

  • a constant-expression,

  • an init-declarator or a mem-initializer, including the constituent expressions of the initializer,

  • an invocation of a destructor generated at the end of the lifetime of an object other than a temporary object ([class.temporary]), or

  • an expression that is not a subexpression of another expression and that is not otherwise part of a full-expression.

I am not sure whether or not the full-expression related to foo{} is returner(foo{}) or returner(foo{}).get().

like image 407
Vittorio Romeo Avatar asked Dec 23 '22 11:12

Vittorio Romeo


1 Answers

The important section here is that:

A full-expression is [...] an expression that is not a subexpression of another expression and that is not otherwise part of a full-expression.

So in returner(foo{}).get(), returner(foo{}) is a subexpression of the expression returner(foo{}).get(), so it's not a full-expression. Hence:

Is it guaranteed that foo{} will be alive for the entire duration of the returner(foo{}).get() expression?

Yes.

like image 140
Barry Avatar answered Jan 19 '23 00:01

Barry