Skip to content

Commit 7fd53ea

Browse files
authored
Merge 2022-11 CWG Motion 12
P2718R0 Wording for P2644R1 Fix for Range-based for Loop
2 parents fb9c2f0 + 29e31fa commit 7fd53ea

File tree

3 files changed

+56
-7
lines changed

3 files changed

+56
-7
lines changed

source/basic.tex

+16-6
Original file line numberDiff line numberDiff line change
@@ -4317,7 +4317,7 @@
43174317
\pnum
43184318
\indextext{initializer!temporary and declarator}%
43194319
\indextext{temporary!order of destruction of}%
4320-
There are three contexts in which temporaries are destroyed at a different
4320+
There are four contexts in which temporaries are destroyed at a different
43214321
point than the end of the full-expression.
43224322
The first context is when a default constructor is called to initialize
43234323
an element of an array with no corresponding initializer\iref{dcl.init}.
@@ -4438,14 +4438,24 @@
44384438
\end{itemize}
44394439

44404440
\pnum
4441-
The destruction of a temporary whose lifetime is not extended by being
4442-
bound to a reference is sequenced before the destruction of every
4441+
The fourth context is when a temporary object other than a function parameter object
4442+
is created in the \grammarterm{for-range-initializer} of a range-based \keyword{for} statement.
4443+
If such a temporary object would otherwise be destroyed
4444+
at the end of the \grammarterm{for-range-initializer} full-expression,
4445+
the object persists for the lifetime of the reference
4446+
initialized by the \grammarterm{for-range-initializer}.
4447+
4448+
\pnum
4449+
The destruction of a temporary whose lifetime is not extended
4450+
beyond the full-expression in which it was created
4451+
is sequenced before the destruction of every
44434452
temporary which is constructed earlier in the same full-expression.
4444-
If the lifetime of two or more temporaries to which references are bound ends
4445-
at the same point,
4453+
If the lifetime of two or more temporaries
4454+
with lifetimes extending beyond the full-expressions in which they were created
4455+
ends at the same point,
44464456
these temporaries are destroyed at that point in the reverse order of the
44474457
completion of their construction.
4448-
In addition, the destruction of temporaries bound to references shall
4458+
In addition, the destruction of such temporaries shall
44494459
take into account the ordering of destruction of objects with static, thread, or
44504460
automatic storage duration\iref{basic.stc.static,basic.stc.thread,basic.stc.auto};
44514461
that is, if

source/compatibility.tex

+23
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,29 @@
6969
// now equivalent to \tcode{arr.operator[](1, 2)} or ill-formed
7070
\end{codeblock}
7171

72+
\rSec2[diff.cpp20.stmt]{\ref{stmt.stmt}: statements}
73+
74+
\diffref{stmt.ranged}
75+
\change
76+
The lifetime of temporary objects in the \grammarterm{for-range-initializer}
77+
is extended until the end of the loop\iref{class.temporary}.
78+
\rationale
79+
Improve usability of the range-based \keyword{for} statement.
80+
\effect
81+
Destructors of some temporary objects are invoked later.
82+
For example:
83+
\begin{codeblock}
84+
void f() {
85+
std::vector<int> v = { 42, 17, 13 };
86+
std::mutex m;
87+
88+
for (int x :
89+
static_cast<void>(std::lock_guard<std::mutex>(m)), v) { // lock released in \CppXX
90+
std::lock_guard<std::mutex> guard(m); // OK in \CppXX, now deadlocks
91+
}
92+
}
93+
\end{codeblock}
94+
7295
\rSec2[diff.cpp20.dcl]{\ref{dcl.dcl}: declarations}
7396

7497
\diffref{dcl.init.string}

source/statements.tex

+17-1
Original file line numberDiff line numberDiff line change
@@ -704,14 +704,30 @@
704704
\end{note}
705705
\end{itemize}
706706
\end{itemize}
707-
708707
\begin{example}
709708
\begin{codeblock}
710709
int array[5] = { 1, 2, 3, 4, 5 };
711710
for (int& x : array)
712711
x *= 2;
713712
\end{codeblock}
714713
\end{example}
714+
\begin{note}
715+
The lifetime of some temporaries in the \grammarterm{for-range-initializer}
716+
is extended to cover the entire loop\iref{class.temporary}.
717+
\end{note}
718+
\begin{example}
719+
\begin{codeblock}
720+
using T = std::list<int>;
721+
const T& f1(const T& t) { return t; }
722+
const T& f2(T t) { return t; }
723+
T g();
724+
725+
void foo() {
726+
for (auto e : f1(g())) {} // OK, lifetime of return value of \tcode{g()} extended
727+
for (auto e : f2(g())) {} // undefined behavior
728+
}
729+
\end{codeblock}
730+
\end{example}
715731

716732
\pnum
717733
In the \grammarterm{decl-specifier-seq} of a \grammarterm{for-range-declaration},

0 commit comments

Comments
 (0)