Title
Lifetime of temporaries in range-based for
Status
c++23
Section
6.7.7 [class.temporary]
Submitter
Thomas J. Gritzan

Created on 2009-05-12.00:00:00 last changed 15 months ago

Messages

Date: 2017-02-15.00:00:00

Notes from the February, 2017 meeting:

CWG was inclined to accept the suggested change but felt that EWG involvement was necessary prior to such a decision.

Date: 2022-11-20.07:54:16

Additional notes, February, 2017:

Posting from Daniel Frey to the std-discussion group:

Some people have tried

  namespace detail {
    template< class C > struct reverse_range {
      explicit reverse_range (C& _c) : c(_c) {}
      auto begin () { using std::rbegin; return rbegin(c); }
      auto end () { using std::rend; return rend(c); }
     private:
      C& c;
    };
  }

  template< class C > auto reverse (C& c) {
    return detail::reverse_range<C>{c};
  }

In an attempt to allow:

  // some function
  std::vector<int> foo();

  // correct usage
  auto v = foo();
  for( auto i : reverse(v) ) { std::cout << i << std::endl; }

  // problematic usage
  for( auto i : reverse(foo()) ) { std::cout << i << std::endl; }

The problem is that the temporary returned by foo() is destructed before the loop starts executing. [This issue] was supposed to be about that, but considers only the top-level temporary.

It might be reasonable to make the range-based for treat the for-range-initializer like a function argument: all temporaries of the expression should be destructed after the execution of the loop. This also removes the only place where binding a reference to a temporary extends its lifetime implicitly, unseen by the user.

Date: 2009-10-15.00:00:00

Rationale (October, 2009):

In the expansion, expression is used to initialize a reference. If expression is a temporary, its lifetime is thus extended to that of the reference, which is the entire for statement.

Date: 2022-11-15.00:00:00

[Accepted at the November, 2022 meeting as part of paper P2718R0.]

Temporaries created in the expression of the range-based for statement are not given special treatment, so they only persist to the end of the expression. This can lead to undefined behavior as __range and the iterators are used in the expansion of the statement. Such temporaries should have their lifetimes extended until the end of the statement.

History
Date User Action Args
2023-07-16 13:00:43adminsetstatus: open -> c++23
2023-07-16 13:00:43adminsetstatus: drwp -> open
2023-02-18 18:43:04adminsetstatus: dr -> drwp
2022-11-25 05:14:04adminsetstatus: drwp -> dr
2022-11-20 07:54:16adminsetstatus: extension -> drwp
2018-02-27 00:00:00adminsetmessages: + msg6033
2018-02-27 00:00:00adminsetmessages: + msg6032
2018-02-27 00:00:00adminsetstatus: nad -> extension
2009-11-08 00:00:00adminsetmessages: + msg2486
2009-11-08 00:00:00adminsetstatus: open -> nad
2009-05-12 00:00:00admincreate