Topic: Aggregated exceptions: Reversing destructor
Author: denis <isocppgroup@denisbider.com>
Date: Sat, 18 Jul 2015 02:15:27 -0700 (PDT)
Raw View
------=_Part_2647_1499913715.1437210927034
Content-Type: multipart/alternative;
boundary="----=_Part_2648_1720161856.1437210927034"
------=_Part_2648_1720161856.1437210927034
Content-Type: text/plain; charset=UTF-8
Hey everyone!
I want to discuss a problem which I believe is limiting C++ unnecessarily
in its potential for powerful expression. The problem is the *single-exception
policy*, and its direct consequence: the marginalization of destructors,
exemplified in recent years by how they're now marked noexcept.
I believe this problem is currently viewed incorrectly by many, and I wish
to propose a solution. The solution is aggregated exceptions. I contend
these are conceptually simple; resolve the Gordian knot of destructor
exceptions; are backward compatible, and straightforward to implement. :-)
There is a widespread belief, held passionately by many, which I believe to
be conceptually in error. This is that destructors are supposed to be
nothing more than little cleanup dwarves. That they should only:
(1) quietly release resources, and
(2) *kindly shut up *about any errors.
I find this a limiting and restrictive view, which does not permit full
expression of destructors as a way to:
(1) schedule code for execution;
(2) determine the order of execution; but
(3) not dictate the exact trigger for execution to take place.
I propose that the limiting view of destructors is not inherently obvious,
but is an accidental ideology. It arises not because we freely choose
this, but because of a little flaw that has plagued C++ since the time it
first introduced exceptions. This flaw is the single-exception policy,
which prevents good answers to questions such as:
- What to do when a destructor throws, and an exception is already in
flight?
- What to do if we're destroying a container, and destructors throw for 2
or more of the contained objects?
I propose the single-exception policy is unnecessarily limiting; that we
should not have to cope with not having answers for these questions in this
day and age; and that support for unlimited aggregated exceptions trivially
answers them.
It is true that support for multiple exceptions is necessary only for use
by destructors. However:
- The support I propose is *conceptually simple*.
- It legitimizes exceptions in destructors, and provides means for *containers
to handle them*.
- It provides a way for destructors to *report errors*. This is something
for which there is currently no solid language support, outside of
std::terminate.
- It emancipates destructors as a way to schedule code for execution. This
is to say any code; even code that may throw. This is a frequent usage
pattern e.g. in database libraries.
The use of destructors for general execution scheduling, rather than only
cleanup, is recognized as something the language *needs* to
support. Currently, it is supported reluctantly: if you want to throw, you
better use noexcept(false); and you better not store an object like that in
a container!
*I propose we can solve this as follows:*
(1) The internal representation of an exception in flight is changed from a
single exception to a list of exceptions. Let's call this the
exception-list.
(2) std::exception_ptr now points to the beginning of the exception-list,
rather than a single exception. Methods are added to std::exception_ptr
allowing a catch handler to walk the exception-list.
(3) When the stack is being unwound due to an exception in flight; and a
destructor exits with another exception; instead of calling std::terminate,
the new exception is simply added to the end of the exception-list.
This is all.
The above is all that's required. These three changes are sufficient:
(A) to emancipate destructors as first-class code, and allow them to use
language functionality to report errors;
(B) to allow containers to aggregate destructor exceptions;
(C) to allow catch handlers to process aggregated exceptions.
However, we can improve our quality of life by introducing syntactic sugar.
The following are suggestions for how this could be done.
For container implementors, we introduce syntax:
try (<std::exception_ptr&>) {
This adds optional parentheses after "try", which if present, changes the
meaning of the try block to: catch any exception-list that exits this
block, and aggregate it to exception_ptr, which is passed by reference. If
the exception_ptr is empty, then it receives the exception-list that exited
the block. If it is non-empty, the two exception-lists are combined.
This allows for practical aggregation of exceptions in containers that
execute many destructors. The same goal could be achieved with a manual
try-catch block, and this could be used in a macro; but special syntax is
cleaner.
*Catch handler considerations:*
- Traditional catch handlers only ever match the first exception in the
exception-list. Unless the program is multi-exception aware and has
modified the list, this is always the first exception that was thrown.
Traditional catch handlers can optionally use the newly added methods on
std::exception_ptr to investigate exceptions other than the first.
- If a traditional catch handler exits without exception, all exceptions in
the exception-list are considered handled. If it re-throws, the original
exception-list is re-thrown. If the handler throws a new exception, only
that new exception is thrown, and the previous exception-list is
disregarded (unless the handler did something to attach it to the new
exception, e.g. via std::nested_exception).
For handlers to be multi-exception aware, we can expect them to use
methods provided by std::exception_ptr to investigate the exception list;
or we may formalize new syntax.
For practicality, I favor new syntax. The following is a suggestion:
We introduce a new catch handler type:
catch (..., <exception-type>) {
Let's call this a "catch-any" handler. It has the following characteristics:
- It matches every occurrence of a matching exception in an exception-list.
This means it can be called repeatedly, multiple times per scope, if there
are multiple matches. We cannot do multiple calls to traditional handlers,
because traditional handlers are not necessarily multi-exception aware, and
do not expect to be called multiple times in a row.
- All catch-any handlers must appear BEFORE traditional catch handlers in
same scope. This is because the catch-any handler filters the list of
exceptions, but the traditional catch handler will be the ultimate handler
if it matches (unless it re-throws).
- If there are multiple catch-any handlers in the same scope, they will be
called potentially repeatedly, and in an order that depends on the order of
exceptions in the exception-list.
- If a catch-any handler throws or re-throws, the new exception is placed
back into the list of exceptions currently being processed, at the same
position as the exception that triggered the handler. If there remain
exceptions in the list, the search of catch-any handlers continues, and the
same catch-any handler might again be executed for another exception in the
list.
- If a catch-any handler exits without exception, the exception that
matched the handler is removed from exception-list. If this was the last
exception, forward progress resumes outside of catch handlers. If more
exceptions are in list, other catch-any handlers at current scope are
tested; then any catch handlers at current scope are tested; and if there's
no match, unwinding continues at the next scope.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2648_1720161856.1437210927034
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><p>Hey everyone!</p><div><br></div><div>I want to=C2=A0dis=
cuss a problem which I believe is limiting C++ unnecessarily in its potenti=
al for powerful expression. The problem is the <strong>single-exception pol=
icy</strong>, and its direct consequence: the marginalization of destructor=
s, exemplified in recent years by=C2=A0how they're now marked=C2=A0<fon=
t face=3D"courier new,monospace">noexcept</font>.</div><div><br></div><div>=
I believe this problem is currently viewed incorrectly by many, and I wish =
to propose a solution. The solution is aggregated exceptions. I contend the=
se are conceptually simple; resolve the Gordian knot of destructor exceptio=
ns; are backward compatible, and straightforward to implement. :-)</div><di=
v><br></div><div>There is a=C2=A0widespread belief, held passionately by ma=
ny, which I believe to be conceptually in error. This is that destructors a=
re supposed to be nothing more than little cleanup dwarves. That they shoul=
d only:</div><div><br></div><div>(1) quietly release resources, and</div><d=
iv>(2) <strong>kindly shut up </strong>about any errors.</div><div><br></di=
v><div>I find this a limiting and restrictive view, which does not permit f=
ull expression of destructors as a way to:</div><div><br></div><div>(1) sch=
edule code for execution;</div><div>(2) determine the order of execution; b=
ut</div><div>(3) not dictate the exact trigger for execution to take place.=
</div><div><br></div><div>I propose that the limiting view of destructors i=
s not inherently obvious, but is an accidental ideology.=C2=A0It arises=C2=
=A0not because we freely choose this,=C2=A0but because of a little flaw tha=
t has plagued C++ since the time it first introduced exceptions. This flaw=
=C2=A0is the single-exception policy, which=C2=A0prevents good answers to q=
uestions such as:</div><div><br></div><div>- What to do when a destructor t=
hrows, and an exception is already in flight?</div><div>- What to do if we&=
#39;re destroying a container, and destructors throw for 2 or more of the c=
ontained objects?</div><div><br></div><div>I propose the single-exception p=
olicy is unnecessarily limiting; that we should not have to cope with not h=
aving answers for these questions in this day and age;=C2=A0and that suppor=
t for unlimited aggregated exceptions trivially answers them.</div><div><br=
></div><div>It is true that support for multiple exceptions is necessary on=
ly for use by destructors. However:</div><div><br></div><div>-=C2=A0The sup=
port I propose is <strong>conceptually simple</strong>.</div><div>- It legi=
timizes exceptions in destructors, and provides means for <strong>container=
s to handle them</strong>.</div><div>- It provides a way for destructors to=
<strong>report errors</strong>. This is something for which there is curre=
ntly no solid language support, outside of <font face=3D"courier new,monosp=
ace">std::terminate</font>.</div><div>- It emancipates destructors as a way=
to schedule code for execution. This is to say any code; even code that ma=
y throw. This is a frequent usage pattern e.g. in database libraries. </div=
><div><br></div><div>The=C2=A0use of destructors for=C2=A0general execution=
scheduling, rather than only cleanup,=C2=A0is recognized as something the =
language <em>needs</em> to support.=C2=A0Currently,=C2=A0it is supported re=
luctantly:=C2=A0if you want to throw,=C2=A0you better use=C2=A0<font face=
=3D"courier new,monospace">noexcept(false);</font> and you better not store=
an object like that in a container!</div><div><br></div><div><strong>I pro=
pose we can solve this as follows:</strong></div><div><br></div><div>(1) Th=
e internal representation of an exception in flight is changed from a singl=
e exception to a list of exceptions. Let's call this the exception-list=
..</div><div><br></div><div>(2) <font face=3D"courier new,monospace">std::ex=
ception_ptr</font> now points to the beginning of the exception-list, rathe=
r than a single exception. Methods are added to <font face=3D"courier new,m=
onospace">std::exception_ptr</font> allowing a catch handler to walk the ex=
ception-list.</div><div><br></div><div>(3) When the stack is being unwound =
due to an exception in flight; and a destructor exits with another exceptio=
n; instead of calling <font face=3D"courier new,monospace">std::terminate</=
font>, the new exception is simply added to the end of the exception-list.<=
/div><div><br></div><div>This is all.</div><div><br></div><div>The above is=
all that's required. These three changes are sufficient:</div><div><br=
></div><div>(A) to emancipate destructors as first-class code,=C2=A0and all=
ow them to use language functionality=C2=A0to report errors;</div><div>(B) =
to allow containers to aggregate destructor exceptions;</div><div>(C) to al=
low catch handlers to process aggregated exceptions.</div><div><br></div><d=
iv>However,=C2=A0we can improve our quality of life by introducing syntacti=
c sugar. The following are suggestions for how this could be done.</div><di=
v><br></div><p>For container implementors, we introduce syntax:</p><div><br=
></div><div><font face=3D"courier new,monospace">=C2=A0 try (<std::excep=
tion_ptr&>) {</font></div><div><br></div><div>This adds optional par=
entheses after "try", which if present, changes the meaning of th=
e try block to: catch any exception-list that exits this block, and aggrega=
te it to <font face=3D"courier new,monospace">exception_ptr</font>, which i=
s passed by reference. If the <font face=3D"courier new,monospace">exceptio=
n_ptr</font> is empty, then it receives the exception-list that exited the =
block. If it is non-empty, the two exception-lists are combined.</div><div>=
<br></div><div>This allows for practical aggregation of exceptions in conta=
iners that execute many destructors. The same goal could be achieved with a=
manual try-catch block,=C2=A0and this could be=C2=A0used=C2=A0in=C2=A0a ma=
cro; but special syntax is cleaner.<br>=C2=A0 <br><strong>Catch handler con=
siderations:</strong></div><div><br></div><div>- Traditional catch handlers=
only ever match the first exception in the exception-list. Unless the prog=
ram is multi-exception aware and has modified the list, this is always the =
first exception that was thrown. Traditional catch handlers can optionally =
use the newly added methods on <font face=3D"courier new,monospace">std::ex=
ception_ptr</font> to investigate exceptions other than the first.</div><di=
v><br></div><div>- If a traditional catch handler exits without exception, =
all exceptions in the exception-list are considered handled. If it re-throw=
s, the original exception-list is re-thrown. If the handler throws a new ex=
ception, only that new exception is thrown, and the previous exception-list=
is disregarded (unless the handler did something to attach it to the new e=
xception, e.g. via <font face=3D"courier new,monospace">std::nested_excepti=
on</font>).</div><div><br></div><div>For handlers to be multi-exception awa=
re, we can expect them to use methods=C2=A0provided by=C2=A0<font face=3D"c=
ourier new,monospace">std::exception_ptr</font> to investigate the exceptio=
n list; or we may formalize new syntax.</div><div><br></div><div>For practi=
cality, I favor new syntax. The following is a suggestion:</div><div><br></=
div><div>We introduce a new catch handler type:</div><div><br></div><div><f=
ont face=3D"courier new,monospace">=C2=A0 catch (..., <exception-type>=
;) {</font><br>=C2=A0 <br>Let's call this a "catch-any" handl=
er. It has the following characteristics:</div><div><br></div><div>- It mat=
ches every occurrence of a matching exception in an exception-list. This me=
ans it can be called repeatedly, multiple times per scope, if there are mul=
tiple matches. We cannot do multiple calls to traditional handlers, because=
traditional handlers are not necessarily multi-exception aware, and do not=
expect to be called multiple times in a row.</div><div><br></div><div>- Al=
l catch-any handlers must appear BEFORE traditional catch handlers in same =
scope. This is because the catch-any handler filters the list of exceptions=
, but the traditional catch handler will be the ultimate handler if it matc=
hes (unless it re-throws).</div><div><br></div><div>- If there are multiple=
catch-any handlers in the same scope, they will be called potentially repe=
atedly, and in an order that depends on the order of exceptions in the exce=
ption-list.</div><div><br></div><div>- If a catch-any handler throws or re-=
throws, the new exception is placed back into the list of exceptions curren=
tly being processed, at the same position as the exception that triggered t=
he handler. If there remain exceptions in the list, the search of catch-any=
handlers continues, and the same catch-any handler might again be executed=
for another exception in the list.</div><div><br></div><div>- If a catch-a=
ny handler exits without exception, the exception that matched the handler =
is removed from exception-list. If this was the last exception, forward pro=
gress resumes outside of catch handlers. If more exceptions are in list, ot=
her catch-any handlers at current scope are tested; then any catch handlers=
at current scope are tested; and if there's no match, unwinding contin=
ues at the next scope.</div><div><br></div><div><br></div><p><br></p></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2648_1720161856.1437210927034--
------=_Part_2647_1499913715.1437210927034--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Sat, 18 Jul 2015 03:33:16 -0700 (PDT)
Raw View
------=_Part_2670_872311420.1437215596193
Content-Type: multipart/alternative;
boundary="----=_Part_2671_133142274.1437215596193"
------=_Part_2671_133142274.1437215596193
Content-Type: text/plain; charset=UTF-8
One more addition to the core of this proposal. This may seem obvious, but
is not:
(4) User-provided destructors now use the same default noexcept
determination as other methods. (I.e., they are no longer marked
noexcept(false) if the compiler-generated destructor would be marked so.)
Perhaps there are other uses for noexcept machinery outside of what I'm
aware of, but it seems to me that his machinery is mainly ugly and
inelegant compensation for the language's inability to handle multiple
exceptions.
If we add support for aggregated exceptions, it seems to me the language
becomes simpler, and the need for noexcept would mostly go away.
On Saturday, July 18, 2015 at 3:15:27 AM UTC-6, denis wrote:
> Hey everyone!
>
> I want to discuss a problem which I believe is limiting C++ unnecessarily
> in its potential for powerful expression. The problem is the *single-exception
> policy*, and its direct consequence: the marginalization of destructors,
> exemplified in recent years by how they're now marked noexcept.
>
> I believe this problem is currently viewed incorrectly by many, and I wish
> to propose a solution. The solution is aggregated exceptions. I contend
> these are conceptually simple; resolve the Gordian knot of destructor
> exceptions; are backward compatible, and straightforward to implement. :-)
>
> There is a widespread belief, held passionately by many, which I believe
> to be conceptually in error. This is that destructors are supposed to be
> nothing more than little cleanup dwarves. That they should only:
>
> (1) quietly release resources, and
> (2) *kindly shut up *about any errors.
>
> I find this a limiting and restrictive view, which does not permit full
> expression of destructors as a way to:
>
> (1) schedule code for execution;
> (2) determine the order of execution; but
> (3) not dictate the exact trigger for execution to take place.
>
> I propose that the limiting view of destructors is not inherently obvious,
> but is an accidental ideology. It arises not because we freely choose
> this, but because of a little flaw that has plagued C++ since the time it
> first introduced exceptions. This flaw is the single-exception policy,
> which prevents good answers to questions such as:
>
> - What to do when a destructor throws, and an exception is already in
> flight?
> - What to do if we're destroying a container, and destructors throw for 2
> or more of the contained objects?
>
> I propose the single-exception policy is unnecessarily limiting; that we
> should not have to cope with not having answers for these questions in this
> day and age; and that support for unlimited aggregated exceptions trivially
> answers them.
>
> It is true that support for multiple exceptions is necessary only for use
> by destructors. However:
>
> - The support I propose is *conceptually simple*.
> - It legitimizes exceptions in destructors, and provides means for *containers
> to handle them*.
> - It provides a way for destructors to *report errors*. This is something
> for which there is currently no solid language support, outside of
> std::terminate.
> - It emancipates destructors as a way to schedule code for execution. This
> is to say any code; even code that may throw. This is a frequent usage
> pattern e.g. in database libraries.
>
> The use of destructors for general execution scheduling, rather than only
> cleanup, is recognized as something the language *needs* to
> support. Currently, it is supported reluctantly: if you want to throw, you
> better use noexcept(false); and you better not store an object like that
> in a container!
>
> *I propose we can solve this as follows:*
>
> (1) The internal representation of an exception in flight is changed from
> a single exception to a list of exceptions. Let's call this the
> exception-list.
>
> (2) std::exception_ptr now points to the beginning of the exception-list,
> rather than a single exception. Methods are added to std::exception_ptr
> allowing a catch handler to walk the exception-list.
>
> (3) When the stack is being unwound due to an exception in flight; and a
> destructor exits with another exception; instead of calling std::terminate,
> the new exception is simply added to the end of the exception-list.
>
> This is all.
>
> The above is all that's required. These three changes are sufficient:
>
> (A) to emancipate destructors as first-class code, and allow them to use
> language functionality to report errors;
> (B) to allow containers to aggregate destructor exceptions;
> (C) to allow catch handlers to process aggregated exceptions.
>
> However, we can improve our quality of life by introducing syntactic
> sugar. The following are suggestions for how this could be done.
>
> For container implementors, we introduce syntax:
>
> try (<std::exception_ptr&>) {
>
> This adds optional parentheses after "try", which if present, changes the
> meaning of the try block to: catch any exception-list that exits this
> block, and aggregate it to exception_ptr, which is passed by reference.
> If the exception_ptr is empty, then it receives the exception-list that
> exited the block. If it is non-empty, the two exception-lists are combined.
>
> This allows for practical aggregation of exceptions in containers that
> execute many destructors. The same goal could be achieved with a manual
> try-catch block, and this could be used in a macro; but special syntax is
> cleaner.
>
> *Catch handler considerations:*
>
> - Traditional catch handlers only ever match the first exception in the
> exception-list. Unless the program is multi-exception aware and has
> modified the list, this is always the first exception that was thrown.
> Traditional catch handlers can optionally use the newly added methods on
> std::exception_ptr to investigate exceptions other than the first.
>
> - If a traditional catch handler exits without exception, all exceptions
> in the exception-list are considered handled. If it re-throws, the original
> exception-list is re-thrown. If the handler throws a new exception, only
> that new exception is thrown, and the previous exception-list is
> disregarded (unless the handler did something to attach it to the new
> exception, e.g. via std::nested_exception).
>
> For handlers to be multi-exception aware, we can expect them to use
> methods provided by std::exception_ptr to investigate the exception list;
> or we may formalize new syntax.
>
> For practicality, I favor new syntax. The following is a suggestion:
>
> We introduce a new catch handler type:
>
> catch (..., <exception-type>) {
>
> Let's call this a "catch-any" handler. It has the following
> characteristics:
>
> - It matches every occurrence of a matching exception in an
> exception-list. This means it can be called repeatedly, multiple times per
> scope, if there are multiple matches. We cannot do multiple calls to
> traditional handlers, because traditional handlers are not necessarily
> multi-exception aware, and do not expect to be called multiple times in a
> row.
>
> - All catch-any handlers must appear BEFORE traditional catch handlers in
> same scope. This is because the catch-any handler filters the list of
> exceptions, but the traditional catch handler will be the ultimate handler
> if it matches (unless it re-throws).
>
> - If there are multiple catch-any handlers in the same scope, they will be
> called potentially repeatedly, and in an order that depends on the order of
> exceptions in the exception-list.
>
> - If a catch-any handler throws or re-throws, the new exception is placed
> back into the list of exceptions currently being processed, at the same
> position as the exception that triggered the handler. If there remain
> exceptions in the list, the search of catch-any handlers continues, and the
> same catch-any handler might again be executed for another exception in the
> list.
>
> - If a catch-any handler exits without exception, the exception that
> matched the handler is removed from exception-list. If this was the last
> exception, forward progress resumes outside of catch handlers. If more
> exceptions are in list, other catch-any handlers at current scope are
> tested; then any catch handlers at current scope are tested; and if there's
> no match, unwinding continues at the next scope.
>
>
>
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2671_133142274.1437215596193
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>One more addition to the core of this proposal. This=
=C2=A0may seem obvious, but is not:</div><div><br></div><div>(4) User-provi=
ded destructors now use the same default <font face=3D"courier new,monospac=
e">noexcept</font> determination as other methods. (I.e., they are no longe=
r marked <font face=3D"courier new,monospace">noexcept(false)</font> if the=
compiler-generated destructor would be marked so.)</div><div><br></div><di=
v>Perhaps there are other uses=C2=A0for <font face=3D"courier new,monospace=
">noexcept</font> machinery outside of what I'm aware of, but it seems =
to me that his machinery is mainly ugly and inelegant compensation for the =
language's inability to handle multiple exceptions.</div><div><br></div=
><div>If we add support for aggregated exceptions, it seems to me the langu=
age becomes simpler, and the need for <font face=3D"courier new,monospace">=
noexcept</font>=C2=A0would mostly go away.</div><div><br><br>On Saturday, J=
uly 18, 2015 at 3:15:27 AM UTC-6, denis wrote:</div><blockquote class=3D"gm=
ail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-le=
ft-color: rgb(204, 204, 204); border-left-width: 1px; border-left-style: so=
lid;"><div dir=3D"ltr"><p>Hey everyone!</p><div><br></div><div>I want to=C2=
=A0discuss a problem which I believe is limiting C++ unnecessarily in its p=
otential for powerful expression. The problem is the <strong>single-excepti=
on policy</strong>, and its direct consequence: the marginalization of dest=
ructors, exemplified in recent years by=C2=A0how they're now marked=C2=
=A0<font face=3D"courier new,monospace">noexcept</font>.</div><div><br></di=
v><div>I believe this problem is currently viewed incorrectly by many, and =
I wish to propose a solution. The solution is aggregated exceptions. I cont=
end these are conceptually simple; resolve the Gordian knot of destructor e=
xceptions; are backward compatible, and straightforward to implement. :-)</=
div><div><br></div><div>There is a=C2=A0widespread belief, held passionatel=
y by many, which I believe to be conceptually in error. This is that destru=
ctors are supposed to be nothing more than little cleanup dwarves. That the=
y should only:</div><div><br></div><div>(1) quietly release resources, and<=
/div><div>(2) <strong>kindly shut up </strong>about any errors.</div><div><=
br></div><div>I find this a limiting and restrictive view, which does not p=
ermit full expression of destructors as a way to:</div><div><br></div><div>=
(1) schedule code for execution;</div><div>(2) determine the order of execu=
tion; but</div><div>(3) not dictate the exact trigger for execution to take=
place.</div><div><br></div><div>I propose that the limiting view of destru=
ctors is not inherently obvious, but is an accidental ideology.=C2=A0It ari=
ses=C2=A0not because we freely choose this,=C2=A0but because of a little fl=
aw that has plagued C++ since the time it first introduced exceptions. This=
flaw=C2=A0is the single-exception policy, which=C2=A0prevents good answers=
to questions such as:</div><div><br></div><div>- What to do when a destruc=
tor throws, and an exception is already in flight?</div><div>- What to do i=
f we're destroying a container, and destructors throw for 2 or more of =
the contained objects?</div><div><br></div><div>I propose the single-except=
ion policy is unnecessarily limiting; that we should not have to cope with =
not having answers for these questions in this day and age;=C2=A0and that s=
upport for unlimited aggregated exceptions trivially answers them.</div><di=
v><br></div><div>It is true that support for multiple exceptions is necessa=
ry only for use by destructors. However:</div><div><br></div><div>-=C2=A0Th=
e support I propose is <strong>conceptually simple</strong>.</div><div>- It=
legitimizes exceptions in destructors, and provides means for <strong>cont=
ainers to handle them</strong>.</div><div>- It provides a way for destructo=
rs to <strong>report errors</strong>. This is something for which there is =
currently no solid language support, outside of <font face=3D"courier new,m=
onospace">std::terminate</font>.</div><div>- It emancipates destructors as =
a way to schedule code for execution. This is to say any code; even code th=
at may throw. This is a frequent usage pattern e.g. in database libraries. =
</div><div><br></div><div>The=C2=A0use of destructors for=C2=A0general exec=
ution scheduling, rather than only cleanup,=C2=A0is recognized as something=
the language <em>needs</em> to support.=C2=A0Currently,=C2=A0it is support=
ed reluctantly:=C2=A0if you want to throw,=C2=A0you better use=C2=A0<font f=
ace=3D"courier new,monospace">noexcept(false);</font> and you better not st=
ore an object like that in a container!</div><div><br></div><div><strong>I =
propose we can solve this as follows:</strong></div><div><br></div><div>(1)=
The internal representation of an exception in flight is changed from a si=
ngle exception to a list of exceptions. Let's call this the exception-l=
ist.</div><div><br></div><div>(2) <font face=3D"courier new,monospace">std:=
:exception_ptr</font> now points to the beginning of the exception-list, ra=
ther than a single exception. Methods are added to <font face=3D"courier ne=
w,monospace">std::exception_ptr</font> allowing a catch handler to walk the=
exception-list.</div><div><br></div><div>(3) When the stack is being unwou=
nd due to an exception in flight; and a destructor exits with another excep=
tion; instead of calling <font face=3D"courier new,monospace">std::terminat=
e</font>, the new exception is simply added to the end of the exception-lis=
t.</div><div><br></div><div>This is all.</div><div><br></div><div>The above=
is all that's required. These three changes are sufficient:</div><div>=
<br></div><div>(A) to emancipate destructors as first-class code,=C2=A0and =
allow them to use language functionality=C2=A0to report errors;</div><div>(=
B) to allow containers to aggregate destructor exceptions;</div><div>(C) to=
allow catch handlers to process aggregated exceptions.</div><div><br></div=
><div>However,=C2=A0we can improve our quality of life by introducing synta=
ctic sugar. The following are suggestions for how this could be done.</div>=
<div><br></div><p>For container implementors, we introduce syntax:</p><div>=
<br></div><div><font face=3D"courier new,monospace">=C2=A0 try (<std::ex=
ception_ptr&>) {</font></div><div><br></div><div>This adds optional =
parentheses after "try", which if present, changes the meaning of=
the try block to: catch any exception-list that exits this block, and aggr=
egate it to <font face=3D"courier new,monospace">exception_ptr</font>, whic=
h is passed by reference. If the <font face=3D"courier new,monospace">excep=
tion_ptr</font> is empty, then it receives the exception-list that exited t=
he block. If it is non-empty, the two exception-lists are combined.</div><d=
iv><br></div><div>This allows for practical aggregation of exceptions in co=
ntainers that execute many destructors. The same goal could be achieved wit=
h a manual try-catch block,=C2=A0and this could be=C2=A0used=C2=A0in=C2=A0a=
macro; but special syntax is cleaner.<br>=C2=A0 <br><strong>Catch handler =
considerations:</strong></div><div><br></div><div>- Traditional catch handl=
ers only ever match the first exception in the exception-list. Unless the p=
rogram is multi-exception aware and has modified the list, this is always t=
he first exception that was thrown. Traditional catch handlers can optional=
ly use the newly added methods on <font face=3D"courier new,monospace">std:=
:exception_ptr</font> to investigate exceptions other than the first.</div>=
<div><br></div><div>- If a traditional catch handler exits without exceptio=
n, all exceptions in the exception-list are considered handled. If it re-th=
rows, the original exception-list is re-thrown. If the handler throws a new=
exception, only that new exception is thrown, and the previous exception-l=
ist is disregarded (unless the handler did something to attach it to the ne=
w exception, e.g. via <font face=3D"courier new,monospace">std::nested_exce=
ption</font>).</div><div><br></div><div>For handlers to be multi-exception =
aware, we can expect them to use methods=C2=A0provided by=C2=A0<font face=
=3D"courier new,monospace">std::exception_ptr</font> to investigate the exc=
eption list; or we may formalize new syntax.</div><div><br></div><div>For p=
racticality, I favor new syntax. The following is a suggestion:</div><div><=
br></div><div>We introduce a new catch handler type:</div><div><br></div><d=
iv><font face=3D"courier new,monospace">=C2=A0 catch (..., <exception-ty=
pe>) {</font><br>=C2=A0 <br>Let's call this a "catch-any" =
handler. It has the following characteristics:</div><div><br></div><div>- I=
t matches every occurrence of a matching exception in an exception-list. Th=
is means it can be called repeatedly, multiple times per scope, if there ar=
e multiple matches. We cannot do multiple calls to traditional handlers, be=
cause traditional handlers are not necessarily multi-exception aware, and d=
o not expect to be called multiple times in a row.</div><div><br></div><div=
>- All catch-any handlers must appear BEFORE traditional catch handlers in =
same scope. This is because the catch-any handler filters the list of excep=
tions, but the traditional catch handler will be the ultimate handler if it=
matches (unless it re-throws).</div><div><br></div><div>- If there are mul=
tiple catch-any handlers in the same scope, they will be called potentially=
repeatedly, and in an order that depends on the order of exceptions in the=
exception-list.</div><div><br></div><div>- If a catch-any handler throws o=
r re-throws, the new exception is placed back into the list of exceptions c=
urrently being processed, at the same position as the exception that trigge=
red the handler. If there remain exceptions in the list, the search of catc=
h-any handlers continues, and the same catch-any handler might again be exe=
cuted for another exception in the list.</div><div><br></div><div>- If a ca=
tch-any handler exits without exception, the exception that matched the han=
dler is removed from exception-list. If this was the last exception, forwar=
d progress resumes outside of catch handlers. If more exceptions are in lis=
t, other catch-any handlers at current scope are tested; then any catch han=
dlers at current scope are tested; and if there's no match, unwinding c=
ontinues at the next scope.</div><div><br></div><div><br></div><p><br></p><=
/div></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2671_133142274.1437215596193--
------=_Part_2670_872311420.1437215596193--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Sat, 18 Jul 2015 03:35:03 -0700 (PDT)
Raw View
------=_Part_2655_1887312553.1437215703510
Content-Type: multipart/alternative;
boundary="----=_Part_2656_1965466464.1437215703510"
------=_Part_2656_1965466464.1437215703510
Content-Type: text/plain; charset=UTF-8
Correction: I meant of course noexcept(true).
This is what happens when you standardize double negatives as part of the
language. ;)
On Saturday, July 18, 2015 at 4:33:16 AM UTC-6, denis bider wrote:
> One more addition to the core of this proposal. This may seem obvious, but
> is not:
>
> (4) User-provided destructors now use the same default noexcept
> determination as other methods. (I.e., they are no longer marked
> noexcept(false) if the compiler-generated destructor would be marked so.)
>
> Perhaps there are other uses for noexcept machinery outside of what I'm
> aware of, but it seems to me that his machinery is mainly ugly and
> inelegant compensation for the language's inability to handle multiple
> exceptions.
>
> If we add support for aggregated exceptions, it seems to me the language
> becomes simpler, and the need for noexcept would mostly go away.
>
>
> On Saturday, July 18, 2015 at 3:15:27 AM UTC-6, denis wrote:
>
>> Hey everyone!
>>
>> I want to discuss a problem which I believe is limiting C++ unnecessarily
>> in its potential for powerful expression. The problem is the *single-exception
>> policy*, and its direct consequence: the marginalization of destructors,
>> exemplified in recent years by how they're now marked noexcept.
>>
>> I believe this problem is currently viewed incorrectly by many, and I
>> wish to propose a solution. The solution is aggregated exceptions. I
>> contend these are conceptually simple; resolve the Gordian knot of
>> destructor exceptions; are backward compatible, and straightforward to
>> implement. :-)
>>
>> There is a widespread belief, held passionately by many, which I believe
>> to be conceptually in error. This is that destructors are supposed to be
>> nothing more than little cleanup dwarves. That they should only:
>>
>> (1) quietly release resources, and
>> (2) *kindly shut up *about any errors.
>>
>> I find this a limiting and restrictive view, which does not permit full
>> expression of destructors as a way to:
>>
>> (1) schedule code for execution;
>> (2) determine the order of execution; but
>> (3) not dictate the exact trigger for execution to take place.
>>
>> I propose that the limiting view of destructors is not inherently
>> obvious, but is an accidental ideology. It arises not because we freely
>> choose this, but because of a little flaw that has plagued C++ since the
>> time it first introduced exceptions. This flaw is the single-exception
>> policy, which prevents good answers to questions such as:
>>
>> - What to do when a destructor throws, and an exception is already in
>> flight?
>> - What to do if we're destroying a container, and destructors throw for 2
>> or more of the contained objects?
>>
>> I propose the single-exception policy is unnecessarily limiting; that we
>> should not have to cope with not having answers for these questions in this
>> day and age; and that support for unlimited aggregated exceptions trivially
>> answers them.
>>
>> It is true that support for multiple exceptions is necessary only for use
>> by destructors. However:
>>
>> - The support I propose is *conceptually simple*.
>> - It legitimizes exceptions in destructors, and provides means for *containers
>> to handle them*.
>> - It provides a way for destructors to *report errors*. This is
>> something for which there is currently no solid language support, outside
>> of std::terminate.
>> - It emancipates destructors as a way to schedule code for execution.
>> This is to say any code; even code that may throw. This is a frequent usage
>> pattern e.g. in database libraries.
>>
>> The use of destructors for general execution scheduling, rather than only
>> cleanup, is recognized as something the language *needs* to
>> support. Currently, it is supported reluctantly: if you want to throw, you
>> better use noexcept(false); and you better not store an object like that
>> in a container!
>>
>> *I propose we can solve this as follows:*
>>
>> (1) The internal representation of an exception in flight is changed from
>> a single exception to a list of exceptions. Let's call this the
>> exception-list.
>>
>> (2) std::exception_ptr now points to the beginning of the
>> exception-list, rather than a single exception. Methods are added to
>> std::exception_ptr allowing a catch handler to walk the exception-list.
>>
>> (3) When the stack is being unwound due to an exception in flight; and a
>> destructor exits with another exception; instead of calling
>> std::terminate, the new exception is simply added to the end of the
>> exception-list.
>>
>> This is all.
>>
>> The above is all that's required. These three changes are sufficient:
>>
>> (A) to emancipate destructors as first-class code, and allow them to use
>> language functionality to report errors;
>> (B) to allow containers to aggregate destructor exceptions;
>> (C) to allow catch handlers to process aggregated exceptions.
>>
>> However, we can improve our quality of life by introducing syntactic
>> sugar. The following are suggestions for how this could be done.
>>
>> For container implementors, we introduce syntax:
>>
>> try (<std::exception_ptr&>) {
>>
>> This adds optional parentheses after "try", which if present, changes the
>> meaning of the try block to: catch any exception-list that exits this
>> block, and aggregate it to exception_ptr, which is passed by reference.
>> If the exception_ptr is empty, then it receives the exception-list that
>> exited the block. If it is non-empty, the two exception-lists are combined.
>>
>> This allows for practical aggregation of exceptions in containers that
>> execute many destructors. The same goal could be achieved with a manual
>> try-catch block, and this could be used in a macro; but special syntax is
>> cleaner.
>>
>> *Catch handler considerations:*
>>
>> - Traditional catch handlers only ever match the first exception in the
>> exception-list. Unless the program is multi-exception aware and has
>> modified the list, this is always the first exception that was thrown.
>> Traditional catch handlers can optionally use the newly added methods on
>> std::exception_ptr to investigate exceptions other than the first.
>>
>> - If a traditional catch handler exits without exception, all exceptions
>> in the exception-list are considered handled. If it re-throws, the original
>> exception-list is re-thrown. If the handler throws a new exception, only
>> that new exception is thrown, and the previous exception-list is
>> disregarded (unless the handler did something to attach it to the new
>> exception, e.g. via std::nested_exception).
>>
>> For handlers to be multi-exception aware, we can expect them to use
>> methods provided by std::exception_ptr to investigate the exception
>> list; or we may formalize new syntax.
>>
>> For practicality, I favor new syntax. The following is a suggestion:
>>
>> We introduce a new catch handler type:
>>
>> catch (..., <exception-type>) {
>>
>> Let's call this a "catch-any" handler. It has the following
>> characteristics:
>>
>> - It matches every occurrence of a matching exception in an
>> exception-list. This means it can be called repeatedly, multiple times per
>> scope, if there are multiple matches. We cannot do multiple calls to
>> traditional handlers, because traditional handlers are not necessarily
>> multi-exception aware, and do not expect to be called multiple times in a
>> row.
>>
>> - All catch-any handlers must appear BEFORE traditional catch handlers in
>> same scope. This is because the catch-any handler filters the list of
>> exceptions, but the traditional catch handler will be the ultimate handler
>> if it matches (unless it re-throws).
>>
>> - If there are multiple catch-any handlers in the same scope, they will
>> be called potentially repeatedly, and in an order that depends on the order
>> of exceptions in the exception-list.
>>
>> - If a catch-any handler throws or re-throws, the new exception is placed
>> back into the list of exceptions currently being processed, at the same
>> position as the exception that triggered the handler. If there remain
>> exceptions in the list, the search of catch-any handlers continues, and the
>> same catch-any handler might again be executed for another exception in the
>> list.
>>
>> - If a catch-any handler exits without exception, the exception that
>> matched the handler is removed from exception-list. If this was the last
>> exception, forward progress resumes outside of catch handlers. If more
>> exceptions are in list, other catch-any handlers at current scope are
>> tested; then any catch handlers at current scope are tested; and if there's
>> no match, unwinding continues at the next scope.
>>
>>
>>
>>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2656_1965466464.1437215703510
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Correction: I meant of course <font face=3D"courier n=
ew,monospace">noexcept(true)</font>.</div><div><br></div><div>This is what =
happens when you standardize double negatives as part of the language. ;)</=
div><div><br><br>On Saturday, July 18, 2015 at 4:33:16 AM UTC-6, denis bide=
r wrote:</div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0p=
x 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border-l=
eft-width: 1px; border-left-style: solid;"><div dir=3D"ltr"><div>One more a=
ddition to the core of this proposal. This=C2=A0may seem obvious, but is no=
t:</div><div><br></div><div>(4) User-provided destructors now use the same =
default <font face=3D"courier new,monospace">noexcept</font> determination =
as other methods. (I.e., they are no longer marked <font face=3D"courier ne=
w,monospace">noexcept(false)</font> if the compiler-generated destructor wo=
uld be marked so.)</div><div><br></div><div>Perhaps there are other uses=C2=
=A0for <font face=3D"courier new,monospace">noexcept</font> machinery outsi=
de of what I'm aware of, but it seems to me that his machinery is mainl=
y ugly and inelegant compensation for the language's inability to handl=
e multiple exceptions.</div><div><br></div><div>If we add support for aggre=
gated exceptions, it seems to me the language becomes simpler, and the need=
for <font face=3D"courier new,monospace">noexcept</font>=C2=A0would mostly=
go away.</div><div><br><br>On Saturday, July 18, 2015 at 3:15:27 AM UTC-6,=
denis wrote:</div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0=
px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); bor=
der-left-width: 1px; border-left-style: solid;"><div dir=3D"ltr"><p>Hey eve=
ryone!</p><div><br></div><div>I want to=C2=A0discuss a problem which I beli=
eve is limiting C++ unnecessarily in its potential for powerful expression.=
The problem is the <strong>single-exception policy</strong>, and its direc=
t consequence: the marginalization of destructors, exemplified in recent ye=
ars by=C2=A0how they're now marked=C2=A0<font face=3D"courier new,monos=
pace">noexcept</font>.</div><div><br></div><div>I believe this problem is c=
urrently viewed incorrectly by many, and I wish to propose a solution. The =
solution is aggregated exceptions. I contend these are conceptually simple;=
resolve the Gordian knot of destructor exceptions; are backward compatible=
, and straightforward to implement. :-)</div><div><br></div><div>There is a=
=C2=A0widespread belief, held passionately by many, which I believe to be c=
onceptually in error. This is that destructors are supposed to be nothing m=
ore than little cleanup dwarves. That they should only:</div><div><br></div=
><div>(1) quietly release resources, and</div><div>(2) <strong>kindly shut =
up </strong>about any errors.</div><div><br></div><div>I find this a limiti=
ng and restrictive view, which does not permit full expression of destructo=
rs as a way to:</div><div><br></div><div>(1) schedule code for execution;</=
div><div>(2) determine the order of execution; but</div><div>(3) not dictat=
e the exact trigger for execution to take place.</div><div><br></div><div>I=
propose that the limiting view of destructors is not inherently obvious, b=
ut is an accidental ideology.=C2=A0It arises=C2=A0not because we freely cho=
ose this,=C2=A0but because of a little flaw that has plagued C++ since the =
time it first introduced exceptions. This flaw=C2=A0is the single-exception=
policy, which=C2=A0prevents good answers to questions such as:</div><div><=
br></div><div>- What to do when a destructor throws, and an exception is al=
ready in flight?</div><div>- What to do if we're destroying a container=
, and destructors throw for 2 or more of the contained objects?</div><div><=
br></div><div>I propose the single-exception policy is unnecessarily limiti=
ng; that we should not have to cope with not having answers for these quest=
ions in this day and age;=C2=A0and that support for unlimited aggregated ex=
ceptions trivially answers them.</div><div><br></div><div>It is true that s=
upport for multiple exceptions is necessary only for use by destructors. Ho=
wever:</div><div><br></div><div>-=C2=A0The support I propose is <strong>con=
ceptually simple</strong>.</div><div>- It legitimizes exceptions in destruc=
tors, and provides means for <strong>containers to handle them</strong>.</d=
iv><div>- It provides a way for destructors to <strong>report errors</stron=
g>. This is something for which there is currently no solid language suppor=
t, outside of <font face=3D"courier new,monospace">std::terminate</font>.</=
div><div>- It emancipates destructors as a way to schedule code for executi=
on. This is to say any code; even code that may throw. This is a frequent u=
sage pattern e.g. in database libraries. </div><div><br></div><div>The=C2=
=A0use of destructors for=C2=A0general execution scheduling, rather than on=
ly cleanup,=C2=A0is recognized as something the language <em>needs</em> to =
support.=C2=A0Currently,=C2=A0it is supported reluctantly:=C2=A0if you want=
to throw,=C2=A0you better use=C2=A0<font face=3D"courier new,monospace">no=
except(false);</font> and you better not store an object like that in a con=
tainer!</div><div><br></div><div><strong>I propose we can solve this as fol=
lows:</strong></div><div><br></div><div>(1) The internal representation of =
an exception in flight is changed from a single exception to a list of exce=
ptions. Let's call this the exception-list.</div><div><br></div><div>(2=
) <font face=3D"courier new,monospace">std::exception_ptr</font> now points=
to the beginning of the exception-list, rather than a single exception. Me=
thods are added to <font face=3D"courier new,monospace">std::exception_ptr<=
/font> allowing a catch handler to walk the exception-list.</div><div><br><=
/div><div>(3) When the stack is being unwound due to an exception in flight=
; and a destructor exits with another exception; instead of calling <font f=
ace=3D"courier new,monospace">std::terminate</font>, the new exception is s=
imply added to the end of the exception-list.</div><div><br></div><div>This=
is all.</div><div><br></div><div>The above is all that's required. The=
se three changes are sufficient:</div><div><br></div><div>(A) to emancipate=
destructors as first-class code,=C2=A0and allow them to use language funct=
ionality=C2=A0to report errors;</div><div>(B) to allow containers to aggreg=
ate destructor exceptions;</div><div>(C) to allow catch handlers to process=
aggregated exceptions.</div><div><br></div><div>However,=C2=A0we can impro=
ve our quality of life by introducing syntactic sugar. The following are su=
ggestions for how this could be done.</div><div><br></div><p>For container =
implementors, we introduce syntax:</p><div><br></div><div><font face=3D"cou=
rier new,monospace">=C2=A0 try (<std::exception_ptr&>) {</font></=
div><div><br></div><div>This adds optional parentheses after "try"=
;, which if present, changes the meaning of the try block to: catch any exc=
eption-list that exits this block, and aggregate it to <font face=3D"courie=
r new,monospace">exception_ptr</font>, which is passed by reference. If the=
<font face=3D"courier new,monospace">exception_ptr</font> is empty, then i=
t receives the exception-list that exited the block. If it is non-empty, th=
e two exception-lists are combined.</div><div><br></div><div>This allows fo=
r practical aggregation of exceptions in containers that execute many destr=
uctors. The same goal could be achieved with a manual try-catch block,=C2=
=A0and this could be=C2=A0used=C2=A0in=C2=A0a macro; but special syntax is =
cleaner.<br>=C2=A0 <br><strong>Catch handler considerations:</strong></div>=
<div><br></div><div>- Traditional catch handlers only ever match the first =
exception in the exception-list. Unless the program is multi-exception awar=
e and has modified the list, this is always the first exception that was th=
rown. Traditional catch handlers can optionally use the newly added methods=
on <font face=3D"courier new,monospace">std::exception_ptr</font> to inves=
tigate exceptions other than the first.</div><div><br></div><div>- If a tra=
ditional catch handler exits without exception, all exceptions in the excep=
tion-list are considered handled. If it re-throws, the original exception-l=
ist is re-thrown. If the handler throws a new exception, only that new exce=
ption is thrown, and the previous exception-list is disregarded (unless the=
handler did something to attach it to the new exception, e.g. via <font fa=
ce=3D"courier new,monospace">std::nested_exception</font>).</div><div><br><=
/div><div>For handlers to be multi-exception aware, we can expect them to u=
se methods=C2=A0provided by=C2=A0<font face=3D"courier new,monospace">std::=
exception_ptr</font> to investigate the exception list; or we may formalize=
new syntax.</div><div><br></div><div>For practicality, I favor new syntax.=
The following is a suggestion:</div><div><br></div><div>We introduce a new=
catch handler type:</div><div><br></div><div><font face=3D"courier new,mon=
ospace">=C2=A0 catch (..., <exception-type>) {</font><br>=C2=A0 <br>L=
et's call this a "catch-any" handler. It has the following ch=
aracteristics:</div><div><br></div><div>- It matches every occurrence of a =
matching exception in an exception-list. This means it can be called repeat=
edly, multiple times per scope, if there are multiple matches. We cannot do=
multiple calls to traditional handlers, because traditional handlers are n=
ot necessarily multi-exception aware, and do not expect to be called multip=
le times in a row.</div><div><br></div><div>- All catch-any handlers must a=
ppear BEFORE traditional catch handlers in same scope. This is because the =
catch-any handler filters the list of exceptions, but the traditional catch=
handler will be the ultimate handler if it matches (unless it re-throws).<=
/div><div><br></div><div>- If there are multiple catch-any handlers in the =
same scope, they will be called potentially repeatedly, and in an order tha=
t depends on the order of exceptions in the exception-list.</div><div><br><=
/div><div>- If a catch-any handler throws or re-throws, the new exception i=
s placed back into the list of exceptions currently being processed, at the=
same position as the exception that triggered the handler. If there remain=
exceptions in the list, the search of catch-any handlers continues, and th=
e same catch-any handler might again be executed for another exception in t=
he list.</div><div><br></div><div>- If a catch-any handler exits without ex=
ception, the exception that matched the handler is removed from exception-l=
ist. If this was the last exception, forward progress resumes outside of ca=
tch handlers. If more exceptions are in list, other catch-any handlers at c=
urrent scope are tested; then any catch handlers at current scope are teste=
d; and if there's no match, unwinding continues at the next scope.</div=
><div><br></div><div><br></div><p><br></p></div></blockquote></div></blockq=
uote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2656_1965466464.1437215703510--
------=_Part_2655_1887312553.1437215703510--
.
Author: David Krauss <potswa@gmail.com>
Date: Sat, 18 Jul 2015 19:17:13 +0800
Raw View
--Apple-Mail=_B95CA13D-FA2A-46F5-83FD-C23DDCABBE60
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
> On 2015=E2=80=9307=E2=80=9318, at 5:15 PM, denis <isocppgroup@denisbider.=
com> wrote:
>=20
> - If a traditional catch handler exits without exception, all exceptions =
in the exception-list are considered handled.
Therein lies the rub.
The current system doesn=E2=80=99t call std::terminate (or std::unexpected)=
just because it=E2=80=99s confused. An exception is a contract between the=
thrower and the catcher, and throwing into an unwind breaks that contract.=
Terminating the program is the only safe course of action when a contract =
is broken irrecoverably.
If the status quo were to ignore exceptions in unwinding, your proposal wou=
ld be a viable way to handle them. Instead, it changes the behavior of exis=
ting programs to be more tolerant.
Perhaps it would be safe to allow multiple exceptions in flight, as long as=
no catch block exits normally until all exceptions have been handled. Ther=
e would need to be a rethrow_next facility. I don=E2=80=99t know, though, i=
f that=E2=80=99s any better than what std::nested_exception can already do.
See also the thread =E2=80=9Cnested exceptions=E2=80=9D from this past Apri=
l 23-May 11, which examines a very similar idea.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_B95CA13D-FA2A-46F5-83FD-C23DDCABBE60
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><br class=3D""><di=
v><blockquote type=3D"cite" class=3D""><div class=3D"">On 2015=E2=80=9307=
=E2=80=9318, at 5:15 PM, denis <<a href=3D"mailto:isocppgroup@denisbider=
..com" class=3D"">isocppgroup@denisbider.com</a>> wrote:</div><br class=
=3D"Apple-interchange-newline"><div class=3D""><span style=3D"font-family: =
Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-=
weight: normal; letter-spacing: normal; line-height: normal; orphans: auto;=
text-align: start; text-indent: 0px; text-transform: none; white-space: no=
rmal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; floa=
t: none; display: inline !important;" class=3D"">- If a traditional catch h=
andler exits without exception, all exceptions in the exception-list are co=
nsidered handled.</span></div></blockquote></div><br class=3D""><div class=
=3D"">Therein lies the rub.</div><div class=3D""><br class=3D""></div><div =
class=3D"">The current system doesn=E2=80=99t call <font face=3D"Courier" c=
lass=3D"">std::terminate</font> (or <font face=3D"Courier" class=3D"">std::=
unexpected</font>) just because it=E2=80=99s confused. An exception is a co=
ntract between the thrower and the catcher, and throwing into an unwind bre=
aks that contract. Terminating the program is the only safe course of actio=
n when a contract is broken irrecoverably.</div><div class=3D""><br class=
=3D""></div><div class=3D"">If the status quo were to ignore exceptions in =
unwinding, your proposal would be a viable way to handle them. Instead, it =
changes the behavior of existing programs to be more tolerant.</div><div cl=
ass=3D""><br class=3D""></div><div class=3D"">Perhaps it would be safe to a=
llow multiple exceptions in flight, as long as no <font face=3D"Courier" cl=
ass=3D"">catch</font> block exits normally until all exceptions have been h=
andled. There would need to be a <font face=3D"Courier" class=3D"">rethrow_=
next</font> facility. I don=E2=80=99t know, though, if that=E2=80=99s any b=
etter than what <font face=3D"Courier" class=3D"">std::nested_exception</fo=
nt> can already do.</div><div class=3D""><br class=3D""></div><div class=3D=
"">See also the thread =E2=80=9Cnested exceptions=E2=80=9D from this past A=
pril 23-May 11, which examines a very similar idea.</div><div class=3D""><b=
r class=3D""></div></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_B95CA13D-FA2A-46F5-83FD-C23DDCABBE60--
.
Author: denisbider.mobile@gmail.com
Date: Sat, 18 Jul 2015 04:44:09 -0700 (PDT)
Raw View
------=_Part_2685_1652587249.1437219849580
Content-Type: multipart/alternative;
boundary="----=_Part_2686_394538955.1437219849589"
------=_Part_2686_394538955.1437219849589
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
> Instead, it changes the behavior of existing programs to be more tolerant=
..
Is the concern about change in behavior only when it changes from=20
intolerance to more tolerance?
Because currently, as-is, I have a change in behavior in the following code=
:
struct A { ~A() { throw "whee"; } };
int main() {
try { A a; }
catch (char const* z) {
std::cout << z << std::endl;
}
}
.... depending on whether I compile that with -std=3Dgnu++11, or not.
In C++03, the above program outputs "whee"; in C++11, it calls=20
std::terminate. It so happens that, even with -Wall, the particular=20
implementation (g++) outputs no warnings or errors alerting to this change=
=20
in behavior.
Are you saying the above is okay, because it is a shift toward *in*
tolerance?
I can understand that position if that's what you're saying; but I want to=
=20
make it clear that this is what you're saying.
denis
On Saturday, July 18, 2015 at 5:17:22 AM UTC-6, David Krauss wrote:
>
> On 2015=E2=80=9307=E2=80=9318, at 5:15 PM, denis <isocp...@denisbider.com=
<javascript:>>=20
> wrote:
>
> - If a traditional catch handler exits without exception, all exceptions=
=20
> in the exception-list are considered handled.
>
>
> Therein lies the rub.
>
> The current system doesn=E2=80=99t call std::terminate (or std::unexpecte=
d) just=20
> because it=E2=80=99s confused. An exception is a contract between the thr=
ower and=20
> the catcher, and throwing into an unwind breaks that contract. Terminatin=
g=20
> the program is the only safe course of action when a contract is broken=
=20
> irrecoverably.
>
> If the status quo were to ignore exceptions in unwinding, your proposal=
=20
> would be a viable way to handle them. Instead, it changes the behavior of=
=20
> existing programs to be more tolerant.
>
> Perhaps it would be safe to allow multiple exceptions in flight, as long=
=20
> as no catch block exits normally until all exceptions have been handled.=
=20
> There would need to be a rethrow_next facility. I don=E2=80=99t know, tho=
ugh, if=20
> that=E2=80=99s any better than what std::nested_exception can already do.
>
> See also the thread =E2=80=9Cnested exceptions=E2=80=9D from this past Ap=
ril 23-May 11,=20
> which examines a very similar idea.
>
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_2686_394538955.1437219849589
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>> Instead, it changes the behavior of existing pro=
grams to be more tolerant.</div><div><br></div><div>Is the concern about ch=
ange in behavior only when it changes from intolerance to more tolerance?</=
div><div><br></div><div>Because currently, as-is, I have a change in behavi=
or in the following code:</div><div><br></div><div><font face=3D"courier ne=
w,monospace">struct A { ~A() { throw "whee"; } };</font></div><di=
v><font face=3D"Courier New">int main() {</font></div><div><font face=3D"Co=
urier New">=C2=A0 try { A a; }</font></div><div><font face=3D"Courier New">=
=C2=A0=C2=A0catch (char const* z) {</font></div><div><font face=3D"Courier =
New">=C2=A0=C2=A0=C2=A0 std::cout << z << std::endl;</font></di=
v><div><font face=3D"Courier New">=C2=A0 }</font></div><div><font face=3D"C=
ourier New">}</font></div><p><font face=3D"Courier New"><br></font></p><div=
>... depending on whether I compile that with -std=3Dgnu++11, or not.</div>=
<div><br></div><div>In C++03, the above program outputs "whee"; i=
n C++11, it calls <font face=3D"courier new,monospace">std::terminate<font =
face=3D"arial,sans-serif">.=C2=A0It so happens that, even with -Wall,=C2=A0=
the particular implementation (g++) outputs no warnings or errors alerting =
to this change in behavior.</font></font></div><div><br></div><div>Are you =
saying the above is okay, because it is a shift toward <strong>in</strong>t=
olerance?</div><div><br></div><div>I can understand that position if that&#=
39;s what you're saying; but=C2=A0I want to make it clear that this is =
what you're saying.</div><div><br></div><div>denis</div><div><br><br>On=
Saturday, July 18, 2015 at 5:17:22 AM UTC-6, David Krauss wrote:</div><blo=
ckquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-l=
eft: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px; bo=
rder-left-style: solid;"><div style=3D"-ms-word-wrap: break-word;"><br><div=
><blockquote type=3D"cite"><div>On 2015=E2=80=9307=E2=80=9318, at 5:15 PM, =
denis <<a onmousedown=3D"this.href=3D'javascript:';return true;"=
onclick=3D"this.href=3D'javascript:';return true;" href=3D"javascr=
ipt:" target=3D"_blank" rel=3D"nofollow">isocp...@denisbider.com</a>> wr=
ote:</div><br><div><span style=3D"font: 12px/normal Helvetica; text-transfo=
rm: none; text-indent: 0px; letter-spacing: normal; word-spacing: 0px; floa=
t: none; display: inline !important; white-space: normal; font-size-adjust:=
none; font-stretch: normal;">- If a traditional catch handler exits withou=
t exception, all exceptions in the exception-list are considered handled.</=
span></div></blockquote></div><br><div>Therein lies the rub.</div><div><br>=
</div><div>The current system doesn=E2=80=99t call <font face=3D"Courier">s=
td::terminate</font> (or <font face=3D"Courier">std::unexpected</font>) jus=
t because it=E2=80=99s confused. An exception is a contract between the thr=
ower and the catcher, and throwing into an unwind breaks that contract. Ter=
minating the program is the only safe course of action when a contract is b=
roken irrecoverably.</div><div><br></div><div>If the status quo were to ign=
ore exceptions in unwinding, your proposal would be a viable way to handle =
them. Instead, it changes the behavior of existing programs to be more tole=
rant.</div><div><br></div><div>Perhaps it would be safe to allow multiple e=
xceptions in flight, as long as no <font face=3D"Courier">catch</font> bloc=
k exits normally until all exceptions have been handled. There would need t=
o be a <font face=3D"Courier">rethrow_next</font> facility. I don=E2=80=99t=
know, though, if that=E2=80=99s any better than what <font face=3D"Courier=
">std::nested_exception</font> can already do.</div><div><br></div><div>See=
also the thread =E2=80=9Cnested exceptions=E2=80=9D from this past April 2=
3-May 11, which examines a very similar idea.</div><div><br></div></div></b=
lockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2686_394538955.1437219849589--
------=_Part_2685_1652587249.1437219849580--
.
Author: denisbider.mobile@gmail.com
Date: Sat, 18 Jul 2015 05:03:46 -0700 (PDT)
Raw View
------=_Part_10_562788311.1437221026744
Content-Type: multipart/alternative;
boundary="----=_Part_11_1586143384.1437221026745"
------=_Part_11_1586143384.1437221026745
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
If any change of behavior from less tolerance to more tolerance is indeed=
=20
what we want to avoid, the following are possible solutions:
(1) As you mentioned: if a traditional catch handler exits normally without=
=20
having dismissed any aggregated exceptions, program calls std::terminate.
The simplest way to dismiss aggregated exceptions might be e.g. with a=20
method like std::current_exception().dismiss_all().=20
Shortcoming: the call to std::terminate that would otherwise take place is=
=20
postponed; but perhaps this is acceptable.
(2) Exceptions can be aggregated only if at least one derives from=20
std::aggregate_exception.
If neither do, previous behavior occurs (std::terminate at the point of=20
aggregation). But if one of them does, this indicates the application is=20
aware of the new behavior.
Shortcoming: exceptions thrown by the STL cannot derive from=20
std::aggregate_exception by default, and therefore cannot aggregate with=20
each other. However, they can aggregate with user-defined exceptions. There=
=20
could be a function like std::enable_aggregate_exceptions() that would=20
opt-in to new behavior.
On Saturday, July 18, 2015 at 5:44:09 AM UTC-6, denisbid...@gmail.com wrote=
:
> > Instead, it changes the behavior of existing programs to be more=20
> tolerant.
>
> Is the concern about change in behavior only when it changes from=20
> intolerance to more tolerance?
>
> Because currently, as-is, I have a change in behavior in the following=20
> code:
>
> struct A { ~A() { throw "whee"; } };
> int main() {
> try { A a; }
> catch (char const* z) {
> std::cout << z << std::endl;
> }
> }
>
>
> ... depending on whether I compile that with -std=3Dgnu++11, or not.
>
> In C++03, the above program outputs "whee"; in C++11, it calls=20
> std::terminate. It so happens that, even with -Wall, the particular=20
> implementation (g++) outputs no warnings or errors alerting to this chang=
e=20
> in behavior.
>
> Are you saying the above is okay, because it is a shift toward *in*
> tolerance?
>
> I can understand that position if that's what you're saying; but I want t=
o=20
> make it clear that this is what you're saying.
>
> denis
>
>
> On Saturday, July 18, 2015 at 5:17:22 AM UTC-6, David Krauss wrote:
>
>>
>> On 2015=E2=80=9307=E2=80=9318, at 5:15 PM, denis <isocp...@denisbider.co=
m> wrote:
>>
>> - If a traditional catch handler exits without exception, all exceptions=
=20
>> in the exception-list are considered handled.
>>
>>
>> Therein lies the rub.
>>
>> The current system doesn=E2=80=99t call std::terminate (or std::unexpect=
ed) just=20
>> because it=E2=80=99s confused. An exception is a contract between the th=
rower and=20
>> the catcher, and throwing into an unwind breaks that contract. Terminati=
ng=20
>> the program is the only safe course of action when a contract is broken=
=20
>> irrecoverably.
>>
>> If the status quo were to ignore exceptions in unwinding, your proposal=
=20
>> would be a viable way to handle them. Instead, it changes the behavior o=
f=20
>> existing programs to be more tolerant.
>>
>> Perhaps it would be safe to allow multiple exceptions in flight, as long=
=20
>> as no catch block exits normally until all exceptions have been handled.=
=20
>> There would need to be a rethrow_next facility. I don=E2=80=99t know, th=
ough, if=20
>> that=E2=80=99s any better than what std::nested_exception can already do=
..
>>
>> See also the thread =E2=80=9Cnested exceptions=E2=80=9D from this past A=
pril 23-May 11,=20
>> which examines a very similar idea.
>>
>>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_11_1586143384.1437221026745
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>If any change of behavior from less tolerance to more=
tolerance is indeed what we want to avoid, the following are possible solu=
tions:</div><div><br></div><div><br></div><div>(1)=C2=A0As you mentioned: i=
f=C2=A0a traditional catch handler exits normally without having dismissed =
any aggregated exceptions, program calls <font face=3D"courier new,monospac=
e">std::terminate</font>.</div><div><br></div><div>The simplest way to dism=
iss aggregated exceptions might be=C2=A0e.g. with a method like=C2=A0<font =
face=3D"courier new,monospace">std::current_exception().dismiss_all()<font =
face=3D"arial,sans-serif">. </font></font></div><div><br></div><div>Shortco=
ming: the call to <font face=3D"courier new,monospace">std::terminate<font =
face=3D"arial,sans-serif"> that would otherwise take place is postponed; bu=
t perhaps this is acceptable.</font></font></div><div><br></div><div><br></=
div><div>(2)=C2=A0Exceptions=C2=A0can be aggregated=C2=A0only if at least o=
ne derives from <font face=3D"courier new,monospace">std::aggregate_excepti=
on</font>.</div><div><br></div><div>If neither do, previous behavior occurs=
(<font face=3D"courier new,monospace">std::terminate</font> at the point o=
f aggregation). But if one of them does, this indicates the application is =
aware of the new behavior.</div><div><br></div><div>Shortcoming: exceptions=
thrown by the STL cannot derive from <font face=3D"courier new,monospace">=
std::aggregate_exception<font face=3D"arial,sans-serif"> by default, and th=
erefore cannot aggregate with each other. However, they can aggregate with =
user-defined exceptions. There could be a function like=C2=A0 <font face=3D=
"courier new,monospace">std::enable_aggregate_exceptions() <font face=3D"ar=
ial,sans-serif">that would opt-in to new behavior.</font></font></font></fo=
nt></div><div><br></div><div><br><br>On Saturday, July 18, 2015 at 5:44:09 =
AM UTC-6, denisbid...@gmail.com wrote:</div><blockquote class=3D"gmail_quot=
e" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color=
: rgb(204, 204, 204); border-left-width: 1px; border-left-style: solid;"><d=
iv dir=3D"ltr"><div>> Instead, it changes the behavior of existing progr=
ams to be more tolerant.</div><div><br></div><div>Is the concern about chan=
ge in behavior only when it changes from intolerance to more tolerance?</di=
v><div><br></div><div>Because currently, as-is, I have a change in behavior=
in the following code:</div><div><br></div><div><font face=3D"courier new,=
monospace">struct A { ~A() { throw "whee"; } };</font></div><div>=
<font face=3D"Courier New">int main() {</font></div><div><font face=3D"Cour=
ier New">=C2=A0 try { A a; }</font></div><div><font face=3D"Courier New">=
=C2=A0=C2=A0catch (char const* z) {</font></div><div><font face=3D"Courier =
New">=C2=A0=C2=A0=C2=A0 std::cout << z << std::endl;</font></di=
v><div><font face=3D"Courier New">=C2=A0 }</font></div><div><font face=3D"C=
ourier New">}</font></div><p><font face=3D"Courier New"><br></font></p><div=
>... depending on whether I compile that with -std=3Dgnu++11, or not.</div>=
<div><br></div><div>In C++03, the above program outputs "whee"; i=
n C++11, it calls <font face=3D"courier new,monospace">std::terminate<font =
face=3D"arial,sans-serif">.=C2=A0It so happens that, even with -Wall,=C2=A0=
the particular implementation (g++) outputs no warnings or errors alerting =
to this change in behavior.</font></font></div><div><br></div><div>Are you =
saying the above is okay, because it is a shift toward <strong>in</strong>t=
olerance?</div><div><br></div><div>I can understand that position if that&#=
39;s what you're saying; but=C2=A0I want to make it clear that this is =
what you're saying.</div><div><br></div><div>denis</div><div><br><br>On=
Saturday, July 18, 2015 at 5:17:22 AM UTC-6, David Krauss wrote:</div><blo=
ckquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-l=
eft: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px; bo=
rder-left-style: solid;"><div><br><div><blockquote type=3D"cite"><div>On 20=
15=E2=80=9307=E2=80=9318, at 5:15 PM, denis <<a rel=3D"nofollow">isocp..=
..@denisbider.com</a>> wrote:</div><br><div><span style=3D"font: 12px/nor=
mal Helvetica; text-transform: none; text-indent: 0px; letter-spacing: norm=
al; word-spacing: 0px; float: none; display: inline !important; white-space=
: normal; font-size-adjust: none; font-stretch: normal;">- If a traditional=
catch handler exits without exception, all exceptions in the exception-lis=
t are considered handled.</span></div></blockquote></div><br><div>Therein l=
ies the rub.</div><div><br></div><div>The current system doesn=E2=80=99t ca=
ll <font face=3D"Courier">std::terminate</font> (or <font face=3D"Courier">=
std::unexpected</font>) just because it=E2=80=99s confused. An exception is=
a contract between the thrower and the catcher, and throwing into an unwin=
d breaks that contract. Terminating the program is the only safe course of =
action when a contract is broken irrecoverably.</div><div><br></div><div>If=
the status quo were to ignore exceptions in unwinding, your proposal would=
be a viable way to handle them. Instead, it changes the behavior of existi=
ng programs to be more tolerant.</div><div><br></div><div>Perhaps it would =
be safe to allow multiple exceptions in flight, as long as no <font face=3D=
"Courier">catch</font> block exits normally until all exceptions have been =
handled. There would need to be a <font face=3D"Courier">rethrow_next</font=
> facility. I don=E2=80=99t know, though, if that=E2=80=99s any better than=
what <font face=3D"Courier">std::nested_exception</font> can already do.</=
div><div><br></div><div>See also the thread =E2=80=9Cnested exceptions=E2=
=80=9D from this past April 23-May 11, which examines a very similar idea.<=
/div><div><br></div></div></blockquote></div></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_11_1586143384.1437221026745--
------=_Part_10_562788311.1437221026744--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Sat, 18 Jul 2015 05:21:59 -0700 (PDT)
Raw View
------=_Part_2681_985948341.1437222119353
Content-Type: multipart/alternative;
boundary="----=_Part_2682_2093110973.1437222119354"
------=_Part_2682_2093110973.1437222119354
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Hmm. There is a third solution:
(3) At the point where an exception would be passed to a traditional catch=
=20
handler, there may remain only one exception in the exception-list. If=20
multiple exceptions remain, the program calls std::terminate instead of=20
entering the catch handler.
This prevents entering a traditional catch handler with more than one=20
exception, and requires any aggregated exceptions to be peeled off using=20
catch-any handlers. Applications that are aware of exception aggregation=20
must use catch-any handlers to cause any change in behavior.
An exception could be made for blanket catch (...), to support its use to=
=20
re-throw without caring about what it's re-throwing.
On Saturday, July 18, 2015 at 6:03:46 AM UTC-6, denisbid...@gmail.com wrote=
:
> If any change of behavior from less tolerance to more tolerance is indeed=
=20
> what we want to avoid, the following are possible solutions:
>
>
> (1) As you mentioned: if a traditional catch handler exits normally=20
> without having dismissed any aggregated exceptions, program calls=20
> std::terminate.
>
> The simplest way to dismiss aggregated exceptions might be e.g. with a=20
> method like std::current_exception().dismiss_all().=20
>
> Shortcoming: the call to std::terminate that would otherwise take place=
=20
> is postponed; but perhaps this is acceptable.
>
>
> (2) Exceptions can be aggregated only if at least one derives from=20
> std::aggregate_exception.
>
> If neither do, previous behavior occurs (std::terminate at the point of=
=20
> aggregation). But if one of them does, this indicates the application is=
=20
> aware of the new behavior.
>
> Shortcoming: exceptions thrown by the STL cannot derive from=20
> std::aggregate_exception by default, and therefore cannot aggregate with=
=20
> each other. However, they can aggregate with user-defined exceptions. The=
re=20
> could be a function like std::enable_aggregate_exceptions() that would=
=20
> opt-in to new behavior.
>
>
>
> On Saturday, July 18, 2015 at 5:44:09 AM UTC-6, denisbid...@gmail.com=20
> wrote:
>
>> > Instead, it changes the behavior of existing programs to be more=20
>> tolerant.
>>
>> Is the concern about change in behavior only when it changes from=20
>> intolerance to more tolerance?
>>
>> Because currently, as-is, I have a change in behavior in the following=
=20
>> code:
>>
>> struct A { ~A() { throw "whee"; } };
>> int main() {
>> try { A a; }
>> catch (char const* z) {
>> std::cout << z << std::endl;
>> }
>> }
>>
>>
>> ... depending on whether I compile that with -std=3Dgnu++11, or not.
>>
>> In C++03, the above program outputs "whee"; in C++11, it calls=20
>> std::terminate. It so happens that, even with -Wall, the particular=20
>> implementation (g++) outputs no warnings or errors alerting to this chan=
ge=20
>> in behavior.
>>
>> Are you saying the above is okay, because it is a shift toward *in*
>> tolerance?
>>
>> I can understand that position if that's what you're saying; but I want=
=20
>> to make it clear that this is what you're saying.
>>
>> denis
>>
>>
>> On Saturday, July 18, 2015 at 5:17:22 AM UTC-6, David Krauss wrote:
>>
>>>
>>> On 2015=E2=80=9307=E2=80=9318, at 5:15 PM, denis <isocp...@denisbider.c=
om> wrote:
>>>
>>> - If a traditional catch handler exits without exception, all exception=
s=20
>>> in the exception-list are considered handled.
>>>
>>>
>>> Therein lies the rub.
>>>
>>> The current system doesn=E2=80=99t call std::terminate (or std::unexpec=
ted)=20
>>> just because it=E2=80=99s confused. An exception is a contract between =
the thrower=20
>>> and the catcher, and throwing into an unwind breaks that contract.=20
>>> Terminating the program is the only safe course of action when a contra=
ct=20
>>> is broken irrecoverably.
>>>
>>> If the status quo were to ignore exceptions in unwinding, your proposal=
=20
>>> would be a viable way to handle them. Instead, it changes the behavior =
of=20
>>> existing programs to be more tolerant.
>>>
>>> Perhaps it would be safe to allow multiple exceptions in flight, as lon=
g=20
>>> as no catch block exits normally until all exceptions have been=20
>>> handled. There would need to be a rethrow_next facility. I don=E2=80=99=
t know,=20
>>> though, if that=E2=80=99s any better than what std::nested_exception ca=
n=20
>>> already do.
>>>
>>> See also the thread =E2=80=9Cnested exceptions=E2=80=9D from this past =
April 23-May 11,=20
>>> which examines a very similar idea.
>>>
>>>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_2682_2093110973.1437222119354
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Hmm.=C2=A0There is=C2=A0a third solution:</div><div><=
br></div><div>(3)=C2=A0At the point where an exception would be passed to a=
traditional catch handler, there may remain only one exception in the exce=
ption-list. If multiple exceptions remain, the program calls <font face=3D"=
courier new,monospace">std::terminate</font> instead of entering the catch =
handler.</div><div><br></div><div>This prevents entering a traditional catc=
h handler with more than one exception, and requires any aggregated excepti=
ons to be peeled off using catch-any handlers. Applications that are aware =
of exception aggregation must use catch-any handlers to cause any change in=
behavior.</div><div><br></div><div>An exception could be made for blanket =
<font face=3D"courier new,monospace">catch (...)</font>,=C2=A0to support it=
s use=C2=A0to re-throw without caring about what it's re-throwing.</div=
><div><br></div><div><br><br>On Saturday, July 18, 2015 at 6:03:46 AM UTC-6=
, denisbid...@gmail.com wrote:</div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(20=
4, 204, 204); border-left-width: 1px; border-left-style: solid;"><div dir=
=3D"ltr"><div>If any change of behavior from less tolerance to more toleran=
ce is indeed what we want to avoid, the following are possible solutions:</=
div><div><br></div><div><br></div><div>(1)=C2=A0As you mentioned: if=C2=A0a=
traditional catch handler exits normally without having dismissed any aggr=
egated exceptions, program calls <font face=3D"courier new,monospace">std::=
terminate</font>.</div><div><br></div><div>The simplest way to dismiss aggr=
egated exceptions might be=C2=A0e.g. with a method like=C2=A0<font face=3D"=
courier new,monospace">std::current_exception().dismiss_all()<font face=3D"=
arial,sans-serif">. </font></font></div><div><br></div><div>Shortcoming: th=
e call to <font face=3D"courier new,monospace">std::terminate<font face=3D"=
arial,sans-serif"> that would otherwise take place is postponed; but perhap=
s this is acceptable.</font></font></div><div><br></div><div><br></div><div=
>(2)=C2=A0Exceptions=C2=A0can be aggregated=C2=A0only if at least one deriv=
es from <font face=3D"courier new,monospace">std::aggregate_exception</font=
>.</div><div><br></div><div>If neither do, previous behavior occurs (<font =
face=3D"courier new,monospace">std::terminate</font> at the point of aggreg=
ation). But if one of them does, this indicates the application is aware of=
the new behavior.</div><div><br></div><div>Shortcoming: exceptions thrown =
by the STL cannot derive from <font face=3D"courier new,monospace">std::agg=
regate_exception<font face=3D"arial,sans-serif"> by default, and therefore =
cannot aggregate with each other. However, they can aggregate with user-def=
ined exceptions. There could be a function like=C2=A0 <font face=3D"courier=
new,monospace">std::enable_aggregate_exceptions() <font face=3D"arial,sans=
-serif">that would opt-in to new behavior.</font></font></font></font></div=
><div><br></div><div><br><br>On Saturday, July 18, 2015 at 5:44:09 AM UTC-6=
, <a>denisbid...@gmail.com</a> wrote:</div><blockquote class=3D"gmail_quote=
" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color:=
rgb(204, 204, 204); border-left-width: 1px; border-left-style: solid;"><di=
v dir=3D"ltr"><div>> Instead, it changes the behavior of existing progra=
ms to be more tolerant.</div><div><br></div><div>Is the concern about chang=
e in behavior only when it changes from intolerance to more tolerance?</div=
><div><br></div><div>Because currently, as-is, I have a change in behavior =
in the following code:</div><div><br></div><div><font face=3D"courier new,m=
onospace">struct A { ~A() { throw "whee"; } };</font></div><div><=
font face=3D"Courier New">int main() {</font></div><div><font face=3D"Couri=
er New">=C2=A0 try { A a; }</font></div><div><font face=3D"Courier New">=C2=
=A0=C2=A0catch (char const* z) {</font></div><div><font face=3D"Courier New=
">=C2=A0=C2=A0=C2=A0 std::cout << z << std::endl;</font></div><=
div><font face=3D"Courier New">=C2=A0 }</font></div><div><font face=3D"Cour=
ier New">}</font></div><p><font face=3D"Courier New"><br></font></p><div>..=
.. depending on whether I compile that with -std=3Dgnu++11, or not.</div><di=
v><br></div><div>In C++03, the above program outputs "whee"; in C=
++11, it calls <font face=3D"courier new,monospace">std::terminate<font fac=
e=3D"arial,sans-serif">.=C2=A0It so happens that, even with -Wall,=C2=A0the=
particular implementation (g++) outputs no warnings or errors alerting to =
this change in behavior.</font></font></div><div><br></div><div>Are you say=
ing the above is okay, because it is a shift toward <strong>in</strong>tole=
rance?</div><div><br></div><div>I can understand that position if that'=
s what you're saying; but=C2=A0I want to make it clear that this is wha=
t you're saying.</div><div><br></div><div>denis</div><div><br><br>On Sa=
turday, July 18, 2015 at 5:17:22 AM UTC-6, David Krauss wrote:</div><blockq=
uote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left=
: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px; borde=
r-left-style: solid;"><div><br><div><blockquote type=3D"cite"><div>On 2015=
=E2=80=9307=E2=80=9318, at 5:15 PM, denis <<a rel=3D"nofollow">isocp...@=
denisbider.com</a>> wrote:</div><br><div><span style=3D"font: 12px/norma=
l Helvetica; text-transform: none; text-indent: 0px; letter-spacing: normal=
; word-spacing: 0px; float: none; display: inline !important; white-space: =
normal; font-size-adjust: none; font-stretch: normal;">- If a traditional c=
atch handler exits without exception, all exceptions in the exception-list =
are considered handled.</span></div></blockquote></div><br><div>Therein lie=
s the rub.</div><div><br></div><div>The current system doesn=E2=80=99t call=
<font face=3D"Courier">std::terminate</font> (or <font face=3D"Courier">st=
d::unexpected</font>) just because it=E2=80=99s confused. An exception is a=
contract between the thrower and the catcher, and throwing into an unwind =
breaks that contract. Terminating the program is the only safe course of ac=
tion when a contract is broken irrecoverably.</div><div><br></div><div>If t=
he status quo were to ignore exceptions in unwinding, your proposal would b=
e a viable way to handle them. Instead, it changes the behavior of existing=
programs to be more tolerant.</div><div><br></div><div>Perhaps it would be=
safe to allow multiple exceptions in flight, as long as no <font face=3D"C=
ourier">catch</font> block exits normally until all exceptions have been ha=
ndled. There would need to be a <font face=3D"Courier">rethrow_next</font> =
facility. I don=E2=80=99t know, though, if that=E2=80=99s any better than w=
hat <font face=3D"Courier">std::nested_exception</font> can already do.</di=
v><div><br></div><div>See also the thread =E2=80=9Cnested exceptions=E2=80=
=9D from this past April 23-May 11, which examines a very similar idea.</di=
v><div><br></div></div></blockquote></div></blockquote></div></blockquote><=
/div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2682_2093110973.1437222119354--
------=_Part_2681_985948341.1437222119353--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Sat, 18 Jul 2015 11:04:25 -0500
Raw View
--047d7bfea0f4bfe16c051b2877aa
Content-Type: text/plain; charset=UTF-8
On 18 July 2015 at 04:15, denis <isocppgroup@denisbider.com> wrote:
> (3) When the stack is being unwound due to an exception in flight; and a
> destructor exits with another exception; instead of calling std::terminate,
> the new exception is simply added to the end of the exception-list.
>
How do you do this w/o using the heap? If you use the heap, the allocation
may fail and throw an exception.
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--047d7bfea0f4bfe16c051b2877aa
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra">On 18 July 2015 at 04:15, denis=
<span dir=3D"ltr"><<a href=3D"mailto:isocppgroup@denisbider.com" target=
=3D"_blank">isocppgroup@denisbider.com</a>></span> wrote:<br><div class=
=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div>(3) When the stack is =
being unwound due to an exception in flight; and a destructor exits with an=
other exception; instead of calling <font face=3D"courier new,monospace">st=
d::terminate</font>, the new exception is simply added to the end of the ex=
ception-list.</div><div></div></blockquote></div><br>How do you do this w/o=
using the heap?=C2=A0 If you use the heap, the allocation may fail and thr=
ow an exception.<br>-- <br><div class=3D"gmail_signature">=C2=A0Nevin "=
;:-)" Liber=C2=A0 <mailto:<a href=3D"mailto:nevin@eviloverlord.com"=
target=3D"_blank">nevin@eviloverlord.com</a>>=C2=A0 (847) 691-1404</div=
>
</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7bfea0f4bfe16c051b2877aa--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Sat, 18 Jul 2015 11:15:09 -0700 (PDT)
Raw View
------=_Part_212_161401187.1437243309928
Content-Type: multipart/alternative;
boundary="----=_Part_213_299075317.1437243309929"
------=_Part_213_299075317.1437243309929
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
> How do you do this w/o using the heap? If you use the heap, the=20
allocation may fail and throw an exception.
Excellent question! You Sleep(0) until allocation succeeds.
Here is the full reasoning from a recent post, in which I first described=
=20
this proposal:
http://denisbider.blogspot.com/2015/07/errors-in-destructors-2.html
*But what if the exception is bad_alloc, and there's no memory for=20
secondary exceptions?*=20
The program should wait for memory to become available.
In 20 years, I have never seen *bad_alloc* on Windows unless the program=20
requested an unreasonable amount of memory. In all of these cases,=20
normal-sized allocations could still continue.
Windows will go to extreme lengths to avoid failing a reasonable memory=20
request. I argue that this is what an operating system should do. If a=20
program finds itself in a position where it cannot allocate a small amount=
=20
of memory, it should spin with *Sleep()*, and wait for memory to become=20
available. If the memory is being exhausted by another process or thread,=
=20
it will eventually finish or be killed, and other processes can continue.=
=20
If the memory is being exhausted by the same thread, then the program is in=
=20
a borked state, and might as well hang, so someone can attach to it with a=
=20
debugger. In this case, the program needs to be fixed.
We should not design exception handling as if the typical case is going to=
=20
be a low-memory condition in which *operator new* fails for reasonable=20
allocations. For reasonable use, *operator new* should never fail. If we're=
=20
allocating memory for an exception, the allocator should succeed or wait=20
indefinitely.
When the human economy runs out of something vital, our go-to response is=
=20
to queue for it. There's no reason a program shouldn't wait if it needs=20
something vital =E2=80=94 such as a small amount of memory to proceed with=
=20
exception handling.
On Saturday, July 18, 2015 at 10:05:06 AM UTC-6, Nevin ":-)" Liber wrote:
> On 18 July 2015 at 04:15, denis <isocp...@denisbider.com <javascript:>>=
=20
> wrote:
>
>> (3) When the stack is being unwound due to an exception in flight; and a=
=20
>> destructor exits with another exception; instead of calling=20
>> std::terminate, the new exception is simply added to the end of the=20
>> exception-list.
>>
>
> How do you do this w/o using the heap? If you use the heap, the=20
> allocation may fail and throw an exception.
> --=20
> Nevin ":-)" Liber <mailto:ne...@eviloverlord.com <javascript:>> (847)=
=20
> 691-1404
> =20
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_213_299075317.1437243309929
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>> How do you do this w/o using the heap?=C2=A0 If =
you use the heap, the allocation may fail and throw an exception.</div><div=
><br></div><div>Excellent question! You Sleep(0) until allocation succeeds.=
</div><div><br></div><div>Here is the full reasoning from a recent post, in=
which I first described this=C2=A0proposal:</div><div><br></div><div><a hr=
ef=3D"http://denisbider.blogspot.com/2015/07/errors-in-destructors-2.html">=
http://denisbider.blogspot.com/2015/07/errors-in-destructors-2.html</a></di=
v><div><br></div><div><strong>But what if the exception is <i>bad_alloc</i>=
, and there's no memory for secondary exceptions?<br></strong>
<br>
The program should wait for memory to become available.<br>
<br>
In 20 years, I have never seen <i>bad_alloc</i> on Windows unless the=20
program requested an unreasonable amount of memory. In all of these=20
cases, normal-sized allocations could still continue.<br>
<br>
Windows will go to extreme lengths to avoid failing a reasonable memory=20
request. I argue that this is what an operating system should do. If a=20
program finds itself in a position where it cannot allocate a small=20
amount of memory, it should spin with <i>Sleep()</i>, and wait for=20
memory to become available. If the memory is being exhausted by another=20
process or thread, it will eventually finish or be killed, and other=20
processes can continue. If the memory is being exhausted by the same=20
thread, then the program is in a borked state, and might as well hang,=20
so someone can attach to it with a debugger. In this case, the program=20
needs to be fixed.<br>
<br>
We should not design exception handling as if the typical case is going to =
be a low-memory condition in which <i>operator new</i> fails for reasonable=
allocations. For reasonable use, <i>operator new</i> should never fail. If=
we're allocating memory for an exception, the allocator should succeed=
or wait indefinitely.<br>
<br>
When the human economy runs out of something vital, our go-to response=20
is to queue for it. There's no reason a program shouldn't wait if i=
t=20
needs something vital =E2=80=94 such as a small amount of memory to proceed=
with
exception handling.</div><div><br></div><div><br><br>On Saturday, July 18,=
2015 at 10:05:06 AM UTC-6, Nevin ":-)" Liber wrote:</div><blockq=
uote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left=
: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px; borde=
r-left-style: solid;"><div dir=3D"ltr"><div>On 18 July 2015 at 04:15, denis=
<span dir=3D"ltr"><<a onmousedown=3D"this.href=3D'javascript:';=
return true;" onclick=3D"this.href=3D'javascript:';return true;" hr=
ef=3D"javascript:" target=3D"_blank" rel=3D"nofollow">isocp...@denisbider.c=
om</a>></span> wrote:<br><div class=3D"gmail_quote"><blockquote class=3D=
"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border=
-left-color: rgb(204, 204, 204); border-left-width: 1px; border-left-style:=
solid;"><div>(3) When the stack is being unwound due to an exception in fl=
ight; and a destructor exits with another exception; instead of calling <fo=
nt face=3D"courier new,monospace">std::terminate</font>, the new exception =
is simply added to the end of the exception-list.</div><div></div></blockqu=
ote></div><br>How do you do this w/o using the heap?=C2=A0 If you use the h=
eap, the allocation may fail and throw an exception.<br>-- <br><div>=C2=A0N=
evin ":-)" Liber=C2=A0 <mailto:<a onmousedown=3D"this.href=3D&=
#39;javascript:';return true;" onclick=3D"this.href=3D'javascript:&=
#39;;return true;" href=3D"javascript:" target=3D"_blank" rel=3D"nofollow">=
ne...@eviloverlord.com</a>>=C2=A0 (847) 691-1404</div>
</div></div>
</blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_213_299075317.1437243309929--
------=_Part_212_161401187.1437243309928--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Sat, 18 Jul 2015 13:08:26 -0700
Raw View
On Saturday 18 July 2015 11:15:09 denis bider wrote:
> > How do you do this w/o using the heap? If you use the heap, the
>
> allocation may fail and throw an exception.
>
> Excellent question! You Sleep(0) until allocation succeeds.
Not acceptable. Please propose a different function that will not cause a live-
lock in systems that cannot create more memory.
> *But what if the exception is bad_alloc, and there's no memory for
> secondary exceptions?*
> The program should wait for memory to become available.
And what if it never becomes available? This can occur for programs that:
a) run without virtual memory (such as an OS kernel)
b) have reached administratively- or architecturally-imposed limits
And this is not even counting on programs that behaved incorrectly and have
corrupted the malloc state.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Sat, 18 Jul 2015 13:14:25 -0700
Raw View
On Saturday 18 July 2015 02:15:27 denis wrote:
> (1) The internal representation of an exception in flight is changed from a
> single exception to a list of exceptions. Let's call this the
> exception-list.
>
> (2) std::exception_ptr now points to the beginning of the exception-list,
> rather than a single exception. Methods are added to std::exception_ptr
> allowing a catch handler to walk the exception-list.
>
> (3) When the stack is being unwound due to an exception in flight; and a
> destructor exits with another exception; instead of calling std::terminate,
> the new exception is simply added to the end of the exception-list.
>
> This is all.
Please explain the following situation: if a destructor can report error
conditions, what's the state of the object after its destructor throws?
For example:
struct A { ~A() { throw "whee"; } };
int main() {
A *a = new A;
delete a;
}
If ~A() throws, is operator delete still called?
Expanding:
struct B { A a1, a2; };
When ~B() is invoked, a2.~A() will throw. What happens to a1?
And then there's the case of exception thrown during stack unwinding *due* to
an exception:
void f()
{
A a;
throw 42;
}
When the stack is unwound exiting f(), a.~A() is called and that throws. What
should happen in this case?
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Sat, 18 Jul 2015 13:22:19 -0700 (PDT)
Raw View
------=_Part_2992_208023160.1437250939650
Content-Type: multipart/alternative;
boundary="----=_Part_2993_1881814630.1437250939651"
------=_Part_2993_1881814630.1437250939651
Content-Type: text/plain; charset=UTF-8
Could you refer me to at least one, but if possible several, example
systems that:
- use C++, including especially exception functionality;
- are subject to limitations such as found in an OS kernel?
This is not because I don't believe that such systems exist, but because I
wish to understand more about them.
[Currently, my understanding is that kernel developers either avoid C++;
and/or use a subset of its features; and/or use private versions of C++
features that are designed for a better fit of the intended environment.]
The foregoing being said - is finding memory to aggregate exceptions not an
implementation detail that depends on the intended environment?
How do you handle stack allocation, for instance, in this limited
environment?
What prevents you from using a stack-like technique to pre-allocate memory
for aggregation of exceptions?
C++ already does not provide guarantees about how deeply a function can
call itself, for example. If a function recurses "too deply", it is
understood that the program or thread terminates. If you're in a limited
memory environment, and run out of pre-allocated memory for aggregated
exceptions, what's the problem with std::terminate?
On Saturday, July 18, 2015 at 2:08:31 PM UTC-6, Thiago Macieira wrote:
> On Saturday 18 July 2015 11:15:09 denis bider wrote:
> > > How do you do this w/o using the heap? If you use the heap, the
> >
> > allocation may fail and throw an exception.
> >
> > Excellent question! You Sleep(0) until allocation succeeds.
>
> Not acceptable. Please propose a different function that will not cause a
> live-
> lock in systems that cannot create more memory.
>
> > *But what if the exception is bad_alloc, and there's no memory for
> > secondary exceptions?*
> > The program should wait for memory to become available.
>
> And what if it never becomes available? This can occur for programs that:
>
> a) run without virtual memory (such as an OS kernel)
> b) have reached administratively- or architecturally-imposed limits
>
> And this is not even counting on programs that behaved incorrectly and
> have
> corrupted the malloc state.
>
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
> PGP/GPG: 0x6EF45358; fingerprint:
> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
>
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2993_1881814630.1437250939651
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Could you refer me to=C2=A0at least one, but=C2=A0if =
possible=C2=A0several, example systems that:</div><div><br></div><div>- use=
C++, including especially exception functionality;</div><div><br></div><di=
v>- are subject to limitations such as found in an OS kernel?</div><div><br=
></div><div>This is not because I don't believe that such systems exist=
, but because I wish to understand more about them.</div><div><br></div><di=
v>[Currently, my understanding is that kernel developers either avoid C++; =
and/or use a subset of its features; and/or use private versions of C++ fea=
tures that are designed for a better fit of the intended environment.]</div=
><div><br></div><div><br></div><div>The foregoing=C2=A0being said=C2=A0-=C2=
=A0is finding memory to aggregate exceptions not an implementation detail t=
hat depends on the intended environment?</div><div><br></div><div>How do yo=
u handle stack allocation, for instance, in this limited environment?</div>=
<div><br></div><div>What prevents you from using a=C2=A0stack-like techniqu=
e to pre-allocate memory for aggregation of exceptions?</div><div><br></div=
><div>C++ already does not provide guarantees about how deeply a function c=
an call itself, for example. If a function recurses "too deply", =
it is understood that the program or thread terminates. If you're in a =
limited memory environment, and run out of pre-allocated memory for aggrega=
ted exceptions, what's the problem with std::terminate?</div><div><br><=
br>On Saturday, July 18, 2015 at 2:08:31 PM UTC-6, Thiago Macieira wrote:</=
div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; p=
adding-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-width:=
1px; border-left-style: solid;">On Saturday 18 July 2015 11:15:09 denis bi=
der wrote:
<br>> > How do you do this w/o using the heap? =C2=A0If you use the h=
eap, the
<br>>=20
<br>> allocation may fail and throw an exception.
<br>>=20
<br>> Excellent question! You Sleep(0) until allocation succeeds.
<br>
<br>Not acceptable. Please propose a different function that will not cause=
a live-
<br>lock in systems that cannot create more memory.
<br>
<br>> *But what if the exception is bad_alloc, and there's no memory=
for
<br>> secondary exceptions?*
<br>> The program should wait for memory to become available.
<br>
<br>And what if it never becomes available? This can occur for programs tha=
t:
<br>
<br>=C2=A0a) run without virtual memory (such as an OS kernel)
<br>=C2=A0b) have reached administratively- or architecturally-imposed limi=
ts
<br>
<br>And this is not even counting on programs that behaved incorrectly and =
have=20
<br>corrupted the malloc state.
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a onmousedown=3D"this.href=3D'http:/=
/www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\75D\46sntz\0751\46u=
sg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.=
href=3D'http://www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\7=
5D\46sntz\0751\46usg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;=
" href=3D"http://macieira.info" target=3D"_blank" rel=3D"nofollow">macieira=
..info</a> - thiago (AT) <a onmousedown=3D"this.href=3D'http://www.googl=
e.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\75AFQjCNHGRJd=
o5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'http=
://www.google.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\7=
5AFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;" href=3D"http://kde.o=
rg" target=3D"_blank" rel=3D"nofollow">kde.org</a>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>=C2=A0 =C2=A0 =C2=A0 PGP/GPG: 0x6EF45358; fingerprint:
<br>=C2=A0 =C2=A0 =C2=A0 E067 918B B660 DBD1 105C =C2=A0966C 33F5 F005 6EF4=
5358
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2993_1881814630.1437250939651--
------=_Part_2992_208023160.1437250939650--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Sat, 18 Jul 2015 13:39:49 -0700 (PDT)
Raw View
------=_Part_2996_44236690.1437251989310
Content-Type: multipart/alternative;
boundary="----=_Part_2997_487657513.1437251989310"
------=_Part_2997_487657513.1437251989310
Content-Type: text/plain; charset=UTF-8
Unless my understanding is faulty, your first example does not seem to
involve multi-exceptions. Therefore, behavior under my proposal would be
identical to behavior now. The main function lacks a try/catch block, so
that's an issue. However, if you add a try/catch block around main, the
code will compile fine in C++03, it will work, and yes, operator delete
will be called. The same is the case in C++11 and 14, as long as you take
care to add noexcept(false) to the destructor.
In your second example, struct B containing a1 and a2: when ~B is invoked,
a2.~A() throws "whee", creating exception-list with a single entry, char
const[] "whee". According to normal C++ destruction proceedings, a1.~A() is
then invoked, which also throws "whee", adding another exception-list
entry. The exception-list now has two entries, both of them char const[]
"whee".
In your third example, with the f function: throw 42 occurs first, creating
exception-list with a single exception, int 42. This is followed by ~A,
which throws; when control leaves destructor, exception "whee" is added to
exception-list. Exception-list now contains int 42, and char const[] "whee".
Further processing depends on what other code called this code.
On Saturday, July 18, 2015 at 2:14:29 PM UTC-6, Thiago Macieira wrote:
> On Saturday 18 July 2015 02:15:27 denis wrote:
> > (1) The internal representation of an exception in flight is changed
> from a
> > single exception to a list of exceptions. Let's call this the
> > exception-list.
> >
> > (2) std::exception_ptr now points to the beginning of the
> exception-list,
> > rather than a single exception. Methods are added to std::exception_ptr
> > allowing a catch handler to walk the exception-list.
> >
> > (3) When the stack is being unwound due to an exception in flight; and a
> > destructor exits with another exception; instead of calling
> std::terminate,
> > the new exception is simply added to the end of the exception-list.
> >
> > This is all.
>
> Please explain the following situation: if a destructor can report error
> conditions, what's the state of the object after its destructor throws?
>
> For example:
>
> struct A { ~A() { throw "whee"; } };
> int main() {
> A *a = new A;
> delete a;
> }
>
> If ~A() throws, is operator delete still called?
>
> Expanding:
>
> struct B { A a1, a2; };
>
> When ~B() is invoked, a2.~A() will throw. What happens to a1?
>
> And then there's the case of exception thrown during stack unwinding *due*
> to
> an exception:
>
> void f()
> {
> A a;
> throw 42;
> }
>
> When the stack is unwound exiting f(), a.~A() is called and that throws.
> What
> should happen in this case?
>
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
> PGP/GPG: 0x6EF45358; fingerprint:
> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
>
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2997_487657513.1437251989310
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Unless my understanding is faulty, your=C2=A0first ex=
ample does not seem to involve multi-exceptions. Therefore,=C2=A0behavior u=
nder my proposal would be identical to behavior now.=C2=A0The <font face=3D=
"courier new,monospace">main </font>function=C2=A0lacks a try/catch block, =
so that's an issue. However, if you add a try/catch block around <font =
face=3D"courier new,monospace">main</font>, the code will compile fine in C=
++03, it will work, and yes, operator delete will be called. The same is th=
e case in C++11 and 14, as long as you take care to=C2=A0add <font face=3D"=
courier new,monospace">noexcept(false)</font> to the destructor.</div><div>=
<br></div><div>In your second example, struct B containing a1 and a2: when =
~B is invoked, a2.~A() throws "whee", creating exception-list wit=
h a single entry, char const[] "whee". According to normal C++ de=
struction proceedings, a1.~A() is then invoked, which also throws "whe=
e", adding another exception-list entry. The exception-list now has tw=
o entries, both of them char const[] "whee".</div><div><br></div>=
<div>In your third example, with the f function: throw 42 occurs first, cre=
ating exception-list with a single exception, int 42.=C2=A0This is followed=
by ~A, which throws; when control leaves destructor, exception "whee&=
quot; is added to exception-list. Exception-list now contains int 42, and c=
har const[] "whee".</div><div><br></div><div>Further processing d=
epends on what other code called this code.</div><div><br><br>On Saturday, =
July 18, 2015 at 2:14:29 PM UTC-6, Thiago Macieira wrote:</div><blockquote =
class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex=
; border-left-color: rgb(204, 204, 204); border-left-width: 1px; border-lef=
t-style: solid;">On Saturday 18 July 2015 02:15:27 denis wrote:
<br>> (1) The internal representation of an exception in flight is chang=
ed from a=20
<br>> single exception to a list of exceptions. Let's call this the
<br>> exception-list.
<br>>=20
<br>> (2) std::exception_ptr now points to the beginning of the exceptio=
n-list,=20
<br>> rather than a single exception. Methods are added to std::exceptio=
n_ptr=20
<br>> allowing a catch handler to walk the exception-list.
<br>>=20
<br>> (3) When the stack is being unwound due to an exception in flight;=
and a=20
<br>> destructor exits with another exception; instead of calling std::t=
erminate,=20
<br>> the new exception is simply added to the end of the exception-list=
..
<br>>=20
<br>> This is all.
<br>
<br>Please explain the following situation: if a destructor can report erro=
r=20
<br>conditions, what's the state of the object after its destructor thr=
ows?
<br>
<br>For example:
<br>
<br>struct A { ~A() { throw "whee"; } };
<br>int main() {
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0A *a =3D new A;
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0delete a;
<br>}
<br>
<br>If ~A() throws, is operator delete still called?
<br>
<br>Expanding:
<br>
<br>struct B { A a1, a2; };
<br>
<br>When ~B() is invoked, a2.~A() will throw. What happens to a1?
<br>
<br>And then there's the case of exception thrown during stack unwindin=
g *due* to=20
<br>an exception:
<br>
<br>void f()
<br>{
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0A a;
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0throw 42;
<br>}
<br>
<br>When the stack is unwound exiting f(), a.~A() is called and that throws=
.. What=20
<br>should happen in this case?
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a onmousedown=3D"this.href=3D'http:/=
/www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\75D\46sntz\0751\46u=
sg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.=
href=3D'http://www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\7=
5D\46sntz\0751\46usg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;=
" href=3D"http://macieira.info" target=3D"_blank" rel=3D"nofollow">macieira=
..info</a> - thiago (AT) <a onmousedown=3D"this.href=3D'http://www.googl=
e.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\75AFQjCNHGRJd=
o5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'http=
://www.google.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\7=
5AFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;" href=3D"http://kde.o=
rg" target=3D"_blank" rel=3D"nofollow">kde.org</a>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>=C2=A0 =C2=A0 =C2=A0 PGP/GPG: 0x6EF45358; fingerprint:
<br>=C2=A0 =C2=A0 =C2=A0 E067 918B B660 DBD1 105C =C2=A0966C 33F5 F005 6EF4=
5358
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2997_487657513.1437251989310--
------=_Part_2996_44236690.1437251989310--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Sat, 18 Jul 2015 14:16:47 -0700 (PDT)
Raw View
------=_Part_2984_33581056.1437254207548
Content-Type: multipart/alternative;
boundary="----=_Part_2985_275690640.1437254207549"
------=_Part_2985_275690640.1437254207549
Content-Type: text/plain; charset=UTF-8
A follow-up thought on the below:
In the multi-exception proposal, in most common environments, applications
would no longer have to worry about std::uncaught_exception(). It would
always be okay for a destructor to throw.
However, in limited memory environments, it seems that the same type of
need that is currently addressed by std::uncaught_exception() could be
usefully addressed by a function like:
bool std::can_throw(size_t);
This function would return true if there is available memory to throw an
exception object of parameter size; or false if there isn't such memory.
Again, in most common environments, applications would not have to concern
themselves with this. However, in limited-memory environments, a function
like that would replace std::uncaught_exception() in its role to allow a
destructor to determine whether a throw at this point can be handled, or
will result in std::terminate.
This function would also never have to be called by non-destructor code.
The assumption would be that, like now, a single exception can always be
handled.
On Saturday, July 18, 2015 at 2:22:19 PM UTC-6, denis bider wrote:
> Could you refer me to at least one, but if possible several, example
> systems that:
>
> - use C++, including especially exception functionality;
>
> - are subject to limitations such as found in an OS kernel?
>
> This is not because I don't believe that such systems exist, but because I
> wish to understand more about them.
>
> [Currently, my understanding is that kernel developers either avoid C++;
> and/or use a subset of its features; and/or use private versions of C++
> features that are designed for a better fit of the intended environment.]
>
>
> The foregoing being said - is finding memory to aggregate exceptions not
> an implementation detail that depends on the intended environment?
>
> How do you handle stack allocation, for instance, in this limited
> environment?
>
> What prevents you from using a stack-like technique to pre-allocate memory
> for aggregation of exceptions?
>
> C++ already does not provide guarantees about how deeply a function can
> call itself, for example. If a function recurses "too deply", it is
> understood that the program or thread terminates. If you're in a limited
> memory environment, and run out of pre-allocated memory for aggregated
> exceptions, what's the problem with std::terminate?
>
>
> On Saturday, July 18, 2015 at 2:08:31 PM UTC-6, Thiago Macieira wrote:
>
>> On Saturday 18 July 2015 11:15:09 denis bider wrote:
>> > > How do you do this w/o using the heap? If you use the heap, the
>> >
>> > allocation may fail and throw an exception.
>> >
>> > Excellent question! You Sleep(0) until allocation succeeds.
>>
>> Not acceptable. Please propose a different function that will not cause a
>> live-
>> lock in systems that cannot create more memory.
>>
>> > *But what if the exception is bad_alloc, and there's no memory for
>> > secondary exceptions?*
>> > The program should wait for memory to become available.
>>
>> And what if it never becomes available? This can occur for programs that:
>>
>> a) run without virtual memory (such as an OS kernel)
>> b) have reached administratively- or architecturally-imposed limits
>>
>> And this is not even counting on programs that behaved incorrectly and
>> have
>> corrupted the malloc state.
>>
>> --
>> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
>> Software Architect - Intel Open Source Technology Center
>> PGP/GPG: 0x6EF45358; fingerprint:
>> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
>>
>>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2985_275690640.1437254207549
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>A follow-up thought on the below:</div><div><br></div=
><div>In the multi-exception proposal, in most common environments, applica=
tions would no longer have to worry about <font face=3D"courier new,monospa=
ce">std::uncaught_exception()<font face=3D"arial,sans-serif">. It would alw=
ays be okay for a destructor to throw.</font></font></div><div><br></div><d=
iv>However, in limited memory environments, it seems that the same type of =
need that is currently addressed by <font face=3D"courier new,monospace">st=
d::uncaught_exception()<font face=3D"arial,sans-serif"> could be usefully a=
ddressed by a function like:</font></font></div><div><br></div><div><font f=
ace=3D"courier new,monospace">bool std::can_throw(size_t);</font></div><div=
><font face=3D"Courier New"><br></font></div><div><font face=3D"arial,sans-=
serif">This function would return <font face=3D"courier new,monospace">true=
</font> if there is available memory to throw an exception object of parame=
ter size; or <font face=3D"courier new,monospace">false<font face=3D"arial,=
sans-serif"> if there isn't such memory.</font></font></font></div><div=
><br></div><div>Again, in most common environments, applications would not =
have to concern themselves with this. However, in limited-memory environmen=
ts, a function like that would replace <font face=3D"courier new,monospace"=
>std::uncaught_exception() <font face=3D"arial,sans-serif">in its role to a=
llow a destructor to determine whether a throw at this point can be handled=
, or will result in <font face=3D"courier new,monospace">std::terminate</fo=
nt>.</font></font></div><div><br></div><div>This function would also never =
have to be called by non-destructor code. The assumption would be that, lik=
e now,=C2=A0a single exception can always be handled.</div><div><br><br>On =
Saturday, July 18, 2015 at 2:22:19 PM UTC-6, denis bider wrote:</div><block=
quote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-lef=
t: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px; bord=
er-left-style: solid;"><div dir=3D"ltr"><div>Could you refer me to=C2=A0at =
least one, but=C2=A0if possible=C2=A0several, example systems that:</div><d=
iv><br></div><div>- use C++, including especially exception functionality;<=
/div><div><br></div><div>- are subject to limitations such as found in an O=
S kernel?</div><div><br></div><div>This is not because I don't believe =
that such systems exist, but because I wish to understand more about them.<=
/div><div><br></div><div>[Currently, my understanding is that kernel develo=
pers either avoid C++; and/or use a subset of its features; and/or use priv=
ate versions of C++ features that are designed for a better fit of the inte=
nded environment.]</div><div><br></div><div><br></div><div>The foregoing=C2=
=A0being said=C2=A0-=C2=A0is finding memory to aggregate exceptions not an =
implementation detail that depends on the intended environment?</div><div><=
br></div><div>How do you handle stack allocation, for instance, in this lim=
ited environment?</div><div><br></div><div>What prevents you from using a=
=C2=A0stack-like technique to pre-allocate memory for aggregation of except=
ions?</div><div><br></div><div>C++ already does not provide guarantees abou=
t how deeply a function can call itself, for example. If a function recurse=
s "too deply", it is understood that the program or thread termin=
ates. If you're in a limited memory environment, and run out of pre-all=
ocated memory for aggregated exceptions, what's the problem with std::t=
erminate?</div><div><br><br>On Saturday, July 18, 2015 at 2:08:31 PM UTC-6,=
Thiago Macieira wrote:</div><blockquote class=3D"gmail_quote" style=3D"mar=
gin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204,=
204); border-left-width: 1px; border-left-style: solid;">On Saturday 18 Ju=
ly 2015 11:15:09 denis bider wrote:
<br>> > How do you do this w/o using the heap? =C2=A0If you use the h=
eap, the
<br>>=20
<br>> allocation may fail and throw an exception.
<br>>=20
<br>> Excellent question! You Sleep(0) until allocation succeeds.
<br>
<br>Not acceptable. Please propose a different function that will not cause=
a live-
<br>lock in systems that cannot create more memory.
<br>
<br>> *But what if the exception is bad_alloc, and there's no memory=
for
<br>> secondary exceptions?*
<br>> The program should wait for memory to become available.
<br>
<br>And what if it never becomes available? This can occur for programs tha=
t:
<br>
<br>=C2=A0a) run without virtual memory (such as an OS kernel)
<br>=C2=A0b) have reached administratively- or architecturally-imposed limi=
ts
<br>
<br>And this is not even counting on programs that behaved incorrectly and =
have=20
<br>corrupted the malloc state.
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a onmousedown=3D"this.href=3D'http:/=
/www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\75D\46sntz\0751\46u=
sg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.=
href=3D'http://www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\7=
5D\46sntz\0751\46usg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;=
" href=3D"http://macieira.info" target=3D"_blank" rel=3D"nofollow">macieira=
..info</a> - thiago (AT) <a onmousedown=3D"this.href=3D'http://www.googl=
e.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\75AFQjCNHGRJd=
o5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'http=
://www.google.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\7=
5AFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;" href=3D"http://kde.o=
rg" target=3D"_blank" rel=3D"nofollow">kde.org</a>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>=C2=A0 =C2=A0 =C2=A0 PGP/GPG: 0x6EF45358; fingerprint:
<br>=C2=A0 =C2=A0 =C2=A0 E067 918B B660 DBD1 105C =C2=A0966C 33F5 F005 6EF4=
5358
<br>
<br></blockquote></div></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2985_275690640.1437254207549--
------=_Part_2984_33581056.1437254207548--
.
Author: Vitali Lovich <vlovich@gmail.com>
Date: Sat, 18 Jul 2015 15:33:10 -0700
Raw View
--Apple-Mail=_9B104758-DF75-45A6-B927-E2E2A438A116
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8
I think the motivating problem raised here is a valid one. It=E2=80=99s pr=
obably also a rarer problem. It also happens to be impossible to solve in =
a reliable way without language/library support.
Sleep 0 is not really an acceptable solution for all the reasons raised & m=
any more. A reasonable compromise could be that bad_alloc would still call=
std::terminate as OOM conditions are generally irrecoverable anyway.
This might not require large language changes. If there were a std::unwind=
ing_exception() that returned the exception_ptr to the exception currently =
in-flight,
that could let the user manage the responsibility of addressing how they wa=
nt to handle multiple exceptions in-flight. They could ensure that they we=
re throwing their own exception type to which they could append the excepti=
ons & deal with OOM scenarios as needed.
The caveat there is that there probably would be benefit to also providing =
some language facility to replace the in-flight exception so that you could=
transform the exception being thrown as it propogates up the stack (so tha=
t you could upgrade something to std::nested_exception).
Apologies if the "nested exceptions=E2=80=9D thread David alludes to alread=
y covers this ground.
> On Jul 18, 2015, at 2:16 PM, denis bider <isocppgroup@denisbider.com> wro=
te:
>=20
> A follow-up thought on the below:
>=20
> In the multi-exception proposal, in most common environments, application=
s would no longer have to worry about std::uncaught_exception(). It would a=
lways be okay for a destructor to throw.
>=20
> However, in limited memory environments, it seems that the same type of n=
eed that is currently addressed by std::uncaught_exception() could be usefu=
lly addressed by a function like:
>=20
> bool std::can_throw(size_t);
>=20
> This function would return true if there is available memory to throw an =
exception object of parameter size; or false if there isn't such memory.
>=20
> Again, in most common environments, applications would not have to concer=
n themselves with this. However, in limited-memory environments, a function=
like that would replace std::uncaught_exception() in its role to allow a d=
estructor to determine whether a throw at this point can be handled, or wil=
l result in std::terminate.
>=20
> This function would also never have to be called by non-destructor code. =
The assumption would be that, like now, a single exception can always be ha=
ndled.
>=20
>=20
> On Saturday, July 18, 2015 at 2:22:19 PM UTC-6, denis bider wrote:
> Could you refer me to at least one, but if possible several, example syst=
ems that:
>=20
> - use C++, including especially exception functionality;
>=20
> - are subject to limitations such as found in an OS kernel?
>=20
> This is not because I don't believe that such systems exist, but because =
I wish to understand more about them.
>=20
> [Currently, my understanding is that kernel developers either avoid C++; =
and/or use a subset of its features; and/or use private versions of C++ fea=
tures that are designed for a better fit of the intended environment.]
>=20
>=20
> The foregoing being said - is finding memory to aggregate exceptions not =
an implementation detail that depends on the intended environment?
>=20
> How do you handle stack allocation, for instance, in this limited environ=
ment?
>=20
> What prevents you from using a stack-like technique to pre-allocate memor=
y for aggregation of exceptions?
>=20
> C++ already does not provide guarantees about how deeply a function can c=
all itself, for example. If a function recurses "too deply", it is understo=
od that the program or thread terminates. If you're in a limited memory env=
ironment, and run out of pre-allocated memory for aggregated exceptions, wh=
at's the problem with std::terminate?
>=20
>=20
> On Saturday, July 18, 2015 at 2:08:31 PM UTC-6, Thiago Macieira wrote:
> On Saturday 18 July 2015 11:15:09 denis bider wrote:=20
> > > How do you do this w/o using the heap? If you use the heap, the=20
> >=20
> > allocation may fail and throw an exception.=20
> >=20
> > Excellent question! You Sleep(0) until allocation succeeds.=20
>=20
> Not acceptable. Please propose a different function that will not cause a=
live-=20
> lock in systems that cannot create more memory.=20
>=20
> > *But what if the exception is bad_alloc, and there's no memory for=20
> > secondary exceptions?*=20
> > The program should wait for memory to become available.=20
>=20
> And what if it never becomes available? This can occur for programs that:=
=20
>=20
> a) run without virtual memory (such as an OS kernel)=20
> b) have reached administratively- or architecturally-imposed limits=20
>=20
> And this is not even counting on programs that behaved incorrectly and ha=
ve=20
> corrupted the malloc state.=20
>=20
> --=20
> Thiago Macieira - thiago (AT) macieira.info <http://macieira.info/> - thi=
ago (AT) kde.org <http://kde.org/>=20
> Software Architect - Intel Open Source Technology Center=20
> PGP/GPG: 0x6EF45358; fingerprint:=20
> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358=20
>=20
>=20
> --=20
>=20
> ---=20
> You received this message because you are subscribed to the Google Groups=
"ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an=
email to std-proposals+unsubscribe@isocpp.org <mailto:std-proposals+unsubs=
cribe@isocpp.org>.
> To post to this group, send email to std-proposals@isocpp.org <mailto:std=
-proposals@isocpp.org>.
> Visit this group at http://groups.google.com/a/isocpp.org/group/std-propo=
sals/ <http://groups.google.com/a/isocpp.org/group/std-proposals/>.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--Apple-Mail=_9B104758-DF75-45A6-B927-E2E2A438A116
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8
<html><head><meta http-equiv=3D"Content-Type" content=3D"text/html charset=
=3Dutf-8"></head><body style=3D"word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><div class=3D"">I =
think the motivating problem raised here is a valid one. It=E2=80=99s=
probably also a rarer problem. It also happens to be impossible to s=
olve in a reliable way without language/library support.</div><div class=3D=
""><br class=3D""></div><div class=3D"">Sleep 0 is not really an acceptable=
solution for all the reasons raised & many more. A reasonable co=
mpromise could be that bad_alloc would still call std::terminate as OOM con=
ditions are generally irrecoverable anyway.</div><div class=3D""><br class=
=3D""></div><div class=3D"">This might not require large language changes. =
If there were a std::unwinding_exception() that returned the exceptio=
n_ptr to the exception currently in-flight,</div><div class=3D"">that could=
let the user manage the responsibility of addressing how they want to hand=
le multiple exceptions in-flight. They could ensure that they were th=
rowing their own exception type to which they could append the exceptions &=
amp; deal with OOM scenarios as needed.</div><div class=3D""><br class=3D""=
></div><div class=3D"">The caveat there is that there probably would be ben=
efit to also providing some language facility to replace the in-flight exce=
ption so that you could transform the exception being thrown as it propogat=
es up the stack (so that you could upgrade something to std::nested_excepti=
on).</div><div class=3D""><br class=3D""></div><div class=3D"">Apologies if=
the "nested exceptions=E2=80=9D thread David alludes to already covers thi=
s ground.</div><div class=3D""><div class=3D""><br class=3D""><div><blockqu=
ote type=3D"cite" class=3D""><div class=3D"">On Jul 18, 2015, at 2:16 PM, d=
enis bider <<a href=3D"mailto:isocppgroup@denisbider.com" class=3D"">iso=
cppgroup@denisbider.com</a>> wrote:</div><br class=3D"Apple-interchange-=
newline"><div class=3D""><div dir=3D"ltr" class=3D""><div class=3D"">A foll=
ow-up thought on the below:</div><div class=3D""><br class=3D""></div><div =
class=3D"">In the multi-exception proposal, in most common environments, ap=
plications would no longer have to worry about <font face=3D"courier new,mo=
nospace" class=3D"">std::uncaught_exception()<font face=3D"arial,sans-serif=
" class=3D"">. It would always be okay for a destructor to throw.</font></f=
ont></div><div class=3D""><br class=3D""></div><div class=3D"">However, in =
limited memory environments, it seems that the same type of need that is cu=
rrently addressed by <font face=3D"courier new,monospace" class=3D"">std::u=
ncaught_exception()<font face=3D"arial,sans-serif" class=3D""> could be use=
fully addressed by a function like:</font></font></div><div class=3D""><br =
class=3D""></div><div class=3D""><font face=3D"courier new,monospace" class=
=3D"">bool std::can_throw(size_t);</font></div><div class=3D""><font face=
=3D"Courier New" class=3D""><br class=3D""></font></div><div class=3D""><fo=
nt face=3D"arial,sans-serif" class=3D"">This function would return <font fa=
ce=3D"courier new,monospace" class=3D"">true</font> if there is available m=
emory to throw an exception object of parameter size; or <font face=3D"cour=
ier new,monospace" class=3D"">false<font face=3D"arial,sans-serif" class=3D=
""> if there isn't such memory.</font></font></font></div><div class=3D""><=
br class=3D""></div><div class=3D"">Again, in most common environments, app=
lications would not have to concern themselves with this. However, in limit=
ed-memory environments, a function like that would replace <font face=3D"co=
urier new,monospace" class=3D"">std::uncaught_exception() <font face=3D"ari=
al,sans-serif" class=3D"">in its role to allow a destructor to determine wh=
ether a throw at this point can be handled, or will result in <font face=3D=
"courier new,monospace" class=3D"">std::terminate</font>.</font></font></di=
v><div class=3D""><br class=3D""></div><div class=3D"">This function would =
also never have to be called by non-destructor code. The assumption would b=
e that, like now, a single exception can always be handled.</div><div =
class=3D""><br class=3D""><br class=3D"">On Saturday, July 18, 2015 at 2:22=
:19 PM UTC-6, denis bider wrote:</div><blockquote class=3D"gmail_quote" sty=
le=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(=
204, 204, 204); border-left-width: 1px; border-left-style: solid;"><div dir=
=3D"ltr" class=3D""><div class=3D"">Could you refer me to at least one=
, but if possible several, example systems that:</div><div class=
=3D""><br class=3D""></div><div class=3D"">- use C++, including especially =
exception functionality;</div><div class=3D""><br class=3D""></div><div cla=
ss=3D"">- are subject to limitations such as found in an OS kernel?</div><d=
iv class=3D""><br class=3D""></div><div class=3D"">This is not because I do=
n't believe that such systems exist, but because I wish to understand more =
about them.</div><div class=3D""><br class=3D""></div><div class=3D"">[Curr=
ently, my understanding is that kernel developers either avoid C++; and/or =
use a subset of its features; and/or use private versions of C++ features t=
hat are designed for a better fit of the intended environment.]</div><div c=
lass=3D""><br class=3D""></div><div class=3D""><br class=3D""></div><div cl=
ass=3D"">The foregoing being said - is finding memory to agg=
regate exceptions not an implementation detail that depends on the intended=
environment?</div><div class=3D""><br class=3D""></div><div class=3D"">How=
do you handle stack allocation, for instance, in this limited environment?=
</div><div class=3D""><br class=3D""></div><div class=3D"">What prevents yo=
u from using a stack-like technique to pre-allocate memory for aggrega=
tion of exceptions?</div><div class=3D""><br class=3D""></div><div class=3D=
"">C++ already does not provide guarantees about how deeply a function can =
call itself, for example. If a function recurses "too deply", it is underst=
ood that the program or thread terminates. If you're in a limited memory en=
vironment, and run out of pre-allocated memory for aggregated exceptions, w=
hat's the problem with std::terminate?</div><div class=3D""><br class=3D"">=
<br class=3D"">On Saturday, July 18, 2015 at 2:08:31 PM UTC-6, Thiago Macie=
ira wrote:</div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px =
0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border=
-left-width: 1px; border-left-style: solid;">On Saturday 18 July 2015 11:15=
:09 denis bider wrote:
<br class=3D"">> > How do you do this w/o using the heap? If yo=
u use the heap, the
<br class=3D"">>=20
<br class=3D"">> allocation may fail and throw an exception.
<br class=3D"">>=20
<br class=3D"">> Excellent question! You Sleep(0) until allocation succe=
eds.
<br class=3D"">
<br class=3D"">Not acceptable. Please propose a different function that wil=
l not cause a live-
<br class=3D"">lock in systems that cannot create more memory.
<br class=3D"">
<br class=3D"">> *But what if the exception is bad_alloc, and there's no=
memory for
<br class=3D"">> secondary exceptions?*
<br class=3D"">> The program should wait for memory to become available.
<br class=3D"">
<br class=3D"">And what if it never becomes available? This can occur for p=
rograms that:
<br class=3D"">
<br class=3D""> a) run without virtual memory (such as an OS kernel)
<br class=3D""> b) have reached administratively- or architecturally-i=
mposed limits
<br class=3D"">
<br class=3D"">And this is not even counting on programs that behaved incor=
rectly and have=20
<br class=3D"">corrupted the malloc state.
<br class=3D"">
<br class=3D"">--=20
<br class=3D"">Thiago Macieira - thiago (AT) <a onmousedown=3D"this.href=3D=
'http://www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\75D\46sntz\0=
751\46usg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"th=
is.href=3D'http://www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\75=
D\46sntz\0751\46usg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" hre=
f=3D"http://macieira.info/" target=3D"_blank" rel=3D"nofollow" class=3D"">m=
acieira.info</a> - thiago (AT) <a onmousedown=3D"this.href=3D'http://www.go=
ogle.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\75AFQjCNHG=
RJdo5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'http://ww=
w.google.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\75AFQj=
CNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;" href=3D"http://kde.org/" targ=
et=3D"_blank" rel=3D"nofollow" class=3D"">kde.org</a>
<br class=3D""> Software Architect - Intel Open Source Technolo=
gy Center
<br class=3D""> PGP/GPG: 0x6EF45358; fingerprint:
<br class=3D""> E067 918B B660 DBD1 105C 966C 33F=
5 F005 6EF4 5358
<br class=3D"">
<br class=3D""></blockquote></div></blockquote></div><div class=3D""><br cl=
ass=3D"webkit-block-placeholder"></div>
-- <br class=3D"">
<br class=3D"">
--- <br class=3D"">
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.<br class=3D"">
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" class=3D"">=
std-proposals+unsubscribe@isocpp.org</a>.<br class=3D"">
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" class=3D"">std-proposals@isocpp.org</a>.<br class=3D"">
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" class=3D"">http://groups.google.com/a/isocpp.org/group/std-=
proposals/</a>.<br class=3D"">
</div></blockquote></div><br class=3D""></div></div></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--Apple-Mail=_9B104758-DF75-45A6-B927-E2E2A438A116--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Sun, 19 Jul 2015 00:20:54 -0700 (PDT)
Raw View
------=_Part_3251_1932547564.1437290454275
Content-Type: multipart/alternative;
boundary="----=_Part_3252_1360619668.1437290454276"
------=_Part_3252_1360619668.1437290454276
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
That is true:
- something like std::unwinding_exception; allowing concurrent access to=20
both an outer exception in flight, and to std::current_exception in a=20
destructor catch handler;
- and then a mechanism to allow a catch handler in a destructor, or in a=20
container implementation, to access and manipulate the exception pointed to=
=20
by std::exception_ptr;
- or if not providing direct access, then some way to aggregate two std::ex=
ception_ptr=20
into one;
.... if we had that, *at minimum*, then a person who has access to their=20
entire code base could rig their system to support multi-exceptions. It=20
would require aggregation catch handlers to be added to destructors that=20
may throw; custom, non-STL containers to support aggregation; and of=20
course, modifying all the catch handlers around. But it would be *doable*, =
if=20
you have complete control.
My concern, though, is that if the language takes such a lukewarm approach,=
=20
it will be heading down the wrong path.
I do not wish to offend anyone who was involved with noexcept, and may be=
=20
partial to it. However, in my view, it is a kludge. It is an architectural=
=20
misunderstanding - a patch to cover up a defect in design.
There is no reason the language can't handle multiple exceptions in stack=
=20
unwinding. Just add them to a list, and then require catch-any handlers=20
that process them all. If any single exception remains, it can be handed=20
to a traditional catch handler. All code can now safely throw.
This is a *minor *design change that - just like that - fixes the problem.
But what the language has done instead is adopt this noexcept kludge, which=
=20
not only creates double negatives - noexcept(false): I will *not *not throw=
=20
exceptions? - but effectively creates two languages out of one.
With noexcept, we have:
(1) code that can throw; and
(2) code that can't throw, and must use the equivalent of P/Invoke=20
(extensive try-catch handlers) to safely call code that does.
Any algorithm, any object, any service, will first be implemented as normal=
=20
code that can throw. *Then*, at one point, you will realize you need it in=
=20
a destructor. Now, you have to implement it again - as code that *does not*
throw.
This is *ugly*. I'm deeply frustrated that the language decided on such a=
=20
kludge, when it is instead possible to adopt an elegant, true solution.
It's not too late! noexcept is not yet in use everywhere. And arguably, it=
=20
will never be *too late.* It may be too late to save our *pride*, but if=20
C++ is still around, our children may recognize noexcept was a mistake,=20
and standardize multi-exceptions in 2040.
But we should fix this mistake *now.* Let's not allow noexcept to become=20
our legacy.
On Saturday, July 18, 2015 at 4:33:14 PM UTC-6, vlovich wrote:
> I think the motivating problem raised here is a valid one. It=E2=80=99s =
probably=20
> also a rarer problem. It also happens to be impossible to solve in a=20
> reliable way without language/library support.
>
> Sleep 0 is not really an acceptable solution for all the reasons raised &=
=20
> many more. A reasonable compromise could be that bad_alloc would still=
=20
> call std::terminate as OOM conditions are generally irrecoverable anyway.
>
> This might not require large language changes. If there were a=20
> std::unwinding_exception() that returned the exception_ptr to the excepti=
on=20
> currently in-flight,
> that could let the user manage the responsibility of addressing how they=
=20
> want to handle multiple exceptions in-flight. They could ensure that the=
y=20
> were throwing their own exception type to which they could append the=20
> exceptions & deal with OOM scenarios as needed.
>
> The caveat there is that there probably would be benefit to also providin=
g=20
> some language facility to replace the in-flight exception so that you cou=
ld=20
> transform the exception being thrown as it propogates up the stack (so th=
at=20
> you could upgrade something to std::nested_exception).
>
> Apologies if the "nested exceptions=E2=80=9D thread David alludes to alre=
ady=20
> covers this ground.
>
> On Jul 18, 2015, at 2:16 PM, denis bider <isocp...@denisbider.com=20
> <javascript:>> wrote:
>
> A follow-up thought on the below:
>
> In the multi-exception proposal, in most common environments, application=
s=20
> would no longer have to worry about std::uncaught_exception(). It would=
=20
> always be okay for a destructor to throw.
>
> However, in limited memory environments, it seems that the same type of=
=20
> need that is currently addressed by std::uncaught_exception() could be=20
> usefully addressed by a function like:
>
> bool std::can_throw(size_t);
>
> This function would return true if there is available memory to throw an=
=20
> exception object of parameter size; or false if there isn't such memory.
>
> Again, in most common environments, applications would not have to concer=
n=20
> themselves with this. However, in limited-memory environments, a function=
=20
> like that would replace std::uncaught_exception() in its role to allow a=
=20
> destructor to determine whether a throw at this point can be handled, or=
=20
> will result in std::terminate.
>
> This function would also never have to be called by non-destructor code.=
=20
> The assumption would be that, like now, a single exception can always be=
=20
> handled.
>
>
> On Saturday, July 18, 2015 at 2:22:19 PM UTC-6, denis bider wrote:
>
>> Could you refer me to at least one, but if possible several, example=20
>> systems that:
>>
>> - use C++, including especially exception functionality;
>>
>> - are subject to limitations such as found in an OS kernel?
>>
>> This is not because I don't believe that such systems exist, but because=
=20
>> I wish to understand more about them.
>>
>> [Currently, my understanding is that kernel developers either avoid C++;=
=20
>> and/or use a subset of its features; and/or use private versions of C++=
=20
>> features that are designed for a better fit of the intended environment.=
]
>>
>>
>> The foregoing being said - is finding memory to aggregate exceptions not=
=20
>> an implementation detail that depends on the intended environment?
>>
>> How do you handle stack allocation, for instance, in this limited=20
>> environment?
>>
>> What prevents you from using a stack-like technique to pre-allocate=20
>> memory for aggregation of exceptions?
>>
>> C++ already does not provide guarantees about how deeply a function can=
=20
>> call itself, for example. If a function recurses "too deply", it is=20
>> understood that the program or thread terminates. If you're in a limited=
=20
>> memory environment, and run out of pre-allocated memory for aggregated=
=20
>> exceptions, what's the problem with std::terminate?
>>
>>
>> On Saturday, July 18, 2015 at 2:08:31 PM UTC-6, Thiago Macieira wrote:
>>
>>> On Saturday 18 July 2015 11:15:09 denis bider wrote:=20
>>> > > How do you do this w/o using the heap? If you use the heap, the=20
>>> >=20
>>> > allocation may fail and throw an exception.=20
>>> >=20
>>> > Excellent question! You Sleep(0) until allocation succeeds.=20
>>>
>>> Not acceptable. Please propose a different function that will not cause=
=20
>>> a live-=20
>>> lock in systems that cannot create more memory.=20
>>>
>>> > *But what if the exception is bad_alloc, and there's no memory for=20
>>> > secondary exceptions?*=20
>>> > The program should wait for memory to become available.=20
>>>
>>> And what if it never becomes available? This can occur for programs=20
>>> that:=20
>>>
>>> a) run without virtual memory (such as an OS kernel)=20
>>> b) have reached administratively- or architecturally-imposed limits=20
>>>
>>> And this is not even counting on programs that behaved incorrectly and=
=20
>>> have=20
>>> corrupted the malloc state.=20
>>>
>>> --=20
>>> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org=20
>>> Software Architect - Intel Open Source Technology Center=20
>>> PGP/GPG: 0x6EF45358; fingerprint:=20
>>> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358=20
>>>
>>>
> --=20
>
> ---=20
> You received this message because you are subscribed to the Google Groups=
=20
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an=
=20
> email to std-proposal...@isocpp.org <javascript:>.
> To post to this group, send email to std-pr...@isocpp.org <javascript:>.
> Visit this group at=20
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
>
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_3252_1360619668.1437290454276
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>That is true:</div><div><br></div><div>-=C2=A0somethi=
ng like <font face=3D"courier new,monospace">std::unwinding_exception</font=
>; allowing concurrent access to both an outer exception in flight, and to<=
font face=3D"courier new,monospace">=C2=A0std::current_exception</font> in =
a destructor catch handler;</div><div><br></div><div>- and then a mechanism=
to allow a catch handler in a destructor, or in a container implementation=
, to access and manipulate=C2=A0the exception pointed to by=C2=A0<font face=
=3D"courier new,monospace">std::exception_ptr;</font></div><div><br></div><=
div><font face=3D"Courier New">- </font>or if not providing direct access, =
then some way to aggregate two <font face=3D"courier new,monospace">std::ex=
ception_ptr </font>into one;</div><div><br></div><div>... if we had that, <=
em>at minimum</em>, then a person who has access to their entire code base =
could rig their system to support multi-exceptions. It would require=C2=A0a=
ggregation=C2=A0catch handlers=C2=A0to be added to destructors that may thr=
ow; custom, non-STL containers to support aggregation; and of course, modif=
ying all the catch handlers around. But it would be <em>doable</em>,=C2=A0i=
f you have complete control.</div><div><br></div><div>My concern, though, i=
s that if the language takes=C2=A0such a lukewarm=C2=A0approach, it will be=
heading down the wrong path.</div><div><br></div><div>I do not wish=C2=A0t=
o offend anyone who was involved with <font face=3D"courier new,monospace">=
noexcept</font><font face=3D"Arial">, and may be partial to=C2=A0it.=C2=A0H=
owever, in my view, it is a kludge. It is an architectural misunderstanding=
-=C2=A0a=C2=A0patch=C2=A0to cover up=C2=A0a defect in design.</font></div>=
<div><font face=3D"Arial"><br></font></div><div><font face=3D"Arial">There =
is no reason the language can't handle multiple exceptions in stack unw=
inding. Just add them to a list, and then require catch-any handlers that p=
rocess them all.=C2=A0If any single exception remains,=C2=A0it can be=C2=A0=
handed to=C2=A0a traditional catch handler. All code can now safely throw.<=
/font></div><div><br></div><div>This is a <em>minor </em>design change that=
-=C2=A0just like that -=C2=A0fixes the problem.</div><div><br></div><div>B=
ut what the language has done instead is adopt this <font face=3D"Courier N=
ew">noexcept<font face=3D"arial,sans-serif"> kludge, which not only=C2=A0cr=
eates double negatives=C2=A0- <font face=3D"courier new,monospace">noexcept=
(false)</font>: I will <em>not </em>not throw exceptions? -=C2=A0but=C2=A0e=
ffectively creates two languages out of one.</font></font></div><div><br></=
div><div><font face=3D"Courier New"><font face=3D"arial,sans-serif">With <f=
ont face=3D"courier new,monospace">noexcept</font>, we have:</font></font><=
/div><div><font face=3D"Courier New"><font face=3D"arial,sans-serif"><br></=
font></font></div><div><font face=3D"Courier New"><font face=3D"arial,sans-=
serif">(1) code that can throw; and</font></font></div><div><font face=3D"C=
ourier New"><font face=3D"arial,sans-serif"><br></font></font></div><div><f=
ont face=3D"Courier New"><font face=3D"arial,sans-serif">(2) code that can&=
#39;t throw, and must use the equivalent of P/Invoke (extensive try-catch h=
andlers)=C2=A0to safely call code that does.</font></font></div><div><font =
face=3D"Courier New"><font face=3D"arial,sans-serif"><br></font></font></di=
v><div><font face=3D"Courier New"><font face=3D"arial,sans-serif">Any algor=
ithm, any object, any service,=C2=A0will first be implemented as normal cod=
e that can throw. <em>Then</em>, at one point, you will realize you need it=
in a destructor. Now, you have to implement it again -=C2=A0as code that=
=C2=A0<em>does not</em>=C2=A0throw.</font></font></div><div><br></div><div>=
This is <em>ugly</em>. I'm=C2=A0deeply frustrated=C2=A0that the languag=
e=C2=A0decided on=C2=A0such a kludge,=C2=A0when it is instead possible to a=
dopt=C2=A0an elegant, true solution.</div><div><br></div><div>It's not =
too late! <font face=3D"courier new,monospace">noexcept</font> is not yet i=
n use everywhere. And arguably, it will never be <em>too late.</em> It may =
be too late to save our <em>pride</em>, but if C++ is still around, our chi=
ldren may recognize <font face=3D"courier new,monospace">noexcept<font face=
=3D"arial,sans-serif"> was a mistake, and=C2=A0standardize multi-exceptions=
in 2040.</font></font></div><div><br></div><div>But we should fix this mis=
take <em>now.</em> Let's not allow=C2=A0<font face=3D"courier new,monos=
pace">noexcept</font> to become our legacy.</div><div><br><br>On Saturday, =
July 18, 2015 at 4:33:14 PM UTC-6, vlovich wrote:</div><blockquote class=3D=
"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border=
-left-color: rgb(204, 204, 204); border-left-width: 1px; border-left-style:=
solid;"><div style=3D"-ms-word-wrap: break-word;"><div>I think the motivat=
ing problem raised here is a valid one. =C2=A0It=E2=80=99s probably also a =
rarer problem. =C2=A0It also happens to be impossible to solve in a reliabl=
e way without language/library support.</div><div><br></div><div>Sleep 0 is=
not really an acceptable solution for all the reasons raised & many mo=
re. =C2=A0A reasonable compromise could be that bad_alloc would still call =
std::terminate as OOM conditions are generally irrecoverable anyway.</div><=
div><br></div><div>This might not require large language changes. =C2=A0If =
there were a std::unwinding_exception() that returned the exception_ptr to =
the exception currently in-flight,</div><div>that could let the user manage=
the responsibility of addressing how they want to handle multiple exceptio=
ns in-flight. =C2=A0They could ensure that they were throwing their own exc=
eption type to which they could append the exceptions & deal with OOM s=
cenarios as needed.</div><div><br></div><div>The caveat there is that there=
probably would be benefit to also providing some language facility to repl=
ace the in-flight exception so that you could transform the exception being=
thrown as it propogates up the stack (so that you could upgrade something =
to std::nested_exception).</div><div><br></div><div>Apologies if the "=
nested exceptions=E2=80=9D thread David alludes to already covers this grou=
nd.</div><div><div><br><div><blockquote type=3D"cite"><div>On Jul 18, 2015,=
at 2:16 PM, denis bider <<a onmousedown=3D"this.href=3D'javascript:=
';return true;" onclick=3D"this.href=3D'javascript:';return tru=
e;" href=3D"javascript:" target=3D"_blank" rel=3D"nofollow">isocp...@denisb=
ider.com</a>> wrote:</div><br><div><div dir=3D"ltr"><div>A follow-up tho=
ught on the below:</div><div><br></div><div>In the multi-exception proposal=
, in most common environments, applications would no longer have to worry a=
bout <font face=3D"courier new,monospace">std::uncaught_exception()<font fa=
ce=3D"arial,sans-serif">. It would always be okay for a destructor to throw=
..</font></font></div><div><br></div><div>However, in limited memory environ=
ments, it seems that the same type of need that is currently addressed by <=
font face=3D"courier new,monospace">std::uncaught_exception()<font face=3D"=
arial,sans-serif"> could be usefully addressed by a function like:</font></=
font></div><div><br></div><div><font face=3D"courier new,monospace">bool st=
d::can_throw(size_t);</font></div><div><font face=3D"Courier New"><br></fon=
t></div><div><font face=3D"arial,sans-serif">This function would return <fo=
nt face=3D"courier new,monospace">true</font> if there is available memory =
to throw an exception object of parameter size; or <font face=3D"courier ne=
w,monospace">false<font face=3D"arial,sans-serif"> if there isn't such =
memory.</font></font></font></div><div><br></div><div>Again, in most common=
environments, applications would not have to concern themselves with this.=
However, in limited-memory environments, a function like that would replac=
e <font face=3D"courier new,monospace">std::uncaught_exception() <font face=
=3D"arial,sans-serif">in its role to allow a destructor to determine whethe=
r a throw at this point can be handled, or will result in <font face=3D"cou=
rier new,monospace">std::terminate</font>.</font></font></div><div><br></di=
v><div>This function would also never have to be called by non-destructor c=
ode. The assumption would be that, like now,=C2=A0a single exception can al=
ways be handled.</div><div><br><br>On Saturday, July 18, 2015 at 2:22:19 PM=
UTC-6, denis bider wrote:</div><blockquote class=3D"gmail_quote" style=3D"=
margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 2=
04, 204); border-left-width: 1px; border-left-style: solid;"><div dir=3D"lt=
r"><div>Could you refer me to=C2=A0at least one, but=C2=A0if possible=C2=A0=
several, example systems that:</div><div><br></div><div>- use C++, includin=
g especially exception functionality;</div><div><br></div><div>- are subjec=
t to limitations such as found in an OS kernel?</div><div><br></div><div>Th=
is is not because I don't believe that such systems exist, but because =
I wish to understand more about them.</div><div><br></div><div>[Currently, =
my understanding is that kernel developers either avoid C++; and/or use a s=
ubset of its features; and/or use private versions of C++ features that are=
designed for a better fit of the intended environment.]</div><div><br></di=
v><div><br></div><div>The foregoing=C2=A0being said=C2=A0-=C2=A0is finding =
memory to aggregate exceptions not an implementation detail that depends on=
the intended environment?</div><div><br></div><div>How do you handle stack=
allocation, for instance, in this limited environment?</div><div><br></div=
><div>What prevents you from using a=C2=A0stack-like technique to pre-alloc=
ate memory for aggregation of exceptions?</div><div><br></div><div>C++ alre=
ady does not provide guarantees about how deeply a function can call itself=
, for example. If a function recurses "too deply", it is understo=
od that the program or thread terminates. If you're in a limited memory=
environment, and run out of pre-allocated memory for aggregated exceptions=
, what's the problem with std::terminate?</div><div><br><br>On Saturday=
, July 18, 2015 at 2:08:31 PM UTC-6, Thiago Macieira wrote:</div><blockquot=
e class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1=
ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px; border-l=
eft-style: solid;">On Saturday 18 July 2015 11:15:09 denis bider wrote:
<br>> > How do you do this w/o using the heap? =C2=A0If you use the h=
eap, the
<br>>=20
<br>> allocation may fail and throw an exception.
<br>>=20
<br>> Excellent question! You Sleep(0) until allocation succeeds.
<br>
<br>Not acceptable. Please propose a different function that will not cause=
a live-
<br>lock in systems that cannot create more memory.
<br>
<br>> *But what if the exception is bad_alloc, and there's no memory=
for
<br>> secondary exceptions?*
<br>> The program should wait for memory to become available.
<br>
<br>And what if it never becomes available? This can occur for programs tha=
t:
<br>
<br>=C2=A0a) run without virtual memory (such as an OS kernel)
<br>=C2=A0b) have reached administratively- or architecturally-imposed limi=
ts
<br>
<br>And this is not even counting on programs that behaved incorrectly and =
have=20
<br>corrupted the malloc state.
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a onmousedown=3D"this.href=3D'http:/=
/www.google.com/url?q\75http%3A%2F%2Fmacieira.info%2F\46sa\75D\46sntz\0751\=
46usg\75AFQjCNF-oWll0ePaEIGIGXXWqBmBl0xL5g';return true;" onclick=3D"th=
is.href=3D'http://www.google.com/url?q\75http%3A%2F%2Fmacieira.info%2F\=
46sa\75D\46sntz\0751\46usg\75AFQjCNF-oWll0ePaEIGIGXXWqBmBl0xL5g';return=
true;" href=3D"http://macieira.info/" target=3D"_blank" rel=3D"nofollow">m=
acieira.info</a> - thiago (AT) <a onmousedown=3D"this.href=3D'http://ww=
w.google.com/url?q\75http%3A%2F%2Fkde.org%2F\46sa\75D\46sntz\0751\46usg\75A=
FQjCNEOPhDOcIjyT9NDV_UrwAL5xJUhWQ';return true;" onclick=3D"this.href=
=3D'http://www.google.com/url?q\75http%3A%2F%2Fkde.org%2F\46sa\75D\46sn=
tz\0751\46usg\75AFQjCNEOPhDOcIjyT9NDV_UrwAL5xJUhWQ';return true;" href=
=3D"http://kde.org/" target=3D"_blank" rel=3D"nofollow">kde.org</a>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>=C2=A0 =C2=A0 =C2=A0 PGP/GPG: 0x6EF45358; fingerprint:
<br>=C2=A0 =C2=A0 =C2=A0 E067 918B B660 DBD1 105C =C2=A0966C 33F5 F005 6EF4=
5358
<br>
<br></blockquote></div></blockquote></div><div><br></div>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a onmousedown=3D"this.href=3D'javascript:';return true;" o=
nclick=3D"this.href=3D'javascript:';return true;" href=3D"javascrip=
t:" target=3D"_blank" rel=3D"nofollow">std-proposal...@isocpp.org</a>.<br>
To post to this group, send email to <a onmousedown=3D"this.href=3D'jav=
ascript:';return true;" onclick=3D"this.href=3D'javascript:';re=
turn true;" href=3D"javascript:" target=3D"_blank" rel=3D"nofollow">std-pr.=
...@isocpp.org</a>.<br>
Visit this group at <a onmousedown=3D"this.href=3D'http://groups.google=
..com/a/isocpp.org/group/std-proposals/';return true;" onclick=3D"this.h=
ref=3D'http://groups.google.com/a/isocpp.org/group/std-proposals/';=
return true;" href=3D"http://groups.google.com/a/isocpp.org/group/std-propo=
sals/" target=3D"_blank" rel=3D"nofollow">http://groups.google.com/a/isocpp=
..org/group/std-proposals/</a>.<br>
</div></blockquote></div><br></div></div></div></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3252_1360619668.1437290454276--
------=_Part_3251_1932547564.1437290454275--
.
Author: wheretib@gmail.com
Date: Sun, 19 Jul 2015 04:03:42 -0700 (PDT)
Raw View
------=_Part_106_1795291163.1437303822791
Content-Type: multipart/alternative;
boundary="----=_Part_107_1224380463.1437303822791"
------=_Part_107_1224380463.1437303822791
Content-Type: text/plain; charset=UTF-8
On Saturday, July 18, 2015 at 9:15:10 PM UTC+3, denis bider wrote:
>
> In 20 years, I have never seen *bad_alloc* on Windows unless the program
> requested an unreasonable amount of memory. In all of these cases,
> normal-sized allocations could still continue.
>
> Windows will go to extreme lengths to avoid failing a reasonable memory
> request. I argue that this is what an operating system should do.
>
For example, Windows Phone devices with 512 MB of memory are running
Windows 8/8.1/10, but only allow 140/180 MB of memory for a single process
and do not have a paging file. So for a resource-heavy application it is
possible to see bad_alloc quite 'early' due to running out of memory.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_107_1224380463.1437303822791
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Saturday, July 18, 2015 at 9:15:10 PM UTC+3, denis bide=
r wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>=
In 20 years, I have never seen <i>bad_alloc</i> on Windows unless the=20
program requested an unreasonable amount of memory. In all of these=20
cases, normal-sized allocations could still continue.<br>
<br>=C2=A0Windows will go to extreme lengths to avoid failing a reasonable =
memory=20
request. I argue that this is what an operating system should do.=C2=A0</di=
v></div></blockquote><div>=C2=A0</div><div>For example, Windows Phone devic=
es with 512 MB of memory are running Windows 8/8.1/10, but only allow 140/1=
80 MB of memory for a single process and do not have a paging file. So for =
a resource-heavy application it is possible to see bad_alloc quite 'ear=
ly' due to running out of memory.</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_107_1224380463.1437303822791--
------=_Part_106_1795291163.1437303822791--
.
Author: Farid Mehrabi <farid.mehrabi@gmail.com>
Date: Sun, 19 Jul 2015 15:56:42 +0430
Raw View
--001a113abaa06723e4051b38b474
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
=E2=80=8BI know it is a little OT, but I can`t cease myself. What happened =
to the
simpler approach that I call early (near) catch in contrast to the late
(far) catch:
try{...}
near catch(E e){
}
2015-07-19 15:33 GMT+04:30 <wheretib@gmail.com>:
> On Saturday, July 18, 2015 at 9:15:10 PM UTC+3, denis bider wrote:
>>
>> In 20 years, I have never seen *bad_alloc* on Windows unless the program
>> requested an unreasonable amount of memory. In all of these cases,
>> normal-sized allocations could still continue.
>>
>> Windows will go to extreme lengths to avoid failing a reasonable memory
>> request. I argue that this is what an operating system should do.
>>
>
> For example, Windows Phone devices with 512 MB of memory are running
> Windows 8/8.1/10, but only allow 140/180 MB of memory for a single proces=
s
> and do not have a paging file. So for a resource-heavy application it is
> possible to see bad_alloc quite 'early' due to running out of memory.
>
--
---
You received this message because you are subscribed to the Google Groups
"ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at
http://groups.google.com/a/isocpp.org/group/std-proposals/.
--=20
how am I supposed to end the twisted road of your hair in such a dark
night??
unless the candle of your face does shed some light upon my way!!!
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--001a113abaa06723e4051b38b474
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"rtl"><div class=3D"gmail_default" style=3D"font-family:'ari=
al narrow',sans-serif;font-size:large" dir=3D"ltr">=E2=80=8BI know it i=
s a little OT, but I can`t cease myself. What happened to the simpler appro=
ach that I call early (near) catch in contrast to the late (far) catch:</di=
v><div class=3D"gmail_default" style=3D"font-family:'arial narrow',=
sans-serif;font-size:large" dir=3D"ltr"><br></div><div class=3D"gmail_defau=
lt" style=3D"font-family:'arial narrow',sans-serif;font-size:large"=
dir=3D"ltr">try{...}</div><div class=3D"gmail_default" style=3D"font-famil=
y:'arial narrow',sans-serif;font-size:large" dir=3D"ltr">near catch=
(E e){</div><div class=3D"gmail_default" style=3D"font-family:'arial na=
rrow',sans-serif;font-size:large" dir=3D"ltr"><br></div><div class=3D"g=
mail_default" style=3D"font-family:'arial narrow',sans-serif;font-s=
ize:large" dir=3D"ltr">}</div></div><div class=3D"gmail_extra"><div dir=3D"=
ltr"><br><div class=3D"gmail_quote">2015-07-19 15:33 GMT+04:30 <span dir=
=3D"ltr"><<a href=3D"mailto:wheretib@gmail.com" target=3D"_blank">wheret=
ib@gmail.com</a>></span>:<br><blockquote class=3D"gmail_quote" style=3D"=
margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=
=3D"">On Saturday, July 18, 2015 at 9:15:10 PM UTC+3, denis bider wrote:<bl=
ockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-l=
eft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>In 20 years, I h=
ave never seen <i>bad_alloc</i> on Windows unless the=20
program requested an unreasonable amount of memory. In all of these=20
cases, normal-sized allocations could still continue.<br>
<br>=C2=A0Windows will go to extreme lengths to avoid failing a reasonable =
memory=20
request. I argue that this is what an operating system should do.=C2=A0</di=
v></div></blockquote><div>=C2=A0</div></span><div>For example, Windows Phon=
e devices with 512 MB of memory are running Windows 8/8.1/10, but only allo=
w 140/180 MB of memory for a single process and do not have a paging file. =
So for a resource-heavy application it is possible to see bad_alloc quite &=
#39;early' due to running out of memory.</div></blockquote></div><div c=
lass=3D"HOEnZb"><div class=3D"h5">
<p></p>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_=
blank">std-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</div></div></div><br clear=3D"all"><div><br></div>-- <br><div class=3D"gma=
il_signature"><div dir=3D"rtl"><div><div dir=3D"ltr">how am I supposed to e=
nd the twisted road of=C2=A0 your hair in such a dark night??<br>unless the=
candle of your face does shed some light upon my way!!!<br></div></div></d=
iv></div>
</div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a113abaa06723e4051b38b474--
.
Author: inkwizytoryankes@gmail.com
Date: Sun, 19 Jul 2015 04:32:17 -0700 (PDT)
Raw View
------=_Part_3295_252868072.1437305537464
Content-Type: multipart/alternative;
boundary="----=_Part_3296_1566730324.1437305537464"
------=_Part_3296_1566730324.1437305537464
Content-Type: text/plain; charset=UTF-8
On Saturday, July 18, 2015 at 10:08:31 PM UTC+2, Thiago Macieira wrote:
>
> On Saturday 18 July 2015 11:15:09 denis bider wrote:
> > > How do you do this w/o using the heap? If you use the heap, the
> >
> > allocation may fail and throw an exception.
> >
> > Excellent question! You Sleep(0) until allocation succeeds.
>
> Not acceptable. Please propose a different function that will not cause a
> live-
> lock in systems that cannot create more memory.
>
> Exactly, this is security hole. Many programs can accept data of varying
sizes. Then attacker can prepare valid data that exceeded capacity of
attack target (like zip or xml bomb).
`Sleep(0)` loop will never break because system will never have required
memory.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_3296_1566730324.1437305537464
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Saturday, July 18, 2015 at 10:08:31 PM UTC+2, T=
hiago Macieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Saturd=
ay 18 July 2015 11:15:09 denis bider wrote:
<br>> > How do you do this w/o using the heap? =C2=A0If you use the h=
eap, the
<br>>=20
<br>> allocation may fail and throw an exception.
<br>>=20
<br>> Excellent question! You Sleep(0) until allocation succeeds.
<br>
<br>Not acceptable. Please propose a different function that will not cause=
a live-
<br>lock in systems that cannot create more memory.
<br>
<br></blockquote><div>Exactly, this is security hole. Many programs can acc=
ept data of varying sizes. Then attacker can prepare valid data that exceed=
ed capacity of attack target (like zip or xml bomb).<br>`Sleep(0)` loop wil=
l never break because system will never have required memory.<br></div><div=
>=C2=A0</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3296_1566730324.1437305537464--
------=_Part_3295_252868072.1437305537464--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Sun, 19 Jul 2015 05:03:43 -0700 (PDT)
Raw View
------=_Part_143_1849306955.1437307423969
Content-Type: multipart/alternative;
boundary="----=_Part_144_1208502201.1437307423969"
------=_Part_144_1208502201.1437307423969
Content-Type: text/plain; charset=UTF-8
I agree with comments that waiting for memory is a bad policy.
I support the suggestion that std::terminate should be the go-to option
when memory for exception aggregation cannot be secured.
For applications that need to guarantee that exception unwinding will
succeed in all circumstances, a sufficient amount of memory can be
pre-reserved, e.g. via exposing something like:
void std::preallocate_exception_memory(size_t max_count, size_t max_bytes);
If this is a guarantee you must have, then you:
- Analyze your program for the maximum number of exceptions you think it
may need to handle concurrently.
- Call the above function to preallocate memory at start.
There is also my previous suggestion for:
bool std::can_throw(size_t);
In the multi-exception paradigm, this would provide similar functionality
that std::uncaught_exception() provides currently. It provides a destructor
a way to detect a circumstance where throwing an exception would result in
std::terminate(); and in that case, allows the destructor to do something
else if it wants to.
When std::preallocate_exception_memory() has been called with parameters
appropriate for the program, std::can_throw() would always return true in
practice. It would also always return true outside of destructors.
I think these two suggestions would adequately address use of
multi-exceptions in limited-memory environments.
A program that doesn't wish to use any of this could also continue to use
existing mechanics with no change in behavior. A program can still use
noexcept destructors. If it uses destructors that are noexcept(false), it
can still call std::uncaught_exception() and not throw if an exception is
in progress. To avoid aggregated exceptions from containers, the program
can still avoid using containers to store objects whose destructors are
noexcept(false), - which is currently the only safe practice.
In other words - if the program adheres to all the same limitations that we
have in place today, it will experience no shortcomings. However, a
function like std::preallocate_exception_memory() would make it safe to use
aggregated exceptions in limited memory environments, also.
I do not see this as much different than pre-allocating a large enough
stack.
On Sunday, July 19, 2015 at 5:03:42 AM UTC-6, wher...@gmail.com wrote:
> On Saturday, July 18, 2015 at 9:15:10 PM UTC+3, denis bider wrote:
>>
>> In 20 years, I have never seen *bad_alloc* on Windows unless the program
>> requested an unreasonable amount of memory. In all of these cases,
>> normal-sized allocations could still continue.
>>
>> Windows will go to extreme lengths to avoid failing a reasonable memory
>> request. I argue that this is what an operating system should do.
>>
>
> For example, Windows Phone devices with 512 MB of memory are running
> Windows 8/8.1/10, but only allow 140/180 MB of memory for a single process
> and do not have a paging file. So for a resource-heavy application it is
> possible to see bad_alloc quite 'early' due to running out of memory.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_144_1208502201.1437307423969
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>I agree=C2=A0with comments that waiting for memory is=
a bad policy.</div><div><br></div><div>I=C2=A0support=C2=A0the suggestion=
=C2=A0that=C2=A0=C2=A0<font face=3D"courier new,monospace">std::terminate<f=
ont face=3D"arial,sans-serif">=C2=A0should be the go-to=C2=A0option when me=
mory for exception aggregation cannot be secured.</font></font></div><div><=
br></div><div><br></div><div>For applications that need to guarantee that e=
xception unwinding will succeed in all circumstances, a sufficient amount o=
f memory can be pre-reserved, e.g. via exposing something like:</div><div><=
br></div><div><font face=3D"courier new,monospace">void std::preallocate_ex=
ception_memory(size_t max_count, size_t max_bytes);</font></div><div><br></=
div><div>If this is a guarantee you must have, then you:</div><div><br></di=
v><div>- Analyze your program for the maximum number of exceptions you thin=
k it may need to handle concurrently.</div><div><br></div><div>-=C2=A0Call =
the above function to preallocate memory at start.</div><div><br></div><div=
><br></div><div>There is also=C2=A0my previous suggestion for:</div><div><f=
ont face=3D"Courier New"><br></font></div><div><font face=3D"Courier New">b=
ool std::can_throw(size_t);</font></div><div><font face=3D"Courier New"><br=
></font></div><div><font face=3D"Arial">In the multi-exception paradigm, th=
is=C2=A0would provide similar functionality that <font face=3D"courier new,=
monospace">std::uncaught_exception()</font> provides currently. It provides=
a destructor a way to detect a circumstance where throwing an exception wo=
uld result in <font face=3D"courier new,monospace">std::terminate()</font>;=
and in that case, allows the destructor to do something else if it wants t=
o.</font></div><div><br></div><div>When=C2=A0<font face=3D"courier new,mono=
space">std::preallocate_exception_memory() <font face=3D"arial,sans-serif">=
has been called with parameters appropriate for the program,=C2=A0<font fac=
e=3D"courier new,monospace">std::can_throw()</font> would always return <fo=
nt face=3D"courier new,monospace">true </font>in practice. It would also al=
ways return <font face=3D"courier new,monospace">true</font> outside of des=
tructors.</font></font></div><div><br></div><div><br></div><div>I think the=
se two suggestions would adequately address use of multi-exceptions in limi=
ted-memory environments.</div><div><br></div><div>A=C2=A0program that doesn=
't wish to use any of this could also continue to use existing mechanic=
s with no change in behavior. A program can still use <font face=3D"courier=
new,monospace">noexcept<font face=3D"arial,sans-serif"> destructors. If it=
uses destructors that are <font face=3D"courier new,monospace">noexcept(fa=
lse)<font face=3D"arial,sans-serif">, it can still call <font face=3D"couri=
er new,monospace">std::uncaught_exception()<font face=3D"arial,sans-serif">=
and not throw if an exception is in progress. To avoid aggregated exceptio=
ns from containers, the program can still avoid using containers to store o=
bjects whose destructors are <font face=3D"courier new,monospace">noexcept(=
false)<font face=3D"arial,sans-serif">, - which is currently the only safe =
practice.</font></font></font></font></font></font></font></font></div><div=
><br></div><div>In other words - if the program adheres to all the same lim=
itations that we have in place today, it will experience no shortcomings. H=
owever, a function like <font face=3D"courier new,monospace">std::prealloca=
te_exception_memory()</font> would make it safe to use aggregated exception=
s in limited memory environments, also.</div><div><br></div><div>I do not s=
ee this as much different than pre-allocating a large enough stack.</div><d=
iv><br></div><div><br>On Sunday, July 19, 2015 at 5:03:42 AM UTC-6, wher...=
@gmail.com wrote:</div><blockquote class=3D"gmail_quote" style=3D"margin: 0=
px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204);=
border-left-width: 1px; border-left-style: solid;"><div dir=3D"ltr">On Sat=
urday, July 18, 2015 at 9:15:10 PM UTC+3, denis bider wrote:<blockquote cla=
ss=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; b=
order-left-color: rgb(204, 204, 204); border-left-width: 1px; border-left-s=
tyle: solid;"><div dir=3D"ltr"><div>In 20 years, I have never seen <i>bad_a=
lloc</i> on Windows unless the=20
program requested an unreasonable amount of memory. In all of these=20
cases, normal-sized allocations could still continue.<br>
<br>=C2=A0Windows will go to extreme lengths to avoid failing a reasonable =
memory=20
request. I argue that this is what an operating system should do.=C2=A0</di=
v></div></blockquote><div>=C2=A0</div><div>For example, Windows Phone devic=
es with 512 MB of memory are running Windows 8/8.1/10, but only allow 140/1=
80 MB of memory for a single process and do not have a paging file. So for =
a resource-heavy application it is possible to see bad_alloc quite 'ear=
ly' due to running out of memory.</div></div></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_144_1208502201.1437307423969--
------=_Part_143_1849306955.1437307423969--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Sun, 19 Jul 2015 09:33:46 -0700 (PDT)
Raw View
------=_Part_3273_541868619.1437323626768
Content-Type: multipart/alternative;
boundary="----=_Part_3274_1775617063.1437323626769"
------=_Part_3274_1775617063.1437323626769
Content-Type: text/plain; charset=UTF-8
Based on feedback I've received, here and elsewhere, the Aggregated
Exceptions proposal has evolved, and would benefit from a page where
its most recent state is published.
I have created this page in this post:
http://denisbider.blogspot.com/2015/07/aggregated-exceptions-proposal-summary.html
This does not contain new information compared to what has been so far
discussed here, but it summarizes the state of the proposal.
On Sunday, July 19, 2015 at 6:03:44 AM UTC-6, denis bider wrote:
> I agree with comments that waiting for memory is a bad policy.
>
> I support the suggestion that std::terminate should be the go-to option
> when memory for exception aggregation cannot be secured.
>
>
> For applications that need to guarantee that exception unwinding will
> succeed in all circumstances, a sufficient amount of memory can be
> pre-reserved, e.g. via exposing something like:
>
> void std::preallocate_exception_memory(size_t max_count, size_t max_bytes);
>
> If this is a guarantee you must have, then you:
>
> - Analyze your program for the maximum number of exceptions you think it
> may need to handle concurrently.
>
> - Call the above function to preallocate memory at start.
>
>
> There is also my previous suggestion for:
>
> bool std::can_throw(size_t);
>
> In the multi-exception paradigm, this would provide similar functionality
> that std::uncaught_exception() provides currently. It provides a
> destructor a way to detect a circumstance where throwing an exception would
> result in std::terminate(); and in that case, allows the destructor to do
> something else if it wants to.
>
> When std::preallocate_exception_memory() has been called with parameters
> appropriate for the program, std::can_throw() would always return true in
> practice. It would also always return true outside of destructors.
>
>
> I think these two suggestions would adequately address use of
> multi-exceptions in limited-memory environments.
>
> A program that doesn't wish to use any of this could also continue to use
> existing mechanics with no change in behavior. A program can still use
> noexcept destructors. If it uses destructors that are noexcept(false), it
> can still call std::uncaught_exception() and not throw if an exception is
> in progress. To avoid aggregated exceptions from containers, the program
> can still avoid using containers to store objects whose destructors are
> noexcept(false), - which is currently the only safe practice.
>
> In other words - if the program adheres to all the same limitations that
> we have in place today, it will experience no shortcomings. However, a
> function like std::preallocate_exception_memory() would make it safe to
> use aggregated exceptions in limited memory environments, also.
>
> I do not see this as much different than pre-allocating a large enough
> stack.
>
>
> On Sunday, July 19, 2015 at 5:03:42 AM UTC-6, wher...@gmail.com wrote:
>
>> On Saturday, July 18, 2015 at 9:15:10 PM UTC+3, denis bider wrote:
>>>
>>> In 20 years, I have never seen *bad_alloc* on Windows unless the
>>> program requested an unreasonable amount of memory. In all of these cases,
>>> normal-sized allocations could still continue.
>>>
>>> Windows will go to extreme lengths to avoid failing a reasonable memory
>>> request. I argue that this is what an operating system should do.
>>>
>>
>> For example, Windows Phone devices with 512 MB of memory are running
>> Windows 8/8.1/10, but only allow 140/180 MB of memory for a single process
>> and do not have a paging file. So for a resource-heavy application it is
>> possible to see bad_alloc quite 'early' due to running out of memory.
>>
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_3274_1775617063.1437323626769
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Based on feedback I've received, here and elsewhe=
re, the Aggregated Exceptions proposal has evolved, and would benefit from =
a page where its=C2=A0most recent=C2=A0state is published.</div><div><br></=
div><div>I have created this page in this post:</div><div><br></div><div><a=
href=3D"http://denisbider.blogspot.com/2015/07/aggregated-exceptions-propo=
sal-summary.html">http://denisbider.blogspot.com/2015/07/aggregated-excepti=
ons-proposal-summary.html</a></div><div><br></div><div>This does not contai=
n=C2=A0new information compared to what has been so far discussed here, but=
it summarizes the state of the proposal.<br>
<br><br>On Sunday, July 19, 2015 at 6:03:44 AM UTC-6, denis bider wrote:</d=
iv><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; pa=
dding-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: =
1px; border-left-style: solid;"><div dir=3D"ltr"><div>I agree=C2=A0with com=
ments that waiting for memory is a bad policy.</div><div><br></div><div>I=
=C2=A0support=C2=A0the suggestion=C2=A0that=C2=A0=C2=A0<font face=3D"courie=
r new,monospace">std::terminate<font face=3D"arial,sans-serif">=C2=A0should=
be the go-to=C2=A0option when memory for exception aggregation cannot be s=
ecured.</font></font></div><div><br></div><div><br></div><div>For applicati=
ons that need to guarantee that exception unwinding will succeed in all cir=
cumstances, a sufficient amount of memory can be pre-reserved, e.g. via exp=
osing something like:</div><div><br></div><div><font face=3D"courier new,mo=
nospace">void std::preallocate_exception_memory(size_t max_count, size_t ma=
x_bytes);</font></div><div><br></div><div>If this is a guarantee you must h=
ave, then you:</div><div><br></div><div>- Analyze your program for the maxi=
mum number of exceptions you think it may need to handle concurrently.</div=
><div><br></div><div>-=C2=A0Call the above function to preallocate memory a=
t start.</div><div><br></div><div><br></div><div>There is also=C2=A0my prev=
ious suggestion for:</div><div><font face=3D"Courier New"><br></font></div>=
<div><font face=3D"Courier New">bool std::can_throw(size_t);</font></div><d=
iv><font face=3D"Courier New"><br></font></div><div><font face=3D"Arial">In=
the multi-exception paradigm, this=C2=A0would provide similar functionalit=
y that <font face=3D"courier new,monospace">std::uncaught_exception()</font=
> provides currently. It provides a destructor a way to detect a circumstan=
ce where throwing an exception would result in <font face=3D"courier new,mo=
nospace">std::terminate()</font>; and in that case, allows the destructor t=
o do something else if it wants to.</font></div><div><br></div><div>When=C2=
=A0<font face=3D"courier new,monospace">std::preallocate_exception_memory()=
<font face=3D"arial,sans-serif">has been called with parameters appropriat=
e for the program,=C2=A0<font face=3D"courier new,monospace">std::can_throw=
()</font> would always return <font face=3D"courier new,monospace">true </f=
ont>in practice. It would also always return <font face=3D"courier new,mono=
space">true</font> outside of destructors.</font></font></div><div><br></di=
v><div><br></div><div>I think these two suggestions would adequately addres=
s use of multi-exceptions in limited-memory environments.</div><div><br></d=
iv><div>A=C2=A0program that doesn't wish to use any of this could also =
continue to use existing mechanics with no change in behavior. A program ca=
n still use <font face=3D"courier new,monospace">noexcept<font face=3D"aria=
l,sans-serif"> destructors. If it uses destructors that are <font face=3D"c=
ourier new,monospace">noexcept(false)<font face=3D"arial,sans-serif">, it c=
an still call <font face=3D"courier new,monospace">std::uncaught_exception(=
)<font face=3D"arial,sans-serif"> and not throw if an exception is in progr=
ess. To avoid aggregated exceptions from containers, the program can still =
avoid using containers to store objects whose destructors are <font face=3D=
"courier new,monospace">noexcept(false)<font face=3D"arial,sans-serif">, - =
which is currently the only safe practice.</font></font></font></font></fon=
t></font></font></font></div><div><br></div><div>In other words - if the pr=
ogram adheres to all the same limitations that we have in place today, it w=
ill experience no shortcomings. However, a function like <font face=3D"cour=
ier new,monospace">std::preallocate_exception_memory()</font> would make it=
safe to use aggregated exceptions in limited memory environments, also.</d=
iv><div><br></div><div>I do not see this as much different than pre-allocat=
ing a large enough stack.</div><div><br></div><div><br>On Sunday, July 19, =
2015 at 5:03:42 AM UTC-6, <a>wher...@gmail.com</a> wrote:</div><blockquote =
class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex=
; border-left-color: rgb(204, 204, 204); border-left-width: 1px; border-lef=
t-style: solid;"><div dir=3D"ltr">On Saturday, July 18, 2015 at 9:15:10 PM =
UTC+3, denis bider wrote:<blockquote class=3D"gmail_quote" style=3D"margin:=
0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204=
); border-left-width: 1px; border-left-style: solid;"><div dir=3D"ltr"><div=
>In 20 years, I have never seen <i>bad_alloc</i> on Windows unless the=20
program requested an unreasonable amount of memory. In all of these=20
cases, normal-sized allocations could still continue.<br>
<br>=C2=A0Windows will go to extreme lengths to avoid failing a reasonable =
memory=20
request. I argue that this is what an operating system should do.=C2=A0</di=
v></div></blockquote><div>=C2=A0</div><div>For example, Windows Phone devic=
es with 512 MB of memory are running Windows 8/8.1/10, but only allow 140/1=
80 MB of memory for a single process and do not have a paging file. So for =
a resource-heavy application it is possible to see bad_alloc quite 'ear=
ly' due to running out of memory.</div></div></blockquote></div></block=
quote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_3274_1775617063.1437323626769--
------=_Part_3273_541868619.1437323626768--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Sun, 19 Jul 2015 12:02:39 -0700
Raw View
On Saturday 18 July 2015 13:39:49 denis bider wrote:
> Unless my understanding is faulty, your first example does not seem to
> involve multi-exceptions. Therefore, behavior under my proposal would be
> identical to behavior now.
You're correct, it doesn't involve multi-exceptions. It involves destructors
being allowed to fail.
So your second sentence is completely at odds with your proposal. Your
proposal is that destructors can throw, but "identical to behavior now" is
that destructors are noexcept and, if they accidentally throw, they will call
std::terminate().
I don't have an opinion on multi-exceptions (because I don't use exceptions),
but I do have a problem with destructors being allowed to fail. Resource-
releasing functions cannot fail. Can free() or operator delete fail? They
cannot.
The counter-example is fclose: it *can* fail if fflush fails. But should you
fclose again on the same FILE*? No, you cannot. If it fails, you've got an
unfixable resource leak. That would be the same thing with failing destructors.
> The main function lacks a try/catch block, so
> that's an issue. However, if you add a try/catch block around main, the
> code will compile fine in C++03, it will work, and yes, operator delete
> will be called. The same is the case in C++11 and 14, as long as you take
> care to add noexcept(false) to the destructor.
Not really. Let me simplify:
void f(A *a) { delete a; }
If a->~A() throws, will delete be called? The current behaviour is that it
will not.
And doing what you said reveals you're mistaken: delete is not called:
int main()
{
auto a = new A;
try { delete a; }
catch (...) {}
}
==116679== 1 bytes in 1 blocks are definitely lost in loss record 1 of 2
==116679== at 0x4C29670: operator new(unsigned long) (in
/usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==116679== by 0x40078D: main (in /tmp/test)
> In your second example, struct B containing a1 and a2: when ~B is invoked,
> a2.~A() throws "whee", creating exception-list with a single entry, char
> const[] "whee". According to normal C++ destruction proceedings, a1.~A() is
> then invoked, which also throws "whee", adding another exception-list
> entry. The exception-list now has two entries, both of them char const[]
> "whee".
Ok, now you've explained it. You're saying that the compiler will insert try
blocks around every noexcept(false) destructor of its members and will
continue destruction. Once all of that has happened, it will rethrow the list.
Is that a correct understanding?
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Tue, 21 Jul 2015 09:50:23 -0400
Raw View
On 2015-07-18 14:15, denis bider wrote:
> On Saturday, July 18, 2015 at 10:05:06 AM UTC-6, Nevin ":-)" Liber wrote:
>> How do you do this w/o using the heap? If you use the heap, the=20
>> allocation may fail and throw an exception.
>=20
> Excellent question! You Sleep(0) until allocation succeeds.
And how exactly is the heap usage going to magically get smaller when no
user code is executing? If I've allocated the entire available heap and
have no chance to free anything, how is waiting supposed to make things
better?
> In 20 years, I have never seen *bad_alloc* on Windows
That's nice. Not all C++ programs run on Windows. (In fact, I'd venture
that Windows is even in the minority by the time you get done counting
mobile devices, embedded, etc.)
> Windows will go to extreme lengths to avoid failing a reasonable memory=
=20
> request.
Windows is a poorly designed operating system that places letting
software do what it wants above system stability. Operating systems that
were designed to protect the system from users have strict resource
limits that *may not* be violated. A program that runs into these is
SOL; the OS, *correctly*, is never going to permit additional allocation.
> When the human economy runs out of something vital, our go-to response is=
=20
> to queue for it.
When some unreasonable person demands an unreasonable share of a
valuable resource, we tell them "no".
> There's no reason a program shouldn't wait if it needs=20
> something vital =E2=80=94 such as a small amount of memory to proceed wit=
h=20
> exception handling.
There is an *excellent* reason: it will never get it. The OS doesn't
know *why* a program wants memory, and doesn't (and *shouldn't*) care.
Allowing certain requests to be handled specially just opens the door to
abuse.
(Now... that said, the *C++ runtime* might reasonably set aside a chunk
of memory at startup for exception handling, but you're always going to
have to deal with the possibility that that pool has been exhausted.)
--=20
Matthew
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Tue, 21 Jul 2015 10:07:34 -0400
Raw View
On 2015-07-18 16:22, denis bider wrote:
> Could you refer me to at least one, but if possible several, example
> systems that:
>
> - use C++, including especially exception functionality;
>
> - are subject to limitations such as found in an OS kernel?
Windows Mobile (as noted by "wheretib"). Windows-on-Windows (i.e. 32-bit
userspace on 64-bit kernel; you could readily exhaust the VM address
space despite having plenty of physical memory). Any OS that *isn't*
Windows (especially any process on a POSIX/SUS type kernel run with
non-unlimited 'ulimit -v'). Any embedded platform (few will have VM or
large amounts of RAM).
> This is not because I don't believe that such systems exist, but because I
> wish to understand more about them.
Embedded programming is probably going to be the least like desktop
Windows. (OTOH, that's where you most tend to get people that won't have
anything to do with exceptions.)
Note also that Linux has an interesting behavior when a rogue process
requests too much memory... the kernel simply terminates it. No warning,
no way for the process to recover. No guarantee even (AFAIK) that it is
in the middle of a memory request when it gets killed.
--
Matthew
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Tue, 21 Jul 2015 07:24:42 -0700 (PDT)
Raw View
------=_Part_162_988428369.1437488682463
Content-Type: multipart/alternative;
boundary="----=_Part_163_310181055.1437488682463"
------=_Part_163_310181055.1437488682463
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Matthew,
I appreciate your comments. I believe I've indicated that I've changed my=
=20
mind about this.
The most recent summary of the proposal includes a section about Limited=20
memory environments:
http://denisbider.blogspot.com/2015/07/aggregated-exceptions-proposal-summa=
ry.html#memory
What I suggest largely echoes your observation:
> the *C++ runtime* might reasonably set aside a chunk of memory at=20
startup for
> exception handling, but you're always going to have to deal with the=20
possibility
> that that pool has been exhausted.
I argue that this is a very similar problem as allocating sufficient stack=
=20
space. Well-behaved applications will require a "reasonable" amount of=20
stack, the definition of which may depend on the target environment.
denis
On Tuesday, July 21, 2015 at 7:50:38 AM UTC-6, Matthew Woehlke wrote:
> On 2015-07-18 14:15, denis bider wrote:=20
> > On Saturday, July 18, 2015 at 10:05:06 AM UTC-6, Nevin ":-)" Liber=20
> wrote:=20
> >> How do you do this w/o using the heap? If you use the heap, the=20
> >> allocation may fail and throw an exception.=20
> >=20
> > Excellent question! You Sleep(0) until allocation succeeds.=20
>
> And how exactly is the heap usage going to magically get smaller when no=
=20
> user code is executing? If I've allocated the entire available heap and=
=20
> have no chance to free anything, how is waiting supposed to make things=
=20
> better?=20
>
> > In 20 years, I have never seen *bad_alloc* on Windows=20
>
> That's nice. Not all C++ programs run on Windows. (In fact, I'd venture=
=20
> that Windows is even in the minority by the time you get done counting=20
> mobile devices, embedded, etc.)=20
>
> > Windows will go to extreme lengths to avoid failing a reasonable memory=
=20
> > request.=20
>
> Windows is a poorly designed operating system that places letting=20
> software do what it wants above system stability. Operating systems that=
=20
> were designed to protect the system from users have strict resource=20
> limits that *may not* be violated. A program that runs into these is=20
> SOL; the OS, *correctly*, is never going to permit additional allocation.=
=20
>
> > When the human economy runs out of something vital, our go-to response=
=20
> is=20
> > to queue for it.=20
>
> When some unreasonable person demands an unreasonable share of a=20
> valuable resource, we tell them "no".=20
>
> > There's no reason a program shouldn't wait if it needs=20
> > something vital =E2=80=94 such as a small amount of memory to proceed w=
ith=20
> > exception handling.=20
>
> There is an *excellent* reason: it will never get it. The OS doesn't=20
> know *why* a program wants memory, and doesn't (and *shouldn't*) care.=20
> Allowing certain requests to be handled specially just opens the door to=
=20
> abuse.=20
>
> (Now... that said, the *C++ runtime* might reasonably set aside a chunk=
=20
> of memory at startup for exception handling, but you're always going to=
=20
> have to deal with the possibility that that pool has been exhausted.)=20
>
> --=20
> Matthew=20
>
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_163_310181055.1437488682463
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Matthew,</div><div><br></div><div>I appreciate your c=
omments. I believe I've indicated that I've changed my mind about t=
his.</div><div><br></div><div>The most recent summary of the proposal inclu=
des a section about Limited memory environments:</div><div><br></div><div><=
a href=3D"http://denisbider.blogspot.com/2015/07/aggregated-exceptions-prop=
osal-summary.html#memory">http://denisbider.blogspot.com/2015/07/aggregated=
-exceptions-proposal-summary.html#memory</a></div><div><br></div><div>What =
I suggest largely echoes your observation:</div><div><br></div><div>>=C2=
=A0 the *C++ runtime* might reasonably set aside a chunk of memory at start=
up for</div><div>> exception handling, but you're always going to=C2=
=A0have to deal with the possibility</div><div>> that that pool has been=
exhausted.</div><div><br></div><div>I argue that this is a very similar pr=
oblem as allocating sufficient stack space. Well-behaved applications will =
require a "reasonable" amount of stack, the definition of which m=
ay depend on the target environment.</div><div><br></div><div>denis</div><d=
iv><br><br>On Tuesday, July 21, 2015 at 7:50:38 AM UTC-6, Matthew Woehlke w=
rote:</div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0=
..8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border-left=
-width: 1px; border-left-style: solid;">On 2015-07-18 14:15, denis bider wr=
ote:
<br>> On Saturday, July 18, 2015 at 10:05:06 AM UTC-6, Nevin ":-)&q=
uot; Liber wrote:
<br>>> How do you do this w/o using the heap? =C2=A0If you use the he=
ap, the=20
<br>>> allocation may fail and throw an exception.
<br>>=20
<br>> Excellent question! You Sleep(0) until allocation succeeds.
<br>
<br>And how exactly is the heap usage going to magically get smaller when n=
o
<br>user code is executing? If I've allocated the entire available heap=
and
<br>have no chance to free anything, how is waiting supposed to make things
<br>better?
<br>
<br>> In 20 years, I have never seen *bad_alloc* on Windows
<br>
<br>That's nice. Not all C++ programs run on Windows. (In fact, I'd=
venture
<br>that Windows is even in the minority by the time you get done counting
<br>mobile devices, embedded, etc.)
<br>
<br>> Windows will go to extreme lengths to avoid failing a reasonable m=
emory=20
<br>> request.
<br>
<br>Windows is a poorly designed operating system that places letting
<br>software do what it wants above system stability. Operating systems tha=
t
<br>were designed to protect the system from users have strict resource
<br>limits that *may not* be violated. A program that runs into these is
<br>SOL; the OS, *correctly*, is never going to permit additional allocatio=
n.
<br>
<br>> When the human economy runs out of something vital, our go-to resp=
onse is=20
<br>> to queue for it.
<br>
<br>When some unreasonable person demands an unreasonable share of a
<br>valuable resource, we tell them "no".
<br>
<br>> There's no reason a program shouldn't wait if it needs=20
<br>> something vital =E2=80=94 such as a small amount of memory to proc=
eed with=20
<br>> exception handling.
<br>
<br>There is an *excellent* reason: it will never get it. The OS doesn'=
t
<br>know *why* a program wants memory, and doesn't (and *shouldn't*=
) care.
<br>Allowing certain requests to be handled specially just opens the door t=
o
<br>abuse.
<br>
<br>(Now... that said, the *C++ runtime* might reasonably set aside a chunk
<br>of memory at startup for exception handling, but you're always goin=
g to
<br>have to deal with the possibility that that pool has been exhausted.)
<br>
<br>--=20
<br>Matthew
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_163_310181055.1437488682463--
------=_Part_162_988428369.1437488682463--
.
Author: griwes.mail@gmail.com
Date: Wed, 22 Jul 2015 07:12:18 -0700 (PDT)
Raw View
------=_Part_56_526305820.1437574338591
Content-Type: multipart/alternative;
boundary="----=_Part_57_1222110334.1437574338591"
------=_Part_57_1222110334.1437574338591
Content-Type: text/plain; charset=UTF-8
>
> It's not too late! noexcept is not yet in use everywhere. And arguably,
> it will never be *too late.* It may be too late to save our *pride*, but
> if C++ is still around, our children may recognize noexcept was a
> mistake, and standardize multi-exceptions in 2040.
>
> But we should fix this mistake *now.* Let's not allow noexcept to become
> our legacy.
>
You might want to read on how `noexcept` came into being, what problem it
solves, and why it's absolutely necessary.
You seem to be talking about exceptions, while at the same time not having
a clue about exception safety guarantees and why it's *crucial* for move
semantics. Which is pretty hilarious really.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_57_1222110334.1437574338591
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div>It's not too late! <font face=3D"courier new,monospace">noexce=
pt</font> is not yet in use everywhere. And arguably, it will never be <em>=
too late.</em> It may be too late to save our <em>pride</em>, but if C++ is=
still around, our children may recognize <font face=3D"courier new,monospa=
ce">noexcept<font face=3D"arial,sans-serif"> was a mistake, and=C2=A0standa=
rdize multi-exceptions in 2040.</font></font><br></div><div><br></div><div>=
But we should fix this mistake <em>now.</em> Let's not allow=C2=A0<font=
face=3D"courier new,monospace">noexcept</font> to become our legacy.</div>=
</div></blockquote><div><br></div><div>You might want to read on how `noexc=
ept` came into being, what problem it solves, and why it's absolutely n=
ecessary.</div><div><br></div><div>You seem to be talking about exceptions,=
while at the same time not having a clue about exception safety guarantees=
and why it's *crucial* for move semantics. Which is pretty hilarious r=
eally.=C2=A0</div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_57_1222110334.1437574338591--
------=_Part_56_526305820.1437574338591--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Wed, 22 Jul 2015 15:55:36 +0100
Raw View
--=-vfKGAGf/JsWohTGZncR8
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
noexcept is truly useful for move semantics. It makes sense for move constr=
uctors to not throw. Move should be as much as possible like memcpy.
But forcing destructors not to throw is an over-reach. It's an imposition t=
hat's only necessary because of limitations of the single-exception policy.=
It prevents full use of destructors and exceptions for what they otherwise=
could be.
Database rollback, or installation rollback, are typical examples where you=
can have two errors occurring simultaneously. First, you have an error tha=
t causes the rollback. Then, you have an error in the rollback itself. If t=
his happens in an installer, you want to handle both errors gracefully. Cur=
rently, C++ exceptions cannot do this; the application must be refactored s=
o as to not use exceptions for at least one of these errors. I contend that=
this is an unnecessary limitation. You contend that, for some reason, this=
is how it should be.
Before we continue, I would like to out your deficiencies in impulse contro=
l as a factor that may make a respectful and professional conversation diff=
icult. This was your earlier comment on Reddit, and your tone does not seem=
to have improved since:
"Okay, so you are one of the people who think that exceptions are a flow co=
ntrol tool. Cool, I can now safely ignore everything you are saying, becaus=
e we won't arrive at a point even worth looking at. And yes, now that you'v=
e truly shown you are a moron, I'm being an asshole - like I'm towards most=
of the morons I meet."
Exceptions are a flow control tool by definition. They are a way to stop fo=
rward progress; return to a known point; and handle an error that you can r=
ecover from.
Allowing them to handle multiple errors is not changing what exceptions are=
.. It's making them more useful.
-----Original Message-----=20
From: griwes.mail@gmail.com=20
Sent: Wednesday, July 22, 2015 08:12=20
To: ISO C++ Standard - Future Proposals=20
Subject: Re: [std-proposals] Aggregated exceptions: Reversing destructor ma=
rginalization caused by the single-exception policy=20
> It's not too late! noexcept is not yet in use everywhere. And arguably, i=
t will never be too late. It may be too late to save our pride, but if C++ =
is still around, our children may recognize noexcept was a mistake, and sta=
ndardize multi-exceptions in 2040.
> But we should fix this mistake now. Let's not allow noexcept to become ou=
r legacy.
You might want to read on how `noexcept` came into being, what problem it s=
olves, and why it's absolutely necessary.
You seem to be talking about exceptions, while at the same time not having =
a clue about exception safety guarantees and why it's *crucial* for move se=
mantics. Which is pretty hilarious really.=20
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--=-vfKGAGf/JsWohTGZncR8
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<html><head></head><body>noexcept is truly useful for move semantics. It ma=
kes sense for move constructors to not throw. Move should be as much as pos=
sible like memcpy.<br><br>But forcing destructors not to throw is an over-r=
each. It's an imposition that's only necessary because of limitations of th=
e single-exception policy. It prevents full use of destructors and exceptio=
ns for what they otherwise could be.<br><br>Database rollback, or installat=
ion rollback, are typical examples where you can have two errors occurring =
simultaneously. First, you have an error that causes the rollback. Then, yo=
u have an error in the rollback itself. If this happens in an installer, yo=
u want to handle both errors gracefully. Currently, C++ exceptions cannot d=
o this; the application must be refactored so as to not use exceptions for =
at least one of these errors. I contend that this is an unnecessary limitat=
ion. You contend that, for some reason, this is how it should be.<br><br>Be=
fore we continue, I would like to out your deficiencies in impulse control =
as a factor that may make a respectful and professional conversation diffic=
ult. This was your earlier comment on Reddit, and your tone does not seem t=
o have improved since:<br><br><i>"Okay, so you are one of the people who th=
ink that exceptions are a flow control tool. Cool, I can now safely ignore =
everything you are saying, because we won't arrive at a point even worth lo=
oking at. And yes, now that you've truly shown you are a moron, I'm being a=
n asshole - like I'm towards most of the morons I meet."<br></i><br>Excepti=
ons are a flow control tool <i>by definition</i>. They are a way to stop fo=
rward progress; return to a known point; and handle an error that you can r=
ecover from.<br><br>Allowing them to handle multiple errors is not changing=
what exceptions are. It's making them more useful.<br><br><br>-----Origina=
l Message----- <br>From: griwes.mail@gmail.com <br>Sent: Wednesday, July 22=
, 2015 08:12 <br>To: ISO C++ Standard - Future Proposals <br>Subject: Re: [=
std-proposals] Aggregated exceptions: Reversing destructor marginalization =
caused by the single-exception policy <br><br>> It's not too late! noexc=
ept is not yet in use everywhere. And arguably, it will never be too late. =
It may be too late to save our pride, but if C++ is still around, our child=
ren may recognize noexcept was a mistake, and standardize multi-exceptions =
in 2040.<br><br>> But we should fix this mistake now. Let's not allow no=
except to become our legacy.<br><br>You might want to read on how `noexcept=
` came into being, what problem it solves, and why it's absolutely necessar=
y.<br><br>You seem to be talking about exceptions, while at the same time n=
ot having a clue about exception safety guarantees and why it's *crucial* f=
or move semantics. Which is pretty hilarious really. <br><br></body></html>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--=-vfKGAGf/JsWohTGZncR8--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Wed, 22 Jul 2015 14:36:06 -0700
Raw View
On Wednesday 22 July 2015 15:55:36 denis bider wrote:
> But forcing destructors not to throw is an over-reach. It's an imposition
> that's only necessary because of limitations of the single-exception
> policy.
No, it isn't. I showed that destructors should be noexcept because they're
freeing resources and there's no recourse to a failed destructor.
When a constructor fails by throwing, the sub-objects already constructed are
destructed. What happens if one of them throws during that process?
When a destructor fails half way, you can't re-construct the elements already
destroyed, but it can neither continue destroying. You simply have an unfixable
resource leak.
You suggested that an exception thrown inside a destructor should be queued
and destruction continue, then the whole exception group would be thrown.
Ignoring the memory issues for this, I don't think it would work at all.
=> Starting testcase:
struct A { ~A() { throw 42; } };
struct B { A a1, a2; }
When ~B runs, a1.~A() would throw, the exception would be queued, then the
execution continues at a2.~A() would be executed (and throw again).
=> Modifying:
struct C { A *a1, *a2; C(); ~C() { delete a1; delete a2; } };
Now the same thing happens when a1->~A() throws, but instead of continuing in
compiler-generated code, this must continue on user code.
You may suggest that one should be using smart pointers (std::unique_ptr) in
this, but then we begin involving a third place where code gets executed.
=> Suppose instead:
struct D { A *a1, *a2; D(); ~D() { dispose(a1); dispose(a2); } };
template <typename T> void dispose(T *&ptr)
{
ptr->~T();
remove_from_siblings(ptr);
Allocator::dealloc(ptr);
}
Note how ptr->~T() threw inside dispose(), a function that had nothing to do
with nested exceptions. You have two options here:
1) Require that ALL throwing points be able to deal with code continuing
instead of branching to the exceptional code path.
This violates the requirement that you don't pay for features you don't use.
2) Not resume execution inside dispose(), but resume inside the destructor
~D() that called it.
This may lead to a crash when destroying a2 because its sibling (a1) was not
removed from the list, as the destruction did not finish properly.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Wed, 22 Jul 2015 15:52:16 -0700 (PDT)
Raw View
------=_Part_15_441753177.1437605536747
Content-Type: multipart/alternative;
boundary="----=_Part_16_1660238563.1437605536748"
------=_Part_16_1660238563.1437605536748
Content-Type: text/plain; charset=UTF-8
> I showed that destructors should be noexcept because they're freeing
resources and there's no recourse to a failed destructor.
You did not do such a thing. The statement you make reflects ideology.
There are many things one may want to implement in a destructor that can
fail - and the failure *is* actionable. A whole category of rollbacks - in
installers, in database transactions - is included in this.
> When a constructor fails by throwing, the sub-objects already constructed
are destructed. What happens if one of them throws during that process?
We have discussed this. The destruction process continues normally. Up to
one destructor exception has been supported in C++ always.
My proposal does nothing to change this. Aggregation simply specifies a way
that a destructor can throw *always; *instead of *sometimes*, which already
works.
> => Starting testcase:
>
> struct A { ~A() { throw 42; } };
> struct B { A a1, a2; }
>
> When ~B runs, a1.~A() would throw, the exception would be queued,
> then the execution continues at a2.~A() would be executed
> (and throw again).
Yes. You get two aggregated exceptions. You can handle them. The object is
destroyed properly.
I don't see anything wrong with this case.
> => Modifying:
>
> struct C { A *a1, *a2; C(); ~C() { delete a1; delete a2; } };
>
> Now the same thing happens when a1->~A() throws, but instead of
> continuing in compiler-generated code, this must continue on user code.
>
> You may suggest that one should be using smart pointers
> (std::unique_ptr) in this, but then we begin involving a third
> place where code gets executed.
What you show above is a poor destructor implementation. Yes, you should
definitely be using std::unique_ptr or an equivalent.
If your destructor is complex, and parts of it may throw, you need to make
sure that the rest of your destructor code still executes.
There is *no *difference here between "delete a1", where ~A is
noexcept(false); and calling any random method or function. You would
have an identical problem if you substitute "delete a1" with anything
else that may throw.
> => Suppose instead:
> struct D { A *a1, *a2; D(); ~D() { dispose(a1); dispose(a2); } };
> template <typename T> void dispose(T *&ptr)
This is not substantially different than the above example. "dispose" is
not a noexcept function. If the destructor is ignorant of the "dispose"
implementation - which is what you assume to make your point - this code is
already bad *currently*.
> This violates the requirement that you don't pay for features you don't
use.
My proposal imposes no such cost. If all destructors in your code are
noexcept, all multi-exception support can be safely optimized away.
No additional handling code is necessary unless you *want* to support
throwing destructors.
> 2) Not resume execution inside dispose(), but resume inside the
> destructor ~D() that called it.
Code that calls throwing destructors - such as dispose() in your case
- must be able to handle exceptions from them.
But this is *already* the case. I can declare my destructor
noexcept(false), and your dispose() method will be bad in C++ as-is.
On Wednesday, July 22, 2015 at 3:36:10 PM UTC-6, Thiago Macieira wrote:
> On Wednesday 22 July 2015 15:55:36 denis bider wrote:
> > But forcing destructors not to throw is an over-reach. It's an
> imposition
> > that's only necessary because of limitations of the single-exception
> > policy.
>
> No, it isn't. I showed that destructors should be noexcept because they're
> freeing resources and there's no recourse to a failed destructor.
>
> When a constructor fails by throwing, the sub-objects already constructed
> are
> destructed. What happens if one of them throws during that process?
>
> When a destructor fails half way, you can't re-construct the elements
> already
> destroyed, but it can neither continue destroying. You simply have an
> unfixable
> resource leak.
>
> You suggested that an exception thrown inside a destructor should be
> queued
> and destruction continue, then the whole exception group would be thrown.
> Ignoring the memory issues for this, I don't think it would work at all.
>
> => Starting testcase:
>
> struct A { ~A() { throw 42; } };
> struct B { A a1, a2; }
>
> When ~B runs, a1.~A() would throw, the exception would be queued, then the
> execution continues at a2.~A() would be executed (and throw again).
>
> => Modifying:
>
> struct C { A *a1, *a2; C(); ~C() { delete a1; delete a2; } };
>
> Now the same thing happens when a1->~A() throws, but instead of continuing
> in
> compiler-generated code, this must continue on user code.
>
> You may suggest that one should be using smart pointers (std::unique_ptr)
> in
> this, but then we begin involving a third place where code gets executed.
>
> => Suppose instead:
>
> struct D { A *a1, *a2; D(); ~D() { dispose(a1); dispose(a2); } };
>
> template <typename T> void dispose(T *&ptr)
> {
> ptr->~T();
> remove_from_siblings(ptr);
> Allocator::dealloc(ptr);
> }
>
> Note how ptr->~T() threw inside dispose(), a function that had nothing to
> do
> with nested exceptions. You have two options here:
>
> 1) Require that ALL throwing points be able to deal with code continuing
> instead of branching to the exceptional code path.
>
> This violates the requirement that you don't pay for features you don't
> use.
>
> 2) Not resume execution inside dispose(), but resume inside the destructor
> ~D() that called it.
>
> This may lead to a crash when destroying a2 because its sibling (a1) was
> not
> removed from the list, as the destruction did not finish properly.
>
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
> PGP/GPG: 0x6EF45358; fingerprint:
> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
>
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_16_1660238563.1437605536748
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>> I showed that destructors should be noexcept bec=
ause they're=C2=A0freeing resources and there's no recourse to a fa=
iled destructor. <br></div><div><br></div><div>You did not do such a thing.=
=C2=A0The statement you make reflects ideology.</div><div><br></div><div>Th=
ere are many things one=C2=A0may want to implement in a destructor that can=
fail -=C2=A0and the failure=C2=A0<em>is</em> actionable. A whole category =
of rollbacks - in installers, in database transactions -=C2=A0is included i=
n this.</div><div><br></div><div><br></div><div>> When a constructor fai=
ls by throwing, the sub-objects already constructed are=C2=A0destructed. Wh=
at happens if one of them throws during that process? <br></div><div><br></=
div><div>We have discussed this. The destruction process continues normally=
.. Up to one destructor exception=C2=A0has been supported in C++ always.</di=
v><div><br></div><div>My proposal does nothing to change this.=C2=A0Aggrega=
tion simply specifies a way that a destructor can throw <em>always; </em>in=
stead of <em>sometimes</em>, which already works.</div><div><br></div><div>=
<br></div><div>> =3D> Starting testcase: </div><div>><br>> stru=
ct A { ~A() { throw 42; } }; <br>> struct B { A a1, a2; } </div><div>>=
;<br>> When ~B runs, a1.~A() would throw, the exception would be queued,=
</div><div>> then the=C2=A0=C2=A0execution continues at a2.~A() would be=
executed</div><div>> (and throw again). </div><div><br></div><div>Yes. =
You get two aggregated exceptions. You can handle them. The object is destr=
oyed properly.</div><div><br></div><div>I don't see anything wrong with=
this case.<br></div><div><br></div><div><br></div><div>> =3D> Modify=
ing: <br>> <br>> struct C { A *a1, *a2; C(); ~C() { delete a1; delete=
a2; } }; <br>> <br>> Now the same thing happens when a1->~A() thr=
ows, but instead of</div><div>> continuing in=C2=A0compiler-generated co=
de, this must continue on user code. <br>><br>> You may suggest that =
one should be using smart pointers</div><div>> (std::unique_ptr) in=C2=
=A0this, but then we begin involving a third</div><div>> place where cod=
e gets executed.=C2=A0 </div><div><br></div><div>What you show above is a=
=C2=A0poor destructor implementation. Yes, you should definitely be using s=
td::unique_ptr or an equivalent.</div><div><br></div><div>If your destructo=
r is complex, and parts of it may throw, you need to make sure that the res=
t of your destructor code still executes.</div><div><br></div><div>There is=
<strong>no </strong>difference here between "delete=C2=A0a1", wh=
ere ~A is noexcept(false); and calling any random method or function. You w=
ould have=C2=A0an=C2=A0identical=C2=A0problem if you substitute "delet=
e a1" with anything else=C2=A0that may throw.</div><div><br></div><div=
><br></div><div>> =3D> Suppose instead: <br>>=C2=A0struct D { A *a=
1, *a2; D(); ~D() { dispose(a1); dispose(a2); } }; <br>> template <ty=
pename T> void dispose(T *&ptr) <br></div><div><br></div><div>This i=
s not substantially different than the above example. "dispose" i=
s not a noexcept function. If the destructor is ignorant of the "dispo=
se" implementation -=C2=A0which is what you assume to make your point =
-=C2=A0this code is already bad <em>currently</em>.</div><div><br></div><di=
v><br></div><div>> This violates the requirement that you don't pay =
for features you don't use. <br></div><div><br></div><div>My proposal i=
mposes no such cost. If all destructors in your code are noexcept, all mult=
i-exception support can be safely optimized away.</div><div><br></div><div>=
No additional handling code is necessary unless you <em>want</em> to suppor=
t throwing destructors.</div><div><br></div><div><br></div><div>> 2) Not=
resume execution inside dispose(), but resume inside the</div><div>> de=
structor=C2=A0~D() that called it.</div><div><br></div><div>Code that calls=
throwing destructors -=C2=A0such as dispose() in your case -=C2=A0must be =
able to handle exceptions from them.</div><div><br></div><div>But this is <=
em>already</em> the case. I can declare my destructor noexcept(false), and =
your dispose() method will be bad in C++ as-is.<br><br></div><div><br><br>O=
n Wednesday, July 22, 2015 at 3:36:10 PM UTC-6, Thiago Macieira wrote:</div=
><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padd=
ing-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1p=
x; border-left-style: solid;">On Wednesday 22 July 2015 15:55:36 denis bide=
r wrote:
<br>> But forcing destructors not to throw is an over-reach. It's an=
imposition
<br>> that's only necessary because of limitations of the single-exc=
eption
<br>> policy.
<br>
<br>No, it isn't. I showed that destructors should be noexcept because =
they're=20
<br>freeing resources and there's no recourse to a failed destructor.
<br>
<br>When a constructor fails by throwing, the sub-objects already construct=
ed are=20
<br>destructed. What happens if one of them throws during that process?
<br>
<br>When a destructor fails half way, you can't re-construct the elemen=
ts already=20
<br>destroyed, but it can neither continue destroying. You simply have an u=
nfixable=20
<br>resource leak.
<br>
<br>You suggested that an exception thrown inside a destructor should be qu=
eued=20
<br>and destruction continue, then the whole exception group would be throw=
n.=20
<br>Ignoring the memory issues for this, I don't think it would work at=
all.
<br>
<br>=3D> Starting testcase:
<br>
<br>struct A { ~A() { throw 42; } };
<br>struct B { A a1, a2; }
<br>
<br>When ~B runs, a1.~A() would throw, the exception would be queued, then =
the=20
<br>execution continues at a2.~A() would be executed (and throw again).
<br>
<br>=3D> Modifying:
<br>
<br>struct C { A *a1, *a2; C(); ~C() { delete a1; delete a2; } };
<br>
<br>Now the same thing happens when a1->~A() throws, but instead of cont=
inuing in=20
<br>compiler-generated code, this must continue on user code.
<br>
<br>You may suggest that one should be using smart pointers (std::unique_pt=
r) in=20
<br>this, but then we begin involving a third place where code gets execute=
d.=20
<br>
<br>=3D> Suppose instead:
<br>
<br>struct D { A *a1, *a2; D(); ~D() { dispose(a1); dispose(a2); } };
<br>
<br>template <typename T> void dispose(T *&ptr)
<br>{
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0ptr->~T();
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0remove_from_siblings(pt=
r);
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0Allocator::dealloc(ptr)=
;
<br>}
<br>
<br>Note how ptr->~T() threw inside dispose(), a function that had nothi=
ng to do=20
<br>with nested exceptions. You have two options here:
<br>
<br>1) Require that ALL throwing points be able to deal with code continuin=
g=20
<br>instead of branching to the exceptional code path.
<br>
<br>This violates the requirement that you don't pay for features you d=
on't use.
<br>
<br>2) Not resume execution inside dispose(), but resume inside the destruc=
tor=20
<br>~D() that called it.
<br>
<br>This may lead to a crash when destroying a2 because its sibling (a1) wa=
s not=20
<br>removed from the list, as the destruction did not finish properly.
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a onmousedown=3D"this.href=3D'http:/=
/www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\75D\46sntz\0751\46u=
sg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.=
href=3D'http://www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\7=
5D\46sntz\0751\46usg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;=
" href=3D"http://macieira.info" target=3D"_blank" rel=3D"nofollow">macieira=
..info</a> - thiago (AT) <a onmousedown=3D"this.href=3D'http://www.googl=
e.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\75AFQjCNHGRJd=
o5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'http=
://www.google.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\7=
5AFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;" href=3D"http://kde.o=
rg" target=3D"_blank" rel=3D"nofollow">kde.org</a>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>=C2=A0 =C2=A0 =C2=A0 PGP/GPG: 0x6EF45358; fingerprint:
<br>=C2=A0 =C2=A0 =C2=A0 E067 918B B660 DBD1 105C =C2=A0966C 33F5 F005 6EF4=
5358
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_16_1660238563.1437605536748--
------=_Part_15_441753177.1437605536747--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Wed, 22 Jul 2015 16:04:00 -0700 (PDT)
Raw View
------=_Part_0_7374998.1437606240455
Content-Type: multipart/alternative;
boundary="----=_Part_1_1379712956.1437606240458"
------=_Part_1_1379712956.1437606240458
Content-Type: text/plain; charset=UTF-8
I should additionally point out that the problems you point out are related
to a destructor that is tasked with cleaning up multiple resources.
That's the core of your problem. In the examples shown, RAII is not
properly being used. If you have two resources, they should be cleaned up
in separate destructors. If you have a single destructor freeing multiple
resources, you have a problem if there's an issue freeing one of them.
You should not do this unless the freeing of the two resources is somehow
conditionally related, and you need to implement logic to handle that
properly.
In your example 2, proper structure would require something like
std::unique_ptr.
In example 3, proper structure would require an intermediate RAII object
with a destructor that calls dispose(); one dispose per destructor.
Your existing proposed dispose() implementation is unsafe for throwing
destructors in C++ as-is. You need to use SFINAE to prevent its use with
throwing destructors:
template <typename T, std::enable_if_t<std::is_nothrow_destructible<T>,
int> = 0>
void dispose(T *&ptr) noexcept
{
ptr->~T();
remove_from_siblings(ptr);
Allocator::dealloc(ptr);
}
If you want a version that's safe for throwing destructors, that looks
different.
Again, that's already required for correctness in C++ as-is.
On Wednesday, July 22, 2015 at 4:52:16 PM UTC-6, denis bider wrote:
> > I showed that destructors should be noexcept because they're freeing
> resources and there's no recourse to a failed destructor.
>
> You did not do such a thing. The statement you make reflects ideology.
>
> There are many things one may want to implement in a destructor that can
> fail - and the failure *is* actionable. A whole category of rollbacks -
> in installers, in database transactions - is included in this.
>
>
> > When a constructor fails by throwing, the sub-objects already
> constructed are destructed. What happens if one of them throws during that
> process?
>
> We have discussed this. The destruction process continues normally. Up to
> one destructor exception has been supported in C++ always.
>
> My proposal does nothing to change this. Aggregation simply specifies a
> way that a destructor can throw *always; *instead of *sometimes*, which
> already works.
>
>
> > => Starting testcase:
> >
> > struct A { ~A() { throw 42; } };
> > struct B { A a1, a2; }
> >
> > When ~B runs, a1.~A() would throw, the exception would be queued,
> > then the execution continues at a2.~A() would be executed
> > (and throw again).
>
> Yes. You get two aggregated exceptions. You can handle them. The object is
> destroyed properly.
>
> I don't see anything wrong with this case.
>
>
> > => Modifying:
> >
> > struct C { A *a1, *a2; C(); ~C() { delete a1; delete a2; } };
> >
> > Now the same thing happens when a1->~A() throws, but instead of
> > continuing in compiler-generated code, this must continue on user code.
> >
> > You may suggest that one should be using smart pointers
> > (std::unique_ptr) in this, but then we begin involving a third
> > place where code gets executed.
>
> What you show above is a poor destructor implementation. Yes, you should
> definitely be using std::unique_ptr or an equivalent.
>
> If your destructor is complex, and parts of it may throw, you need to make
> sure that the rest of your destructor code still executes.
>
> There is *no *difference here between "delete a1", where ~A is
> noexcept(false); and calling any random method or function. You would
> have an identical problem if you substitute "delete a1" with anything
> else that may throw.
>
>
> > => Suppose instead:
> > struct D { A *a1, *a2; D(); ~D() { dispose(a1); dispose(a2); } };
> > template <typename T> void dispose(T *&ptr)
>
> This is not substantially different than the above example. "dispose" is
> not a noexcept function. If the destructor is ignorant of the "dispose"
> implementation - which is what you assume to make your point - this code is
> already bad *currently*.
>
>
> > This violates the requirement that you don't pay for features you don't
> use.
>
> My proposal imposes no such cost. If all destructors in your code are
> noexcept, all multi-exception support can be safely optimized away.
>
> No additional handling code is necessary unless you *want* to support
> throwing destructors.
>
>
> > 2) Not resume execution inside dispose(), but resume inside the
> > destructor ~D() that called it.
>
> Code that calls throwing destructors - such as dispose() in your case
> - must be able to handle exceptions from them.
>
> But this is *already* the case. I can declare my destructor
> noexcept(false), and your dispose() method will be bad in C++ as-is.
>
>
>
> On Wednesday, July 22, 2015 at 3:36:10 PM UTC-6, Thiago Macieira wrote:
>
>> On Wednesday 22 July 2015 15:55:36 denis bider wrote:
>> > But forcing destructors not to throw is an over-reach. It's an
>> imposition
>> > that's only necessary because of limitations of the single-exception
>> > policy.
>>
>> No, it isn't. I showed that destructors should be noexcept because
>> they're
>> freeing resources and there's no recourse to a failed destructor.
>>
>> When a constructor fails by throwing, the sub-objects already constructed
>> are
>> destructed. What happens if one of them throws during that process?
>>
>> When a destructor fails half way, you can't re-construct the elements
>> already
>> destroyed, but it can neither continue destroying. You simply have an
>> unfixable
>> resource leak.
>>
>> You suggested that an exception thrown inside a destructor should be
>> queued
>> and destruction continue, then the whole exception group would be thrown.
>> Ignoring the memory issues for this, I don't think it would work at all.
>>
>> => Starting testcase:
>>
>> struct A { ~A() { throw 42; } };
>> struct B { A a1, a2; }
>>
>> When ~B runs, a1.~A() would throw, the exception would be queued, then
>> the
>> execution continues at a2.~A() would be executed (and throw again).
>>
>> => Modifying:
>>
>> struct C { A *a1, *a2; C(); ~C() { delete a1; delete a2; } };
>>
>> Now the same thing happens when a1->~A() throws, but instead of
>> continuing in
>> compiler-generated code, this must continue on user code.
>>
>> You may suggest that one should be using smart pointers (std::unique_ptr)
>> in
>> this, but then we begin involving a third place where code gets executed.
>>
>> => Suppose instead:
>>
>> struct D { A *a1, *a2; D(); ~D() { dispose(a1); dispose(a2); } };
>>
>> template <typename T> void dispose(T *&ptr)
>> {
>> ptr->~T();
>> remove_from_siblings(ptr);
>> Allocator::dealloc(ptr);
>> }
>>
>> Note how ptr->~T() threw inside dispose(), a function that had nothing to
>> do
>> with nested exceptions. You have two options here:
>>
>> 1) Require that ALL throwing points be able to deal with code continuing
>> instead of branching to the exceptional code path.
>>
>> This violates the requirement that you don't pay for features you don't
>> use.
>>
>> 2) Not resume execution inside dispose(), but resume inside the
>> destructor
>> ~D() that called it.
>>
>> This may lead to a crash when destroying a2 because its sibling (a1) was
>> not
>> removed from the list, as the destruction did not finish properly.
>>
>> --
>> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
>> Software Architect - Intel Open Source Technology Center
>> PGP/GPG: 0x6EF45358; fingerprint:
>> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
>>
>>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1_1379712956.1437606240458
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>I should additionally point out that the problems you=
point out are related to a destructor that is tasked with cleaning up mult=
iple resources.</div><div><br></div><div>That's the core of your proble=
m. In the examples shown, RAII is not properly being used. If you have two =
resources, they should be cleaned up in separate destructors. If you have a=
single destructor freeing multiple resources, you have a problem if there&=
#39;s an issue freeing one of them.</div><div><br></div><div>You should not=
do this unless the freeing of the two resources is somehow conditionally r=
elated, and you need to implement logic to handle=C2=A0that properly.</div>=
<div><br></div><div>In your example 2, proper structure would require somet=
hing like std::unique_ptr.</div><div><br></div><div>In example 3, proper st=
ructure would require an intermediate RAII object with a destructor that ca=
lls dispose(); one dispose per destructor.</div><div><br></div><div>Your ex=
isting proposed dispose() implementation is unsafe for throwing destructors=
in C++ as-is. You need to use SFINAE to prevent its use with throwing dest=
ructors:</div><div><br></div><div>template <typename T, std::enable_if_t=
<std::is_nothrow_destructible<T>, int> =3D 0></div><div>void=
dispose(T *&ptr) noexcept<br>{ <br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0ptr->~T(); <br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0remove_from_siblings(ptr); <br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0Allocator::dealloc(ptr); <br>} <br><br></div><div>If you want a=
version that's safe for throwing destructors, that looks different.</d=
iv><div><br></div><div>Again, that's already required for correctness i=
n C++ as-is.</div><div><br></div><div><br>On Wednesday, July 22, 2015 at 4:=
52:16 PM UTC-6, denis bider wrote:</div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rg=
b(204, 204, 204); border-left-width: 1px; border-left-style: solid;"><div d=
ir=3D"ltr"><div>> I showed that destructors should be noexcept because t=
hey're=C2=A0freeing resources and there's no recourse to a failed d=
estructor. <br></div><div><br></div><div>You did not do such a thing.=C2=A0=
The statement you make reflects ideology.</div><div><br></div><div>There ar=
e many things one=C2=A0may want to implement in a destructor that can fail =
-=C2=A0and the failure=C2=A0<em>is</em> actionable. A whole category of rol=
lbacks - in installers, in database transactions -=C2=A0is included in this=
..</div><div><br></div><div><br></div><div>> When a constructor fails by =
throwing, the sub-objects already constructed are=C2=A0destructed. What hap=
pens if one of them throws during that process? <br></div><div><br></div><d=
iv>We have discussed this. The destruction process continues normally. Up t=
o one destructor exception=C2=A0has been supported in C++ always.</div><div=
><br></div><div>My proposal does nothing to change this.=C2=A0Aggregation s=
imply specifies a way that a destructor can throw <em>always; </em>instead =
of <em>sometimes</em>, which already works.</div><div><br></div><div><br></=
div><div>> =3D> Starting testcase: </div><div>><br>> struct A {=
~A() { throw 42; } }; <br>> struct B { A a1, a2; } </div><div>><br>&=
gt; When ~B runs, a1.~A() would throw, the exception would be queued,</div>=
<div>> then the=C2=A0=C2=A0execution continues at a2.~A() would be execu=
ted</div><div>> (and throw again). </div><div><br></div><div>Yes. You ge=
t two aggregated exceptions. You can handle them. The object is destroyed p=
roperly.</div><div><br></div><div>I don't see anything wrong with this =
case.<br></div><div><br></div><div><br></div><div>> =3D> Modifying: <=
br>> <br>> struct C { A *a1, *a2; C(); ~C() { delete a1; delete a2; }=
}; <br>> <br>> Now the same thing happens when a1->~A() throws, b=
ut instead of</div><div>> continuing in=C2=A0compiler-generated code, th=
is must continue on user code. <br>><br>> You may suggest that one sh=
ould be using smart pointers</div><div>> (std::unique_ptr) in=C2=A0this,=
but then we begin involving a third</div><div>> place where code gets e=
xecuted.=C2=A0 </div><div><br></div><div>What you show above is a=C2=A0poor=
destructor implementation. Yes, you should definitely be using std::unique=
_ptr or an equivalent.</div><div><br></div><div>If your destructor is compl=
ex, and parts of it may throw, you need to make sure that the rest of your =
destructor code still executes.</div><div><br></div><div>There is <strong>n=
o </strong>difference here between "delete=C2=A0a1", where ~A is =
noexcept(false); and calling any random method or function. You would have=
=C2=A0an=C2=A0identical=C2=A0problem if you substitute "delete a1"=
; with anything else=C2=A0that may throw.</div><div><br></div><div><br></di=
v><div>> =3D> Suppose instead: <br>>=C2=A0struct D { A *a1, *a2; D=
(); ~D() { dispose(a1); dispose(a2); } }; <br>> template <typename T&=
gt; void dispose(T *&ptr) <br></div><div><br></div><div>This is not sub=
stantially different than the above example. "dispose" is not a n=
oexcept function. If the destructor is ignorant of the "dispose" =
implementation -=C2=A0which is what you assume to make your point -=C2=A0th=
is code is already bad <em>currently</em>.</div><div><br></div><div><br></d=
iv><div>> This violates the requirement that you don't pay for featu=
res you don't use. <br></div><div><br></div><div>My proposal imposes no=
such cost. If all destructors in your code are noexcept, all multi-excepti=
on support can be safely optimized away.</div><div><br></div><div>No additi=
onal handling code is necessary unless you <em>want</em> to support throwin=
g destructors.</div><div><br></div><div><br></div><div>> 2) Not resume e=
xecution inside dispose(), but resume inside the</div><div>> destructor=
=C2=A0~D() that called it.</div><div><br></div><div>Code that calls throwin=
g destructors -=C2=A0such as dispose() in your case -=C2=A0must be able to =
handle exceptions from them.</div><div><br></div><div>But this is <em>alrea=
dy</em> the case. I can declare my destructor noexcept(false), and your dis=
pose() method will be bad in C++ as-is.<br><br></div><div><br><br>On Wednes=
day, July 22, 2015 at 3:36:10 PM UTC-6, Thiago Macieira wrote:</div><blockq=
uote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left=
: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px; borde=
r-left-style: solid;">On Wednesday 22 July 2015 15:55:36 denis bider wrote:
<br>> But forcing destructors not to throw is an over-reach. It's an=
imposition
<br>> that's only necessary because of limitations of the single-exc=
eption
<br>> policy.
<br>
<br>No, it isn't. I showed that destructors should be noexcept because =
they're=20
<br>freeing resources and there's no recourse to a failed destructor.
<br>
<br>When a constructor fails by throwing, the sub-objects already construct=
ed are=20
<br>destructed. What happens if one of them throws during that process?
<br>
<br>When a destructor fails half way, you can't re-construct the elemen=
ts already=20
<br>destroyed, but it can neither continue destroying. You simply have an u=
nfixable=20
<br>resource leak.
<br>
<br>You suggested that an exception thrown inside a destructor should be qu=
eued=20
<br>and destruction continue, then the whole exception group would be throw=
n.=20
<br>Ignoring the memory issues for this, I don't think it would work at=
all.
<br>
<br>=3D> Starting testcase:
<br>
<br>struct A { ~A() { throw 42; } };
<br>struct B { A a1, a2; }
<br>
<br>When ~B runs, a1.~A() would throw, the exception would be queued, then =
the=20
<br>execution continues at a2.~A() would be executed (and throw again).
<br>
<br>=3D> Modifying:
<br>
<br>struct C { A *a1, *a2; C(); ~C() { delete a1; delete a2; } };
<br>
<br>Now the same thing happens when a1->~A() throws, but instead of cont=
inuing in=20
<br>compiler-generated code, this must continue on user code.
<br>
<br>You may suggest that one should be using smart pointers (std::unique_pt=
r) in=20
<br>this, but then we begin involving a third place where code gets execute=
d.=20
<br>
<br>=3D> Suppose instead:
<br>
<br>struct D { A *a1, *a2; D(); ~D() { dispose(a1); dispose(a2); } };
<br>
<br>template <typename T> void dispose(T *&ptr)
<br>{
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0ptr->~T();
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0remove_from_siblings(pt=
r);
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0Allocator::dealloc(ptr)=
;
<br>}
<br>
<br>Note how ptr->~T() threw inside dispose(), a function that had nothi=
ng to do=20
<br>with nested exceptions. You have two options here:
<br>
<br>1) Require that ALL throwing points be able to deal with code continuin=
g=20
<br>instead of branching to the exceptional code path.
<br>
<br>This violates the requirement that you don't pay for features you d=
on't use.
<br>
<br>2) Not resume execution inside dispose(), but resume inside the destruc=
tor=20
<br>~D() that called it.
<br>
<br>This may lead to a crash when destroying a2 because its sibling (a1) wa=
s not=20
<br>removed from the list, as the destruction did not finish properly.
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a onmousedown=3D"this.href=3D'http:/=
/www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\75D\46sntz\0751\46u=
sg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.=
href=3D'http://www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\7=
5D\46sntz\0751\46usg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;=
" href=3D"http://macieira.info" target=3D"_blank" rel=3D"nofollow">macieira=
..info</a> - thiago (AT) <a onmousedown=3D"this.href=3D'http://www.googl=
e.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\75AFQjCNHGRJd=
o5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'http=
://www.google.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\7=
5AFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;" href=3D"http://kde.o=
rg" target=3D"_blank" rel=3D"nofollow">kde.org</a>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>=C2=A0 =C2=A0 =C2=A0 PGP/GPG: 0x6EF45358; fingerprint:
<br>=C2=A0 =C2=A0 =C2=A0 E067 918B B660 DBD1 105C =C2=A0966C 33F5 F005 6EF4=
5358
<br>
<br></blockquote></div></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1_1379712956.1437606240458--
------=_Part_0_7374998.1437606240455--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Wed, 22 Jul 2015 16:49:16 -0700 (PDT)
Raw View
------=_Part_8_1339824476.1437608956242
Content-Type: multipart/alternative;
boundary="----=_Part_9_1300140297.1437608956242"
------=_Part_9_1300140297.1437608956242
Content-Type: text/plain; charset=UTF-8
It seems to me what you're implying is that the average C++ developer is
incapable of writing destructors that work properly in the face of
exceptions. You proposed a dispose() implementation that is unsafe in C++
as-is. You seem to imply that this is code an average developer would
write. You may understand that such code is not currently safe; but you
believe it *ought* to be.
My issue is that this is a compromise in favor of the less competent, which
restricts the language and makes it less expressive. It imposes limitations
on *everyone*, in order to benefit beginners.
I think C++ should be beginner friendly, but without this type of
compromise.
On Wednesday, July 22, 2015 at 5:04:00 PM UTC-6, denis bider wrote:
> I should additionally point out that the problems you point out are
> related to a destructor that is tasked with cleaning up multiple resources.
>
> That's the core of your problem. In the examples shown, RAII is not
> properly being used. If you have two resources, they should be cleaned up
> in separate destructors. If you have a single destructor freeing multiple
> resources, you have a problem if there's an issue freeing one of them.
>
> You should not do this unless the freeing of the two resources is somehow
> conditionally related, and you need to implement logic to handle that
> properly.
>
> In your example 2, proper structure would require something like
> std::unique_ptr.
>
> In example 3, proper structure would require an intermediate RAII object
> with a destructor that calls dispose(); one dispose per destructor.
>
> Your existing proposed dispose() implementation is unsafe for throwing
> destructors in C++ as-is. You need to use SFINAE to prevent its use with
> throwing destructors:
>
> template <typename T, std::enable_if_t<std::is_nothrow_destructible<T>,
> int> = 0>
> void dispose(T *&ptr) noexcept
> {
> ptr->~T();
> remove_from_siblings(ptr);
> Allocator::dealloc(ptr);
> }
>
> If you want a version that's safe for throwing destructors, that looks
> different.
>
> Again, that's already required for correctness in C++ as-is.
>
>
> On Wednesday, July 22, 2015 at 4:52:16 PM UTC-6, denis bider wrote:
>
>> > I showed that destructors should be noexcept because they're freeing
>> resources and there's no recourse to a failed destructor.
>>
>> You did not do such a thing. The statement you make reflects ideology.
>>
>> There are many things one may want to implement in a destructor that can
>> fail - and the failure *is* actionable. A whole category of rollbacks -
>> in installers, in database transactions - is included in this.
>>
>>
>> > When a constructor fails by throwing, the sub-objects already
>> constructed are destructed. What happens if one of them throws during that
>> process?
>>
>> We have discussed this. The destruction process continues normally. Up to
>> one destructor exception has been supported in C++ always.
>>
>> My proposal does nothing to change this. Aggregation simply specifies a
>> way that a destructor can throw *always; *instead of *sometimes*, which
>> already works.
>>
>>
>> > => Starting testcase:
>> >
>> > struct A { ~A() { throw 42; } };
>> > struct B { A a1, a2; }
>> >
>> > When ~B runs, a1.~A() would throw, the exception would be queued,
>> > then the execution continues at a2.~A() would be executed
>> > (and throw again).
>>
>> Yes. You get two aggregated exceptions. You can handle them. The object
>> is destroyed properly.
>>
>> I don't see anything wrong with this case.
>>
>>
>> > => Modifying:
>> >
>> > struct C { A *a1, *a2; C(); ~C() { delete a1; delete a2; } };
>> >
>> > Now the same thing happens when a1->~A() throws, but instead of
>> > continuing in compiler-generated code, this must continue on user code.
>> >
>> > You may suggest that one should be using smart pointers
>> > (std::unique_ptr) in this, but then we begin involving a third
>> > place where code gets executed.
>>
>> What you show above is a poor destructor implementation. Yes, you should
>> definitely be using std::unique_ptr or an equivalent.
>>
>> If your destructor is complex, and parts of it may throw, you need to
>> make sure that the rest of your destructor code still executes.
>>
>> There is *no *difference here between "delete a1", where ~A is
>> noexcept(false); and calling any random method or function. You would
>> have an identical problem if you substitute "delete a1" with anything
>> else that may throw.
>>
>>
>> > => Suppose instead:
>> > struct D { A *a1, *a2; D(); ~D() { dispose(a1); dispose(a2); } };
>> > template <typename T> void dispose(T *&ptr)
>>
>> This is not substantially different than the above example. "dispose" is
>> not a noexcept function. If the destructor is ignorant of the "dispose"
>> implementation - which is what you assume to make your point - this code is
>> already bad *currently*.
>>
>>
>> > This violates the requirement that you don't pay for features you don't
>> use.
>>
>> My proposal imposes no such cost. If all destructors in your code are
>> noexcept, all multi-exception support can be safely optimized away.
>>
>> No additional handling code is necessary unless you *want* to support
>> throwing destructors.
>>
>>
>> > 2) Not resume execution inside dispose(), but resume inside the
>> > destructor ~D() that called it.
>>
>> Code that calls throwing destructors - such as dispose() in your case
>> - must be able to handle exceptions from them.
>>
>> But this is *already* the case. I can declare my destructor
>> noexcept(false), and your dispose() method will be bad in C++ as-is.
>>
>>
>>
>> On Wednesday, July 22, 2015 at 3:36:10 PM UTC-6, Thiago Macieira wrote:
>>
>>> On Wednesday 22 July 2015 15:55:36 denis bider wrote:
>>> > But forcing destructors not to throw is an over-reach. It's an
>>> imposition
>>> > that's only necessary because of limitations of the single-exception
>>> > policy.
>>>
>>> No, it isn't. I showed that destructors should be noexcept because
>>> they're
>>> freeing resources and there's no recourse to a failed destructor.
>>>
>>> When a constructor fails by throwing, the sub-objects already
>>> constructed are
>>> destructed. What happens if one of them throws during that process?
>>>
>>> When a destructor fails half way, you can't re-construct the elements
>>> already
>>> destroyed, but it can neither continue destroying. You simply have an
>>> unfixable
>>> resource leak.
>>>
>>> You suggested that an exception thrown inside a destructor should be
>>> queued
>>> and destruction continue, then the whole exception group would be
>>> thrown.
>>> Ignoring the memory issues for this, I don't think it would work at all.
>>>
>>> => Starting testcase:
>>>
>>> struct A { ~A() { throw 42; } };
>>> struct B { A a1, a2; }
>>>
>>> When ~B runs, a1.~A() would throw, the exception would be queued, then
>>> the
>>> execution continues at a2.~A() would be executed (and throw again).
>>>
>>> => Modifying:
>>>
>>> struct C { A *a1, *a2; C(); ~C() { delete a1; delete a2; } };
>>>
>>> Now the same thing happens when a1->~A() throws, but instead of
>>> continuing in
>>> compiler-generated code, this must continue on user code.
>>>
>>> You may suggest that one should be using smart pointers
>>> (std::unique_ptr) in
>>> this, but then we begin involving a third place where code gets
>>> executed.
>>>
>>> => Suppose instead:
>>>
>>> struct D { A *a1, *a2; D(); ~D() { dispose(a1); dispose(a2); } };
>>>
>>> template <typename T> void dispose(T *&ptr)
>>> {
>>> ptr->~T();
>>> remove_from_siblings(ptr);
>>> Allocator::dealloc(ptr);
>>> }
>>>
>>> Note how ptr->~T() threw inside dispose(), a function that had nothing
>>> to do
>>> with nested exceptions. You have two options here:
>>>
>>> 1) Require that ALL throwing points be able to deal with code continuing
>>> instead of branching to the exceptional code path.
>>>
>>> This violates the requirement that you don't pay for features you don't
>>> use.
>>>
>>> 2) Not resume execution inside dispose(), but resume inside the
>>> destructor
>>> ~D() that called it.
>>>
>>> This may lead to a crash when destroying a2 because its sibling (a1) was
>>> not
>>> removed from the list, as the destruction did not finish properly.
>>>
>>> --
>>> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
>>> Software Architect - Intel Open Source Technology Center
>>> PGP/GPG: 0x6EF45358; fingerprint:
>>> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
>>>
>>>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_9_1300140297.1437608956242
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>It seems to me what you're implying is that the a=
verage C++ developer is incapable of writing destructors that work properly=
in the face of exceptions. You proposed=C2=A0a dispose() implementation th=
at is unsafe in C++ as-is. You=C2=A0seem to imply that this is code an aver=
age developer would write.=C2=A0You may understand that such code is not cu=
rrently safe; but you believe=C2=A0it=C2=A0<em>ought</em> to be.</div><div>=
<br></div><div>My issue is that this is a compromise in favor of the less c=
ompetent, which restricts the language and makes it less expressive. It imp=
oses limitations on <em>everyone</em>, in order to benefit beginners.</div>=
<div><br></div><div>I think C++ should be beginner friendly, but without th=
is type of compromise.</div><div><br><br>On Wednesday, July 22, 2015 at 5:0=
4:00 PM UTC-6, denis bider wrote:</div><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb=
(204, 204, 204); border-left-width: 1px; border-left-style: solid;"><div di=
r=3D"ltr"><div>I should additionally point out that the problems you point =
out are related to a destructor that is tasked with cleaning up multiple re=
sources.</div><div><br></div><div>That's the core of your problem. In t=
he examples shown, RAII is not properly being used. If you have two resourc=
es, they should be cleaned up in separate destructors. If you have a single=
destructor freeing multiple resources, you have a problem if there's a=
n issue freeing one of them.</div><div><br></div><div>You should not do thi=
s unless the freeing of the two resources is somehow conditionally related,=
and you need to implement logic to handle=C2=A0that properly.</div><div><b=
r></div><div>In your example 2, proper structure would require something li=
ke std::unique_ptr.</div><div><br></div><div>In example 3, proper structure=
would require an intermediate RAII object with a destructor that calls dis=
pose(); one dispose per destructor.</div><div><br></div><div>Your existing =
proposed dispose() implementation is unsafe for throwing destructors in C++=
as-is. You need to use SFINAE to prevent its use with throwing destructors=
:</div><div><br></div><div>template <typename T, std::enable_if_t<std=
::is_nothrow_destructible<T>, int> =3D 0></div><div>void dispos=
e(T *&ptr) noexcept<br>{ <br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0ptr->~T(); <br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0rem=
ove_from_siblings(ptr); <br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0Allocator::dealloc(ptr); <br>} <br><br></div><div>If you want a version =
that's safe for throwing destructors, that looks different.</div><div><=
br></div><div>Again, that's already required for correctness in C++ as-=
is.</div><div><br></div><div><br>On Wednesday, July 22, 2015 at 4:52:16 PM =
UTC-6, denis bider wrote:</div><blockquote class=3D"gmail_quote" style=3D"m=
argin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 20=
4, 204); border-left-width: 1px; border-left-style: solid;"><div dir=3D"ltr=
"><div>> I showed that destructors should be noexcept because they'r=
e=C2=A0freeing resources and there's no recourse to a failed destructor=
.. <br></div><div><br></div><div>You did not do such a thing.=C2=A0The state=
ment you make reflects ideology.</div><div><br></div><div>There are many th=
ings one=C2=A0may want to implement in a destructor that can fail -=C2=A0an=
d the failure=C2=A0<em>is</em> actionable. A whole category of rollbacks - =
in installers, in database transactions -=C2=A0is included in this.</div><d=
iv><br></div><div><br></div><div>> When a constructor fails by throwing,=
the sub-objects already constructed are=C2=A0destructed. What happens if o=
ne of them throws during that process? <br></div><div><br></div><div>We hav=
e discussed this. The destruction process continues normally. Up to one des=
tructor exception=C2=A0has been supported in C++ always.</div><div><br></di=
v><div>My proposal does nothing to change this.=C2=A0Aggregation simply spe=
cifies a way that a destructor can throw <em>always; </em>instead of <em>so=
metimes</em>, which already works.</div><div><br></div><div><br></div><div>=
> =3D> Starting testcase: </div><div>><br>> struct A { ~A() { t=
hrow 42; } }; <br>> struct B { A a1, a2; } </div><div>><br>> When =
~B runs, a1.~A() would throw, the exception would be queued,</div><div>>=
then the=C2=A0=C2=A0execution continues at a2.~A() would be executed</div>=
<div>> (and throw again). </div><div><br></div><div>Yes. You get two agg=
regated exceptions. You can handle them. The object is destroyed properly.<=
/div><div><br></div><div>I don't see anything wrong with this case.<br>=
</div><div><br></div><div><br></div><div>> =3D> Modifying: <br>> <=
br>> struct C { A *a1, *a2; C(); ~C() { delete a1; delete a2; } }; <br>&=
gt; <br>> Now the same thing happens when a1->~A() throws, but instea=
d of</div><div>> continuing in=C2=A0compiler-generated code, this must c=
ontinue on user code. <br>><br>> You may suggest that one should be u=
sing smart pointers</div><div>> (std::unique_ptr) in=C2=A0this, but then=
we begin involving a third</div><div>> place where code gets executed.=
=C2=A0 </div><div><br></div><div>What you show above is a=C2=A0poor destruc=
tor implementation. Yes, you should definitely be using std::unique_ptr or =
an equivalent.</div><div><br></div><div>If your destructor is complex, and =
parts of it may throw, you need to make sure that the rest of your destruct=
or code still executes.</div><div><br></div><div>There is <strong>no </stro=
ng>difference here between "delete=C2=A0a1", where ~A is noexcept=
(false); and calling any random method or function. You would have=C2=A0an=
=C2=A0identical=C2=A0problem if you substitute "delete a1" with a=
nything else=C2=A0that may throw.</div><div><br></div><div><br></div><div>&=
gt; =3D> Suppose instead: <br>>=C2=A0struct D { A *a1, *a2; D(); ~D()=
{ dispose(a1); dispose(a2); } }; <br>> template <typename T> void=
dispose(T *&ptr) <br></div><div><br></div><div>This is not substantial=
ly different than the above example. "dispose" is not a noexcept =
function. If the destructor is ignorant of the "dispose" implemen=
tation -=C2=A0which is what you assume to make your point -=C2=A0this code =
is already bad <em>currently</em>.</div><div><br></div><div><br></div><div>=
> This violates the requirement that you don't pay for features you =
don't use. <br></div><div><br></div><div>My proposal imposes no such co=
st. If all destructors in your code are noexcept, all multi-exception suppo=
rt can be safely optimized away.</div><div><br></div><div>No additional han=
dling code is necessary unless you <em>want</em> to support throwing destru=
ctors.</div><div><br></div><div><br></div><div>> 2) Not resume execution=
inside dispose(), but resume inside the</div><div>> destructor=C2=A0~D(=
) that called it.</div><div><br></div><div>Code that calls throwing destruc=
tors -=C2=A0such as dispose() in your case -=C2=A0must be able to handle ex=
ceptions from them.</div><div><br></div><div>But this is <em>already</em> t=
he case. I can declare my destructor noexcept(false), and your dispose() me=
thod will be bad in C++ as-is.<br><br></div><div><br><br>On Wednesday, July=
22, 2015 at 3:36:10 PM UTC-6, Thiago Macieira wrote:</div><blockquote clas=
s=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; bo=
rder-left-color: rgb(204, 204, 204); border-left-width: 1px; border-left-st=
yle: solid;">On Wednesday 22 July 2015 15:55:36 denis bider wrote:
<br>> But forcing destructors not to throw is an over-reach. It's an=
imposition
<br>> that's only necessary because of limitations of the single-exc=
eption
<br>> policy.
<br>
<br>No, it isn't. I showed that destructors should be noexcept because =
they're=20
<br>freeing resources and there's no recourse to a failed destructor.
<br>
<br>When a constructor fails by throwing, the sub-objects already construct=
ed are=20
<br>destructed. What happens if one of them throws during that process?
<br>
<br>When a destructor fails half way, you can't re-construct the elemen=
ts already=20
<br>destroyed, but it can neither continue destroying. You simply have an u=
nfixable=20
<br>resource leak.
<br>
<br>You suggested that an exception thrown inside a destructor should be qu=
eued=20
<br>and destruction continue, then the whole exception group would be throw=
n.=20
<br>Ignoring the memory issues for this, I don't think it would work at=
all.
<br>
<br>=3D> Starting testcase:
<br>
<br>struct A { ~A() { throw 42; } };
<br>struct B { A a1, a2; }
<br>
<br>When ~B runs, a1.~A() would throw, the exception would be queued, then =
the=20
<br>execution continues at a2.~A() would be executed (and throw again).
<br>
<br>=3D> Modifying:
<br>
<br>struct C { A *a1, *a2; C(); ~C() { delete a1; delete a2; } };
<br>
<br>Now the same thing happens when a1->~A() throws, but instead of cont=
inuing in=20
<br>compiler-generated code, this must continue on user code.
<br>
<br>You may suggest that one should be using smart pointers (std::unique_pt=
r) in=20
<br>this, but then we begin involving a third place where code gets execute=
d.=20
<br>
<br>=3D> Suppose instead:
<br>
<br>struct D { A *a1, *a2; D(); ~D() { dispose(a1); dispose(a2); } };
<br>
<br>template <typename T> void dispose(T *&ptr)
<br>{
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0ptr->~T();
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0remove_from_siblings(pt=
r);
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0Allocator::dealloc(ptr)=
;
<br>}
<br>
<br>Note how ptr->~T() threw inside dispose(), a function that had nothi=
ng to do=20
<br>with nested exceptions. You have two options here:
<br>
<br>1) Require that ALL throwing points be able to deal with code continuin=
g=20
<br>instead of branching to the exceptional code path.
<br>
<br>This violates the requirement that you don't pay for features you d=
on't use.
<br>
<br>2) Not resume execution inside dispose(), but resume inside the destruc=
tor=20
<br>~D() that called it.
<br>
<br>This may lead to a crash when destroying a2 because its sibling (a1) wa=
s not=20
<br>removed from the list, as the destruction did not finish properly.
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a onmousedown=3D"this.href=3D'http:/=
/www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\75D\46sntz\0751\46u=
sg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.=
href=3D'http://www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\7=
5D\46sntz\0751\46usg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;=
" href=3D"http://macieira.info" target=3D"_blank" rel=3D"nofollow">macieira=
..info</a> - thiago (AT) <a onmousedown=3D"this.href=3D'http://www.googl=
e.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\75AFQjCNHGRJd=
o5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'http=
://www.google.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\7=
5AFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;" href=3D"http://kde.o=
rg" target=3D"_blank" rel=3D"nofollow">kde.org</a>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>=C2=A0 =C2=A0 =C2=A0 PGP/GPG: 0x6EF45358; fingerprint:
<br>=C2=A0 =C2=A0 =C2=A0 E067 918B B660 DBD1 105C =C2=A0966C 33F5 F005 6EF4=
5358
<br>
<br></blockquote></div></blockquote></div></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_9_1300140297.1437608956242--
------=_Part_8_1339824476.1437608956242--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Wed, 22 Jul 2015 17:04:04 -0700
Raw View
On Wednesday 22 July 2015 15:52:16 denis bider wrote:
> There are many things one may want to implement in a destructor that can
> fail - and the failure *is* actionable. A whole category of rollbacks - in
> installers, in database transactions - is included in this.
Please tell me of an uninstaller that rolls back when it runs into an error.
> > => Starting testcase:
> >
> > struct A { ~A() { throw 42; } };
> > struct B { A a1, a2; }
> >
> > When ~B runs, a1.~A() would throw, the exception would be queued,
> > then the execution continues at a2.~A() would be executed
> > (and throw again).
>
> Yes. You get two aggregated exceptions. You can handle them. The object is
> destroyed properly.
>
> I don't see anything wrong with this case.
This was only the starting point. It gets more complex after this.
>
> > => Modifying:
> >
> > struct C { A *a1, *a2; C(); ~C() { delete a1; delete a2; } };
> >
> > Now the same thing happens when a1->~A() throws, but instead of
> > continuing in compiler-generated code, this must continue on user code.
> >
> > You may suggest that one should be using smart pointers
> > (std::unique_ptr) in this, but then we begin involving a third
> > place where code gets executed.
>
> What you show above is a poor destructor implementation. Yes, you should
> definitely be using std::unique_ptr or an equivalent.
That punts the problem to std::unique_ptr. Now the destructor of your sub-
objects may be called while other sub-objects that should have been destroyed
haven't yet.
> This is not substantially different than the above example. "dispose" is
> not a noexcept function. If the destructor is ignorant of the "dispose"
> implementation - which is what you assume to make your point - this code is
> already bad *currently*.
>
> > This violates the requirement that you don't pay for features you don't
> > use.
>
> My proposal imposes no such cost. If all destructors in your code are
> noexcept, all multi-exception support can be safely optimized away.
>
> No additional handling code is necessary unless you *want* to support
> throwing destructors.
I see what you mean. You're saying that unless I want to handle aggregated
exceptions, I don't have to. So if a destructor throws in my destructor, I can
let it, like today, trigger std::terminate().
But that contradicts the previous part of your proposal: the part that says
that the destructor must continue destruction of the sub-objects when one
throws and then aggregate exceptions.
We may argue whether this is currently bad code or not. But it's a change in
behaviour, with increased memory pressure, for something that is not in use
today.
I assume that you're also saying that this should apply to any stack unwinding
code, not just the destructor's sub-object destruction. That is, the following
will continue execution and aggregate, with unmodified code:
void f()
{
A a1, a2;
}
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Wed, 22 Jul 2015 17:17:22 -0700
Raw View
On Wednesday 22 July 2015 16:49:16 denis bider wrote:
> It seems to me what you're implying is that the average C++ developer is
> incapable of writing destructors that work properly in the face of
> exceptions.
Yes. Your argument is that destructors should be treated like any other
function. Yet any other function is usually *not* a trivial method doing
exactly one thing -- freeing a resource. Your average function is a complex
beast.
Destructors today, with the requirement to attempt to be noexcept, are hard to
write. Developers today rely on exceptions to clean up RAII objects properly.
But making destructors complex and throwing means you need to *manually*
handle the cleanup. Therefore, allowing them to be "regular functions" would
make them that much more complex.
And your average C++ developer can't write a regular function that handles
exceptions already.
So, no, the average C++ developer will not be able to write a destructor that
works properly in the fact of exceptions.
What's more, you're contradicting yourself. You're arguing that destructors
should be allowed to be complex and therefore throw at the same time you're
arguing that destructors should be simple and do one thing.
> You proposed a dispose() implementation that is unsafe in C++ as-is.
Only if the destructor throws. Since they currently don't, it has no problem.
And if it accidentally did after promising it wouldn't, the application would
terminate.
Besides, the function is an oversimplification of existing code that calls
destructors, like std::vector's own destructor.
I'm starting from the point that there is a sizeable codebase which assumes
destructors don't throw. You're starting from a clean slate or only after
everyone (at least the Standard Library) has cleaned up their code to handle
throwing destructors and aggregation of exceptions.
> My issue is that this is a compromise in favor of the less competent, which
> restricts the language and makes it less expressive. It imposes limitations
> on *everyone*, in order to benefit beginners.
>
> I think C++ should be beginner friendly, but without this type of
> compromise.
I get you, but even if we ignore this part of the discussion and that of
policy, there's still the problem of allocating memory as a response to having
no memory available.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Myriachan <myriachan@gmail.com>
Date: Wed, 22 Jul 2015 18:37:06 -0700 (PDT)
Raw View
------=_Part_192_873626352.1437615426907
Content-Type: multipart/alternative;
boundary="----=_Part_193_695353227.1437615426907"
------=_Part_193_695353227.1437615426907
Content-Type: text/plain; charset=UTF-8
On Wednesday, July 22, 2015 at 5:04:09 PM UTC-7, Thiago Macieira wrote:
>
> On Wednesday 22 July 2015 15:52:16 denis bider wrote:
> > There are many things one may want to implement in a destructor that can
> > fail - and the failure *is* actionable. A whole category of rollbacks -
> in
> > installers, in database transactions - is included in this.
>
> Please tell me of an uninstaller that rolls back when it runs into an
> error.
>
>
Visual Studio 2012-2015. They say "Creating system restore point..." at
the start of installation and uninstallation. That said, this is certainly
not implemented in terms of C++ destructor unwinding. Also, I'm on your
side on this one. =^-^=
Melissa
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_193_695353227.1437615426907
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, July 22, 2015 at 5:04:09 PM UTC-7, Thiago Ma=
cieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Wednesday 22 J=
uly 2015 15:52:16 denis bider wrote:
<br>> There are many things one may want to implement in a destructor th=
at can
<br>> fail - and the failure *is* actionable. A whole category of rollba=
cks - in
<br>> installers, in database transactions - is included in this.
<br>
<br>Please tell me of an uninstaller that rolls back when it runs into an e=
rror.
<br>
<br></blockquote><div><br>Visual Studio 2012-2015.=C2=A0 They say "Cre=
ating system restore point..." at the start of installation and uninst=
allation.=C2=A0 That said, this is certainly not implemented in terms of C+=
+ destructor unwinding.=C2=A0 Also, I'm on your side on this one. =3D^-=
^=3D<br><br>Melissa<br><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_193_695353227.1437615426907--
------=_Part_192_873626352.1437615426907--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Wed, 22 Jul 2015 18:43:22 -0700 (PDT)
Raw View
------=_Part_80_625691039.1437615802766
Content-Type: multipart/alternative;
boundary="----=_Part_81_1040293296.1437615802766"
------=_Part_81_1040293296.1437615802766
Content-Type: text/plain; charset=UTF-8
> Please tell me of an uninstaller that rolls back when it runs into an
error.
I am perplexed. This question sounds to me like: "Tell me of a car that has
wheels."
*All installers *must rollback when they run into an error.
Ours do: https://www.bitvise.com/
> That punts the problem to std::unique_ptr. Now the destructor
> of your sub-objects may be called while other sub-objects
> that should have been destroyed haven't yet.
That's how destruction works.
The only way this is an issue is if the 2+ resources you are freeing have
logical interdependencies in the destructor. In this case, you need to
implement destruction properly.
The code you provided does not need multi-exceptions to be incorrect. It is
already incorrect in C++11 if a1 destructor is noexcept(false).
> But that contradicts the previous part of your proposal:
> the part that says that the destructor must continue destruction
> of the sub-objects when one throws and then aggregate exceptions.
It seems evident that this would only be the case if the destructor is *declared
*to throw. This declaration may be explicit or implicit, according to the
rules of the language, as they might be. But if the destructor is
noexcept, then logically std::terminate should be called.
> But it's a change in behaviour, with increased memory pressure,
> for something that is not in use today.
If we keep existing rules for how destructors' noexcept declarations are
determined, there is no change of behavior unless you *actually use *destructors
declared noexcept(false).
Even if you have destructors declared noexcept(false), there is still no
need for additional cost unless you also implement *catch-any* handlers to
handle multi-exceptions.
If your program does not implement any catch-any handlers, then
multi-exception support can again be fully optimized away, so that
std::terminate is called at the point where exceptions would be aggregated.
> That is, the following will continue execution and aggregate,
> with unmodified code:
>
> void f() { A a1, a2; }
I do not propose changes to existing behavior, so yes. If A::~A() throws
and is declared noexcept(false), that's how that snippet *already *behaves
in C++11 and 14.
An exception can already occur in either of those objects' destructors.
Both destructors will still be called.
What *can't *happen right now is that those exceptions cannot aggregate,
and the destructors cannot *both *throw. But either of them can.
On Wednesday, July 22, 2015 at 6:04:09 PM UTC-6, Thiago Macieira wrote:
> On Wednesday 22 July 2015 15:52:16 denis bider wrote:
> > There are many things one may want to implement in a destructor that can
> > fail - and the failure *is* actionable. A whole category of rollbacks -
> in
> > installers, in database transactions - is included in this.
>
> Please tell me of an uninstaller that rolls back when it runs into an
> error.
>
> > > => Starting testcase:
> > >
> > > struct A { ~A() { throw 42; } };
> > > struct B { A a1, a2; }
> > >
> > > When ~B runs, a1.~A() would throw, the exception would be queued,
> > > then the execution continues at a2.~A() would be executed
> > > (and throw again).
> >
> > Yes. You get two aggregated exceptions. You can handle them. The object
> is
> > destroyed properly.
> >
> > I don't see anything wrong with this case.
>
> This was only the starting point. It gets more complex after this.
>
> >
> > > => Modifying:
> > >
> > > struct C { A *a1, *a2; C(); ~C() { delete a1; delete a2; } };
> > >
> > > Now the same thing happens when a1->~A() throws, but instead of
> > > continuing in compiler-generated code, this must continue on user
> code.
> > >
> > > You may suggest that one should be using smart pointers
> > > (std::unique_ptr) in this, but then we begin involving a third
> > > place where code gets executed.
> >
> > What you show above is a poor destructor implementation. Yes, you should
> > definitely be using std::unique_ptr or an equivalent.
>
> That punts the problem to std::unique_ptr. Now the destructor of your sub-
> objects may be called while other sub-objects that should have been
> destroyed
> haven't yet.
>
> > This is not substantially different than the above example. "dispose" is
> > not a noexcept function. If the destructor is ignorant of the "dispose"
> > implementation - which is what you assume to make your point - this code
> is
> > already bad *currently*.
> >
> > > This violates the requirement that you don't pay for features you
> don't
> > > use.
> >
> > My proposal imposes no such cost. If all destructors in your code are
> > noexcept, all multi-exception support can be safely optimized away.
> >
> > No additional handling code is necessary unless you *want* to support
> > throwing destructors.
>
> I see what you mean. You're saying that unless I want to handle aggregated
> exceptions, I don't have to. So if a destructor throws in my destructor, I
> can
> let it, like today, trigger std::terminate().
>
> But that contradicts the previous part of your proposal: the part that
> says
> that the destructor must continue destruction of the sub-objects when one
> throws and then aggregate exceptions.
>
> We may argue whether this is currently bad code or not. But it's a change
> in
> behaviour, with increased memory pressure, for something that is not in
> use
> today.
>
> I assume that you're also saying that this should apply to any stack
> unwinding
> code, not just the destructor's sub-object destruction. That is, the
> following
> will continue execution and aggregate, with unmodified code:
>
> void f()
> {
> A a1, a2;
> }
>
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
> PGP/GPG: 0x6EF45358; fingerprint:
> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
>
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_81_1040293296.1437615802766
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>> Please tell me of an uninstaller that rolls back=
when it runs into an error. <br></div><div><br></div><div>I am perplexed. =
This question sounds to me like:=C2=A0"Tell me of a car that has wheel=
s."</div><div><br></div><div><strong>All installers </strong>must roll=
back when they run into an error.</div><div><br></div><div>Ours do: <a href=
=3D"https://www.bitvise.com/">https://www.bitvise.com/</a></div><div><br></=
div><div><br></div><div>> That punts the problem to std::unique_ptr. Now=
the destructor</div><div>> of your sub-objects may be called while othe=
r sub-objects</div><div>> that should have been destroyed=C2=A0haven'=
;t yet. </div><div><br></div><div>That's how destruction works.</div><d=
iv><br></div><div>The only way this is an issue is if the 2+ resources you =
are freeing have logical interdependencies in the destructor. In this case,=
you need to implement destruction properly.</div><div><br></div><div>The c=
ode you provided does not need multi-exceptions to be incorrect. It is alre=
ady incorrect in C++11 if a1 destructor is noexcept(false).</div><div><br><=
/div><div><br></div><div>> But that contradicts the previous part of you=
r proposal:</div><div>> the part that says=C2=A0that the destructor must=
continue destruction</div><div>> of the sub-objects when one=C2=A0throw=
s and then aggregate exceptions. </div><div><br></div><div>It seems evident=
that this would only be the case if the destructor is=C2=A0<em>declared </=
em>to throw.=C2=A0This declaration may be explicit or implicit, according t=
o the rules of the language, as they might be. But if the destructor is noe=
xcept,=C2=A0then=C2=A0logically std::terminate should be called.</div><div>=
<br></div><div><br></div><div>> But it's a change in=C2=A0behaviour,=
with increased memory pressure,</div><div>> for something that is not i=
n use=C2=A0today. <br></div><div><br></div><div>If we keep existing rules f=
or how destructors' noexcept declarations are determined, there is no c=
hange of behavior unless you <em>actually use </em>destructors declared noe=
xcept(false).</div><div><br></div><div>Even if you have destructors declare=
d noexcept(false), there is still no need for additional cost unless you al=
so implement <em>catch-any</em> handlers to handle multi-exceptions.</div><=
div><br></div><div>If your program=C2=A0does not implement any catch-any ha=
ndlers, then multi-exception support can again be fully optimized away, so =
that std::terminate is called at the point where exceptions would be aggreg=
ated.</div><div><br></div><div><br></div><div>> That is, the following=
=C2=A0=C2=A0will continue execution and aggregate,</div><div>> with unmo=
dified code: <br>><br>> void f() {=C2=A0 A a1, a2; } <br><br></div><d=
iv>I do not propose changes to existing behavior, so yes. If A::~A() throws=
and is declared noexcept(false), that's how that snippet <em>already <=
/em>behaves in C++11 and 14.</div><div><br></div><div>An exception can alre=
ady occur in either of those objects' destructors. Both destructors wil=
l still be called.</div><div><br></div><div>What <em>can't </em>happen =
right now is that those exceptions cannot aggregate, and the destructors ca=
nnot <em>both </em>throw. But either of them can.</div><div><br></div><div>=
<br><br>On Wednesday, July 22, 2015 at 6:04:09 PM UTC-6, Thiago Macieira wr=
ote:</div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.=
8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-=
width: 1px; border-left-style: solid;">On Wednesday 22 July 2015 15:52:16 d=
enis bider wrote:
<br>> There are many things one may want to implement in a destructor th=
at can
<br>> fail - and the failure *is* actionable. A whole category of rollba=
cks - in
<br>> installers, in database transactions - is included in this.
<br>
<br>Please tell me of an uninstaller that rolls back when it runs into an e=
rror.
<br>
<br>> > =3D> Starting testcase:
<br>> >=20
<br>> > struct A { ~A() { throw 42; } };
<br>> > struct B { A a1, a2; }
<br>> >=20
<br>> > When ~B runs, a1.~A() would throw, the exception would be que=
ued,
<br>> > then the =C2=A0execution continues at a2.~A() would be execut=
ed
<br>> > (and throw again).
<br>>=20
<br>> Yes. You get two aggregated exceptions. You can handle them. The o=
bject is
<br>> destroyed properly.
<br>>=20
<br>> I don't see anything wrong with this case.
<br>
<br>This was only the starting point. It gets more complex after this.
<br>
<br>>=20
<br>> > =3D> Modifying:
<br>> >=20
<br>> > struct C { A *a1, *a2; C(); ~C() { delete a1; delete a2; } };
<br>> >=20
<br>> > Now the same thing happens when a1->~A() throws, but inste=
ad of
<br>> > continuing in compiler-generated code, this must continue on =
user code.
<br>> >=20
<br>> > You may suggest that one should be using smart pointers
<br>> > (std::unique_ptr) in this, but then we begin involving a thir=
d
<br>> > place where code gets executed.
<br>>=20
<br>> What you show above is a poor destructor implementation. Yes, you =
should
<br>> definitely be using std::unique_ptr or an equivalent.
<br>
<br>That punts the problem to std::unique_ptr. Now the destructor of your s=
ub-
<br>objects may be called while other sub-objects that should have been des=
troyed=20
<br>haven't yet.
<br>
<br>> This is not substantially different than the above example. "=
dispose" is
<br>> not a noexcept function. If the destructor is ignorant of the &quo=
t;dispose"
<br>> implementation - which is what you assume to make your point - thi=
s code is
<br>> already bad *currently*.
<br>>
<br>> > This violates the requirement that you don't pay for feat=
ures you don't
<br>> > use.
<br>>=20
<br>> My proposal imposes no such cost. If all destructors in your code =
are
<br>> noexcept, all multi-exception support can be safely optimized away=
..
<br>>=20
<br>> No additional handling code is necessary unless you *want* to supp=
ort
<br>> throwing destructors.
<br>
<br>I see what you mean. You're saying that unless I want to handle agg=
regated=20
<br>exceptions, I don't have to. So if a destructor throws in my destru=
ctor, I can=20
<br>let it, like today, trigger std::terminate().
<br>
<br>But that contradicts the previous part of your proposal: the part that =
says=20
<br>that the destructor must continue destruction of the sub-objects when o=
ne=20
<br>throws and then aggregate exceptions.
<br>
<br>We may argue whether this is currently bad code or not. But it's a =
change in=20
<br>behaviour, with increased memory pressure, for something that is not in=
use=20
<br>today.
<br>
<br>I assume that you're also saying that this should apply to any stac=
k unwinding=20
<br>code, not just the destructor's sub-object destruction. That is, th=
e following=20
<br>will continue execution and aggregate, with unmodified code:
<br>
<br>void f()
<br>{
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0A a1, a2;
<br>}
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a onmousedown=3D"this.href=3D'http:/=
/www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\75D\46sntz\0751\46u=
sg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.=
href=3D'http://www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\7=
5D\46sntz\0751\46usg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;=
" href=3D"http://macieira.info" target=3D"_blank" rel=3D"nofollow">macieira=
..info</a> - thiago (AT) <a onmousedown=3D"this.href=3D'http://www.googl=
e.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\75AFQjCNHGRJd=
o5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'http=
://www.google.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\7=
5AFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;" href=3D"http://kde.o=
rg" target=3D"_blank" rel=3D"nofollow">kde.org</a>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>=C2=A0 =C2=A0 =C2=A0 PGP/GPG: 0x6EF45358; fingerprint:
<br>=C2=A0 =C2=A0 =C2=A0 E067 918B B660 DBD1 105C =C2=A0966C 33F5 F005 6EF4=
5358
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_81_1040293296.1437615802766--
------=_Part_80_625691039.1437615802766--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Wed, 22 Jul 2015 18:57:32 -0700 (PDT)
Raw View
------=_Part_61_1376467364.1437616652442
Content-Type: multipart/alternative;
boundary="----=_Part_62_2056717430.1437616652443"
------=_Part_62_2056717430.1437616652443
Content-Type: text/plain; charset=UTF-8
> But making destructors complex and throwing means you
> need to *manually* handle the cleanup. Therefore, allowing
> them to be "regular functions" would make them that much
> more complex.
But this is trivially avoided by not mixing resource-release destructors
with complex destructors.
A destructor should either be of:
(1) a simple resource-release kind (which already may or may not throw); or
(2) the complex function kind (which already may or may not throw).
The complex kind of destructor should be implemented in a class that has no
resources that need explicit freeing.
That does not mean it can't have resources. It can have many resources
freed by sub-objects, e.g. in containers or unique_ptr.
> You're arguing that destructors should be allowed
> to be complex and therefore throw at the same time
> you're arguing that destructors should be simple and
> do one thing.
Resource-release destructors should be simple and should do one thing.
Complex destructors can be complex, but should not try to be
resource-release destructors at the same time.
Note that I do believe resource-release destructors should be able to throw
exceptions, also. Even if they are simple.
> > You proposed a dispose() implementation that is unsafe in C++ as-is.
> Only if the destructor throws. Since they currently don't, it has no
problem.
You have no such assurance unless you test for it.
> You're starting from a clean slate or only after everyone
> (at least the Standard Library) has cleaned up their code to
> handle throwing destructors and aggregation of exceptions.
It would be sufficient for the Standard Library to simply declare it does
not support throwing destructors, by requiring std::is_nothrow_destructible.
To the extent I need containers for objects that aren't nothrow
destructible, I can provide my own.
On Wednesday, July 22, 2015 at 6:17:26 PM UTC-6, Thiago Macieira wrote:
> On Wednesday 22 July 2015 16:49:16 denis bider wrote:
> > It seems to me what you're implying is that the average C++ developer is
> > incapable of writing destructors that work properly in the face of
> > exceptions.
>
> Yes. Your argument is that destructors should be treated like any other
> function. Yet any other function is usually *not* a trivial method doing
> exactly one thing -- freeing a resource. Your average function is a
> complex
> beast.
>
> Destructors today, with the requirement to attempt to be noexcept, are
> hard to
> write. Developers today rely on exceptions to clean up RAII objects
> properly.
> But making destructors complex and throwing means you need to *manually*
> handle the cleanup. Therefore, allowing them to be "regular functions"
> would
> make them that much more complex.
>
> And your average C++ developer can't write a regular function that handles
> exceptions already.
>
> So, no, the average C++ developer will not be able to write a destructor
> that
> works properly in the fact of exceptions.
>
> What's more, you're contradicting yourself. You're arguing that
> destructors
> should be allowed to be complex and therefore throw at the same time
> you're
> arguing that destructors should be simple and do one thing.
>
> > You proposed a dispose() implementation that is unsafe in C++ as-is.
>
> Only if the destructor throws. Since they currently don't, it has no
> problem.
> And if it accidentally did after promising it wouldn't, the application
> would
> terminate.
>
> Besides, the function is an oversimplification of existing code that calls
> destructors, like std::vector's own destructor.
>
> I'm starting from the point that there is a sizeable codebase which
> assumes
> destructors don't throw. You're starting from a clean slate or only after
> everyone (at least the Standard Library) has cleaned up their code to
> handle
> throwing destructors and aggregation of exceptions.
>
> > My issue is that this is a compromise in favor of the less competent,
> which
> > restricts the language and makes it less expressive. It imposes
> limitations
> > on *everyone*, in order to benefit beginners.
> >
> > I think C++ should be beginner friendly, but without this type of
> > compromise.
>
> I get you, but even if we ignore this part of the discussion and that of
> policy, there's still the problem of allocating memory as a response to
> having
> no memory available.
>
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
> PGP/GPG: 0x6EF45358; fingerprint:
> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
>
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_62_2056717430.1437616652443
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>> But making destructors complex and throwing mean=
s you</div><div>> need to *manually*=C2=A0handle the cleanup. Therefore,=
allowing</div><div>> them to be "regular functions" would=C2=
=A0make them that much</div><div>> more complex. </div><div><br></div><d=
iv>But this is trivially avoided by not mixing resource-release destructors=
with complex destructors.</div><div><br></div><div>A destructor should eit=
her be of:</div><div><br></div><div>(1) a simple resource-release kind (whi=
ch already may or may not throw); or</div><div><br></div><div>(2) the compl=
ex function kind (which already may or may not throw).</div><div><br></div>=
<div>The complex kind of destructor should be implemented in a class that h=
as no resources that need explicit freeing.</div><div><br></div><div>That d=
oes not mean it can't have resources. It can have many resources freed =
by sub-objects, e.g. in containers or unique_ptr.</div><div><br></div><div>=
<br></div><div>>=C2=A0 You're arguing that destructors=C2=A0should b=
e allowed</div><div>> to be complex and therefore throw at the same time=
</div><div>> you're=C2=A0arguing that destructors should be simple a=
nd</div><div>> do one thing. </div><div><br></div><div>Resource-release =
destructors should be simple and should do one thing.</div><div><br></div><=
div>Complex destructors can be complex, but should not try to be resource-r=
elease destructors at the same time.</div><div><br></div><div>Note that I d=
o believe resource-release destructors should be able to throw exceptions, =
also. Even if they are simple.</div><div><br></div><div><br></div><div>>=
> You proposed a dispose() implementation that is unsafe in C++ as-is. =
<br>> Only if the destructor throws. Since they currently don't, it =
has no problem.=C2=A0 </div><div><br></div><div>You have no such assurance =
unless you test for it.</div><div><br></div><div><br></div><div>> You=
9;re starting from a clean slate or only after=C2=A0everyone</div><div>>=
(at least the Standard Library) has cleaned up their code to</div><div>>=
; handle=C2=A0throwing destructors and aggregation of exceptions. </div><di=
v><br></div><div>It would be sufficient for the Standard Library to simply =
declare it does not support throwing destructors, by=C2=A0requiring std::is=
_nothrow_destructible.</div><div><br></div><div>To the extent I need contai=
ners for objects that aren't nothrow destructible, I can provide my own=
..<br></div><div><br></div><div><br></div><div><br>On Wednesday, July 22, 20=
15 at 6:17:26 PM UTC-6, Thiago Macieira wrote:</div><blockquote class=3D"gm=
ail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-le=
ft-color: rgb(204, 204, 204); border-left-width: 1px; border-left-style: so=
lid;">On Wednesday 22 July 2015 16:49:16 denis bider wrote:
<br>> It seems to me what you're implying is that the average C++ de=
veloper is=20
<br>> incapable of writing destructors that work properly in the face of=
=20
<br>> exceptions.=20
<br>
<br>Yes. Your argument is that destructors should be treated like any other=
=20
<br>function. Yet any other function is usually *not* a trivial method doin=
g=20
<br>exactly one thing -- freeing a resource. Your average function is a com=
plex=20
<br>beast.
<br>
<br>Destructors today, with the requirement to attempt to be noexcept, are =
hard to=20
<br>write. Developers today rely on exceptions to clean up RAII objects pro=
perly.=20
<br>But making destructors complex and throwing means you need to *manually=
*=20
<br>handle the cleanup. Therefore, allowing them to be "regular functi=
ons" would=20
<br>make them that much more complex.
<br>
<br>And your average C++ developer can't write a regular function that =
handles=20
<br>exceptions already.
<br>
<br>So, no, the average C++ developer will not be able to write a destructo=
r that=20
<br>works properly in the fact of exceptions.
<br>
<br>What's more, you're contradicting yourself. You're arguing =
that destructors=20
<br>should be allowed to be complex and therefore throw at the same time yo=
u're=20
<br>arguing that destructors should be simple and do one thing.
<br>
<br>> You proposed a dispose() implementation that is unsafe in C++ as-i=
s.
<br>
<br>Only if the destructor throws. Since they currently don't, it has n=
o problem.=20
<br>And if it accidentally did after promising it wouldn't, the applica=
tion would=20
<br>terminate.
<br>
<br>Besides, the function is an oversimplification of existing code that ca=
lls=20
<br>destructors, like std::vector's own destructor.
<br>
<br>I'm starting from the point that there is a sizeable codebase which=
assumes=20
<br>destructors don't throw. You're starting from a clean slate or =
only after=20
<br>everyone (at least the Standard Library) has cleaned up their code to h=
andle=20
<br>throwing destructors and aggregation of exceptions.
<br>
<br>> My issue is that this is a compromise in favor of the less compete=
nt, which
<br>> restricts the language and makes it less expressive. It imposes li=
mitations
<br>> on *everyone*, in order to benefit beginners.
<br>>=20
<br>> I think C++ should be beginner friendly, but without this type of
<br>> compromise.
<br>
<br>I get you, but even if we ignore this part of the discussion and that o=
f=20
<br>policy, there's still the problem of allocating memory as a respons=
e to having=20
<br>no memory available.
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a onmousedown=3D"this.href=3D'http:/=
/www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\75D\46sntz\0751\46u=
sg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.=
href=3D'http://www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\7=
5D\46sntz\0751\46usg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;=
" href=3D"http://macieira.info" target=3D"_blank" rel=3D"nofollow">macieira=
..info</a> - thiago (AT) <a onmousedown=3D"this.href=3D'http://www.googl=
e.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\75AFQjCNHGRJd=
o5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'http=
://www.google.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\7=
5AFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;" href=3D"http://kde.o=
rg" target=3D"_blank" rel=3D"nofollow">kde.org</a>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>=C2=A0 =C2=A0 =C2=A0 PGP/GPG: 0x6EF45358; fingerprint:
<br>=C2=A0 =C2=A0 =C2=A0 E067 918B B660 DBD1 105C =C2=A0966C 33F5 F005 6EF4=
5358
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_62_2056717430.1437616652443--
------=_Part_61_1376467364.1437616652442--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Wed, 22 Jul 2015 19:05:48 -0700 (PDT)
Raw View
------=_Part_74_1830115676.1437617148653
Content-Type: multipart/alternative;
boundary="----=_Part_75_1344478456.1437617148661"
------=_Part_75_1344478456.1437617148661
Content-Type: text/plain; charset=UTF-8
> I get you, but even if we ignore this part of the discussion
> and that of policy, there's still the problem of allocating
> memory as a response to having no memory available.
I have addressed this problem.
If you don't want to use multi-exceptions:
(1) Simply don't implement any catch-any handlers in your program, and
allow multi-exception support to be fully optimized away.
If you do want to use multi-exceptions:
(2) Reserve memory upfront with a function like
std::reserve_exception_memory().
(3) If you don't want to do that, call std::can_throw<T>() before actually
throwing from a destructor. Currently, you have to call
std::uncaught_exception(). Same concept.
(4) If you don't want to do that either - risk your program being
std::terminated if you run out of memory.
I don't see where you see an issue.
On Wednesday, July 22, 2015 at 6:17:26 PM UTC-6, Thiago Macieira wrote:
> On Wednesday 22 July 2015 16:49:16 denis bider wrote:
> > It seems to me what you're implying is that the average C++ developer is
> > incapable of writing destructors that work properly in the face of
> > exceptions.
>
> Yes. Your argument is that destructors should be treated like any other
> function. Yet any other function is usually *not* a trivial method doing
> exactly one thing -- freeing a resource. Your average function is a
> complex
> beast.
>
> Destructors today, with the requirement to attempt to be noexcept, are
> hard to
> write. Developers today rely on exceptions to clean up RAII objects
> properly.
> But making destructors complex and throwing means you need to *manually*
> handle the cleanup. Therefore, allowing them to be "regular functions"
> would
> make them that much more complex.
>
> And your average C++ developer can't write a regular function that handles
> exceptions already.
>
> So, no, the average C++ developer will not be able to write a destructor
> that
> works properly in the fact of exceptions.
>
> What's more, you're contradicting yourself. You're arguing that
> destructors
> should be allowed to be complex and therefore throw at the same time
> you're
> arguing that destructors should be simple and do one thing.
>
> > You proposed a dispose() implementation that is unsafe in C++ as-is.
>
> Only if the destructor throws. Since they currently don't, it has no
> problem.
> And if it accidentally did after promising it wouldn't, the application
> would
> terminate.
>
> Besides, the function is an oversimplification of existing code that calls
> destructors, like std::vector's own destructor.
>
> I'm starting from the point that there is a sizeable codebase which
> assumes
> destructors don't throw. You're starting from a clean slate or only after
> everyone (at least the Standard Library) has cleaned up their code to
> handle
> throwing destructors and aggregation of exceptions.
>
> > My issue is that this is a compromise in favor of the less competent,
> which
> > restricts the language and makes it less expressive. It imposes
> limitations
> > on *everyone*, in order to benefit beginners.
> >
> > I think C++ should be beginner friendly, but without this type of
> > compromise.
>
> I get you, but even if we ignore this part of the discussion and that of
> policy, there's still the problem of allocating memory as a response to
> having
> no memory available.
>
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
> PGP/GPG: 0x6EF45358; fingerprint:
> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
>
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_75_1344478456.1437617148661
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>> I get you, but even if we ignore this part of th=
e discussion</div><div>> and that of=C2=A0policy, there's still the =
problem of allocating</div><div>> memory as a response to having=C2=A0no=
memory available. </div><div><br></div><div>I have addressed this problem.=
</div><div><br></div><div>If you don't want to use multi-exceptions:</d=
iv><div><br></div><div>(1) Simply don't implement any catch-any handler=
s in your program, and allow multi-exception support to be fully optimized =
away.</div><div><br></div><div>If you do want to use multi-exceptions:</div=
><div><br></div><div>(2) Reserve memory upfront with a function like std::r=
eserve_exception_memory().</div><div><br></div><div>(3) If you don't wa=
nt to do that, call std::can_throw<T>() before actually throwing from=
a destructor.=C2=A0Currently, you have to call std::uncaught_exception(). =
Same concept.</div><div><br></div><div>(4) If you don't want to do that=
either -=C2=A0risk your program being std::terminated if you run out of me=
mory.</div><div><br></div><div>I don't see where you see an issue.</div=
><div><br><br>On Wednesday, July 22, 2015 at 6:17:26 PM UTC-6, Thiago Macie=
ira wrote:</div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px =
0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border=
-left-width: 1px; border-left-style: solid;">On Wednesday 22 July 2015 16:4=
9:16 denis bider wrote:
<br>> It seems to me what you're implying is that the average C++ de=
veloper is=20
<br>> incapable of writing destructors that work properly in the face of=
=20
<br>> exceptions.=20
<br>
<br>Yes. Your argument is that destructors should be treated like any other=
=20
<br>function. Yet any other function is usually *not* a trivial method doin=
g=20
<br>exactly one thing -- freeing a resource. Your average function is a com=
plex=20
<br>beast.
<br>
<br>Destructors today, with the requirement to attempt to be noexcept, are =
hard to=20
<br>write. Developers today rely on exceptions to clean up RAII objects pro=
perly.=20
<br>But making destructors complex and throwing means you need to *manually=
*=20
<br>handle the cleanup. Therefore, allowing them to be "regular functi=
ons" would=20
<br>make them that much more complex.
<br>
<br>And your average C++ developer can't write a regular function that =
handles=20
<br>exceptions already.
<br>
<br>So, no, the average C++ developer will not be able to write a destructo=
r that=20
<br>works properly in the fact of exceptions.
<br>
<br>What's more, you're contradicting yourself. You're arguing =
that destructors=20
<br>should be allowed to be complex and therefore throw at the same time yo=
u're=20
<br>arguing that destructors should be simple and do one thing.
<br>
<br>> You proposed a dispose() implementation that is unsafe in C++ as-i=
s.
<br>
<br>Only if the destructor throws. Since they currently don't, it has n=
o problem.=20
<br>And if it accidentally did after promising it wouldn't, the applica=
tion would=20
<br>terminate.
<br>
<br>Besides, the function is an oversimplification of existing code that ca=
lls=20
<br>destructors, like std::vector's own destructor.
<br>
<br>I'm starting from the point that there is a sizeable codebase which=
assumes=20
<br>destructors don't throw. You're starting from a clean slate or =
only after=20
<br>everyone (at least the Standard Library) has cleaned up their code to h=
andle=20
<br>throwing destructors and aggregation of exceptions.
<br>
<br>> My issue is that this is a compromise in favor of the less compete=
nt, which
<br>> restricts the language and makes it less expressive. It imposes li=
mitations
<br>> on *everyone*, in order to benefit beginners.
<br>>=20
<br>> I think C++ should be beginner friendly, but without this type of
<br>> compromise.
<br>
<br>I get you, but even if we ignore this part of the discussion and that o=
f=20
<br>policy, there's still the problem of allocating memory as a respons=
e to having=20
<br>no memory available.
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a onmousedown=3D"this.href=3D'http:/=
/www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\75D\46sntz\0751\46u=
sg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.=
href=3D'http://www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\7=
5D\46sntz\0751\46usg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;=
" href=3D"http://macieira.info" target=3D"_blank" rel=3D"nofollow">macieira=
..info</a> - thiago (AT) <a onmousedown=3D"this.href=3D'http://www.googl=
e.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\75AFQjCNHGRJd=
o5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'http=
://www.google.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\7=
5AFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;" href=3D"http://kde.o=
rg" target=3D"_blank" rel=3D"nofollow">kde.org</a>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>=C2=A0 =C2=A0 =C2=A0 PGP/GPG: 0x6EF45358; fingerprint:
<br>=C2=A0 =C2=A0 =C2=A0 E067 918B B660 DBD1 105C =C2=A0966C 33F5 F005 6EF4=
5358
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_75_1344478456.1437617148661--
------=_Part_74_1830115676.1437617148653--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Wed, 22 Jul 2015 23:03:54 -0700
Raw View
On Wednesday 22 July 2015 18:57:32 denis bider wrote:
> But this is trivially avoided by not mixing resource-release destructors
> with complex destructors.
>
> A destructor should either be of:
>
> (1) a simple resource-release kind (which already may or may not throw); or
>
> (2) the complex function kind (which already may or may not throw).
>
> The complex kind of destructor should be implemented in a class that has no
> resources that need explicit freeing.
>
> That does not mean it can't have resources. It can have many resources
> freed by sub-objects, e.g. in containers or unique_ptr.
So if we need rules to make this work, why can't we simply establish a rule
that there should be a throwing function that is supposed to flush resources,
separate from the function that frees the resources (the destructor)?
> > You're arguing that destructors should be allowed
> > to be complex and therefore throw at the same time
> > you're arguing that destructors should be simple and
> > do one thing.
>
> Resource-release destructors should be simple and should do one thing.
>
> Complex destructors can be complex, but should not try to be
> resource-release destructors at the same time.
Yeah, that sounds like two types of functions to me and we should not mix by
calling both of them "destructors".
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Wed, 22 Jul 2015 23:06:52 -0700
Raw View
On Wednesday 22 July 2015 19:05:48 denis bider wrote:
> > I get you, but even if we ignore this part of the discussion
> > and that of policy, there's still the problem of allocating
> > memory as a response to having no memory available.
>
> I have addressed this problem.
>
> If you don't want to use multi-exceptions:
>
> (1) Simply don't implement any catch-any handlers in your program, and
> allow multi-exception support to be fully optimized away.
>
> If you do want to use multi-exceptions:
>
[cut]
>
> I don't see where you see an issue.
How about case 3: I don't care about multi-exceptions, but I'm using a library
that may or may not be using doing it?
Do I have to reserve memory? Or should the library reserve?
Is the reservation global? What happens if third library also needs it and
reserves too?
Finally, what happens if I don't care about multi-exceptions but I get thrown
them? Does my code need modification? Will it behave differently in my catch
handler?
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Wed, 22 Jul 2015 23:25:11 -0700
Raw View
On Wednesday 22 July 2015 18:43:22 denis bider wrote:
> > Please tell me of an uninstaller that rolls back when it runs into an
>
> error.
>
> I am perplexed. This question sounds to me like: "Tell me of a car that has
> wheels."
>
> *All installers *must rollback when they run into an error.
>
> Ours do: https://www.bitvise.com/
I said *uninstaller*. What do you do when you've removed some files, then
something failed? Let's say a filesystem corruption prevents you from removing
certain files, how do you roll back? Do you put the files you had already
removed back in?
Moving to the C++ case: if a sub-object destruction fails, do the previously
destroyed object get re-constructed? That's impossible. In fact, your proposal
is that we ignore the problem and continue destruction.
So it wouldn't be like the uninstaller rollback. It would be like an
uninstaller powering through and leaving an unclean state behind.
> > That punts the problem to std::unique_ptr. Now the destructor
> > of your sub-objects may be called while other sub-objects
> > that should have been destroyed haven't yet.
>
> That's how destruction works.
>
> The only way this is an issue is if the 2+ resources you are freeing have
> logical interdependencies in the destructor. In this case, you need to
> implement destruction properly.
Which gets tricky very quickly, not to mention the fact that some of them
might be partially destroyed and thus in an invalid state.
> The code you provided does not need multi-exceptions to be incorrect. It is
> already incorrect in C++11 if a1 destructor is noexcept(false).
Which, like I said, the destructor is not supposed to be. A noexcept(false)
destructor today is considered, by itself, a problem. Everything using
destructors assumes a contract that they don't throw. A noexcept(false)y
constructor is therefore a contract violation.
> > But it's a change in behaviour, with increased memory pressure,
> > for something that is not in use today.
>
> If we keep existing rules for how destructors' noexcept declarations are
> determined, there is no change of behavior unless you *actually use
> *destructors declared noexcept(false).
So there's a change of behaviour to existing code.
> Even if you have destructors declared noexcept(false), there is still no
> need for additional cost unless you also implement *catch-any* handlers to
> handle multi-exceptions.
As we've agreed, noexcept(false) destructors will do additional work in the
exceptional case because they need to aggregate exceptions. Those destructors
exist today and will start paying for a feature they don't use,
Additionally, I'd expect that even noexcept destructors, for consistency,
should do destruction of all sub-objects, even if terminate() is coming. So
all destructors will start paying the price of this feature.
> If your program does not implement any catch-any handlers, then
> multi-exception support can again be fully optimized away, so that
> std::terminate is called at the point where exceptions would be aggregated.
That's not correct. Multi-exceptions are implicit because of destructors' sub-
object destruction.
> > That is, the following will continue execution and aggregate,
> > with unmodified code:
> >
> > void f() { A a1, a2; }
>
> I do not propose changes to existing behavior, so yes. If A::~A() throws
> and is declared noexcept(false), that's how that snippet *already *behaves
> in C++11 and 14.
But the point is that you are proposing changes to the code above! You may not
have explicitly said so, but it's a consequence of your proposal that
destructors aggregate.
Given:
struct B { A a1, a2; };
Then B's destructor must implement continuation-after-exception and
aggregation if a1.~A() throws. Given that this is the case, they I'd expect
that for consistency the function f above do the same.
And I also expect the destructor below to continue, even though it will
terminate() instead of throwing an aggregate exception:
struct C { A a1, a2; ~C() noexcept {} };
> An exception can already occur in either of those objects' destructors.
> Both destructors will still be called.
Not currently. Your proposal modifies this and that's the crux of the problem.
> What *can't *happen right now is that those exceptions cannot aggregate,
> and the destructors cannot *both *throw. But either of them can.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Thu, 23 Jul 2015 06:49:04 -0700 (PDT)
Raw View
------=_Part_630_1939033007.1437659344458
Content-Type: multipart/alternative;
boundary="----=_Part_631_1476475778.1437659344464"
------=_Part_631_1476475778.1437659344464
Content-Type: text/plain; charset=UTF-8
I would like to point out that, with minimal syntactic sugar,
multi-exceptions provide an easy way to handle code that may throw,
including in destructors.
Let's introduce two constructs, "try aggregate" and "try defer".
- "Try aggregate" starts a block in which there can be "try defer"
statements that aggregate exceptions.
- At the end of the "try aggregate" block, any accumulated exceptions are
thrown as a group.
- If there are no aggregated exceptions, execution continues.
Your example earlier was as follows:
struct D { A *a1, *a2; D(); ~D() { dispose(a1); dispose(a2); } };
template <typename T> void dispose(T *&ptr)
{
ptr->~T();
remove_from_siblings(ptr);
Allocator::dealloc(ptr);
}
As I mention, this is *currently* unsafe if A::~A() is noexcept(false).
This is how it *would* be safe with the "try defer" syntactic sugar. To
avoid introducing contextual keywords, I use "try+" for try defer,
and "try*" for try aggregate:
struct D {
A *a1, *a2;
D();
~D() {
try* {
try+ { dispose(a1); }
try+ { dispose(a2); }
}
}
};
template <typename T> void dispose(T *&ptr)
{
try* {
try+ { ptr->~T(); }
remove_from_siblings(ptr);
Allocator::dealloc(ptr);
}
}
This provides nice, clean, elegant syntax that makes throwing destructors
safe, and easy to handle.
Anyone can understand and safely use this syntax. Even beginners.
Now, to your continuing comments.
There are resolutions to most of the issues you raise. They are apparent
to one who *wants *to solve them. The issue is that you do not *want *that.
You want the opposite; to *not* solve them. You do not want to
acknowledge solutions I have already proposed. Some of the issues you raise
are repeated and *purposeful* misunderstandings.
For a technical argument to make sense, *there must be a reasonable way* I
can find a solution. You *must* be open to my proposal in at least *some
reasonable* scenario. You have to not move your goal posts. If there is no
scenario in which you're open to my proposal, or if you keep moving goal
posts, then a technical argument is a waste of time. It just comes down to
a vote of who is for, and who's against; and whoever has the majority will
prevail.
On Thursday, July 23, 2015 at 12:25:15 AM UTC-6, Thiago Macieira wrote:
> On Wednesday 22 July 2015 18:43:22 denis bider wrote:
> > > Please tell me of an uninstaller that rolls back when it runs into an
> >
> > error.
> >
> > I am perplexed. This question sounds to me like: "Tell me of a car that
> has
> > wheels."
> >
> > *All installers *must rollback when they run into an error.
> >
> > Ours do: https://www.bitvise.com/
>
> I said *uninstaller*. What do you do when you've removed some files, then
> something failed? Let's say a filesystem corruption prevents you from
> removing
> certain files, how do you roll back? Do you put the files you had already
> removed back in?
>
> Moving to the C++ case: if a sub-object destruction fails, do the
> previously
> destroyed object get re-constructed? That's impossible. In fact, your
> proposal
> is that we ignore the problem and continue destruction.
>
> So it wouldn't be like the uninstaller rollback. It would be like an
> uninstaller powering through and leaving an unclean state behind.
>
> > > That punts the problem to std::unique_ptr. Now the destructor
> > > of your sub-objects may be called while other sub-objects
> > > that should have been destroyed haven't yet.
> >
> > That's how destruction works.
> >
> > The only way this is an issue is if the 2+ resources you are freeing
> have
> > logical interdependencies in the destructor. In this case, you need to
> > implement destruction properly.
>
> Which gets tricky very quickly, not to mention the fact that some of them
> might be partially destroyed and thus in an invalid state.
>
> > The code you provided does not need multi-exceptions to be incorrect. It
> is
> > already incorrect in C++11 if a1 destructor is noexcept(false).
>
> Which, like I said, the destructor is not supposed to be. A
> noexcept(false)
> destructor today is considered, by itself, a problem. Everything using
> destructors assumes a contract that they don't throw. A noexcept(false)y
> constructor is therefore a contract violation.
>
> > > But it's a change in behaviour, with increased memory pressure,
> > > for something that is not in use today.
> >
> > If we keep existing rules for how destructors' noexcept declarations are
> > determined, there is no change of behavior unless you *actually use
> > *destructors declared noexcept(false).
>
> So there's a change of behaviour to existing code.
>
> > Even if you have destructors declared noexcept(false), there is still no
> > need for additional cost unless you also implement *catch-any* handlers
> to
> > handle multi-exceptions.
>
> As we've agreed, noexcept(false) destructors will do additional work in
> the
> exceptional case because they need to aggregate exceptions. Those
> destructors
> exist today and will start paying for a feature they don't use,
>
> Additionally, I'd expect that even noexcept destructors, for consistency,
> should do destruction of all sub-objects, even if terminate() is coming.
> So
> all destructors will start paying the price of this feature.
>
> > If your program does not implement any catch-any handlers, then
> > multi-exception support can again be fully optimized away, so that
> > std::terminate is called at the point where exceptions would be
> aggregated.
>
> That's not correct. Multi-exceptions are implicit because of destructors'
> sub-
> object destruction.
>
> > > That is, the following will continue execution and aggregate,
> > > with unmodified code:
> > >
> > > void f() { A a1, a2; }
> >
> > I do not propose changes to existing behavior, so yes. If A::~A() throws
> > and is declared noexcept(false), that's how that snippet *already
> *behaves
> > in C++11 and 14.
>
> But the point is that you are proposing changes to the code above! You may
> not
> have explicitly said so, but it's a consequence of your proposal that
> destructors aggregate.
>
> Given:
>
> struct B { A a1, a2; };
>
> Then B's destructor must implement continuation-after-exception and
> aggregation if a1.~A() throws. Given that this is the case, they I'd
> expect
> that for consistency the function f above do the same.
>
> And I also expect the destructor below to continue, even though it will
> terminate() instead of throwing an aggregate exception:
>
> struct C { A a1, a2; ~C() noexcept {} };
>
> > An exception can already occur in either of those objects' destructors.
> > Both destructors will still be called.
>
> Not currently. Your proposal modifies this and that's the crux of the
> problem.
>
> > What *can't *happen right now is that those exceptions cannot aggregate,
> > and the destructors cannot *both *throw. But either of them can.
>
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
> PGP/GPG: 0x6EF45358; fingerprint:
> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
>
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_631_1476475778.1437659344464
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div><div>I would like to point out that, with minimal syn=
tactic sugar, multi-exceptions provide an easy way to handle code that may =
throw, including in destructors.</div><div><br></div><div>Let's introdu=
ce two constructs, "try aggregate" and "try defer".</di=
v><div><br></div><div>- "Try aggregate" starts a block in which t=
here can be "try defer" statements that aggregate exceptions.</di=
v><div><br></div><div>- At the end of the "try aggregate" block, =
any accumulated exceptions are thrown as a group.</div><div><br></div><div>=
- If there are no aggregated exceptions, execution continues.</div><div><br=
></div><div>Your example earlier was as follows:</div><div><br></div><div><=
br></div><div><font face=3D"courier new,monospace">struct D { A *a1, *a2; D=
(); ~D() { dispose(a1); dispose(a2); } }; <br><br>template <typename T&g=
t; void dispose(T *&ptr) <br>{ <br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0ptr->~T(); <br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0remove_from_siblings(ptr); <br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0Allocator::dealloc(ptr); <br>}</font> <br></div><div><br></div><di=
v><br></div><div>As I mention, this is <em>currently</em> unsafe if A::~A()=
is noexcept(false).</div><div><br></div><div>This is how it <em>would</em>=
be safe with the "try defer" syntactic sugar. To avoid introduci=
ng contextual keywords, I use "try+" for try defer, and=C2=A0&quo=
t;try*" for try aggregate:</div><div><br></div><div><br></div><div><fo=
nt face=3D"courier new,monospace">struct D {</font></div><div><font face=3D=
"courier new,monospace">=C2=A0=C2=A0=C2=A0 A *a1, *a2;</font></div><div><fo=
nt face=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0 D();</font></div><div>=
<font face=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0 ~D() {</font></div>=
<div><font face=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0 try* {</font></div><div><font face=3D"courier new,monospace">=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 try+ { disp=
ose(a1); }</font></div><div><font face=3D"courier new,monospace">=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 try+ { dispose(a2=
); }</font></div><div><font face=3D"courier new,monospace">=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0 }</font></div><div><font face=3D"courier new,mo=
nospace">=C2=A0=C2=A0=C2=A0 }</font></div><div><font face=3D"courier new,mo=
nospace">}; <br></font><br><font face=3D"courier new,monospace">template &l=
t;typename T> void dispose(T *&ptr) <br>{</font></div><div><font fac=
e=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0 try* {<br>=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0 try+ { ptr->~T(); }<br>=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0remove_from_siblings(ptr); <br>=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0Allocator::dealloc(ptr);</font></div><div><fo=
nt face=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0 }<br>}</font> <br></di=
v><div><br></div><div><br></div><div>This provides nice, clean, elegant syn=
tax that makes throwing destructors safe, and easy to handle.</div><div><br=
></div><div>Anyone can understand and safely use this syntax. Even beginner=
s.</div><div><br></div><div><br></div><div>Now, to your continuing comments=
..</div><div><br></div><div>There are resolutions to most of the issues you =
raise.=C2=A0They=C2=A0are apparent to=C2=A0one who <em>wants </em>to solve =
them.=C2=A0The issue is that=C2=A0you do not <em>want </em>that. You want t=
he opposite; to <em>not</em> solve them.=C2=A0You do not want to acknowledg=
e=C2=A0solutions I have already proposed.=C2=A0Some of the issues=C2=A0you =
raise are=C2=A0repeated and=C2=A0<em>purposeful</em> misunderstandings.</di=
v><div><div><br></div><div>For a technical argument to make sense, <em>ther=
e must be a reasonable way</em> I can=C2=A0find a solution. You <em>must</e=
m> be open to my proposal in at least <em>some reasonable</em>=C2=A0scenari=
o. You have to not move your goal posts.=C2=A0If there is no scenario in wh=
ich you're open to my proposal, or if you keep moving goal posts,=C2=A0=
then a technical argument is a waste of time. It just comes down to a vote =
of who is for, and who's against; and=C2=A0whoever has the majority=C2=
=A0will prevail.</div><div><br><br>On Thursday, July 23, 2015 at 12:25:15 A=
M UTC-6, Thiago Macieira wrote:</div></div></div><blockquote class=3D"gmail=
_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-=
color: rgb(204, 204, 204); border-left-width: 1px; border-left-style: solid=
;">On Wednesday 22 July 2015 18:43:22 denis bider wrote:
<br>> > Please tell me of an uninstaller that rolls back when it runs=
into an
<br>>=20
<br>> error.
<br>>=20
<br>> I am perplexed. This question sounds to me like: "Tell me of =
a car that has
<br>> wheels."
<br>>=20
<br>> *All installers *must rollback when they run into an error.
<br>>=20
<br>> Ours do: <a onmousedown=3D"this.href=3D'https://www.google.com=
/url?q\75https%3A%2F%2Fwww.bitvise.com%2F\46sa\75D\46sntz\0751\46usg\75AFQj=
CNH9_QQ7hnBKE1KSKpRXkn_2ZDqTvQ';return true;" onclick=3D"this.href=3D&#=
39;https://www.google.com/url?q\75https%3A%2F%2Fwww.bitvise.com%2F\46sa\75D=
\46sntz\0751\46usg\75AFQjCNH9_QQ7hnBKE1KSKpRXkn_2ZDqTvQ';return true;" =
href=3D"https://www.bitvise.com/" target=3D"_blank" rel=3D"nofollow">https:=
//www.bitvise.com/</a>
<br>
<br>I said *uninstaller*. What do you do when you've removed some files=
, then=20
<br>something failed? Let's say a filesystem corruption prevents you fr=
om removing=20
<br>certain files, how do you roll back? Do you put the files you had alrea=
dy=20
<br>removed back in?
<br>
<br>Moving to the C++ case: if a sub-object destruction fails, do the previ=
ously=20
<br>destroyed object get re-constructed? That's impossible. In fact, yo=
ur proposal=20
<br>is that we ignore the problem and continue destruction.
<br>
<br>So it wouldn't be like the uninstaller rollback. It would be like a=
n=20
<br>uninstaller powering through and leaving an unclean state behind.
<br>
<br>> > That punts the problem to std::unique_ptr. Now the destructor
<br>> > of your sub-objects may be called while other sub-objects
<br>> > that should have been destroyed haven't yet.
<br>>=20
<br>> That's how destruction works.
<br>>=20
<br>> The only way this is an issue is if the 2+ resources you are freei=
ng have
<br>> logical interdependencies in the destructor. In this case, you nee=
d to
<br>> implement destruction properly.
<br>
<br>Which gets tricky very quickly, not to mention the fact that some of th=
em=20
<br>might be partially destroyed and thus in an invalid state.
<br>
<br>> The code you provided does not need multi-exceptions to be incorre=
ct. It is
<br>> already incorrect in C++11 if a1 destructor is noexcept(false).
<br>
<br>Which, like I said, the destructor is not supposed to be. A noexcept(fa=
lse)=20
<br>destructor today is considered, by itself, a problem. Everything using=
=20
<br>destructors assumes a contract that they don't throw. A noexcept(fa=
lse)y=20
<br>constructor is therefore a contract violation.
<br>
<br>> > But it's a change in behaviour, with increased memory pre=
ssure,
<br>> > for something that is not in use today.
<br>>=20
<br>> If we keep existing rules for how destructors' noexcept declar=
ations are
<br>> determined, there is no change of behavior unless you *actually us=
e
<br>> *destructors declared noexcept(false).
<br>
<br>So there's a change of behaviour to existing code.
<br>
<br>> Even if you have destructors declared noexcept(false), there is st=
ill no
<br>> need for additional cost unless you also implement *catch-any* han=
dlers to
<br>> handle multi-exceptions.
<br>
<br>As we've agreed, noexcept(false) destructors will do additional wor=
k in the=20
<br>exceptional case because they need to aggregate exceptions. Those destr=
uctors=20
<br>exist today and will start paying for a feature they don't use,
<br>
<br>Additionally, I'd expect that even noexcept destructors, for consis=
tency,=20
<br>should do destruction of all sub-objects, even if terminate() is coming=
.. So=20
<br>all destructors will start paying the price of this feature.
<br>
<br>> If your program does not implement any catch-any handlers, then
<br>> multi-exception support can again be fully optimized away, so that
<br>> std::terminate is called at the point where exceptions would be ag=
gregated.
<br>
<br>That's not correct. Multi-exceptions are implicit because of destru=
ctors' sub-
<br>object destruction.
<br>
<br>> > That is, the following =C2=A0will continue execution and aggr=
egate,
<br>> > with unmodified code:
<br>> >=20
<br>> > void f() { =C2=A0A a1, a2; }
<br>>=20
<br>> I do not propose changes to existing behavior, so yes. If A::~A() =
throws
<br>> and is declared noexcept(false), that's how that snippet *alre=
ady *behaves
<br>> in C++11 and 14.
<br>
<br>But the point is that you are proposing changes to the code above! You =
may not=20
<br>have explicitly said so, but it's a consequence of your proposal th=
at=20
<br>destructors aggregate.
<br>
<br>Given:
<br>
<br>struct B { A a1, a2; };
<br>
<br>Then B's destructor must implement continuation-after-exception and=
=20
<br>aggregation if a1.~A() throws. Given that this is the case, they I'=
d expect=20
<br>that for consistency the function f above do the same.
<br>
<br>And I also expect the destructor below to continue, even though it will=
=20
<br>terminate() instead of throwing an aggregate exception:
<br>
<br>struct C { A a1, a2; ~C() noexcept {} };
<br>
<br>> An exception can already occur in either of those objects' des=
tructors.
<br>> Both destructors will still be called.
<br>
<br>Not currently. Your proposal modifies this and that's the crux of t=
he problem.
<br>
<br>> What *can't *happen right now is that those exceptions cannot =
aggregate,
<br>> and the destructors cannot *both *throw. But either of them can.
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a onmousedown=3D"this.href=3D'http:/=
/www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\75D\46sntz\0751\46u=
sg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.=
href=3D'http://www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\7=
5D\46sntz\0751\46usg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;=
" href=3D"http://macieira.info" target=3D"_blank" rel=3D"nofollow">macieira=
..info</a> - thiago (AT) <a onmousedown=3D"this.href=3D'http://www.googl=
e.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\75AFQjCNHGRJd=
o5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'http=
://www.google.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\7=
5AFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;" href=3D"http://kde.o=
rg" target=3D"_blank" rel=3D"nofollow">kde.org</a>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>=C2=A0 =C2=A0 =C2=A0 PGP/GPG: 0x6EF45358; fingerprint:
<br>=C2=A0 =C2=A0 =C2=A0 E067 918B B660 DBD1 105C =C2=A0966C 33F5 F005 6EF4=
5358
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_631_1476475778.1437659344464--
------=_Part_630_1939033007.1437659344458--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Thu, 23 Jul 2015 07:32:57 -0700 (PDT)
Raw View
------=_Part_746_210311492.1437661977988
Content-Type: multipart/alternative;
boundary="----=_Part_747_1446535148.1437661977989"
------=_Part_747_1446535148.1437661977989
Content-Type: text/plain; charset=UTF-8
Based on our exchange, I have come to realize that try-defer and
try-aggregate are not just syntactic sugar, but crucial elements of the
proposal that make exception aggregation easy to handle by anyone,
including beginners.
Without these constructs, you are correct that exception aggregation is too
tricky for the average programmer.
With these constructs, it becomes easy and elegant.
I have updated the "Proposal summary" page to include try* and try+:
http://denisbider.blogspot.com/2015/07/aggregated-exceptions-proposal-summary.html
On Thursday, July 23, 2015 at 7:49:04 AM UTC-6, denis bider wrote:
> I would like to point out that, with minimal syntactic sugar,
> multi-exceptions provide an easy way to handle code that may throw,
> including in destructors.
>
> Let's introduce two constructs, "try aggregate" and "try defer".
>
> - "Try aggregate" starts a block in which there can be "try defer"
> statements that aggregate exceptions.
>
> - At the end of the "try aggregate" block, any accumulated exceptions are
> thrown as a group.
>
> - If there are no aggregated exceptions, execution continues.
>
> Your example earlier was as follows:
>
>
> struct D { A *a1, *a2; D(); ~D() { dispose(a1); dispose(a2); } };
>
> template <typename T> void dispose(T *&ptr)
> {
> ptr->~T();
> remove_from_siblings(ptr);
> Allocator::dealloc(ptr);
> }
>
>
> As I mention, this is *currently* unsafe if A::~A() is noexcept(false).
>
> This is how it *would* be safe with the "try defer" syntactic sugar. To
> avoid introducing contextual keywords, I use "try+" for try defer,
> and "try*" for try aggregate:
>
>
> struct D {
> A *a1, *a2;
> D();
> ~D() {
> try* {
> try+ { dispose(a1); }
> try+ { dispose(a2); }
> }
> }
> };
>
> template <typename T> void dispose(T *&ptr)
> {
> try* {
> try+ { ptr->~T(); }
> remove_from_siblings(ptr);
> Allocator::dealloc(ptr);
> }
> }
>
>
> This provides nice, clean, elegant syntax that makes throwing destructors
> safe, and easy to handle.
>
> Anyone can understand and safely use this syntax. Even beginners.
>
>
> Now, to your continuing comments.
>
> There are resolutions to most of the issues you raise. They are apparent
> to one who *wants *to solve them. The issue is that you do not *want *that.
> You want the opposite; to *not* solve them. You do not want to
> acknowledge solutions I have already proposed. Some of the issues you raise
> are repeated and *purposeful* misunderstandings.
>
> For a technical argument to make sense, *there must be a reasonable way*
> I can find a solution. You *must* be open to my proposal in at least *some
> reasonable* scenario. You have to not move your goal posts. If there is
> no scenario in which you're open to my proposal, or if you keep moving goal
> posts, then a technical argument is a waste of time. It just comes down to
> a vote of who is for, and who's against; and whoever has the majority will
> prevail.
>
>
> On Thursday, July 23, 2015 at 12:25:15 AM UTC-6, Thiago Macieira wrote:
>
>> On Wednesday 22 July 2015 18:43:22 denis bider wrote:
>> > > Please tell me of an uninstaller that rolls back when it runs into an
>> >
>> > error.
>> >
>> > I am perplexed. This question sounds to me like: "Tell me of a car that
>> has
>> > wheels."
>> >
>> > *All installers *must rollback when they run into an error.
>> >
>> > Ours do: https://www.bitvise.com/
>>
>> I said *uninstaller*. What do you do when you've removed some files, then
>> something failed? Let's say a filesystem corruption prevents you from
>> removing
>> certain files, how do you roll back? Do you put the files you had already
>> removed back in?
>>
>> Moving to the C++ case: if a sub-object destruction fails, do the
>> previously
>> destroyed object get re-constructed? That's impossible. In fact, your
>> proposal
>> is that we ignore the problem and continue destruction.
>>
>> So it wouldn't be like the uninstaller rollback. It would be like an
>> uninstaller powering through and leaving an unclean state behind.
>>
>> > > That punts the problem to std::unique_ptr. Now the destructor
>> > > of your sub-objects may be called while other sub-objects
>> > > that should have been destroyed haven't yet.
>> >
>> > That's how destruction works.
>> >
>> > The only way this is an issue is if the 2+ resources you are freeing
>> have
>> > logical interdependencies in the destructor. In this case, you need to
>> > implement destruction properly.
>>
>> Which gets tricky very quickly, not to mention the fact that some of them
>> might be partially destroyed and thus in an invalid state.
>>
>> > The code you provided does not need multi-exceptions to be incorrect.
>> It is
>> > already incorrect in C++11 if a1 destructor is noexcept(false).
>>
>> Which, like I said, the destructor is not supposed to be. A
>> noexcept(false)
>> destructor today is considered, by itself, a problem. Everything using
>> destructors assumes a contract that they don't throw. A noexcept(false)y
>> constructor is therefore a contract violation.
>>
>> > > But it's a change in behaviour, with increased memory pressure,
>> > > for something that is not in use today.
>> >
>> > If we keep existing rules for how destructors' noexcept declarations
>> are
>> > determined, there is no change of behavior unless you *actually use
>> > *destructors declared noexcept(false).
>>
>> So there's a change of behaviour to existing code.
>>
>> > Even if you have destructors declared noexcept(false), there is still
>> no
>> > need for additional cost unless you also implement *catch-any* handlers
>> to
>> > handle multi-exceptions.
>>
>> As we've agreed, noexcept(false) destructors will do additional work in
>> the
>> exceptional case because they need to aggregate exceptions. Those
>> destructors
>> exist today and will start paying for a feature they don't use,
>>
>> Additionally, I'd expect that even noexcept destructors, for consistency,
>> should do destruction of all sub-objects, even if terminate() is coming.
>> So
>> all destructors will start paying the price of this feature.
>>
>> > If your program does not implement any catch-any handlers, then
>> > multi-exception support can again be fully optimized away, so that
>> > std::terminate is called at the point where exceptions would be
>> aggregated.
>>
>> That's not correct. Multi-exceptions are implicit because of destructors'
>> sub-
>> object destruction.
>>
>> > > That is, the following will continue execution and aggregate,
>> > > with unmodified code:
>> > >
>> > > void f() { A a1, a2; }
>> >
>> > I do not propose changes to existing behavior, so yes. If A::~A()
>> throws
>> > and is declared noexcept(false), that's how that snippet *already
>> *behaves
>> > in C++11 and 14.
>>
>> But the point is that you are proposing changes to the code above! You
>> may not
>> have explicitly said so, but it's a consequence of your proposal that
>> destructors aggregate.
>>
>> Given:
>>
>> struct B { A a1, a2; };
>>
>> Then B's destructor must implement continuation-after-exception and
>> aggregation if a1.~A() throws. Given that this is the case, they I'd
>> expect
>> that for consistency the function f above do the same.
>>
>> And I also expect the destructor below to continue, even though it will
>> terminate() instead of throwing an aggregate exception:
>>
>> struct C { A a1, a2; ~C() noexcept {} };
>>
>> > An exception can already occur in either of those objects' destructors.
>> > Both destructors will still be called.
>>
>> Not currently. Your proposal modifies this and that's the crux of the
>> problem.
>>
>> > What *can't *happen right now is that those exceptions cannot
>> aggregate,
>> > and the destructors cannot *both *throw. But either of them can.
>>
>> --
>> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
>> Software Architect - Intel Open Source Technology Center
>> PGP/GPG: 0x6EF45358; fingerprint:
>> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
>>
>>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_747_1446535148.1437661977989
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Based on our exchange, I have come to realize that tr=
y-defer and try-aggregate are not just syntactic sugar, but crucial element=
s of the proposal that make exception aggregation easy to handle by anyone,=
including beginners.</div><div><br></div><div>Without these constructs, yo=
u are correct that exception aggregation is too tricky for the average prog=
rammer.</div><div><br></div><div>With these constructs, it becomes easy and=
elegant.</div><div><br></div><div>I have updated the "Proposal summar=
y" page to include try* and try+:</div><div><br></div><div><a href=3D"=
http://denisbider.blogspot.com/2015/07/aggregated-exceptions-proposal-summa=
ry.html">http://denisbider.blogspot.com/2015/07/aggregated-exceptions-propo=
sal-summary.html</a></div><div><br><br>On Thursday, July 23, 2015 at 7:49:0=
4 AM UTC-6, denis bider wrote:</div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(20=
4, 204, 204); border-left-width: 1px; border-left-style: solid;"><div dir=
=3D"ltr"><div><div>I would like to point out that, with minimal syntactic s=
ugar, multi-exceptions provide an easy way to handle code that may throw, i=
ncluding in destructors.</div><div><br></div><div>Let's introduce two c=
onstructs, "try aggregate" and "try defer".</div><div><=
br></div><div>- "Try aggregate" starts a block in which there can=
be "try defer" statements that aggregate exceptions.</div><div><=
br></div><div>- At the end of the "try aggregate" block, any accu=
mulated exceptions are thrown as a group.</div><div><br></div><div>- If the=
re are no aggregated exceptions, execution continues.</div><div><br></div><=
div>Your example earlier was as follows:</div><div><br></div><div><br></div=
><div><font face=3D"courier new,monospace">struct D { A *a1, *a2; D(); ~D()=
{ dispose(a1); dispose(a2); } }; <br><br>template <typename T> void =
dispose(T *&ptr) <br>{ <br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0ptr->~T(); <br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0rem=
ove_from_siblings(ptr); <br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0Allocator::dealloc(ptr); <br>}</font> <br></div><div><br></div><div><br>=
</div><div>As I mention, this is <em>currently</em> unsafe if A::~A() is no=
except(false).</div><div><br></div><div>This is how it <em>would</em> be sa=
fe with the "try defer" syntactic sugar. To avoid introducing con=
textual keywords, I use "try+" for try defer, and=C2=A0"try*=
" for try aggregate:</div><div><br></div><div><br></div><div><font fac=
e=3D"courier new,monospace">struct D {</font></div><div><font face=3D"couri=
er new,monospace">=C2=A0=C2=A0=C2=A0 A *a1, *a2;</font></div><div><font fac=
e=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0 D();</font></div><div><font =
face=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0 ~D() {</font></div><div><=
font face=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 try* {</font></div><div><font face=3D"courier new,monospace">=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 try+ { dispose(a1=
); }</font></div><div><font face=3D"courier new,monospace">=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 try+ { dispose(a2); }</=
font></div><div><font face=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 }</font></div><div><font face=3D"courier new,monospac=
e">=C2=A0=C2=A0=C2=A0 }</font></div><div><font face=3D"courier new,monospac=
e">}; <br></font><br><font face=3D"courier new,monospace">template <type=
name T> void dispose(T *&ptr) <br>{</font></div><div><font face=3D"c=
ourier new,monospace">=C2=A0=C2=A0=C2=A0 try* {<br>=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0 try+ { ptr->~T(); }<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0remove_from_siblings(ptr); <br>=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0Allocator::dealloc(ptr);</font></div><div><font fac=
e=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0 }<br>}</font> <br></div><div=
><br></div><div><br></div><div>This provides nice, clean, elegant syntax th=
at makes throwing destructors safe, and easy to handle.</div><div><br></div=
><div>Anyone can understand and safely use this syntax. Even beginners.</di=
v><div><br></div><div><br></div><div>Now, to your continuing comments.</div=
><div><br></div><div>There are resolutions to most of the issues you raise.=
=C2=A0They=C2=A0are apparent to=C2=A0one who <em>wants </em>to solve them.=
=C2=A0The issue is that=C2=A0you do not <em>want </em>that. You want the op=
posite; to <em>not</em> solve them.=C2=A0You do not want to acknowledge=C2=
=A0solutions I have already proposed.=C2=A0Some of the issues=C2=A0you rais=
e are=C2=A0repeated and=C2=A0<em>purposeful</em> misunderstandings.</div><d=
iv><div><br></div><div>For a technical argument to make sense, <em>there mu=
st be a reasonable way</em> I can=C2=A0find a solution. You <em>must</em> b=
e open to my proposal in at least <em>some reasonable</em>=C2=A0scenario. Y=
ou have to not move your goal posts.=C2=A0If there is no scenario in which =
you're open to my proposal, or if you keep moving goal posts,=C2=A0then=
a technical argument is a waste of time. It just comes down to a vote of w=
ho is for, and who's against; and=C2=A0whoever has the majority=C2=A0wi=
ll prevail.</div><div><br><br>On Thursday, July 23, 2015 at 12:25:15 AM UTC=
-6, Thiago Macieira wrote:</div></div></div><blockquote class=3D"gmail_quot=
e" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color=
: rgb(204, 204, 204); border-left-width: 1px; border-left-style: solid;">On=
Wednesday 22 July 2015 18:43:22 denis bider wrote:
<br>> > Please tell me of an uninstaller that rolls back when it runs=
into an
<br>>=20
<br>> error.
<br>>=20
<br>> I am perplexed. This question sounds to me like: "Tell me of =
a car that has
<br>> wheels."
<br>>=20
<br>> *All installers *must rollback when they run into an error.
<br>>=20
<br>> Ours do: <a onmousedown=3D"this.href=3D'https://www.google.com=
/url?q\75https%3A%2F%2Fwww.bitvise.com%2F\46sa\75D\46sntz\0751\46usg\75AFQj=
CNH9_QQ7hnBKE1KSKpRXkn_2ZDqTvQ';return true;" onclick=3D"this.href=3D&#=
39;https://www.google.com/url?q\75https%3A%2F%2Fwww.bitvise.com%2F\46sa\75D=
\46sntz\0751\46usg\75AFQjCNH9_QQ7hnBKE1KSKpRXkn_2ZDqTvQ';return true;" =
href=3D"https://www.bitvise.com/" target=3D"_blank" rel=3D"nofollow">https:=
//www.bitvise.com/</a>
<br>
<br>I said *uninstaller*. What do you do when you've removed some files=
, then=20
<br>something failed? Let's say a filesystem corruption prevents you fr=
om removing=20
<br>certain files, how do you roll back? Do you put the files you had alrea=
dy=20
<br>removed back in?
<br>
<br>Moving to the C++ case: if a sub-object destruction fails, do the previ=
ously=20
<br>destroyed object get re-constructed? That's impossible. In fact, yo=
ur proposal=20
<br>is that we ignore the problem and continue destruction.
<br>
<br>So it wouldn't be like the uninstaller rollback. It would be like a=
n=20
<br>uninstaller powering through and leaving an unclean state behind.
<br>
<br>> > That punts the problem to std::unique_ptr. Now the destructor
<br>> > of your sub-objects may be called while other sub-objects
<br>> > that should have been destroyed haven't yet.
<br>>=20
<br>> That's how destruction works.
<br>>=20
<br>> The only way this is an issue is if the 2+ resources you are freei=
ng have
<br>> logical interdependencies in the destructor. In this case, you nee=
d to
<br>> implement destruction properly.
<br>
<br>Which gets tricky very quickly, not to mention the fact that some of th=
em=20
<br>might be partially destroyed and thus in an invalid state.
<br>
<br>> The code you provided does not need multi-exceptions to be incorre=
ct. It is
<br>> already incorrect in C++11 if a1 destructor is noexcept(false).
<br>
<br>Which, like I said, the destructor is not supposed to be. A noexcept(fa=
lse)=20
<br>destructor today is considered, by itself, a problem. Everything using=
=20
<br>destructors assumes a contract that they don't throw. A noexcept(fa=
lse)y=20
<br>constructor is therefore a contract violation.
<br>
<br>> > But it's a change in behaviour, with increased memory pre=
ssure,
<br>> > for something that is not in use today.
<br>>=20
<br>> If we keep existing rules for how destructors' noexcept declar=
ations are
<br>> determined, there is no change of behavior unless you *actually us=
e
<br>> *destructors declared noexcept(false).
<br>
<br>So there's a change of behaviour to existing code.
<br>
<br>> Even if you have destructors declared noexcept(false), there is st=
ill no
<br>> need for additional cost unless you also implement *catch-any* han=
dlers to
<br>> handle multi-exceptions.
<br>
<br>As we've agreed, noexcept(false) destructors will do additional wor=
k in the=20
<br>exceptional case because they need to aggregate exceptions. Those destr=
uctors=20
<br>exist today and will start paying for a feature they don't use,
<br>
<br>Additionally, I'd expect that even noexcept destructors, for consis=
tency,=20
<br>should do destruction of all sub-objects, even if terminate() is coming=
.. So=20
<br>all destructors will start paying the price of this feature.
<br>
<br>> If your program does not implement any catch-any handlers, then
<br>> multi-exception support can again be fully optimized away, so that
<br>> std::terminate is called at the point where exceptions would be ag=
gregated.
<br>
<br>That's not correct. Multi-exceptions are implicit because of destru=
ctors' sub-
<br>object destruction.
<br>
<br>> > That is, the following =C2=A0will continue execution and aggr=
egate,
<br>> > with unmodified code:
<br>> >=20
<br>> > void f() { =C2=A0A a1, a2; }
<br>>=20
<br>> I do not propose changes to existing behavior, so yes. If A::~A() =
throws
<br>> and is declared noexcept(false), that's how that snippet *alre=
ady *behaves
<br>> in C++11 and 14.
<br>
<br>But the point is that you are proposing changes to the code above! You =
may not=20
<br>have explicitly said so, but it's a consequence of your proposal th=
at=20
<br>destructors aggregate.
<br>
<br>Given:
<br>
<br>struct B { A a1, a2; };
<br>
<br>Then B's destructor must implement continuation-after-exception and=
=20
<br>aggregation if a1.~A() throws. Given that this is the case, they I'=
d expect=20
<br>that for consistency the function f above do the same.
<br>
<br>And I also expect the destructor below to continue, even though it will=
=20
<br>terminate() instead of throwing an aggregate exception:
<br>
<br>struct C { A a1, a2; ~C() noexcept {} };
<br>
<br>> An exception can already occur in either of those objects' des=
tructors.
<br>> Both destructors will still be called.
<br>
<br>Not currently. Your proposal modifies this and that's the crux of t=
he problem.
<br>
<br>> What *can't *happen right now is that those exceptions cannot =
aggregate,
<br>> and the destructors cannot *both *throw. But either of them can.
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a onmousedown=3D"this.href=3D'http:/=
/www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\75D\46sntz\0751\46u=
sg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.=
href=3D'http://www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\7=
5D\46sntz\0751\46usg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;=
" href=3D"http://macieira.info" target=3D"_blank" rel=3D"nofollow">macieira=
..info</a> - thiago (AT) <a onmousedown=3D"this.href=3D'http://www.googl=
e.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\75AFQjCNHGRJd=
o5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'http=
://www.google.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\7=
5AFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;" href=3D"http://kde.o=
rg" target=3D"_blank" rel=3D"nofollow">kde.org</a>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>=C2=A0 =C2=A0 =C2=A0 PGP/GPG: 0x6EF45358; fingerprint:
<br>=C2=A0 =C2=A0 =C2=A0 E067 918B B660 DBD1 105C =C2=A0966C 33F5 F005 6EF4=
5358
<br>
<br></blockquote></div></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_747_1446535148.1437661977989--
------=_Part_746_210311492.1437661977988--
.
Author: =?UTF-8?Q?Micha=C5=82_Dominiak?= <griwes@griwes.info>
Date: Thu, 23 Jul 2015 15:20:08 +0000
Raw View
--001a1134c49ec2aa46051b8c6cea
Content-Type: text/plain; charset=UTF-8
So now your proposal also requires littering our code with weird `try`
blocks. No good.
Exceptions are meant to be "transparent", so code that doesn't explicitly
*handle* errors doesn't need to care about them *at all*, ignoring their
existence. Your proposal now changes that entirely, making all the code
using *some* 3rd party code have to deal with weirdness.
On Thu, Jul 23, 2015 at 4:32 PM denis bider <isocppgroup@denisbider.com>
wrote:
> Based on our exchange, I have come to realize that try-defer and
> try-aggregate are not just syntactic sugar, but crucial elements of the
> proposal that make exception aggregation easy to handle by anyone,
> including beginners.
>
> Without these constructs, you are correct that exception aggregation is
> too tricky for the average programmer.
>
> With these constructs, it becomes easy and elegant.
>
> I have updated the "Proposal summary" page to include try* and try+:
>
>
> http://denisbider.blogspot.com/2015/07/aggregated-exceptions-proposal-summary.html
>
>
> On Thursday, July 23, 2015 at 7:49:04 AM UTC-6, denis bider wrote:
>
>> I would like to point out that, with minimal syntactic sugar,
>> multi-exceptions provide an easy way to handle code that may throw,
>> including in destructors.
>>
>> Let's introduce two constructs, "try aggregate" and "try defer".
>>
>> - "Try aggregate" starts a block in which there can be "try defer"
>> statements that aggregate exceptions.
>>
>> - At the end of the "try aggregate" block, any accumulated exceptions are
>> thrown as a group.
>>
>> - If there are no aggregated exceptions, execution continues.
>>
>> Your example earlier was as follows:
>>
>>
>> struct D { A *a1, *a2; D(); ~D() { dispose(a1); dispose(a2); } };
>>
>> template <typename T> void dispose(T *&ptr)
>> {
>> ptr->~T();
>> remove_from_siblings(ptr);
>> Allocator::dealloc(ptr);
>> }
>>
>>
>> As I mention, this is *currently* unsafe if A::~A() is noexcept(false).
>>
>> This is how it *would* be safe with the "try defer" syntactic sugar. To
>> avoid introducing contextual keywords, I use "try+" for try defer,
>> and "try*" for try aggregate:
>>
>>
>> struct D {
>> A *a1, *a2;
>> D();
>> ~D() {
>> try* {
>> try+ { dispose(a1); }
>> try+ { dispose(a2); }
>> }
>> }
>> };
>>
>> template <typename T> void dispose(T *&ptr)
>> {
>> try* {
>> try+ { ptr->~T(); }
>> remove_from_siblings(ptr);
>> Allocator::dealloc(ptr);
>> }
>> }
>>
>>
>> This provides nice, clean, elegant syntax that makes throwing destructors
>> safe, and easy to handle.
>>
>> Anyone can understand and safely use this syntax. Even beginners.
>>
>>
>> Now, to your continuing comments.
>>
>> There are resolutions to most of the issues you raise. They are apparent
>> to one who *wants *to solve them. The issue is that you do not *want *that.
>> You want the opposite; to *not* solve them. You do not want to
>> acknowledge solutions I have already proposed. Some of the issues you raise
>> are repeated and *purposeful* misunderstandings.
>>
>> For a technical argument to make sense, *there must be a reasonable way*
>> I can find a solution. You *must* be open to my proposal in at least *some
>> reasonable* scenario. You have to not move your goal posts. If there is
>> no scenario in which you're open to my proposal, or if you keep moving goal
>> posts, then a technical argument is a waste of time. It just comes down to
>> a vote of who is for, and who's against; and whoever has the majority will
>> prevail.
>>
>>
>> On Thursday, July 23, 2015 at 12:25:15 AM UTC-6, Thiago Macieira wrote:
>>
>>> On Wednesday 22 July 2015 18:43:22 denis bider wrote:
>>> > > Please tell me of an uninstaller that rolls back when it runs into
>>> an
>>> >
>>> > error.
>>> >
>>> > I am perplexed. This question sounds to me like: "Tell me of a car
>>> that has
>>> > wheels."
>>> >
>>> > *All installers *must rollback when they run into an error.
>>> >
>>> > Ours do: https://www.bitvise.com/
>>>
>>> I said *uninstaller*. What do you do when you've removed some files,
>>> then
>>> something failed? Let's say a filesystem corruption prevents you from
>>> removing
>>> certain files, how do you roll back? Do you put the files you had
>>> already
>>> removed back in?
>>>
>>> Moving to the C++ case: if a sub-object destruction fails, do the
>>> previously
>>> destroyed object get re-constructed? That's impossible. In fact, your
>>> proposal
>>> is that we ignore the problem and continue destruction.
>>>
>>> So it wouldn't be like the uninstaller rollback. It would be like an
>>> uninstaller powering through and leaving an unclean state behind.
>>>
>>> > > That punts the problem to std::unique_ptr. Now the destructor
>>> > > of your sub-objects may be called while other sub-objects
>>> > > that should have been destroyed haven't yet.
>>> >
>>> > That's how destruction works.
>>> >
>>> > The only way this is an issue is if the 2+ resources you are freeing
>>> have
>>> > logical interdependencies in the destructor. In this case, you need to
>>> > implement destruction properly.
>>>
>>> Which gets tricky very quickly, not to mention the fact that some of
>>> them
>>> might be partially destroyed and thus in an invalid state.
>>>
>>> > The code you provided does not need multi-exceptions to be incorrect.
>>> It is
>>> > already incorrect in C++11 if a1 destructor is noexcept(false).
>>>
>>> Which, like I said, the destructor is not supposed to be. A
>>> noexcept(false)
>>> destructor today is considered, by itself, a problem. Everything using
>>> destructors assumes a contract that they don't throw. A noexcept(false)y
>>> constructor is therefore a contract violation.
>>>
>>> > > But it's a change in behaviour, with increased memory pressure,
>>> > > for something that is not in use today.
>>> >
>>> > If we keep existing rules for how destructors' noexcept declarations
>>> are
>>> > determined, there is no change of behavior unless you *actually use
>>> > *destructors declared noexcept(false).
>>>
>>> So there's a change of behaviour to existing code.
>>>
>>> > Even if you have destructors declared noexcept(false), there is still
>>> no
>>> > need for additional cost unless you also implement *catch-any*
>>> handlers to
>>> > handle multi-exceptions.
>>>
>>> As we've agreed, noexcept(false) destructors will do additional work in
>>> the
>>> exceptional case because they need to aggregate exceptions. Those
>>> destructors
>>> exist today and will start paying for a feature they don't use,
>>>
>>> Additionally, I'd expect that even noexcept destructors, for
>>> consistency,
>>> should do destruction of all sub-objects, even if terminate() is coming.
>>> So
>>> all destructors will start paying the price of this feature.
>>>
>>> > If your program does not implement any catch-any handlers, then
>>> > multi-exception support can again be fully optimized away, so that
>>> > std::terminate is called at the point where exceptions would be
>>> aggregated.
>>>
>>> That's not correct. Multi-exceptions are implicit because of
>>> destructors' sub-
>>> object destruction.
>>>
>>> > > That is, the following will continue execution and aggregate,
>>> > > with unmodified code:
>>> > >
>>> > > void f() { A a1, a2; }
>>> >
>>> > I do not propose changes to existing behavior, so yes. If A::~A()
>>> throws
>>> > and is declared noexcept(false), that's how that snippet *already
>>> *behaves
>>> > in C++11 and 14.
>>>
>>> But the point is that you are proposing changes to the code above! You
>>> may not
>>> have explicitly said so, but it's a consequence of your proposal that
>>> destructors aggregate.
>>>
>>> Given:
>>>
>>> struct B { A a1, a2; };
>>>
>>> Then B's destructor must implement continuation-after-exception and
>>> aggregation if a1.~A() throws. Given that this is the case, they I'd
>>> expect
>>> that for consistency the function f above do the same.
>>>
>>> And I also expect the destructor below to continue, even though it will
>>> terminate() instead of throwing an aggregate exception:
>>>
>>> struct C { A a1, a2; ~C() noexcept {} };
>>>
>>> > An exception can already occur in either of those objects'
>>> destructors.
>>> > Both destructors will still be called.
>>>
>>> Not currently. Your proposal modifies this and that's the crux of the
>>> problem.
>>>
>>> > What *can't *happen right now is that those exceptions cannot
>>> aggregate,
>>> > and the destructors cannot *both *throw. But either of them can.
>>>
>>> --
>>> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
>>> Software Architect - Intel Open Source Technology Center
>>> PGP/GPG: 0x6EF45358; fingerprint:
>>> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
>>>
>>> --
>
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/Y6gjtmVyzBo/unsubscribe
> .
> To unsubscribe from this group and all its topics, send an email to
> std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--001a1134c49ec2aa46051b8c6cea
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">So now your proposal also requires littering our code with=
weird `try` blocks. No good.<div><br></div><div>Exceptions are meant to be=
"transparent", so code that doesn't explicitly *handle* erro=
rs doesn't need to care about them *at all*, ignoring their existence. =
Your proposal now changes that entirely, making all the code using *some* 3=
rd party code have to deal with weirdness.</div></div><br><div class=3D"gma=
il_quote"><div dir=3D"ltr">On Thu, Jul 23, 2015 at 4:32 PM denis bider <=
<a href=3D"mailto:isocppgroup@denisbider.com">isocppgroup@denisbider.com</a=
>> wrote:<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0 0=
0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>=
Based on our exchange, I have come to realize that try-defer and try-aggreg=
ate are not just syntactic sugar, but crucial elements of the proposal that=
make exception aggregation easy to handle by anyone, including beginners.<=
/div><div><br></div><div>Without these constructs, you are correct that exc=
eption aggregation is too tricky for the average programmer.</div><div><br>=
</div><div>With these constructs, it becomes easy and elegant.</div><div><b=
r></div><div>I have updated the "Proposal summary" page to includ=
e try* and try+:</div><div><br></div><div><a href=3D"http://denisbider.blog=
spot.com/2015/07/aggregated-exceptions-proposal-summary.html" target=3D"_bl=
ank">http://denisbider.blogspot.com/2015/07/aggregated-exceptions-proposal-=
summary.html</a></div></div><div dir=3D"ltr"><div><br><br>On Thursday, July=
23, 2015 at 7:49:04 AM UTC-6, denis bider wrote:</div><blockquote class=3D=
"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;border-lef=
t-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid"><di=
v dir=3D"ltr"><div><div>I would like to point out that, with minimal syntac=
tic sugar, multi-exceptions provide an easy way to handle code that may thr=
ow, including in destructors.</div><div><br></div><div>Let's introduce =
two constructs, "try aggregate" and "try defer".</div><=
div><br></div><div>- "Try aggregate" starts a block in which ther=
e can be "try defer" statements that aggregate exceptions.</div><=
div><br></div><div>- At the end of the "try aggregate" block, any=
accumulated exceptions are thrown as a group.</div><div><br></div><div>- I=
f there are no aggregated exceptions, execution continues.</div><div><br></=
div><div>Your example earlier was as follows:</div><div><br></div><div><br>=
</div><div><font face=3D"courier new,monospace">struct D { A *a1, *a2; D();=
~D() { dispose(a1); dispose(a2); } }; <br><br>template <typename T> =
void dispose(T *&ptr) <br>{ <br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0ptr->~T(); <br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
remove_from_siblings(ptr); <br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0Allocator::dealloc(ptr); <br>}</font> <br></div><div><br></div><div><=
br></div><div>As I mention, this is <em>currently</em> unsafe if A::~A() is=
noexcept(false).</div><div><br></div><div>This is how it <em>would</em> be=
safe with the "try defer" syntactic sugar. To avoid introducing =
contextual keywords, I use "try+" for try defer, and=C2=A0"t=
ry*" for try aggregate:</div><div><br></div><div><br></div><div><font =
face=3D"courier new,monospace">struct D {</font></div><div><font face=3D"co=
urier new,monospace">=C2=A0=C2=A0=C2=A0 A *a1, *a2;</font></div><div><font =
face=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0 D();</font></div><div><fo=
nt face=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0 ~D() {</font></div><di=
v><font face=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0 try* {</font></div><div><font face=3D"courier new,monospace">=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 try+ { dispose=
(a1); }</font></div><div><font face=3D"courier new,monospace">=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 try+ { dispose(a2); =
}</font></div><div><font face=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0 }</font></div><div><font face=3D"courier new,monos=
pace">=C2=A0=C2=A0=C2=A0 }</font></div><div><font face=3D"courier new,monos=
pace">}; <br></font><br><font face=3D"courier new,monospace">template <t=
ypename T> void dispose(T *&ptr) <br>{</font></div><div><font face=
=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0 try* {<br>=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0 try+ { ptr->~T(); }<br>=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0remove_from_siblings(ptr); <br>=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0Allocator::dealloc(ptr);</font></div><div><fo=
nt face=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0 }<br>}</font> <br></di=
v><div><br></div><div><br></div><div>This provides nice, clean, elegant syn=
tax that makes throwing destructors safe, and easy to handle.</div><div><br=
></div><div>Anyone can understand and safely use this syntax. Even beginner=
s.</div><div><br></div><div><br></div><div>Now, to your continuing comments=
..</div><div><br></div><div>There are resolutions to most of the issues you =
raise.=C2=A0They=C2=A0are apparent to=C2=A0one who <em>wants </em>to solve =
them.=C2=A0The issue is that=C2=A0you do not <em>want </em>that. You want t=
he opposite; to <em>not</em> solve them.=C2=A0You do not want to acknowledg=
e=C2=A0solutions I have already proposed.=C2=A0Some of the issues=C2=A0you =
raise are=C2=A0repeated and=C2=A0<em>purposeful</em> misunderstandings.</di=
v><div><div><br></div><div>For a technical argument to make sense, <em>ther=
e must be a reasonable way</em> I can=C2=A0find a solution. You <em>must</e=
m> be open to my proposal in at least <em>some reasonable</em>=C2=A0scenari=
o. You have to not move your goal posts.=C2=A0If there is no scenario in wh=
ich you're open to my proposal, or if you keep moving goal posts,=C2=A0=
then a technical argument is a waste of time. It just comes down to a vote =
of who is for, and who's against; and=C2=A0whoever has the majority=C2=
=A0will prevail.</div><div><br><br>On Thursday, July 23, 2015 at 12:25:15 A=
M UTC-6, Thiago Macieira wrote:</div></div></div><blockquote class=3D"gmail=
_quote" style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-colo=
r:rgb(204,204,204);border-left-width:1px;border-left-style:solid">On Wednes=
day 22 July 2015 18:43:22 denis bider wrote:
<br>> > Please tell me of an uninstaller that rolls back when it runs=
into an
<br>>=20
<br>> error.
<br>>=20
<br>> I am perplexed. This question sounds to me like: "Tell me of =
a car that has
<br>> wheels."
<br>>=20
<br>> *All installers *must rollback when they run into an error.
<br>>=20
<br>> Ours do: <a href=3D"https://www.bitvise.com/" rel=3D"nofollow" tar=
get=3D"_blank">https://www.bitvise.com/</a>
<br>
<br>I said *uninstaller*. What do you do when you've removed some files=
, then=20
<br>something failed? Let's say a filesystem corruption prevents you fr=
om removing=20
<br>certain files, how do you roll back? Do you put the files you had alrea=
dy=20
<br>removed back in?
<br>
<br>Moving to the C++ case: if a sub-object destruction fails, do the previ=
ously=20
<br>destroyed object get re-constructed? That's impossible. In fact, yo=
ur proposal=20
<br>is that we ignore the problem and continue destruction.
<br>
<br>So it wouldn't be like the uninstaller rollback. It would be like a=
n=20
<br>uninstaller powering through and leaving an unclean state behind.
<br>
<br>> > That punts the problem to std::unique_ptr. Now the destructor
<br>> > of your sub-objects may be called while other sub-objects
<br>> > that should have been destroyed haven't yet.
<br>>=20
<br>> That's how destruction works.
<br>>=20
<br>> The only way this is an issue is if the 2+ resources you are freei=
ng have
<br>> logical interdependencies in the destructor. In this case, you nee=
d to
<br>> implement destruction properly.
<br>
<br>Which gets tricky very quickly, not to mention the fact that some of th=
em=20
<br>might be partially destroyed and thus in an invalid state.
<br>
<br>> The code you provided does not need multi-exceptions to be incorre=
ct. It is
<br>> already incorrect in C++11 if a1 destructor is noexcept(false).
<br>
<br>Which, like I said, the destructor is not supposed to be. A noexcept(fa=
lse)=20
<br>destructor today is considered, by itself, a problem. Everything using=
=20
<br>destructors assumes a contract that they don't throw. A noexcept(fa=
lse)y=20
<br>constructor is therefore a contract violation.
<br>
<br>> > But it's a change in behaviour, with increased memory pre=
ssure,
<br>> > for something that is not in use today.
<br>>=20
<br>> If we keep existing rules for how destructors' noexcept declar=
ations are
<br>> determined, there is no change of behavior unless you *actually us=
e
<br>> *destructors declared noexcept(false).
<br>
<br>So there's a change of behaviour to existing code.
<br>
<br>> Even if you have destructors declared noexcept(false), there is st=
ill no
<br>> need for additional cost unless you also implement *catch-any* han=
dlers to
<br>> handle multi-exceptions.
<br>
<br>As we've agreed, noexcept(false) destructors will do additional wor=
k in the=20
<br>exceptional case because they need to aggregate exceptions. Those destr=
uctors=20
<br>exist today and will start paying for a feature they don't use,
<br>
<br>Additionally, I'd expect that even noexcept destructors, for consis=
tency,=20
<br>should do destruction of all sub-objects, even if terminate() is coming=
.. So=20
<br>all destructors will start paying the price of this feature.
<br>
<br>> If your program does not implement any catch-any handlers, then
<br>> multi-exception support can again be fully optimized away, so that
<br>> std::terminate is called at the point where exceptions would be ag=
gregated.
<br>
<br>That's not correct. Multi-exceptions are implicit because of destru=
ctors' sub-
<br>object destruction.
<br>
<br>> > That is, the following =C2=A0will continue execution and aggr=
egate,
<br>> > with unmodified code:
<br>> >=20
<br>> > void f() { =C2=A0A a1, a2; }
<br>>=20
<br>> I do not propose changes to existing behavior, so yes. If A::~A() =
throws
<br>> and is declared noexcept(false), that's how that snippet *alre=
ady *behaves
<br>> in C++11 and 14.
<br>
<br>But the point is that you are proposing changes to the code above! You =
may not=20
<br>have explicitly said so, but it's a consequence of your proposal th=
at=20
<br>destructors aggregate.
<br>
<br>Given:
<br>
<br>struct B { A a1, a2; };
<br>
<br>Then B's destructor must implement continuation-after-exception and=
=20
<br>aggregation if a1.~A() throws. Given that this is the case, they I'=
d expect=20
<br>that for consistency the function f above do the same.
<br>
<br>And I also expect the destructor below to continue, even though it will=
=20
<br>terminate() instead of throwing an aggregate exception:
<br>
<br>struct C { A a1, a2; ~C() noexcept {} };
<br>
<br>> An exception can already occur in either of those objects' des=
tructors.
<br>> Both destructors will still be called.
<br>
<br>Not currently. Your proposal modifies this and that's the crux of t=
he problem.
<br>
<br>> What *can't *happen right now is that those exceptions cannot =
aggregate,
<br>> and the destructors cannot *both *throw. But either of them can.
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a href=3D"http://macieira.info" rel=3D"n=
ofollow" target=3D"_blank">macieira.info</a> - thiago (AT) <a href=3D"http:=
//kde.org" rel=3D"nofollow" target=3D"_blank">kde.org</a>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>=C2=A0 =C2=A0 =C2=A0 PGP/GPG: 0x6EF45358; fingerprint:
<br>=C2=A0 =C2=A0 =C2=A0 E067 918B B660 DBD1 105C =C2=A0966C 33F5 F005 6EF4=
5358
<br>
<br></blockquote></div></blockquote></div>
<p></p>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/Y6gjtmVyzBo/unsubscribe" target=3D"_blan=
k">https://groups.google.com/a/isocpp.org/d/topic/std-proposals/Y6gjtmVyzBo=
/unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_blank">std-prop=
osals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1134c49ec2aa46051b8c6cea--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Thu, 23 Jul 2015 09:12:58 -0700 (PDT)
Raw View
------=_Part_306_25517389.1437667978608
Content-Type: multipart/alternative;
boundary="----=_Part_307_1644965942.1437667978608"
------=_Part_307_1644965942.1437667978608
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
But exceptions are *not* transparent. One must be aware of exception safety=
=20
in *every single line of code* one writes. This will always be the case.
What I am suggesting are tools that make it easier to *manage* exceptions.=
=20
This makes exceptions more *powerful*.
Forget about destructors. Currently, you don't have a way to run 100 *tasks=
*,=20
and handle exceptions from more than one of them gracefully.
With multi-exceptions, you do. This could come highly convenient if you=20
want to execute 100 tasks in parallel.
Desktop computers have 8 or more virtual cores now. Applications=20
increasingly need to make use of them. C++ has made strides in making this=
=20
easier by adding standard library threading.
But the single-exception policy fails in this case. You run 8 or 16=20
parallel tasks, and 2 or 3 of them throw. You can't use exceptions to=20
convey this failure. They can't cross the thread boundary because you have=
=20
no way of aggregating them.
With this proposal, you do. You can have one thread run N parallel tasks;=
=20
collect exceptions from them; and convey them to the caller.
This is powerful stuff; and it's necessary. Without this, you have to=20
resort to inelegant, ad-hoc solutions for reporting errors. You have an=20
exception mechanism, but it's partial. It's not general. It's not complete.
On Thursday, July 23, 2015 at 9:20:22 AM UTC-6, Micha=C5=82 Dominiak wrote:
> So now your proposal also requires littering our code with weird `try`=20
> blocks. No good.
>
> Exceptions are meant to be "transparent", so code that doesn't explicitly=
=20
> *handle* errors doesn't need to care about them *at all*, ignoring their=
=20
> existence. Your proposal now changes that entirely, making all the code=
=20
> using *some* 3rd party code have to deal with weirdness.
>
> On Thu, Jul 23, 2015 at 4:32 PM denis bider <isocp...@denisbider.com=20
> <javascript:>> wrote:
>
>> Based on our exchange, I have come to realize that try-defer and=20
>> try-aggregate are not just syntactic sugar, but crucial elements of the=
=20
>> proposal that make exception aggregation easy to handle by anyone,=20
>> including beginners.
>>
>> Without these constructs, you are correct that exception aggregation is=
=20
>> too tricky for the average programmer.
>>
>> With these constructs, it becomes easy and elegant.
>>
>> I have updated the "Proposal summary" page to include try* and try+:
>>
>>
>> http://denisbider.blogspot.com/2015/07/aggregated-exceptions-proposal-su=
mmary.html
>>
>>
>> On Thursday, July 23, 2015 at 7:49:04 AM UTC-6, denis bider wrote:
>>
>>> I would like to point out that, with minimal syntactic sugar,=20
>>> multi-exceptions provide an easy way to handle code that may throw,=20
>>> including in destructors.
>>>
>>> Let's introduce two constructs, "try aggregate" and "try defer".
>>>
>>> - "Try aggregate" starts a block in which there can be "try defer"=20
>>> statements that aggregate exceptions.
>>>
>>> - At the end of the "try aggregate" block, any accumulated exceptions=
=20
>>> are thrown as a group.
>>>
>>> - If there are no aggregated exceptions, execution continues.
>>>
>>> Your example earlier was as follows:
>>>
>>>
>>> struct D { A *a1, *a2; D(); ~D() { dispose(a1); dispose(a2); } };=20
>>>
>>> template <typename T> void dispose(T *&ptr)=20
>>> {=20
>>> ptr->~T();=20
>>> remove_from_siblings(ptr);=20
>>> Allocator::dealloc(ptr);=20
>>> }=20
>>>
>>>
>>> As I mention, this is *currently* unsafe if A::~A() is noexcept(false).
>>>
>>> This is how it *would* be safe with the "try defer" syntactic sugar. To=
=20
>>> avoid introducing contextual keywords, I use "try+" for try defer,=20
>>> and "try*" for try aggregate:
>>>
>>>
>>> struct D {
>>> A *a1, *a2;
>>> D();
>>> ~D() {
>>> try* {
>>> try+ { dispose(a1); }
>>> try+ { dispose(a2); }
>>> }
>>> }
>>> };=20
>>>
>>> template <typename T> void dispose(T *&ptr)=20
>>> {
>>> try* {
>>> try+ { ptr->~T(); }
>>> remove_from_siblings(ptr);=20
>>> Allocator::dealloc(ptr);
>>> }
>>> }=20
>>>
>>>
>>> This provides nice, clean, elegant syntax that makes throwing=20
>>> destructors safe, and easy to handle.
>>>
>>> Anyone can understand and safely use this syntax. Even beginners.
>>>
>>>
>>> Now, to your continuing comments.
>>>
>>> There are resolutions to most of the issues you raise. They are apparen=
t=20
>>> to one who *wants *to solve them. The issue is that you do not *want *t=
hat.=20
>>> You want the opposite; to *not* solve them. You do not want to=20
>>> acknowledge solutions I have already proposed. Some of the issues you r=
aise=20
>>> are repeated and *purposeful* misunderstandings.
>>>
>>> For a technical argument to make sense, *there must be a reasonable way=
*=20
>>> I can find a solution. You *must* be open to my proposal in at least *s=
ome=20
>>> reasonable* scenario. You have to not move your goal posts. If there is=
=20
>>> no scenario in which you're open to my proposal, or if you keep moving =
goal=20
>>> posts, then a technical argument is a waste of time. It just comes down=
to=20
>>> a vote of who is for, and who's against; and whoever has the majority w=
ill=20
>>> prevail.
>>>
>>>
>>> On Thursday, July 23, 2015 at 12:25:15 AM UTC-6, Thiago Macieira wrote:
>>>
>>>> On Wednesday 22 July 2015 18:43:22 denis bider wrote:=20
>>>> > > Please tell me of an uninstaller that rolls back when it runs into=
=20
>>>> an=20
>>>> >=20
>>>> > error.=20
>>>> >=20
>>>> > I am perplexed. This question sounds to me like: "Tell me of a car=
=20
>>>> that has=20
>>>> > wheels."=20
>>>> >=20
>>>> > *All installers *must rollback when they run into an error.=20
>>>> >=20
>>>> > Ours do: https://www.bitvise.com/=20
>>>>
>>>> I said *uninstaller*. What do you do when you've removed some files,=
=20
>>>> then=20
>>>> something failed? Let's say a filesystem corruption prevents you from=
=20
>>>> removing=20
>>>> certain files, how do you roll back? Do you put the files you had=20
>>>> already=20
>>>> removed back in?=20
>>>>
>>>> Moving to the C++ case: if a sub-object destruction fails, do the=20
>>>> previously=20
>>>> destroyed object get re-constructed? That's impossible. In fact, your=
=20
>>>> proposal=20
>>>> is that we ignore the problem and continue destruction.=20
>>>>
>>>> So it wouldn't be like the uninstaller rollback. It would be like an=
=20
>>>> uninstaller powering through and leaving an unclean state behind.=20
>>>>
>>>> > > That punts the problem to std::unique_ptr. Now the destructor=20
>>>> > > of your sub-objects may be called while other sub-objects=20
>>>> > > that should have been destroyed haven't yet.=20
>>>> >=20
>>>> > That's how destruction works.=20
>>>> >=20
>>>> > The only way this is an issue is if the 2+ resources you are freeing=
=20
>>>> have=20
>>>> > logical interdependencies in the destructor. In this case, you need=
=20
>>>> to=20
>>>> > implement destruction properly.=20
>>>>
>>>> Which gets tricky very quickly, not to mention the fact that some of=
=20
>>>> them=20
>>>> might be partially destroyed and thus in an invalid state.=20
>>>>
>>>> > The code you provided does not need multi-exceptions to be incorrect=
..=20
>>>> It is=20
>>>> > already incorrect in C++11 if a1 destructor is noexcept(false).=20
>>>>
>>>> Which, like I said, the destructor is not supposed to be. A=20
>>>> noexcept(false)=20
>>>> destructor today is considered, by itself, a problem. Everything using=
=20
>>>> destructors assumes a contract that they don't throw. A=20
>>>> noexcept(false)y=20
>>>> constructor is therefore a contract violation.=20
>>>>
>>>> > > But it's a change in behaviour, with increased memory pressure,=20
>>>> > > for something that is not in use today.=20
>>>> >=20
>>>> > If we keep existing rules for how destructors' noexcept declarations=
=20
>>>> are=20
>>>> > determined, there is no change of behavior unless you *actually use=
=20
>>>> > *destructors declared noexcept(false).=20
>>>>
>>>> So there's a change of behaviour to existing code.=20
>>>>
>>>> > Even if you have destructors declared noexcept(false), there is stil=
l=20
>>>> no=20
>>>> > need for additional cost unless you also implement *catch-any*=20
>>>> handlers to=20
>>>> > handle multi-exceptions.=20
>>>>
>>>> As we've agreed, noexcept(false) destructors will do additional work i=
n=20
>>>> the=20
>>>> exceptional case because they need to aggregate exceptions. Those=20
>>>> destructors=20
>>>> exist today and will start paying for a feature they don't use,=20
>>>>
>>>> Additionally, I'd expect that even noexcept destructors, for=20
>>>> consistency,=20
>>>> should do destruction of all sub-objects, even if terminate() is=20
>>>> coming. So=20
>>>> all destructors will start paying the price of this feature.=20
>>>>
>>>> > If your program does not implement any catch-any handlers, then=20
>>>> > multi-exception support can again be fully optimized away, so that=
=20
>>>> > std::terminate is called at the point where exceptions would be=20
>>>> aggregated.=20
>>>>
>>>> That's not correct. Multi-exceptions are implicit because of=20
>>>> destructors' sub-=20
>>>> object destruction.=20
>>>>
>>>> > > That is, the following will continue execution and aggregate,=20
>>>> > > with unmodified code:=20
>>>> > >=20
>>>> > > void f() { A a1, a2; }=20
>>>> >=20
>>>> > I do not propose changes to existing behavior, so yes. If A::~A()=20
>>>> throws=20
>>>> > and is declared noexcept(false), that's how that snippet *already=20
>>>> *behaves=20
>>>> > in C++11 and 14.=20
>>>>
>>>> But the point is that you are proposing changes to the code above! You=
=20
>>>> may not=20
>>>> have explicitly said so, but it's a consequence of your proposal that=
=20
>>>> destructors aggregate.=20
>>>>
>>>> Given:=20
>>>>
>>>> struct B { A a1, a2; };=20
>>>>
>>>> Then B's destructor must implement continuation-after-exception and=20
>>>> aggregation if a1.~A() throws. Given that this is the case, they I'd=
=20
>>>> expect=20
>>>> that for consistency the function f above do the same.=20
>>>>
>>>> And I also expect the destructor below to continue, even though it wil=
l=20
>>>> terminate() instead of throwing an aggregate exception:=20
>>>>
>>>> struct C { A a1, a2; ~C() noexcept {} };=20
>>>>
>>>> > An exception can already occur in either of those objects'=20
>>>> destructors.=20
>>>> > Both destructors will still be called.=20
>>>>
>>>> Not currently. Your proposal modifies this and that's the crux of the=
=20
>>>> problem.=20
>>>>
>>>> > What *can't *happen right now is that those exceptions cannot=20
>>>> aggregate,=20
>>>> > and the destructors cannot *both *throw. But either of them can.=20
>>>>
>>>> --=20
>>>> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org=20
>>>> Software Architect - Intel Open Source Technology Center=20
>>>> PGP/GPG: 0x6EF45358; fingerprint:=20
>>>> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358=20
>>>>
>>>> --=20
>>
>> ---=20
>> You received this message because you are subscribed to a topic in the=
=20
>> Google Groups "ISO C++ Standard - Future Proposals" group.
>> To unsubscribe from this topic, visit=20
>> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/Y6gjtmVyzBo=
/unsubscribe
>> .
>> To unsubscribe from this group and all its topics, send an email to=20
>> std-proposal...@isocpp.org <javascript:>.
>> To post to this group, send email to std-pr...@isocpp.org <javascript:>.
>> Visit this group at=20
>> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>>
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_307_1644965942.1437667978608
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>But exceptions are <em>not</em> transparent. One must=
be aware of exception safety in <em>every single line of code</em> one wri=
tes. This will always be the case.</div><div><br></div><div>What I am sugge=
sting are tools that make it easier to=C2=A0<em>manage</em> exceptions. Thi=
s=C2=A0makes exceptions more <em>powerful</em>.</div><div><br></div><div>Fo=
rget about destructors. Currently, you don't have a way to run 100 <em>=
tasks</em>, and handle exceptions from more than one of them gracefully.</d=
iv><div><br></div><div>With multi-exceptions, you do. This could=C2=A0come =
highly=C2=A0convenient if you want to execute 100 tasks in parallel.</div><=
div><br></div><div>Desktop computers have 8 or more virtual cores now. Appl=
ications increasingly need to make use of them. C++ has made strides in mak=
ing this easier by adding standard library threading.</div><div><br></div><=
div>But the single-exception policy fails in this case. You run 8 or 16 par=
allel tasks, and 2 or 3=C2=A0of them throw. You can't use exceptions to=
convey this failure. They can't cross the thread boundary because you =
have no way of aggregating them.</div><div><br></div><div>With this proposa=
l, you do. You can have one thread run N parallel tasks; collect exceptions=
from them; and convey them to the caller.</div><div><br></div><div>This is=
powerful stuff; and it's necessary. Without this, you have to resort t=
o inelegant, ad-hoc solutions for reporting errors. You have an exception m=
echanism, but it's partial. It's not general. It's not complete=
..</div><div><br><br>On Thursday, July 23, 2015 at 9:20:22 AM UTC-6, Micha=
=C5=82 Dominiak wrote:</div><blockquote class=3D"gmail_quote" style=3D"marg=
in: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, =
204); border-left-width: 1px; border-left-style: solid;"><div dir=3D"ltr">S=
o now your proposal also requires littering our code with weird `try` block=
s. No good.<div><br></div><div>Exceptions are meant to be "transparent=
", so code that doesn't explicitly *handle* errors doesn't nee=
d to care about them *at all*, ignoring their existence. Your proposal now =
changes that entirely, making all the code using *some* 3rd party code have=
to deal with weirdness.</div></div><br><div class=3D"gmail_quote"><div dir=
=3D"ltr">On Thu, Jul 23, 2015 at 4:32 PM denis bider <<a onmousedown=3D"=
this.href=3D'javascript:';return true;" onclick=3D"this.href=3D'=
;javascript:';return true;" href=3D"javascript:" target=3D"_blank" rel=
=3D"nofollow">isocp...@denisbider.com</a>> wrote:<br></div><blockquote c=
lass=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex;=
border-left-color: rgb(204, 204, 204); border-left-width: 1px; border-left=
-style: solid;"><div dir=3D"ltr"><div>Based on our exchange, I have come to=
realize that try-defer and try-aggregate are not just syntactic sugar, but=
crucial elements of the proposal that make exception aggregation easy to h=
andle by anyone, including beginners.</div><div><br></div><div>Without thes=
e constructs, you are correct that exception aggregation is too tricky for =
the average programmer.</div><div><br></div><div>With these constructs, it =
becomes easy and elegant.</div><div><br></div><div>I have updated the "=
;Proposal summary" page to include try* and try+:</div><div><br></div>=
<div><a onmousedown=3D"this.href=3D'http://www.google.com/url?q\75http%=
3A%2F%2Fdenisbider.blogspot.com%2F2015%2F07%2Faggregated-exceptions-proposa=
l-summary.html\46sa\75D\46sntz\0751\46usg\75AFQjCNHoV_qxRzQyc3J8kc7gVKbZDBr=
k6w';return true;" onclick=3D"this.href=3D'http://www.google.com/ur=
l?q\75http%3A%2F%2Fdenisbider.blogspot.com%2F2015%2F07%2Faggregated-excepti=
ons-proposal-summary.html\46sa\75D\46sntz\0751\46usg\75AFQjCNHoV_qxRzQyc3J8=
kc7gVKbZDBrk6w';return true;" href=3D"http://denisbider.blogspot.com/20=
15/07/aggregated-exceptions-proposal-summary.html" target=3D"_blank" rel=3D=
"nofollow">http://denisbider.blogspot.com/2015/07/aggregated-exceptions-pro=
posal-summary.html</a></div></div><div dir=3D"ltr"><div><br><br>On Thursday=
, July 23, 2015 at 7:49:04 AM UTC-6, denis bider wrote:</div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; =
border-left-color: rgb(204, 204, 204); border-left-width: 1px; border-left-=
style: solid;"><div dir=3D"ltr"><div><div>I would like to point out that, w=
ith minimal syntactic sugar, multi-exceptions provide an easy way to handle=
code that may throw, including in destructors.</div><div><br></div><div>Le=
t's introduce two constructs, "try aggregate" and "try d=
efer".</div><div><br></div><div>- "Try aggregate" starts a b=
lock in which there can be "try defer" statements that aggregate =
exceptions.</div><div><br></div><div>- At the end of the "try aggregat=
e" block, any accumulated exceptions are thrown as a group.</div><div>=
<br></div><div>- If there are no aggregated exceptions, execution continues=
..</div><div><br></div><div>Your example earlier was as follows:</div><div><=
br></div><div><br></div><div><font face=3D"courier new,monospace">struct D =
{ A *a1, *a2; D(); ~D() { dispose(a1); dispose(a2); } }; <br><br>template &=
lt;typename T> void dispose(T *&ptr) <br>{ <br>=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0ptr->~T(); <br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0remove_from_siblings(ptr); <br>=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0Allocator::dealloc(ptr); <br>}</font> <br></div><di=
v><br></div><div><br></div><div>As I mention, this is <em>currently</em> un=
safe if A::~A() is noexcept(false).</div><div><br></div><div>This is how it=
<em>would</em> be safe with the "try defer" syntactic sugar. To =
avoid introducing contextual keywords, I use "try+" for try defer=
, and=C2=A0"try*" for try aggregate:</div><div><br></div><div><br=
></div><div><font face=3D"courier new,monospace">struct D {</font></div><di=
v><font face=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0 A *a1, *a2;</font=
></div><div><font face=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0 D();</f=
ont></div><div><font face=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0 ~D()=
{</font></div><div><font face=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0 try* {</font></div><div><font face=3D"courier new,=
monospace">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 try+ { dispose(a1); }</font></div><div><font face=3D"courier new,monosp=
ace">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 try=
+ { dispose(a2); }</font></div><div><font face=3D"courier new,monospace">=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }</font></div><div><font face=3D=
"courier new,monospace">=C2=A0=C2=A0=C2=A0 }</font></div><div><font face=3D=
"courier new,monospace">}; <br></font><br><font face=3D"courier new,monospa=
ce">template <typename T> void dispose(T *&ptr) <br>{</font></div=
><div><font face=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0 try* {<br>=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 try+ { ptr->~T(); }<br>=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0remove_from_siblings(ptr); <br>=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0Allocator::dealloc(ptr);</font=
></div><div><font face=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0 }<br>}<=
/font> <br></div><div><br></div><div><br></div><div>This provides nice, cle=
an, elegant syntax that makes throwing destructors safe, and easy to handle=
..</div><div><br></div><div>Anyone can understand and safely use this syntax=
.. Even beginners.</div><div><br></div><div><br></div><div>Now, to your cont=
inuing comments.</div><div><br></div><div>There are resolutions to most of =
the issues you raise.=C2=A0They=C2=A0are apparent to=C2=A0one who <em>wants=
</em>to solve them.=C2=A0The issue is that=C2=A0you do not <em>want </em>t=
hat. You want the opposite; to <em>not</em> solve them.=C2=A0You do not wan=
t to acknowledge=C2=A0solutions I have already proposed.=C2=A0Some of the i=
ssues=C2=A0you raise are=C2=A0repeated and=C2=A0<em>purposeful</em> misunde=
rstandings.</div><div><div><br></div><div>For a technical argument to make =
sense, <em>there must be a reasonable way</em> I can=C2=A0find a solution. =
You <em>must</em> be open to my proposal in at least <em>some reasonable</e=
m>=C2=A0scenario. You have to not move your goal posts.=C2=A0If there is no=
scenario in which you're open to my proposal, or if you keep moving go=
al posts,=C2=A0then a technical argument is a waste of time. It just comes =
down to a vote of who is for, and who's against; and=C2=A0whoever has t=
he majority=C2=A0will prevail.</div><div><br><br>On Thursday, July 23, 2015=
at 12:25:15 AM UTC-6, Thiago Macieira wrote:</div></div></div><blockquote =
class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex=
; border-left-color: rgb(204, 204, 204); border-left-width: 1px; border-lef=
t-style: solid;">On Wednesday 22 July 2015 18:43:22 denis bider wrote:
<br>> > Please tell me of an uninstaller that rolls back when it runs=
into an
<br>>=20
<br>> error.
<br>>=20
<br>> I am perplexed. This question sounds to me like: "Tell me of =
a car that has
<br>> wheels."
<br>>=20
<br>> *All installers *must rollback when they run into an error.
<br>>=20
<br>> Ours do: <a onmousedown=3D"this.href=3D'https://www.google.com=
/url?q\75https%3A%2F%2Fwww.bitvise.com%2F\46sa\75D\46sntz\0751\46usg\75AFQj=
CNH9_QQ7hnBKE1KSKpRXkn_2ZDqTvQ';return true;" onclick=3D"this.href=3D&#=
39;https://www.google.com/url?q\75https%3A%2F%2Fwww.bitvise.com%2F\46sa\75D=
\46sntz\0751\46usg\75AFQjCNH9_QQ7hnBKE1KSKpRXkn_2ZDqTvQ';return true;" =
href=3D"https://www.bitvise.com/" target=3D"_blank" rel=3D"nofollow">https:=
//www.bitvise.com/</a>
<br>
<br>I said *uninstaller*. What do you do when you've removed some files=
, then=20
<br>something failed? Let's say a filesystem corruption prevents you fr=
om removing=20
<br>certain files, how do you roll back? Do you put the files you had alrea=
dy=20
<br>removed back in?
<br>
<br>Moving to the C++ case: if a sub-object destruction fails, do the previ=
ously=20
<br>destroyed object get re-constructed? That's impossible. In fact, yo=
ur proposal=20
<br>is that we ignore the problem and continue destruction.
<br>
<br>So it wouldn't be like the uninstaller rollback. It would be like a=
n=20
<br>uninstaller powering through and leaving an unclean state behind.
<br>
<br>> > That punts the problem to std::unique_ptr. Now the destructor
<br>> > of your sub-objects may be called while other sub-objects
<br>> > that should have been destroyed haven't yet.
<br>>=20
<br>> That's how destruction works.
<br>>=20
<br>> The only way this is an issue is if the 2+ resources you are freei=
ng have
<br>> logical interdependencies in the destructor. In this case, you nee=
d to
<br>> implement destruction properly.
<br>
<br>Which gets tricky very quickly, not to mention the fact that some of th=
em=20
<br>might be partially destroyed and thus in an invalid state.
<br>
<br>> The code you provided does not need multi-exceptions to be incorre=
ct. It is
<br>> already incorrect in C++11 if a1 destructor is noexcept(false).
<br>
<br>Which, like I said, the destructor is not supposed to be. A noexcept(fa=
lse)=20
<br>destructor today is considered, by itself, a problem. Everything using=
=20
<br>destructors assumes a contract that they don't throw. A noexcept(fa=
lse)y=20
<br>constructor is therefore a contract violation.
<br>
<br>> > But it's a change in behaviour, with increased memory pre=
ssure,
<br>> > for something that is not in use today.
<br>>=20
<br>> If we keep existing rules for how destructors' noexcept declar=
ations are
<br>> determined, there is no change of behavior unless you *actually us=
e
<br>> *destructors declared noexcept(false).
<br>
<br>So there's a change of behaviour to existing code.
<br>
<br>> Even if you have destructors declared noexcept(false), there is st=
ill no
<br>> need for additional cost unless you also implement *catch-any* han=
dlers to
<br>> handle multi-exceptions.
<br>
<br>As we've agreed, noexcept(false) destructors will do additional wor=
k in the=20
<br>exceptional case because they need to aggregate exceptions. Those destr=
uctors=20
<br>exist today and will start paying for a feature they don't use,
<br>
<br>Additionally, I'd expect that even noexcept destructors, for consis=
tency,=20
<br>should do destruction of all sub-objects, even if terminate() is coming=
.. So=20
<br>all destructors will start paying the price of this feature.
<br>
<br>> If your program does not implement any catch-any handlers, then
<br>> multi-exception support can again be fully optimized away, so that
<br>> std::terminate is called at the point where exceptions would be ag=
gregated.
<br>
<br>That's not correct. Multi-exceptions are implicit because of destru=
ctors' sub-
<br>object destruction.
<br>
<br>> > That is, the following =C2=A0will continue execution and aggr=
egate,
<br>> > with unmodified code:
<br>> >=20
<br>> > void f() { =C2=A0A a1, a2; }
<br>>=20
<br>> I do not propose changes to existing behavior, so yes. If A::~A() =
throws
<br>> and is declared noexcept(false), that's how that snippet *alre=
ady *behaves
<br>> in C++11 and 14.
<br>
<br>But the point is that you are proposing changes to the code above! You =
may not=20
<br>have explicitly said so, but it's a consequence of your proposal th=
at=20
<br>destructors aggregate.
<br>
<br>Given:
<br>
<br>struct B { A a1, a2; };
<br>
<br>Then B's destructor must implement continuation-after-exception and=
=20
<br>aggregation if a1.~A() throws. Given that this is the case, they I'=
d expect=20
<br>that for consistency the function f above do the same.
<br>
<br>And I also expect the destructor below to continue, even though it will=
=20
<br>terminate() instead of throwing an aggregate exception:
<br>
<br>struct C { A a1, a2; ~C() noexcept {} };
<br>
<br>> An exception can already occur in either of those objects' des=
tructors.
<br>> Both destructors will still be called.
<br>
<br>Not currently. Your proposal modifies this and that's the crux of t=
he problem.
<br>
<br>> What *can't *happen right now is that those exceptions cannot =
aggregate,
<br>> and the destructors cannot *both *throw. But either of them can.
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a onmousedown=3D"this.href=3D'http:/=
/www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\75D\46sntz\0751\46u=
sg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.=
href=3D'http://www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\7=
5D\46sntz\0751\46usg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;=
" href=3D"http://macieira.info" target=3D"_blank" rel=3D"nofollow">macieira=
..info</a> - thiago (AT) <a onmousedown=3D"this.href=3D'http://www.googl=
e.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\75AFQjCNHGRJd=
o5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'http=
://www.google.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\7=
5AFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;" href=3D"http://kde.o=
rg" target=3D"_blank" rel=3D"nofollow">kde.org</a>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>=C2=A0 =C2=A0 =C2=A0 PGP/GPG: 0x6EF45358; fingerprint:
<br>=C2=A0 =C2=A0 =C2=A0 E067 918B B660 DBD1 105C =C2=A0966C 33F5 F005 6EF4=
5358
<br>
<br></blockquote></div></blockquote></div>
<p></p>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a onmousedown=3D"this.href=3D'ht=
tps://groups.google.com/a/isocpp.org/d/topic/std-proposals/Y6gjtmVyzBo/unsu=
bscribe';return true;" onclick=3D"this.href=3D'https://groups.googl=
e.com/a/isocpp.org/d/topic/std-proposals/Y6gjtmVyzBo/unsubscribe';retur=
n true;" href=3D"https://groups.google.com/a/isocpp.org/d/topic/std-proposa=
ls/Y6gjtmVyzBo/unsubscribe" target=3D"_blank" rel=3D"nofollow">https://grou=
ps.google.com/a/isocpp.org/d/topic/std-proposals/Y6gjtmVyzBo/unsubscribe</a=
>.<br>
To unsubscribe from this group and all its topics, send an email to <a onmo=
usedown=3D"this.href=3D'javascript:';return true;" onclick=3D"this.=
href=3D'javascript:';return true;" href=3D"javascript:" target=3D"_=
blank" rel=3D"nofollow">std-proposal...@isocpp.org</a>.<br>
To post to this group, send email to <a onmousedown=3D"this.href=3D'jav=
ascript:';return true;" onclick=3D"this.href=3D'javascript:';re=
turn true;" href=3D"javascript:" target=3D"_blank" rel=3D"nofollow">std-pr.=
...@isocpp.org</a>.<br>
Visit this group at <a onmousedown=3D"this.href=3D'http://groups.google=
..com/a/isocpp.org/group/std-proposals/';return true;" onclick=3D"this.h=
ref=3D'http://groups.google.com/a/isocpp.org/group/std-proposals/';=
return true;" href=3D"http://groups.google.com/a/isocpp.org/group/std-propo=
sals/" target=3D"_blank" rel=3D"nofollow">http://groups.google.com/a/isocpp=
..org/group/std-proposals/</a>.<br>
</blockquote></div>
</blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_307_1644965942.1437667978608--
------=_Part_306_25517389.1437667978608--
.
Author: =?UTF-8?Q?Micha=C5=82_Dominiak?= <griwes@griwes.info>
Date: Thu, 23 Jul 2015 16:22:10 +0000
Raw View
--001a1134c49ea3c728051b8d4aa3
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Please do watch Jon Kalb's talk from CppCon; it should enlighten you about
why you are wrong about this.
On Thu, 23 Jul 2015 6:13 PM denis bider <isocppgroup@denisbider.com> wrote:
> But exceptions are *not* transparent. One must be aware of exception
> safety in *every single line of code* one writes. This will always be the
> case.
>
> What I am suggesting are tools that make it easier to *manage*
> exceptions. This makes exceptions more *powerful*.
>
> Forget about destructors. Currently, you don't have a way to run 100
> *tasks*, and handle exceptions from more than one of them gracefully.
>
> With multi-exceptions, you do. This could come highly convenient if you
> want to execute 100 tasks in parallel.
>
> Desktop computers have 8 or more virtual cores now. Applications
> increasingly need to make use of them. C++ has made strides in making thi=
s
> easier by adding standard library threading.
>
> But the single-exception policy fails in this case. You run 8 or 16
> parallel tasks, and 2 or 3 of them throw. You can't use exceptions to
> convey this failure. They can't cross the thread boundary because you hav=
e
> no way of aggregating them.
>
> With this proposal, you do. You can have one thread run N parallel tasks;
> collect exceptions from them; and convey them to the caller.
>
> This is powerful stuff; and it's necessary. Without this, you have to
> resort to inelegant, ad-hoc solutions for reporting errors. You have an
> exception mechanism, but it's partial. It's not general. It's not complet=
e.
>
>
> On Thursday, July 23, 2015 at 9:20:22 AM UTC-6, Micha=C5=82 Dominiak wrot=
e:
>
>> So now your proposal also requires littering our code with weird `try`
>> blocks. No good.
>>
>> Exceptions are meant to be "transparent", so code that doesn't explicitl=
y
>> *handle* errors doesn't need to care about them *at all*, ignoring their
>> existence. Your proposal now changes that entirely, making all the code
>> using *some* 3rd party code have to deal with weirdness.
>>
>> On Thu, Jul 23, 2015 at 4:32 PM denis bider <isocp...@denisbider.com>
>> wrote:
>>
> Based on our exchange, I have come to realize that try-defer and
>>> try-aggregate are not just syntactic sugar, but crucial elements of the
>>> proposal that make exception aggregation easy to handle by anyone,
>>> including beginners.
>>>
>>> Without these constructs, you are correct that exception aggregation is
>>> too tricky for the average programmer.
>>>
>>> With these constructs, it becomes easy and elegant.
>>>
>>> I have updated the "Proposal summary" page to include try* and try+:
>>>
>>>
>>> http://denisbider.blogspot.com/2015/07/aggregated-exceptions-proposal-s=
ummary.html
>>>
>>>
>>> On Thursday, July 23, 2015 at 7:49:04 AM UTC-6, denis bider wrote:
>>>
>>>> I would like to point out that, with minimal syntactic sugar,
>>>> multi-exceptions provide an easy way to handle code that may throw,
>>>> including in destructors.
>>>>
>>>> Let's introduce two constructs, "try aggregate" and "try defer".
>>>>
>>>> - "Try aggregate" starts a block in which there can be "try defer"
>>>> statements that aggregate exceptions.
>>>>
>>>> - At the end of the "try aggregate" block, any accumulated exceptions
>>>> are thrown as a group.
>>>>
>>>> - If there are no aggregated exceptions, execution continues.
>>>>
>>>> Your example earlier was as follows:
>>>>
>>>>
>>>> struct D { A *a1, *a2; D(); ~D() { dispose(a1); dispose(a2); } };
>>>>
>>>> template <typename T> void dispose(T *&ptr)
>>>> {
>>>> ptr->~T();
>>>> remove_from_siblings(ptr);
>>>> Allocator::dealloc(ptr);
>>>> }
>>>>
>>>>
>>>> As I mention, this is *currently* unsafe if A::~A() is noexcept(false)=
..
>>>>
>>>> This is how it *would* be safe with the "try defer" syntactic sugar.
>>>> To avoid introducing contextual keywords, I use "try+" for try defer,
>>>> and "try*" for try aggregate:
>>>>
>>>>
>>>> struct D {
>>>> A *a1, *a2;
>>>> D();
>>>> ~D() {
>>>> try* {
>>>> try+ { dispose(a1); }
>>>> try+ { dispose(a2); }
>>>> }
>>>> }
>>>> };
>>>>
>>>> template <typename T> void dispose(T *&ptr)
>>>> {
>>>> try* {
>>>> try+ { ptr->~T(); }
>>>> remove_from_siblings(ptr);
>>>> Allocator::dealloc(ptr);
>>>> }
>>>> }
>>>>
>>>>
>>>> This provides nice, clean, elegant syntax that makes throwing
>>>> destructors safe, and easy to handle.
>>>>
>>>> Anyone can understand and safely use this syntax. Even beginners.
>>>>
>>>>
>>>> Now, to your continuing comments.
>>>>
>>>> There are resolutions to most of the issues you raise. They are
>>>> apparent to one who *wants *to solve them. The issue is that you do
>>>> not *want *that. You want the opposite; to *not* solve them. You do
>>>> not want to acknowledge solutions I have already proposed. Some of the
>>>> issues you raise are repeated and *purposeful* misunderstandings.
>>>>
>>>> For a technical argument to make sense, *there must be a reasonable
>>>> way* I can find a solution. You *must* be open to my proposal in at
>>>> least *some reasonable* scenario. You have to not move your goal
>>>> posts. If there is no scenario in which you're open to my proposal, or=
if
>>>> you keep moving goal posts, then a technical argument is a waste of ti=
me.
>>>> It just comes down to a vote of who is for, and who's against; and who=
ever
>>>> has the majority will prevail.
>>>>
>>>>
>>>> On Thursday, July 23, 2015 at 12:25:15 AM UTC-6, Thiago Macieira wrote=
:
>>>>
>>>>> On Wednesday 22 July 2015 18:43:22 denis bider wrote:
>>>>> > > Please tell me of an uninstaller that rolls back when it runs int=
o
>>>>> an
>>>>> >
>>>>> > error.
>>>>> >
>>>>> > I am perplexed. This question sounds to me like: "Tell me of a car
>>>>> that has
>>>>> > wheels."
>>>>> >
>>>>> > *All installers *must rollback when they run into an error.
>>>>> >
>>>>> > Ours do: https://www.bitvise.com/
>>>>>
>>>>> I said *uninstaller*. What do you do when you've removed some files,
>>>>> then
>>>>> something failed? Let's say a filesystem corruption prevents you from
>>>>> removing
>>>>> certain files, how do you roll back? Do you put the files you had
>>>>> already
>>>>> removed back in?
>>>>>
>>>>> Moving to the C++ case: if a sub-object destruction fails, do the
>>>>> previously
>>>>> destroyed object get re-constructed? That's impossible. In fact, your
>>>>> proposal
>>>>> is that we ignore the problem and continue destruction.
>>>>>
>>>>> So it wouldn't be like the uninstaller rollback. It would be like an
>>>>> uninstaller powering through and leaving an unclean state behind.
>>>>>
>>>>> > > That punts the problem to std::unique_ptr. Now the destructor
>>>>> > > of your sub-objects may be called while other sub-objects
>>>>> > > that should have been destroyed haven't yet.
>>>>> >
>>>>> > That's how destruction works.
>>>>> >
>>>>> > The only way this is an issue is if the 2+ resources you are freein=
g
>>>>> have
>>>>> > logical interdependencies in the destructor. In this case, you need
>>>>> to
>>>>> > implement destruction properly.
>>>>>
>>>>> Which gets tricky very quickly, not to mention the fact that some of
>>>>> them
>>>>> might be partially destroyed and thus in an invalid state.
>>>>>
>>>>> > The code you provided does not need multi-exceptions to be
>>>>> incorrect. It is
>>>>> > already incorrect in C++11 if a1 destructor is noexcept(false).
>>>>>
>>>>> Which, like I said, the destructor is not supposed to be. A
>>>>> noexcept(false)
>>>>> destructor today is considered, by itself, a problem. Everything usin=
g
>>>>> destructors assumes a contract that they don't throw. A
>>>>> noexcept(false)y
>>>>> constructor is therefore a contract violation.
>>>>>
>>>>> > > But it's a change in behaviour, with increased memory pressure,
>>>>> > > for something that is not in use today.
>>>>> >
>>>>> > If we keep existing rules for how destructors' noexcept declaration=
s
>>>>> are
>>>>> > determined, there is no change of behavior unless you *actually use
>>>>> > *destructors declared noexcept(false).
>>>>>
>>>>> So there's a change of behaviour to existing code.
>>>>>
>>>>> > Even if you have destructors declared noexcept(false), there is
>>>>> still no
>>>>> > need for additional cost unless you also implement *catch-any*
>>>>> handlers to
>>>>> > handle multi-exceptions.
>>>>>
>>>>> As we've agreed, noexcept(false) destructors will do additional work
>>>>> in the
>>>>> exceptional case because they need to aggregate exceptions. Those
>>>>> destructors
>>>>> exist today and will start paying for a feature they don't use,
>>>>>
>>>>> Additionally, I'd expect that even noexcept destructors, for
>>>>> consistency,
>>>>> should do destruction of all sub-objects, even if terminate() is
>>>>> coming. So
>>>>> all destructors will start paying the price of this feature.
>>>>>
>>>>> > If your program does not implement any catch-any handlers, then
>>>>> > multi-exception support can again be fully optimized away, so that
>>>>> > std::terminate is called at the point where exceptions would be
>>>>> aggregated.
>>>>>
>>>>> That's not correct. Multi-exceptions are implicit because of
>>>>> destructors' sub-
>>>>> object destruction.
>>>>>
>>>>> > > That is, the following will continue execution and aggregate,
>>>>> > > with unmodified code:
>>>>> > >
>>>>> > > void f() { A a1, a2; }
>>>>> >
>>>>> > I do not propose changes to existing behavior, so yes. If A::~A()
>>>>> throws
>>>>> > and is declared noexcept(false), that's how that snippet *already
>>>>> *behaves
>>>>> > in C++11 and 14.
>>>>>
>>>>> But the point is that you are proposing changes to the code above! Yo=
u
>>>>> may not
>>>>> have explicitly said so, but it's a consequence of your proposal that
>>>>> destructors aggregate.
>>>>>
>>>>> Given:
>>>>>
>>>>> struct B { A a1, a2; };
>>>>>
>>>>> Then B's destructor must implement continuation-after-exception and
>>>>> aggregation if a1.~A() throws. Given that this is the case, they I'd
>>>>> expect
>>>>> that for consistency the function f above do the same.
>>>>>
>>>>> And I also expect the destructor below to continue, even though it
>>>>> will
>>>>> terminate() instead of throwing an aggregate exception:
>>>>>
>>>>> struct C { A a1, a2; ~C() noexcept {} };
>>>>>
>>>>> > An exception can already occur in either of those objects'
>>>>> destructors.
>>>>> > Both destructors will still be called.
>>>>>
>>>>> Not currently. Your proposal modifies this and that's the crux of the
>>>>> problem.
>>>>>
>>>>> > What *can't *happen right now is that those exceptions cannot
>>>>> aggregate,
>>>>> > and the destructors cannot *both *throw. But either of them can.
>>>>>
>>>>> --
>>>>> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
>>>>> Software Architect - Intel Open Source Technology Center
>>>>> PGP/GPG: 0x6EF45358; fingerprint:
>>>>> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
>>>>>
>>>>> --
>>>
>>> ---
>>> You received this message because you are subscribed to a topic in the
>>> Google Groups "ISO C++ Standard - Future Proposals" group.
>>> To unsubscribe from this topic, visit
>>> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/Y6gjtmVyzB=
o/unsubscribe
>>> .
>>>
>> To unsubscribe from this group and all its topics, send an email to
>>> std-proposal...@isocpp.org.
>>> To post to this group, send email to std-pr...@isocpp.org.
>>
>>
>>> Visit this group at
>>> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>>>
>>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--001a1134c49ea3c728051b8d4aa3
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<p dir=3D"ltr">Please do watch Jon Kalb's talk from CppCon; it should e=
nlighten you about why you are wrong about this.</p>
<br><div class=3D"gmail_quote"><div dir=3D"ltr">On Thu, 23 Jul 2015 6:13 PM=
=C2=A0denis bider <<a href=3D"mailto:isocppgroup@denisbider.com">isocppg=
roup@denisbider.com</a>> wrote:<br></div><blockquote class=3D"gmail_quot=
e" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">=
<div dir=3D"ltr"><div>But exceptions are <em>not</em> transparent. One must=
be aware of exception safety in <em>every single line of code</em> one wri=
tes. This will always be the case.</div><div><br></div><div>What I am sugge=
sting are tools that make it easier to=C2=A0<em>manage</em> exceptions. Thi=
s=C2=A0makes exceptions more <em>powerful</em>.</div><div><br></div><div>Fo=
rget about destructors. Currently, you don't have a way to run 100 <em>=
tasks</em>, and handle exceptions from more than one of them gracefully.</d=
iv><div><br></div><div>With multi-exceptions, you do. This could=C2=A0come =
highly=C2=A0convenient if you want to execute 100 tasks in parallel.</div><=
div><br></div><div>Desktop computers have 8 or more virtual cores now. Appl=
ications increasingly need to make use of them. C++ has made strides in mak=
ing this easier by adding standard library threading.</div><div><br></div><=
div>But the single-exception policy fails in this case. You run 8 or 16 par=
allel tasks, and 2 or 3=C2=A0of them throw. You can't use exceptions to=
convey this failure. They can't cross the thread boundary because you =
have no way of aggregating them.</div><div><br></div><div>With this proposa=
l, you do. You can have one thread run N parallel tasks; collect exceptions=
from them; and convey them to the caller.</div><div><br></div><div>This is=
powerful stuff; and it's necessary. Without this, you have to resort t=
o inelegant, ad-hoc solutions for reporting errors. You have an exception m=
echanism, but it's partial. It's not general. It's not complete=
..</div></div><div dir=3D"ltr"><div><br><br>On Thursday, July 23, 2015 at 9:=
20:22 AM UTC-6, Micha=C5=82 Dominiak wrote:</div></div><div dir=3D"ltr"><bl=
ockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding-le=
ft:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left=
-style:solid"><div dir=3D"ltr">So now your proposal also requires littering=
our code with weird `try` blocks. No good.<div><br></div><div>Exceptions a=
re meant to be "transparent", so code that doesn't explicitly=
*handle* errors doesn't need to care about them *at all*, ignoring the=
ir existence. Your proposal now changes that entirely, making all the code =
using *some* 3rd party code have to deal with weirdness.</div></div><br></b=
lockquote></div><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D=
"margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,20=
4);border-left-width:1px;border-left-style:solid"><div class=3D"gmail_quote=
"><div dir=3D"ltr">On Thu, Jul 23, 2015 at 4:32 PM denis bider <<a rel=
=3D"nofollow">isocp...@denisbider.com</a>> wrote:<br></div></div></block=
quote></div><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);b=
order-left-width:1px;border-left-style:solid"><div class=3D"gmail_quote"><b=
lockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding-l=
eft:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-lef=
t-style:solid"><div dir=3D"ltr"><div>Based on our exchange, I have come to =
realize that try-defer and try-aggregate are not just syntactic sugar, but =
crucial elements of the proposal that make exception aggregation easy to ha=
ndle by anyone, including beginners.</div><div><br></div><div>Without these=
constructs, you are correct that exception aggregation is too tricky for t=
he average programmer.</div><div><br></div><div>With these constructs, it b=
ecomes easy and elegant.</div><div><br></div><div>I have updated the "=
Proposal summary" page to include try* and try+:</div><div><br></div><=
div><a href=3D"http://denisbider.blogspot.com/2015/07/aggregated-exceptions=
-proposal-summary.html" rel=3D"nofollow" target=3D"_blank">http://denisbide=
r.blogspot.com/2015/07/aggregated-exceptions-proposal-summary.html</a></div=
></div><div dir=3D"ltr"><div><br><br>On Thursday, July 23, 2015 at 7:49:04 =
AM UTC-6, denis bider wrote:</div><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204=
,204);border-left-width:1px;border-left-style:solid"><div dir=3D"ltr"><div>=
<div>I would like to point out that, with minimal syntactic sugar, multi-ex=
ceptions provide an easy way to handle code that may throw, including in de=
structors.</div><div><br></div><div>Let's introduce two constructs, &qu=
ot;try aggregate" and "try defer".</div><div><br></div><div>=
- "Try aggregate" starts a block in which there can be "try =
defer" statements that aggregate exceptions.</div><div><br></div><div>=
- At the end of the "try aggregate" block, any accumulated except=
ions are thrown as a group.</div><div><br></div><div>- If there are no aggr=
egated exceptions, execution continues.</div><div><br></div><div>Your examp=
le earlier was as follows:</div><div><br></div><div><br></div><div><font fa=
ce=3D"courier new,monospace">struct D { A *a1, *a2; D(); ~D() { dispose(a1)=
; dispose(a2); } }; <br><br>template <typename T> void dispose(T *&am=
p;ptr) <br>{ <br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0ptr->~T=
(); <br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0remove_from_sibling=
s(ptr); <br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0Allocator::deal=
loc(ptr); <br>}</font> <br></div><div><br></div><div><br></div><div>As I me=
ntion, this is <em>currently</em> unsafe if A::~A() is noexcept(false).</di=
v><div><br></div><div>This is how it <em>would</em> be safe with the "=
try defer" syntactic sugar. To avoid introducing contextual keywords, =
I use "try+" for try defer, and=C2=A0"try*" for try agg=
regate:</div><div><br></div><div><br></div><div><font face=3D"courier new,m=
onospace">struct D {</font></div><div><font face=3D"courier new,monospace">=
=C2=A0=C2=A0=C2=A0 A *a1, *a2;</font></div><div><font face=3D"courier new,m=
onospace">=C2=A0=C2=A0=C2=A0 D();</font></div><div><font face=3D"courier ne=
w,monospace">=C2=A0=C2=A0=C2=A0 ~D() {</font></div><div><font face=3D"couri=
er new,monospace">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 try* {</font><=
/div><div><font face=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 try+ { dispose(a1); }</font></div><=
div><font face=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 try+ { dispose(a2); }</font></div><div><f=
ont face=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 }</font></div><div><font face=3D"courier new,monospace">=C2=A0=C2=A0=C2=
=A0 }</font></div><div><font face=3D"courier new,monospace">}; <br></font><=
br><font face=3D"courier new,monospace">template <typename T> void di=
spose(T *&ptr) <br>{</font></div><div><font face=3D"courier new,monospa=
ce">=C2=A0=C2=A0=C2=A0 try* {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
try+ { ptr->~T(); }<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
remove_from_siblings(ptr); <br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0Allocator::dealloc(ptr);</font></div><div><font face=3D"courier new,m=
onospace">=C2=A0=C2=A0=C2=A0 }<br>}</font> <br></div><div><br></div><div><b=
r></div><div>This provides nice, clean, elegant syntax that makes throwing =
destructors safe, and easy to handle.</div><div><br></div><div>Anyone can u=
nderstand and safely use this syntax. Even beginners.</div><div><br></div><=
div><br></div><div>Now, to your continuing comments.</div><div><br></div><d=
iv>There are resolutions to most of the issues you raise.=C2=A0They=C2=A0ar=
e apparent to=C2=A0one who <em>wants </em>to solve them.=C2=A0The issue is =
that=C2=A0you do not <em>want </em>that. You want the opposite; to <em>not<=
/em> solve them.=C2=A0You do not want to acknowledge=C2=A0solutions I have =
already proposed.=C2=A0Some of the issues=C2=A0you raise are=C2=A0repeated =
and=C2=A0<em>purposeful</em> misunderstandings.</div><div><div><br></div><d=
iv>For a technical argument to make sense, <em>there must be a reasonable w=
ay</em> I can=C2=A0find a solution. You <em>must</em> be open to my proposa=
l in at least <em>some reasonable</em>=C2=A0scenario. You have to not move =
your goal posts.=C2=A0If there is no scenario in which you're open to m=
y proposal, or if you keep moving goal posts,=C2=A0then a technical argumen=
t is a waste of time. It just comes down to a vote of who is for, and who&#=
39;s against; and=C2=A0whoever has the majority=C2=A0will prevail.</div><di=
v><br><br>On Thursday, July 23, 2015 at 12:25:15 AM UTC-6, Thiago Macieira =
wrote:</div></div></div><blockquote class=3D"gmail_quote" style=3D"margin:0=
px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border=
-left-width:1px;border-left-style:solid">On Wednesday 22 July 2015 18:43:22=
denis bider wrote:
<br>> > Please tell me of an uninstaller that rolls back when it runs=
into an
<br>>=20
<br>> error.
<br>>=20
<br>> I am perplexed. This question sounds to me like: "Tell me of =
a car that has
<br>> wheels."
<br>>=20
<br>> *All installers *must rollback when they run into an error.
<br>>=20
<br>> Ours do: <a href=3D"https://www.bitvise.com/" rel=3D"nofollow" tar=
get=3D"_blank">https://www.bitvise.com/</a>
<br>
<br>I said *uninstaller*. What do you do when you've removed some files=
, then=20
<br>something failed? Let's say a filesystem corruption prevents you fr=
om removing=20
<br>certain files, how do you roll back? Do you put the files you had alrea=
dy=20
<br>removed back in?
<br>
<br>Moving to the C++ case: if a sub-object destruction fails, do the previ=
ously=20
<br>destroyed object get re-constructed? That's impossible. In fact, yo=
ur proposal=20
<br>is that we ignore the problem and continue destruction.
<br>
<br>So it wouldn't be like the uninstaller rollback. It would be like a=
n=20
<br>uninstaller powering through and leaving an unclean state behind.
<br>
<br>> > That punts the problem to std::unique_ptr. Now the destructor
<br>> > of your sub-objects may be called while other sub-objects
<br>> > that should have been destroyed haven't yet.
<br>>=20
<br>> That's how destruction works.
<br>>=20
<br>> The only way this is an issue is if the 2+ resources you are freei=
ng have
<br>> logical interdependencies in the destructor. In this case, you nee=
d to
<br>> implement destruction properly.
<br>
<br>Which gets tricky very quickly, not to mention the fact that some of th=
em=20
<br>might be partially destroyed and thus in an invalid state.
<br>
<br>> The code you provided does not need multi-exceptions to be incorre=
ct. It is
<br>> already incorrect in C++11 if a1 destructor is noexcept(false).
<br>
<br>Which, like I said, the destructor is not supposed to be. A noexcept(fa=
lse)=20
<br>destructor today is considered, by itself, a problem. Everything using=
=20
<br>destructors assumes a contract that they don't throw. A noexcept(fa=
lse)y=20
<br>constructor is therefore a contract violation.
<br>
<br>> > But it's a change in behaviour, with increased memory pre=
ssure,
<br>> > for something that is not in use today.
<br>>=20
<br>> If we keep existing rules for how destructors' noexcept declar=
ations are
<br>> determined, there is no change of behavior unless you *actually us=
e
<br>> *destructors declared noexcept(false).
<br>
<br>So there's a change of behaviour to existing code.
<br>
<br>> Even if you have destructors declared noexcept(false), there is st=
ill no
<br>> need for additional cost unless you also implement *catch-any* han=
dlers to
<br>> handle multi-exceptions.
<br>
<br>As we've agreed, noexcept(false) destructors will do additional wor=
k in the=20
<br>exceptional case because they need to aggregate exceptions. Those destr=
uctors=20
<br>exist today and will start paying for a feature they don't use,
<br>
<br>Additionally, I'd expect that even noexcept destructors, for consis=
tency,=20
<br>should do destruction of all sub-objects, even if terminate() is coming=
.. So=20
<br>all destructors will start paying the price of this feature.
<br>
<br>> If your program does not implement any catch-any handlers, then
<br>> multi-exception support can again be fully optimized away, so that
<br>> std::terminate is called at the point where exceptions would be ag=
gregated.
<br>
<br>That's not correct. Multi-exceptions are implicit because of destru=
ctors' sub-
<br>object destruction.
<br>
<br>> > That is, the following =C2=A0will continue execution and aggr=
egate,
<br>> > with unmodified code:
<br>> >=20
<br>> > void f() { =C2=A0A a1, a2; }
<br>>=20
<br>> I do not propose changes to existing behavior, so yes. If A::~A() =
throws
<br>> and is declared noexcept(false), that's how that snippet *alre=
ady *behaves
<br>> in C++11 and 14.
<br>
<br>But the point is that you are proposing changes to the code above! You =
may not=20
<br>have explicitly said so, but it's a consequence of your proposal th=
at=20
<br>destructors aggregate.
<br>
<br>Given:
<br>
<br>struct B { A a1, a2; };
<br>
<br>Then B's destructor must implement continuation-after-exception and=
=20
<br>aggregation if a1.~A() throws. Given that this is the case, they I'=
d expect=20
<br>that for consistency the function f above do the same.
<br>
<br>And I also expect the destructor below to continue, even though it will=
=20
<br>terminate() instead of throwing an aggregate exception:
<br>
<br>struct C { A a1, a2; ~C() noexcept {} };
<br>
<br>> An exception can already occur in either of those objects' des=
tructors.
<br>> Both destructors will still be called.
<br>
<br>Not currently. Your proposal modifies this and that's the crux of t=
he problem.
<br>
<br>> What *can't *happen right now is that those exceptions cannot =
aggregate,
<br>> and the destructors cannot *both *throw. But either of them can.
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a href=3D"http://macieira.info" rel=3D"n=
ofollow" target=3D"_blank">macieira.info</a> - thiago (AT) <a href=3D"http:=
//kde.org" rel=3D"nofollow" target=3D"_blank">kde.org</a>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>=C2=A0 =C2=A0 =C2=A0 PGP/GPG: 0x6EF45358; fingerprint:
<br>=C2=A0 =C2=A0 =C2=A0 E067 918B B660 DBD1 105C =C2=A0966C 33F5 F005 6EF4=
5358
<br>
<br></blockquote></div></blockquote></div>
<p></p>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/Y6gjtmVyzBo/unsubscribe" rel=3D"nofollow=
" target=3D"_blank">https://groups.google.com/a/isocpp.org/d/topic/std-prop=
osals/Y6gjtmVyzBo/unsubscribe</a>.<br></blockquote></div></blockquote></div=
><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px=
0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-=
width:1px;border-left-style:solid"><div class=3D"gmail_quote"><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;bor=
der-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:sol=
id">
To unsubscribe from this group and all its topics, send an email to <a rel=
=3D"nofollow">std-proposal...@isocpp.org</a>.<br>
To post to this group, send email to <a rel=3D"nofollow">std-pr...@isocpp.o=
rg</a>.</blockquote></div></blockquote></div><div dir=3D"ltr"><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding-left:1ex;bor=
der-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:sol=
id"><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"m=
argin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204)=
;border-left-width:1px;border-left-style:solid"><br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" rel=3D"nofollow" target=3D"_blank">http://groups.google.com=
/a/isocpp.org/group/std-proposals/</a>.<br>
</blockquote></div></blockquote></div></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a1134c49ea3c728051b8d4aa3--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Thu, 23 Jul 2015 14:18:17 -0700 (PDT)
Raw View
------=_Part_1160_564374645.1437686297782
Content-Type: multipart/alternative;
boundary="----=_Part_1161_767517168.1437686297783"
------=_Part_1161_767517168.1437686297783
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
I'm watching the video slowly, while I also reimplement my container to use=
=20
standard library constructions like=20
std::is_nothrow_move_constructible, instead of my own IsMovable trait +=20
memcpy.
Preliminary thought:
A huge amount of issues arise from the fact that we're not recognizing that=
=20
the vast majority of C++ objects are trivially movable using memcpy,=20
regardless of the objects' internal complexity.
The original mistake in C++ language design was assuming that copying,=20
rather than moving, is the primary operation. Moving is, by far, the more=
=20
primary. The fact that we spent 20 years aping move operations via copy +=
=20
destruct is insane.
We have fixed this somewhat by adopting move semantics, but we're still=20
doing them in a way that is somewhat insane. When using standard library=20
conventions, moving a container involves loops that do this:
new (newPtr) T(std::move(*oldPtr));
oldPtr->~T();
Instead of doing this:
memcpy(newPtr, oldPtr, sizeof(T));
In almost all cases; for almost all objects; we could just do the memcpy,=
=20
without informing the object, and without calling any destructors for the=
=20
old memory location.
Even though this would be safe to do for *nearly all objects*, the library=
=20
doesn't expose a trait to indicate this.
Instead, we focus on assuring that the move constructor and the destructor=
=20
are noexcept.
It's stupid.
We spent 20 years *deep copying *objects when we want to move them.
Are we going to spend another 20 years before we're smart enough to expose=
=20
an "is trivially movable" trait, and then just perform *memcpy*?
On Thursday, July 23, 2015 at 10:22:24 AM UTC-6, Micha=C5=82 Dominiak wrote=
:
> Please do watch Jon Kalb's talk from CppCon; it should enlighten you abou=
t=20
> why you are wrong about this.
>
> On Thu, 23 Jul 2015 6:13 PM denis bider <isocp...@denisbider.com=20
> <javascript:>> wrote:
>
>> But exceptions are *not* transparent. One must be aware of exception=20
>> safety in *every single line of code* one writes. This will always be=20
>> the case.
>>
>> What I am suggesting are tools that make it easier to *manage*=20
>> exceptions. This makes exceptions more *powerful*.
>>
>> Forget about destructors. Currently, you don't have a way to run 100=20
>> *tasks*, and handle exceptions from more than one of them gracefully.
>>
>> With multi-exceptions, you do. This could come highly convenient if you=
=20
>> want to execute 100 tasks in parallel.
>>
>> Desktop computers have 8 or more virtual cores now. Applications=20
>> increasingly need to make use of them. C++ has made strides in making th=
is=20
>> easier by adding standard library threading.
>>
>> But the single-exception policy fails in this case. You run 8 or 16=20
>> parallel tasks, and 2 or 3 of them throw. You can't use exceptions to=20
>> convey this failure. They can't cross the thread boundary because you ha=
ve=20
>> no way of aggregating them.
>>
>> With this proposal, you do. You can have one thread run N parallel tasks=
;=20
>> collect exceptions from them; and convey them to the caller.
>>
>> This is powerful stuff; and it's necessary. Without this, you have to=20
>> resort to inelegant, ad-hoc solutions for reporting errors. You have an=
=20
>> exception mechanism, but it's partial. It's not general. It's not comple=
te.
>>
>>
>> On Thursday, July 23, 2015 at 9:20:22 AM UTC-6, Micha=C5=82 Dominiak wro=
te:
>>
>>> So now your proposal also requires littering our code with weird `try`=
=20
>>> blocks. No good.
>>>
>>> Exceptions are meant to be "transparent", so code that doesn't=20
>>> explicitly *handle* errors doesn't need to care about them *at all*,=20
>>> ignoring their existence. Your proposal now changes that entirely, maki=
ng=20
>>> all the code using *some* 3rd party code have to deal with weirdness.
>>>
>>> On Thu, Jul 23, 2015 at 4:32 PM denis bider <isocp...@denisbider.com>=
=20
>>> wrote:
>>>
>> Based on our exchange, I have come to realize that try-defer and=20
>>>> try-aggregate are not just syntactic sugar, but crucial elements of th=
e=20
>>>> proposal that make exception aggregation easy to handle by anyone,=20
>>>> including beginners.
>>>>
>>>> Without these constructs, you are correct that exception aggregation i=
s=20
>>>> too tricky for the average programmer.
>>>>
>>>> With these constructs, it becomes easy and elegant.
>>>>
>>>> I have updated the "Proposal summary" page to include try* and try+:
>>>>
>>>>
>>>> http://denisbider.blogspot.com/2015/07/aggregated-exceptions-proposal-=
summary.html
>>>>
>>>>
>>>> On Thursday, July 23, 2015 at 7:49:04 AM UTC-6, denis bider wrote:
>>>>
>>>>> I would like to point out that, with minimal syntactic sugar,=20
>>>>> multi-exceptions provide an easy way to handle code that may throw,=
=20
>>>>> including in destructors.
>>>>>
>>>>> Let's introduce two constructs, "try aggregate" and "try defer".
>>>>>
>>>>> - "Try aggregate" starts a block in which there can be "try defer"=20
>>>>> statements that aggregate exceptions.
>>>>>
>>>>> - At the end of the "try aggregate" block, any accumulated exceptions=
=20
>>>>> are thrown as a group.
>>>>>
>>>>> - If there are no aggregated exceptions, execution continues.
>>>>>
>>>>> Your example earlier was as follows:
>>>>>
>>>>>
>>>>> struct D { A *a1, *a2; D(); ~D() { dispose(a1); dispose(a2); } };=20
>>>>>
>>>>> template <typename T> void dispose(T *&ptr)=20
>>>>> {=20
>>>>> ptr->~T();=20
>>>>> remove_from_siblings(ptr);=20
>>>>> Allocator::dealloc(ptr);=20
>>>>> }=20
>>>>>
>>>>>
>>>>> As I mention, this is *currently* unsafe if A::~A() is=20
>>>>> noexcept(false).
>>>>>
>>>>> This is how it *would* be safe with the "try defer" syntactic sugar.=
=20
>>>>> To avoid introducing contextual keywords, I use "try+" for try defer,=
=20
>>>>> and "try*" for try aggregate:
>>>>>
>>>>>
>>>>> struct D {
>>>>> A *a1, *a2;
>>>>> D();
>>>>> ~D() {
>>>>> try* {
>>>>> try+ { dispose(a1); }
>>>>> try+ { dispose(a2); }
>>>>> }
>>>>> }
>>>>> };=20
>>>>>
>>>>> template <typename T> void dispose(T *&ptr)=20
>>>>> {
>>>>> try* {
>>>>> try+ { ptr->~T(); }
>>>>> remove_from_siblings(ptr);=20
>>>>> Allocator::dealloc(ptr);
>>>>> }
>>>>> }=20
>>>>>
>>>>>
>>>>> This provides nice, clean, elegant syntax that makes throwing=20
>>>>> destructors safe, and easy to handle.
>>>>>
>>>>> Anyone can understand and safely use this syntax. Even beginners.
>>>>>
>>>>>
>>>>> Now, to your continuing comments.
>>>>>
>>>>> There are resolutions to most of the issues you raise. They are=20
>>>>> apparent to one who *wants *to solve them. The issue is that you do=
=20
>>>>> not *want *that. You want the opposite; to *not* solve them. You do=
=20
>>>>> not want to acknowledge solutions I have already proposed. Some of th=
e=20
>>>>> issues you raise are repeated and *purposeful* misunderstandings.
>>>>>
>>>>> For a technical argument to make sense, *there must be a reasonable=
=20
>>>>> way* I can find a solution. You *must* be open to my proposal in at=
=20
>>>>> least *some reasonable* scenario. You have to not move your goal=20
>>>>> posts. If there is no scenario in which you're open to my proposal, o=
r if=20
>>>>> you keep moving goal posts, then a technical argument is a waste of t=
ime.=20
>>>>> It just comes down to a vote of who is for, and who's against; and wh=
oever=20
>>>>> has the majority will prevail.
>>>>>
>>>>>
>>>>> On Thursday, July 23, 2015 at 12:25:15 AM UTC-6, Thiago Macieira wrot=
e:
>>>>>
>>>>>> On Wednesday 22 July 2015 18:43:22 denis bider wrote:=20
>>>>>> > > Please tell me of an uninstaller that rolls back when it runs=20
>>>>>> into an=20
>>>>>> >=20
>>>>>> > error.=20
>>>>>> >=20
>>>>>> > I am perplexed. This question sounds to me like: "Tell me of a car=
=20
>>>>>> that has=20
>>>>>> > wheels."=20
>>>>>> >=20
>>>>>> > *All installers *must rollback when they run into an error.=20
>>>>>> >=20
>>>>>> > Ours do: https://www.bitvise.com/=20
>>>>>>
>>>>>> I said *uninstaller*. What do you do when you've removed some files,=
=20
>>>>>> then=20
>>>>>> something failed? Let's say a filesystem corruption prevents you fro=
m=20
>>>>>> removing=20
>>>>>> certain files, how do you roll back? Do you put the files you had=20
>>>>>> already=20
>>>>>> removed back in?=20
>>>>>>
>>>>>> Moving to the C++ case: if a sub-object destruction fails, do the=20
>>>>>> previously=20
>>>>>> destroyed object get re-constructed? That's impossible. In fact, you=
r=20
>>>>>> proposal=20
>>>>>> is that we ignore the problem and continue destruction.=20
>>>>>>
>>>>>> So it wouldn't be like the uninstaller rollback. It would be like an=
=20
>>>>>> uninstaller powering through and leaving an unclean state behind.=20
>>>>>>
>>>>>> > > That punts the problem to std::unique_ptr. Now the destructor=20
>>>>>> > > of your sub-objects may be called while other sub-objects=20
>>>>>> > > that should have been destroyed haven't yet.=20
>>>>>> >=20
>>>>>> > That's how destruction works.=20
>>>>>> >=20
>>>>>> > The only way this is an issue is if the 2+ resources you are=20
>>>>>> freeing have=20
>>>>>> > logical interdependencies in the destructor. In this case, you nee=
d=20
>>>>>> to=20
>>>>>> > implement destruction properly.=20
>>>>>>
>>>>>> Which gets tricky very quickly, not to mention the fact that some of=
=20
>>>>>> them=20
>>>>>> might be partially destroyed and thus in an invalid state.=20
>>>>>>
>>>>>> > The code you provided does not need multi-exceptions to be=20
>>>>>> incorrect. It is=20
>>>>>> > already incorrect in C++11 if a1 destructor is noexcept(false).=20
>>>>>>
>>>>>> Which, like I said, the destructor is not supposed to be. A=20
>>>>>> noexcept(false)=20
>>>>>> destructor today is considered, by itself, a problem. Everything=20
>>>>>> using=20
>>>>>> destructors assumes a contract that they don't throw. A=20
>>>>>> noexcept(false)y=20
>>>>>> constructor is therefore a contract violation.=20
>>>>>>
>>>>>> > > But it's a change in behaviour, with increased memory pressure,=
=20
>>>>>> > > for something that is not in use today.=20
>>>>>> >=20
>>>>>> > If we keep existing rules for how destructors' noexcept=20
>>>>>> declarations are=20
>>>>>> > determined, there is no change of behavior unless you *actually us=
e=20
>>>>>> > *destructors declared noexcept(false).=20
>>>>>>
>>>>>> So there's a change of behaviour to existing code.=20
>>>>>>
>>>>>> > Even if you have destructors declared noexcept(false), there is=20
>>>>>> still no=20
>>>>>> > need for additional cost unless you also implement *catch-any*=20
>>>>>> handlers to=20
>>>>>> > handle multi-exceptions.=20
>>>>>>
>>>>>> As we've agreed, noexcept(false) destructors will do additional work=
=20
>>>>>> in the=20
>>>>>> exceptional case because they need to aggregate exceptions. Those=20
>>>>>> destructors=20
>>>>>> exist today and will start paying for a feature they don't use,=20
>>>>>>
>>>>>> Additionally, I'd expect that even noexcept destructors, for=20
>>>>>> consistency,=20
>>>>>> should do destruction of all sub-objects, even if terminate() is=20
>>>>>> coming. So=20
>>>>>> all destructors will start paying the price of this feature.=20
>>>>>>
>>>>>> > If your program does not implement any catch-any handlers, then=20
>>>>>> > multi-exception support can again be fully optimized away, so that=
=20
>>>>>> > std::terminate is called at the point where exceptions would be=20
>>>>>> aggregated.=20
>>>>>>
>>>>>> That's not correct. Multi-exceptions are implicit because of=20
>>>>>> destructors' sub-=20
>>>>>> object destruction.=20
>>>>>>
>>>>>> > > That is, the following will continue execution and aggregate,=
=20
>>>>>> > > with unmodified code:=20
>>>>>> > >=20
>>>>>> > > void f() { A a1, a2; }=20
>>>>>> >=20
>>>>>> > I do not propose changes to existing behavior, so yes. If A::~A()=
=20
>>>>>> throws=20
>>>>>> > and is declared noexcept(false), that's how that snippet *already=
=20
>>>>>> *behaves=20
>>>>>> > in C++11 and 14.=20
>>>>>>
>>>>>> But the point is that you are proposing changes to the code above!=
=20
>>>>>> You may not=20
>>>>>> have explicitly said so, but it's a consequence of your proposal tha=
t=20
>>>>>> destructors aggregate.=20
>>>>>>
>>>>>> Given:=20
>>>>>>
>>>>>> struct B { A a1, a2; };=20
>>>>>>
>>>>>> Then B's destructor must implement continuation-after-exception and=
=20
>>>>>> aggregation if a1.~A() throws. Given that this is the case, they I'd=
=20
>>>>>> expect=20
>>>>>> that for consistency the function f above do the same.=20
>>>>>>
>>>>>> And I also expect the destructor below to continue, even though it=
=20
>>>>>> will=20
>>>>>> terminate() instead of throwing an aggregate exception:=20
>>>>>>
>>>>>> struct C { A a1, a2; ~C() noexcept {} };=20
>>>>>>
>>>>>> > An exception can already occur in either of those objects'=20
>>>>>> destructors.=20
>>>>>> > Both destructors will still be called.=20
>>>>>>
>>>>>> Not currently. Your proposal modifies this and that's the crux of th=
e=20
>>>>>> problem.=20
>>>>>>
>>>>>> > What *can't *happen right now is that those exceptions cannot=20
>>>>>> aggregate,=20
>>>>>> > and the destructors cannot *both *throw. But either of them can.=
=20
>>>>>>
>>>>>> --=20
>>>>>> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org=20
>>>>>> Software Architect - Intel Open Source Technology Center=20
>>>>>> PGP/GPG: 0x6EF45358; fingerprint:=20
>>>>>> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358=20
>>>>>>
>>>>>> --=20
>>>>
>>>> ---=20
>>>> You received this message because you are subscribed to a topic in the=
=20
>>>> Google Groups "ISO C++ Standard - Future Proposals" group.
>>>> To unsubscribe from this topic, visit=20
>>>> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/Y6gjtmVyz=
Bo/unsubscribe
>>>> .
>>>>
>>> To unsubscribe from this group and all its topics, send an email to=20
>>>> std-proposal...@isocpp.org.
>>>> To post to this group, send email to std-pr...@isocpp.org.
>>>
>>>
>>>> Visit this group at=20
>>>> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>>>>
>>>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1161_767517168.1437686297783
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>I'm watching the video slowly, while I also reimp=
lement my container to use standard library constructions like std::is_noth=
row_move_constructible,=C2=A0instead of my own IsMovable trait + memcpy.</d=
iv><div><br></div><div>Preliminary thought:</div><div><br></div><div>A huge=
amount of issues arise from the fact that we're not recognizing that t=
he vast majority of C++ objects are trivially movable using memcpy, regardl=
ess of the objects' internal complexity.</div><div><br></div><div>The o=
riginal mistake in C++ language design was assuming that copying, rather th=
an moving, is the primary operation. Moving is, by far, the more primary. T=
he fact that we spent 20 years aping move operations via copy + destruct is=
insane.</div><div><br></div><div>We have fixed this somewhat by adopting m=
ove semantics, but we're still doing them in a way that is somewhat ins=
ane. When using standard library conventions, moving a container involves l=
oops that do this:</div><div><br></div><div>new (newPtr) T(std::move(*oldPt=
r));</div><div>oldPtr->~T();</div><div><br></div><div>Instead of doing t=
his:</div><div><br></div><div>memcpy(newPtr, oldPtr, sizeof(T));</div><div>=
<br></div><div>In almost all cases; for almost all objects; we could just d=
o the memcpy, without informing the object, and without calling any destruc=
tors for the old memory location.</div><div><br></div><div>Even though this=
would be safe to do for <strong>nearly all objects</strong>, the library d=
oesn't expose a trait to indicate this.</div><div><br></div><div>Instea=
d, we focus on assuring that the move constructor and the destructor are no=
except.</div><div><br></div><div>It's stupid.</div><div><br></div><div>=
We spent 20 years <strong>deep copying </strong>objects when we want to mov=
e them.</div><div><br></div><div>Are we going to spend another 20 years bef=
ore we're smart enough to expose an "is trivially movable" tr=
ait, and then just perform <strong>memcpy</strong>?</div><div><br></div><di=
v><br>On Thursday, July 23, 2015 at 10:22:24 AM UTC-6, Micha=C5=82 Dominiak=
wrote:</div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px=
0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border-le=
ft-width: 1px; border-left-style: solid;"><p dir=3D"ltr">Please do watch Jo=
n Kalb's talk from CppCon; it should enlighten you about why you are wr=
ong about this.</p>
<br><div class=3D"gmail_quote"><div dir=3D"ltr">On Thu, 23 Jul 2015 6:13 PM=
=C2=A0denis bider <<a onmousedown=3D"this.href=3D'javascript:';r=
eturn true;" onclick=3D"this.href=3D'javascript:';return true;" hre=
f=3D"javascript:" target=3D"_blank" rel=3D"nofollow">isocp...@denisbider.co=
m</a>> wrote:<br></div><blockquote class=3D"gmail_quote" style=3D"margin=
: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 20=
4); border-left-width: 1px; border-left-style: solid;"><div dir=3D"ltr"><di=
v>But exceptions are <em>not</em> transparent. One must be aware of excepti=
on safety in <em>every single line of code</em> one writes. This will alway=
s be the case.</div><div><br></div><div>What I am suggesting are tools that=
make it easier to=C2=A0<em>manage</em> exceptions. This=C2=A0makes excepti=
ons more <em>powerful</em>.</div><div><br></div><div>Forget about destructo=
rs. Currently, you don't have a way to run 100 <em>tasks</em>, and hand=
le exceptions from more than one of them gracefully.</div><div><br></div><d=
iv>With multi-exceptions, you do. This could=C2=A0come highly=C2=A0convenie=
nt if you want to execute 100 tasks in parallel.</div><div><br></div><div>D=
esktop computers have 8 or more virtual cores now. Applications increasingl=
y need to make use of them. C++ has made strides in making this easier by a=
dding standard library threading.</div><div><br></div><div>But the single-e=
xception policy fails in this case. You run 8 or 16 parallel tasks, and 2 o=
r 3=C2=A0of them throw. You can't use exceptions to convey this failure=
.. They can't cross the thread boundary because you have no way of aggre=
gating them.</div><div><br></div><div>With this proposal, you do. You can h=
ave one thread run N parallel tasks; collect exceptions from them; and conv=
ey them to the caller.</div><div><br></div><div>This is powerful stuff; and=
it's necessary. Without this, you have to resort to inelegant, ad-hoc =
solutions for reporting errors. You have an exception mechanism, but it'=
;s partial. It's not general. It's not complete.</div></div><div di=
r=3D"ltr"><div><br><br>On Thursday, July 23, 2015 at 9:20:22 AM UTC-6, Mich=
a=C5=82 Dominiak wrote:</div></div><div dir=3D"ltr"><blockquote class=3D"gm=
ail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-le=
ft-color: rgb(204, 204, 204); border-left-width: 1px; border-left-style: so=
lid;"><div dir=3D"ltr">So now your proposal also requires littering our cod=
e with weird `try` blocks. No good.<div><br></div><div>Exceptions are meant=
to be "transparent", so code that doesn't explicitly *handle=
* errors doesn't need to care about them *at all*, ignoring their exist=
ence. Your proposal now changes that entirely, making all the code using *s=
ome* 3rd party code have to deal with weirdness.</div></div><br></blockquot=
e></div><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:=
0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204=
); border-left-width: 1px; border-left-style: solid;"><div class=3D"gmail_q=
uote"><div dir=3D"ltr">On Thu, Jul 23, 2015 at 4:32 PM denis bider <<a r=
el=3D"nofollow">isocp...@denisbider.com</a>> wrote:<br></div></div></blo=
ckquote></div><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"m=
argin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 20=
4, 204); border-left-width: 1px; border-left-style: solid;"><div class=3D"g=
mail_quote"><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px =
0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border-lef=
t-width: 1px; border-left-style: solid;"><div dir=3D"ltr"><div>Based on our=
exchange, I have come to realize that try-defer and try-aggregate are not =
just syntactic sugar, but crucial elements of the proposal that make except=
ion aggregation easy to handle by anyone, including beginners.</div><div><b=
r></div><div>Without these constructs, you are correct that exception aggre=
gation is too tricky for the average programmer.</div><div><br></div><div>W=
ith these constructs, it becomes easy and elegant.</div><div><br></div><div=
>I have updated the "Proposal summary" page to include try* and t=
ry+:</div><div><br></div><div><a onmousedown=3D"this.href=3D'http://www=
..google.com/url?q\75http%3A%2F%2Fdenisbider.blogspot.com%2F2015%2F07%2Faggr=
egated-exceptions-proposal-summary.html\46sa\75D\46sntz\0751\46usg\75AFQjCN=
HoV_qxRzQyc3J8kc7gVKbZDBrk6w';return true;" onclick=3D"this.href=3D'=
;http://www.google.com/url?q\75http%3A%2F%2Fdenisbider.blogspot.com%2F2015%=
2F07%2Faggregated-exceptions-proposal-summary.html\46sa\75D\46sntz\0751\46u=
sg\75AFQjCNHoV_qxRzQyc3J8kc7gVKbZDBrk6w';return true;" href=3D"http://d=
enisbider.blogspot.com/2015/07/aggregated-exceptions-proposal-summary.html"=
target=3D"_blank" rel=3D"nofollow">http://denisbider.blogspot.com/2015/07/=
aggregated-exceptions-proposal-summary.html</a></div></div><div dir=3D"ltr"=
><div><br><br>On Thursday, July 23, 2015 at 7:49:04 AM UTC-6, denis bider w=
rote:</div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0=
..8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border-left=
-width: 1px; border-left-style: solid;"><div dir=3D"ltr"><div><div>I would =
like to point out that, with minimal syntactic sugar, multi-exceptions prov=
ide an easy way to handle code that may throw, including in destructors.</d=
iv><div><br></div><div>Let's introduce two constructs, "try aggreg=
ate" and "try defer".</div><div><br></div><div>- "Try a=
ggregate" starts a block in which there can be "try defer" s=
tatements that aggregate exceptions.</div><div><br></div><div>- At the end =
of the "try aggregate" block, any accumulated exceptions are thro=
wn as a group.</div><div><br></div><div>- If there are no aggregated except=
ions, execution continues.</div><div><br></div><div>Your example earlier wa=
s as follows:</div><div><br></div><div><br></div><div><font face=3D"courier=
new,monospace">struct D { A *a1, *a2; D(); ~D() { dispose(a1); dispose(a2)=
; } }; <br><br>template <typename T> void dispose(T *&ptr) <br>{ =
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0ptr->~T(); <br>=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0remove_from_siblings(ptr); <br=
>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0Allocator::dealloc(ptr); <=
br>}</font> <br></div><div><br></div><div><br></div><div>As I mention, this=
is <em>currently</em> unsafe if A::~A() is noexcept(false).</div><div><br>=
</div><div>This is how it <em>would</em> be safe with the "try defer&q=
uot; syntactic sugar. To avoid introducing contextual keywords, I use "=
;try+" for try defer, and=C2=A0"try*" for try aggregate:</di=
v><div><br></div><div><br></div><div><font face=3D"courier new,monospace">s=
truct D {</font></div><div><font face=3D"courier new,monospace">=C2=A0=C2=
=A0=C2=A0 A *a1, *a2;</font></div><div><font face=3D"courier new,monospace"=
>=C2=A0=C2=A0=C2=A0 D();</font></div><div><font face=3D"courier new,monospa=
ce">=C2=A0=C2=A0=C2=A0 ~D() {</font></div><div><font face=3D"courier new,mo=
nospace">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 try* {</font></div><div=
><font face=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 try+ { dispose(a1); }</font></div><div><font=
face=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0 try+ { dispose(a2); }</font></div><div><font face=
=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }</fo=
nt></div><div><font face=3D"courier new,monospace">=C2=A0=C2=A0=C2=A0 }</fo=
nt></div><div><font face=3D"courier new,monospace">}; <br></font><br><font =
face=3D"courier new,monospace">template <typename T> void dispose(T *=
&ptr) <br>{</font></div><div><font face=3D"courier new,monospace">=C2=
=A0=C2=A0=C2=A0 try* {<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 try+ {=
ptr->~T(); }<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0remove_=
from_siblings(ptr); <br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0All=
ocator::dealloc(ptr);</font></div><div><font face=3D"courier new,monospace"=
>=C2=A0=C2=A0=C2=A0 }<br>}</font> <br></div><div><br></div><div><br></div><=
div>This provides nice, clean, elegant syntax that makes throwing destructo=
rs safe, and easy to handle.</div><div><br></div><div>Anyone can understand=
and safely use this syntax. Even beginners.</div><div><br></div><div><br><=
/div><div>Now, to your continuing comments.</div><div><br></div><div>There =
are resolutions to most of the issues you raise.=C2=A0They=C2=A0are apparen=
t to=C2=A0one who <em>wants </em>to solve them.=C2=A0The issue is that=C2=
=A0you do not <em>want </em>that. You want the opposite; to <em>not</em> so=
lve them.=C2=A0You do not want to acknowledge=C2=A0solutions I have already=
proposed.=C2=A0Some of the issues=C2=A0you raise are=C2=A0repeated and=C2=
=A0<em>purposeful</em> misunderstandings.</div><div><div><br></div><div>For=
a technical argument to make sense, <em>there must be a reasonable way</em=
> I can=C2=A0find a solution. You <em>must</em> be open to my proposal in a=
t least <em>some reasonable</em>=C2=A0scenario. You have to not move your g=
oal posts.=C2=A0If there is no scenario in which you're open to my prop=
osal, or if you keep moving goal posts,=C2=A0then a technical argument is a=
waste of time. It just comes down to a vote of who is for, and who's a=
gainst; and=C2=A0whoever has the majority=C2=A0will prevail.</div><div><br>=
<br>On Thursday, July 23, 2015 at 12:25:15 AM UTC-6, Thiago Macieira wrote:=
</div></div></div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0p=
x 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); bord=
er-left-width: 1px; border-left-style: solid;">On Wednesday 22 July 2015 18=
:43:22 denis bider wrote:
<br>> > Please tell me of an uninstaller that rolls back when it runs=
into an
<br>>=20
<br>> error.
<br>>=20
<br>> I am perplexed. This question sounds to me like: "Tell me of =
a car that has
<br>> wheels."
<br>>=20
<br>> *All installers *must rollback when they run into an error.
<br>>=20
<br>> Ours do: <a onmousedown=3D"this.href=3D'https://www.google.com=
/url?q\75https%3A%2F%2Fwww.bitvise.com%2F\46sa\75D\46sntz\0751\46usg\75AFQj=
CNH9_QQ7hnBKE1KSKpRXkn_2ZDqTvQ';return true;" onclick=3D"this.href=3D&#=
39;https://www.google.com/url?q\75https%3A%2F%2Fwww.bitvise.com%2F\46sa\75D=
\46sntz\0751\46usg\75AFQjCNH9_QQ7hnBKE1KSKpRXkn_2ZDqTvQ';return true;" =
href=3D"https://www.bitvise.com/" target=3D"_blank" rel=3D"nofollow">https:=
//www.bitvise.com/</a>
<br>
<br>I said *uninstaller*. What do you do when you've removed some files=
, then=20
<br>something failed? Let's say a filesystem corruption prevents you fr=
om removing=20
<br>certain files, how do you roll back? Do you put the files you had alrea=
dy=20
<br>removed back in?
<br>
<br>Moving to the C++ case: if a sub-object destruction fails, do the previ=
ously=20
<br>destroyed object get re-constructed? That's impossible. In fact, yo=
ur proposal=20
<br>is that we ignore the problem and continue destruction.
<br>
<br>So it wouldn't be like the uninstaller rollback. It would be like a=
n=20
<br>uninstaller powering through and leaving an unclean state behind.
<br>
<br>> > That punts the problem to std::unique_ptr. Now the destructor
<br>> > of your sub-objects may be called while other sub-objects
<br>> > that should have been destroyed haven't yet.
<br>>=20
<br>> That's how destruction works.
<br>>=20
<br>> The only way this is an issue is if the 2+ resources you are freei=
ng have
<br>> logical interdependencies in the destructor. In this case, you nee=
d to
<br>> implement destruction properly.
<br>
<br>Which gets tricky very quickly, not to mention the fact that some of th=
em=20
<br>might be partially destroyed and thus in an invalid state.
<br>
<br>> The code you provided does not need multi-exceptions to be incorre=
ct. It is
<br>> already incorrect in C++11 if a1 destructor is noexcept(false).
<br>
<br>Which, like I said, the destructor is not supposed to be. A noexcept(fa=
lse)=20
<br>destructor today is considered, by itself, a problem. Everything using=
=20
<br>destructors assumes a contract that they don't throw. A noexcept(fa=
lse)y=20
<br>constructor is therefore a contract violation.
<br>
<br>> > But it's a change in behaviour, with increased memory pre=
ssure,
<br>> > for something that is not in use today.
<br>>=20
<br>> If we keep existing rules for how destructors' noexcept declar=
ations are
<br>> determined, there is no change of behavior unless you *actually us=
e
<br>> *destructors declared noexcept(false).
<br>
<br>So there's a change of behaviour to existing code.
<br>
<br>> Even if you have destructors declared noexcept(false), there is st=
ill no
<br>> need for additional cost unless you also implement *catch-any* han=
dlers to
<br>> handle multi-exceptions.
<br>
<br>As we've agreed, noexcept(false) destructors will do additional wor=
k in the=20
<br>exceptional case because they need to aggregate exceptions. Those destr=
uctors=20
<br>exist today and will start paying for a feature they don't use,
<br>
<br>Additionally, I'd expect that even noexcept destructors, for consis=
tency,=20
<br>should do destruction of all sub-objects, even if terminate() is coming=
.. So=20
<br>all destructors will start paying the price of this feature.
<br>
<br>> If your program does not implement any catch-any handlers, then
<br>> multi-exception support can again be fully optimized away, so that
<br>> std::terminate is called at the point where exceptions would be ag=
gregated.
<br>
<br>That's not correct. Multi-exceptions are implicit because of destru=
ctors' sub-
<br>object destruction.
<br>
<br>> > That is, the following =C2=A0will continue execution and aggr=
egate,
<br>> > with unmodified code:
<br>> >=20
<br>> > void f() { =C2=A0A a1, a2; }
<br>>=20
<br>> I do not propose changes to existing behavior, so yes. If A::~A() =
throws
<br>> and is declared noexcept(false), that's how that snippet *alre=
ady *behaves
<br>> in C++11 and 14.
<br>
<br>But the point is that you are proposing changes to the code above! You =
may not=20
<br>have explicitly said so, but it's a consequence of your proposal th=
at=20
<br>destructors aggregate.
<br>
<br>Given:
<br>
<br>struct B { A a1, a2; };
<br>
<br>Then B's destructor must implement continuation-after-exception and=
=20
<br>aggregation if a1.~A() throws. Given that this is the case, they I'=
d expect=20
<br>that for consistency the function f above do the same.
<br>
<br>And I also expect the destructor below to continue, even though it will=
=20
<br>terminate() instead of throwing an aggregate exception:
<br>
<br>struct C { A a1, a2; ~C() noexcept {} };
<br>
<br>> An exception can already occur in either of those objects' des=
tructors.
<br>> Both destructors will still be called.
<br>
<br>Not currently. Your proposal modifies this and that's the crux of t=
he problem.
<br>
<br>> What *can't *happen right now is that those exceptions cannot =
aggregate,
<br>> and the destructors cannot *both *throw. But either of them can.
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a onmousedown=3D"this.href=3D'http:/=
/www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\75D\46sntz\0751\46u=
sg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.=
href=3D'http://www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\7=
5D\46sntz\0751\46usg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;=
" href=3D"http://macieira.info" target=3D"_blank" rel=3D"nofollow">macieira=
..info</a> - thiago (AT) <a onmousedown=3D"this.href=3D'http://www.googl=
e.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\75AFQjCNHGRJd=
o5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'http=
://www.google.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\7=
5AFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;" href=3D"http://kde.o=
rg" target=3D"_blank" rel=3D"nofollow">kde.org</a>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>=C2=A0 =C2=A0 =C2=A0 PGP/GPG: 0x6EF45358; fingerprint:
<br>=C2=A0 =C2=A0 =C2=A0 E067 918B B660 DBD1 105C =C2=A0966C 33F5 F005 6EF4=
5358
<br>
<br></blockquote></div></blockquote></div>
<p></p>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a onmousedown=3D"this.href=3D'ht=
tps://groups.google.com/a/isocpp.org/d/topic/std-proposals/Y6gjtmVyzBo/unsu=
bscribe';return true;" onclick=3D"this.href=3D'https://groups.googl=
e.com/a/isocpp.org/d/topic/std-proposals/Y6gjtmVyzBo/unsubscribe';retur=
n true;" href=3D"https://groups.google.com/a/isocpp.org/d/topic/std-proposa=
ls/Y6gjtmVyzBo/unsubscribe" target=3D"_blank" rel=3D"nofollow">https://grou=
ps.google.com/a/isocpp.org/d/topic/std-proposals/Y6gjtmVyzBo/unsubscribe</a=
>.<br></blockquote></div></blockquote></div><div dir=3D"ltr"><blockquote cl=
ass=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; =
border-left-color: rgb(204, 204, 204); border-left-width: 1px; border-left-=
style: solid;"><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote"=
style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: =
rgb(204, 204, 204); border-left-width: 1px; border-left-style: solid;">
To unsubscribe from this group and all its topics, send an email to <a rel=
=3D"nofollow">std-proposal...@isocpp.org</a>.<br>
To post to this group, send email to <a rel=3D"nofollow">std-pr...@isocpp.o=
rg</a>.</blockquote></div></blockquote></div><div dir=3D"ltr"><blockquote c=
lass=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex;=
border-left-color: rgb(204, 204, 204); border-left-width: 1px; border-left=
-style: solid;"><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote=
" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color:=
rgb(204, 204, 204); border-left-width: 1px; border-left-style: solid;"><br=
>
Visit this group at <a onmousedown=3D"this.href=3D'http://groups.google=
..com/a/isocpp.org/group/std-proposals/';return true;" onclick=3D"this.h=
ref=3D'http://groups.google.com/a/isocpp.org/group/std-proposals/';=
return true;" href=3D"http://groups.google.com/a/isocpp.org/group/std-propo=
sals/" target=3D"_blank" rel=3D"nofollow">http://groups.google.com/a/isocpp=
..org/group/std-proposals/</a>.<br>
</blockquote></div></blockquote></div></blockquote></div>
</blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1161_767517168.1437686297783--
------=_Part_1160_564374645.1437686297782--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Thu, 23 Jul 2015 15:42:21 -0700
Raw View
On Thursday 23 July 2015 14:18:17 denis bider wrote:
> We spent 20 years deep copying objects when we want to move them.
>
> Are we going to spend another 20 years before we're smart enough to expose
> an "is trivially movable" trait, and then just perform memcpy?
The problem is that this trait is not something the compiler can know for
certain.
Trivially copyable and movable objects can be memcpy-moved, but there are
other classes that have complex copy/move constructors and are still movable
by memcpy. That is, a compiler trait would have no false positives, but would
have a lot of false negatives. Example: almost every container and value-type
class.
So this isn't something that needs a change in the core language. It's a
library change.
We have it in Qt, but it's ugly (macro, namespace problems):
Q_DECLARE_TYPEINFO(MyClass, Q_MOVABLE_TYPE)
This specialises QTypeInfo<MyClass> and sets isMovable = true. This way, Qt
container classes know this type can be memcpy'ed.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Howard Hinnant <howard.hinnant@gmail.com>
Date: Fri, 24 Jul 2015 07:41:30 -0400
Raw View
On Jul 23, 2015, at 5:18 PM, denis bider <isocppgroup@denisbider.com> wrote=
:
>=20
> Preliminary thought:
>=20
> A huge amount of issues arise from the fact that we're not recognizing th=
at the vast majority of C++ objects are trivially movable using memcpy, reg=
ardless of the objects' internal complexity.
>=20
> The original mistake in C++ language design was assuming that copying, ra=
ther than moving, is the primary operation. Moving is, by far, the more pri=
mary. The fact that we spent 20 years aping move operations via copy + dest=
ruct is insane.
>=20
> We have fixed this somewhat by adopting move semantics, but we're still d=
oing them in a way that is somewhat insane. When using standard library con=
ventions, moving a container involves loops that do this:
>=20
> new (newPtr) T(std::move(*oldPtr));
> oldPtr->~T();
>=20
> Instead of doing this:
>=20
> memcpy(newPtr, oldPtr, sizeof(T));
>=20
> In almost all cases; for almost all objects; we could just do the memcpy,=
without informing the object, and without calling any destructors for the =
old memory location.
Actually you might be surprised at the number of classes where this won=E2=
=80=99t work. Examples include most of the std node-based containers as im=
plemented by libstdc++ and libc++.
>=20
> Even though this would be safe to do for nearly all objects, the library =
doesn't expose a trait to indicate this.
Yes it does.
>=20
> Instead, we focus on assuring that the move constructor and the destructo=
r are noexcept.
Trivial special members get focus roughly equal to that of noexcept special=
members.
>=20
> It's stupid.
>=20
> We spent 20 years deep copying objects when we want to move them.
>=20
> Are we going to spend another 20 years before we're smart enough to expos=
e an "is trivially movable" trait, and then just perform memcpy?
For four years now we=E2=80=99ve had:
template <class T, class... Args> struct is_trivially_constructible;
template <class T> struct is_trivially_default_construct=
ible;
template <class T> struct is_trivially_copy_constructibl=
e;
template <class T> struct is_trivially_move_constructibl=
e;
template <class T, class U> struct is_trivially_assignable;
template <class T> struct is_trivially_copy_assignable;
template <class T> struct is_trivially_move_assignable;
template <class T> struct is_trivially_destructible;
Howard
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: =?UTF-8?Q?David_Rodr=C3=ADguez_Ibeas?= <dibeas@ieee.org>
Date: Fri, 24 Jul 2015 14:43:48 +0100
Raw View
--001a11c2588e8e37cd051b9f31a5
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Answering to Howard's message, but really aimed at Denis:
On Fri, Jul 24, 2015 at 12:41 PM, Howard Hinnant <howard.hinnant@gmail.com>
wrote:
> For four years now we=E2=80=99ve had:
>
> template <class T, class... Args> struct is_trivially_constructible;
> template <class T> struct
> is_trivially_default_constructible;
> template <class T> struct
> is_trivially_copy_constructible;
> template <class T> struct
> is_trivially_move_constructible;
> template <class T, class U> struct is_trivially_assignable;
> template <class T> struct is_trivially_copy_assignable=
;
> template <class T> struct is_trivially_move_assignable=
;
> template <class T> struct is_trivially_destructible;
>
And beyond that, some libraries provide traits that indicate when an object
can be "moved" by memcpy by not calling the destructor on the source
object. I am not sure if that is the case of Q_MOVABLE_TYPE (quick google
search failed me), but it is in EASTL (has_trivial_relocate), BSL
(IsBitwiseMovable), Folly (IsRelocatable). The trait indicates that a
destructive move can be implemented by blasting bits from the source to the
destination and making sure that the destructor is not run over the
source. The destructive move is trivially noexcept and can be used even
with types for which move constructors cannot be noexcept (for example
Dinkumware's or BSL list implementations).
Implementations can use this to efficiently implement capacity grows in
vectors through memcpy (and releasing the source buffer's memory without
running the destructors) or to implement insertions/removals from the
middle of a vector through memmove.
Now, this cannot be inferred in any way by a compiler, and the trait has to
be explicitly reported by the implementor of the type.
On the exception part of the thread... I am not sure how the proposal is
really helping. Users that want to run multiple destructors (assuming a
container implementation) need to write roughly the same amount of code
that they would write now (try block), maybe slightly simpler code (no need
to handle manually nesting exceptions), but this should be rare.
So the main advantage is for compiler-generated destructors what would do
this implicitly over the members at the cost of additional generated code
for the cases where nested exceptions won't happen (the proposal makes
destructors default to noexcept(false), so the compiler can only assume
that they may throw). Additionally this increases the complexity of the
language for all users: anyone that wants to handle exceptions needs to
handle just one exception in flight today, all that code would have to be
adjusted to handle possibly multiple exceptions in flight. Note that the
proposal does not just turn something that may terminate into multiple
exceptions, it also causes multiple exceptions to appear in situations that
are not possible today as an exception flying over a destructor won't exit
the destructor but continue to destroy the rest of the members. I am not
sure, but if I understood it right, code that handles only one exception
(i.e. all code today) could 'std::terminate'
On this note, most of the destructors that I have ever seen "failing" did
not fail while destructing members, but inside the destructor body, similar
to Thiago's 'dispose', and there you would have to do basically the same
that you do today: wrap every operation that can fail into a 'try+' block
I would suggest that you create some non-trivial real-world example that
shows this as a big improvement over the current state of affairs, I fear
that in most real world examples the proposal would not be that different
from today's implementations (where 'try*' and 'try+' are replaced by a
slightly more complex 'try/catch' that transforms into a nested exception,
and the 'catch-any' construct replaces a catch with the nested exceptions,
or a 'exception_list' (which I imagine not that hard to implement in user
code).
I don't think the potential advantage in code is worth the additional
complexity for all users that don't care today.
David
P.S. Some assumptions you have which I don't think are correct:
- Exceptions cannot cross thread boundaries
I am pretty sure that they can, it is already done in 'std::future' for
example. The compiler won't aggregate them for you, but the library could
without having to change the core language.
- The solution makes managing exceptions easier
It does not. It raises the complexity of most uses and it lowers the
complexity of a different subset of users. The increase in complexity is
not huge, but it is broad. The lower complexity is deeper, but more niche.
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--001a11c2588e8e37cd051b9f31a5
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Answering to Howard's message, but really aimed at Den=
is:<br><div class=3D"gmail_extra"><br><div class=3D"gmail_quote">On Fri, Ju=
l 24, 2015 at 12:41 PM, Howard Hinnant <span dir=3D"ltr"><<a href=3D"mai=
lto:howard.hinnant@gmail.com" target=3D"_blank">howard.hinnant@gmail.com</a=
>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 =
0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">For four years now we=
=E2=80=99ve had:<br>
<br>
=C2=A0 =C2=A0 template <class T, class... Args> struct is_trivially_c=
onstructible;<br>
=C2=A0 =C2=A0 template <class T>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 struct is_trivially_default_constructible;<br>
=C2=A0 =C2=A0 template <class T>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 struct is_trivially_copy_constructible;<br>
=C2=A0 =C2=A0 template <class T>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 struct is_trivially_move_constructible;<br>
=C2=A0 =C2=A0 template <class T, class U>=C2=A0 =C2=A0 =C2=A0 =C2=A0s=
truct is_trivially_assignable;<br>
=C2=A0 =C2=A0 template <class T>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 struct is_trivially_copy_assignable;<br>
=C2=A0 =C2=A0 template <class T>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 struct is_trivially_move_assignable;<br>
=C2=A0 =C2=A0 template <class T>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 struct is_trivially_destructible;<br></blockquote><div=
><br>And beyond that, some libraries provide traits that indicate when an o=
bject can be "moved" by memcpy by not calling the destructor on t=
he source object. I am not sure if that is the case of Q_MOVABLE_TYPE (quic=
k google search failed me), but it is in EASTL (has_trivial_relocate), BSL =
(IsBitwiseMovable), Folly (IsRelocatable). The trait indicates that a destr=
uctive move can be implemented by blasting bits from the source to the dest=
ination and making sure that the destructor is not run over the source.=C2=
=A0 The destructive move is trivially noexcept and can be used even with ty=
pes for which move constructors cannot be noexcept (for example Dinkumware&=
#39;s or BSL list implementations).<br><br>Implementations can use this to =
efficiently implement capacity grows in vectors through memcpy (and releasi=
ng the source buffer's memory without running the destructors) or to im=
plement insertions/removals from the middle of a vector through memmove.<br=
><br>Now, this cannot be inferred in any way by a compiler, and the trait h=
as to be explicitly reported by the implementor of the type.<br><br>On the =
exception part of the thread... I am not sure how the proposal is really he=
lping. Users that want to run multiple destructors (assuming a container im=
plementation) need to write roughly the same amount of code that they would=
write now (try block), maybe slightly simpler code (no need to handle manu=
ally nesting exceptions), but this should be rare. =C2=A0<br><br>So the mai=
n advantage is for compiler-generated destructors what would do this implic=
itly over the members at the cost of additional generated code for the case=
s where nested exceptions won't happen (the proposal makes destructors =
default to noexcept(false), so the compiler can only assume that they may t=
hrow). Additionally this increases the complexity of the language for all u=
sers: anyone that wants to handle exceptions needs to handle just one excep=
tion in flight today, all that code would have to be adjusted to handle pos=
sibly multiple exceptions in flight.=C2=A0 Note that the proposal does not =
just turn something that may terminate into multiple exceptions, it also ca=
uses multiple exceptions to appear in situations that are not possible toda=
y as an exception flying over a destructor won't exit the destructor bu=
t continue to destroy the rest of the members.=C2=A0 I am not sure, but if =
I understood it right, code that handles only one exception (i.e. all code =
today) could 'std::terminate'<br><br>On this note, most of the dest=
ructors that I have ever seen "failing" did not fail while destru=
cting members, but inside the destructor body, similar to Thiago's '=
;dispose', and there you would have to do basically the same that you d=
o today: wrap every operation that can fail into a 'try+' block<br>=
<br>I would suggest that you create some non-trivial real-world example tha=
t shows this as a big improvement over the current state of affairs, I fear=
that in most real world examples the proposal would not be that different =
from today's implementations (where 'try*' and 'try+' a=
re replaced by a slightly more complex 'try/catch' that transforms =
into a nested exception, and the 'catch-any' construct replaces a c=
atch with the nested exceptions, or a 'exception_list' (which I ima=
gine not that hard to implement in user code).<br><br>I don't think the=
potential advantage in code is worth the additional complexity for all use=
rs that don't care today.<br><br>=C2=A0 =C2=A0 David<br><br>P.S. Some a=
ssumptions you have which I don't think are correct:<br><br>- Exception=
s cannot cross thread boundaries<br><br>=C2=A0 I am pretty sure that they c=
an, it is already done in 'std::future' for example. The compiler w=
on't aggregate them for you, but the library could without having to ch=
ange the core language.<br><br>- The solution makes managing exceptions eas=
ier<br><br>=C2=A0 It does not. It raises the complexity of most uses and it=
lowers the complexity of a different subset of users. The increase in comp=
lexity is not huge, but it is broad. The lower complexity is deeper, but mo=
re niche.<br><br><br></div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c2588e8e37cd051b9f31a5--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Fri, 24 Jul 2015 11:47:03 -0700 (PDT)
Raw View
------=_Part_777_365915674.1437763623996
Content-Type: multipart/alternative;
boundary="----=_Part_778_991131206.1437763623996"
------=_Part_778_991131206.1437763623996
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Thank you for the reasoned feedback.
I am inclined to withdraw the part of the proposal where destructors would=
=20
default to noexcept(false). It seems a plurality of issues raised with the=
=20
proposal arise from this part, and so it is too much to ask. Programs=20
written with current versions of the language in mind should continue to=20
operate as the developer intended them to.
In fact... I'm inclined to give up on the proposal at all. It's not like I=
=20
can currently make *use *of it. Even if we all agreed it's the way to go,=
=20
it would be 5-10 years before it would be widely available. Until then, all=
=20
the destructors where I'd like to throw exceptions have to be converted to=
=20
do some kind of logging anyway... no matter if this is awkward.
It seems to me:
- If the exception mechanism was designed from scratch, it *should* handle=
=20
multi-exceptions. It seems to me that the mechanism I proposed would be a=
=20
general way to do this.
- If classes were designed from scratch, they *should* be movable by=20
default - removing a lot of destructor use in containers that's in fact=20
unnecessary.
- If we see that design decision XA is better than design decision XB;=20
and if XA is what we would have done, if we had the hindsight and the=20
liberty; then we are compelled to move toward a situation such that XA=20
might be implemented, eventually.
- If we do not move towards better design decisions gradually, over time;=
=20
then another language will do this in a more revolutionary manner.
- If we allow a sufficient number of suboptimal design choices to be=20
accumulated in our language, which are solved by another language, then=20
users writing new software will migrate to that new language.
It seems to me that:
- the single-exception policy;
- a related issue - that we don't assume classes to be bitwise movable *as=
=20
default*, and therefore call destructors too much;=20
.... are just two little chinks, two minor details in C++ that we could have=
=20
done better. They're not deal-breaking, or anything. We can adapt to this,=
=20
and live with this.
But each little shortcoming like this is a brick. And lots of these bricks=
=20
make a wall. And if we don't work to continually dissolve these bricks; if=
=20
we don't continually strive to make the language the best that it *can *be=
=20
- instead of what compatibility dictates;
... then eventually we will build up a wall; and this wall will keep out new=
=20
users; and the new users will use some more elegant language.
These two little bricks do not matter so much if we address others. We can=
=20
select any arbitrary problem, and fix it in place, to keep it around=20
indefinitely. It comes at a long term cost, but we can do this as long as=
=20
other problems are being fixed.
But... these are two little bricks.
Everything must evolve, or be replaced, eventually. I don't think it's=20
viable to maintain backward compatibility indefinitely.
On Friday, July 24, 2015 at 7:43:51 AM UTC-6, David Rodr=C3=ADguez Ibeas wr=
ote:
> Answering to Howard's message, but really aimed at Denis:
>
> On Fri, Jul 24, 2015 at 12:41 PM, Howard Hinnant <howard....@gmail.com=20
> <javascript:>> wrote:
>
>> For four years now we=E2=80=99ve had:
>>
>> template <class T, class... Args> struct is_trivially_constructible;
>> template <class T> struct=20
>> is_trivially_default_constructible;
>> template <class T> struct=20
>> is_trivially_copy_constructible;
>> template <class T> struct=20
>> is_trivially_move_constructible;
>> template <class T, class U> struct is_trivially_assignable;
>> template <class T> struct is_trivially_copy_assignabl=
e;
>> template <class T> struct is_trivially_move_assignabl=
e;
>> template <class T> struct is_trivially_destructible;
>>
>
> And beyond that, some libraries provide traits that indicate when an=20
> object can be "moved" by memcpy by not calling the destructor on the sour=
ce=20
> object. I am not sure if that is the case of Q_MOVABLE_TYPE (quick google=
=20
> search failed me), but it is in EASTL (has_trivial_relocate), BSL=20
> (IsBitwiseMovable), Folly (IsRelocatable). The trait indicates that a=20
> destructive move can be implemented by blasting bits from the source to t=
he=20
> destination and making sure that the destructor is not run over the=20
> source. The destructive move is trivially noexcept and can be used even=
=20
> with types for which move constructors cannot be noexcept (for example=20
> Dinkumware's or BSL list implementations).
>
> Implementations can use this to efficiently implement capacity grows in=
=20
> vectors through memcpy (and releasing the source buffer's memory without=
=20
> running the destructors) or to implement insertions/removals from the=20
> middle of a vector through memmove.
>
> Now, this cannot be inferred in any way by a compiler, and the trait has=
=20
> to be explicitly reported by the implementor of the type.
>
> On the exception part of the thread... I am not sure how the proposal is=
=20
> really helping. Users that want to run multiple destructors (assuming a=
=20
> container implementation) need to write roughly the same amount of code=
=20
> that they would write now (try block), maybe slightly simpler code (no ne=
ed=20
> to handle manually nesting exceptions), but this should be rare. =20
>
> So the main advantage is for compiler-generated destructors what would do=
=20
> this implicitly over the members at the cost of additional generated code=
=20
> for the cases where nested exceptions won't happen (the proposal makes=20
> destructors default to noexcept(false), so the compiler can only assume=
=20
> that they may throw). Additionally this increases the complexity of the=
=20
> language for all users: anyone that wants to handle exceptions needs to=
=20
> handle just one exception in flight today, all that code would have to be=
=20
> adjusted to handle possibly multiple exceptions in flight. Note that the=
=20
> proposal does not just turn something that may terminate into multiple=20
> exceptions, it also causes multiple exceptions to appear in situations th=
at=20
> are not possible today as an exception flying over a destructor won't exi=
t=20
> the destructor but continue to destroy the rest of the members. I am not=
=20
> sure, but if I understood it right, code that handles only one exception=
=20
> (i.e. all code today) could 'std::terminate'
>
> On this note, most of the destructors that I have ever seen "failing" did=
=20
> not fail while destructing members, but inside the destructor body, simil=
ar=20
> to Thiago's 'dispose', and there you would have to do basically the same=
=20
> that you do today: wrap every operation that can fail into a 'try+' block
>
> I would suggest that you create some non-trivial real-world example that=
=20
> shows this as a big improvement over the current state of affairs, I fear=
=20
> that in most real world examples the proposal would not be that different=
=20
> from today's implementations (where 'try*' and 'try+' are replaced by a=
=20
> slightly more complex 'try/catch' that transforms into a nested exception=
,=20
> and the 'catch-any' construct replaces a catch with the nested exceptions=
,=20
> or a 'exception_list' (which I imagine not that hard to implement in user=
=20
> code).
>
> I don't think the potential advantage in code is worth the additional=20
> complexity for all users that don't care today.
>
> David
>
> P.S. Some assumptions you have which I don't think are correct:
>
> - Exceptions cannot cross thread boundaries
>
> I am pretty sure that they can, it is already done in 'std::future' for=
=20
> example. The compiler won't aggregate them for you, but the library could=
=20
> without having to change the core language.
>
> - The solution makes managing exceptions easier
>
> It does not. It raises the complexity of most uses and it lowers the=20
> complexity of a different subset of users. The increase in complexity is=
=20
> not huge, but it is broad. The lower complexity is deeper, but more niche=
..
>
>
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_778_991131206.1437763623996
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Thank you for the reasoned feedback.</div><div><br></=
div><div>I am inclined to withdraw the part of the proposal where destructo=
rs would default to noexcept(false). It seems a plurality of issues raised =
with the proposal arise from this part, and so it is too much to ask. Progr=
ams written with current versions of the language in mind should continue t=
o operate as=C2=A0the developer intended them=C2=A0to.</div><div><br></div>=
<div>In fact...=C2=A0I'm inclined to give up on the proposal at all. It=
's not like I can currently make <em>use </em>of it. Even if we all agr=
eed it's the way to go, it would be 5-10 years before it would be widel=
y available. Until then, all the destructors where I'd like to throw ex=
ceptions have to be converted to do some kind of logging anyway... no matte=
r if this is awkward.</div><div><br></div><div>It seems to me:</div><div><b=
r></div><div>-=C2=A0If the exception mechanism was designed from scratch, i=
t <em>should</em> handle multi-exceptions. It seems to me that the mechanis=
m I proposed would be a general way to do this.</div><div><br></div><div>- =
If classes were designed from scratch, they <em>should</em> be=C2=A0movable=
by default - removing a lot of destructor use in containers that's in =
fact unnecessary.</div><div><br></div><div>- If we see that design decision=
XA is better than design decision XB; and=C2=A0if XA is=C2=A0what we would=
have done, if we had the hindsight and the liberty; then we=C2=A0are compe=
lled to=C2=A0move toward a situation such that XA might be implemented, eve=
ntually.</div><div><br></div><div>- If we do not move towards better design=
decisions gradually, over time; then another language will do this in a mo=
re revolutionary manner.</div><div><br></div><div>- If we allow a sufficien=
t number of suboptimal design choices to be accumulated in our language, wh=
ich are solved by another language, then users writing new software will mi=
grate to that new language.</div><div><br></div><div>It seems to me that:</=
div><div><br></div><div>- the single-exception policy;</div><div><br></div>=
<div>- a related issue - that we don't assume classes to be bitwise mov=
able=C2=A0<em>as default</em>, and therefore call destructors too much; </d=
iv><div><br></div><div>... are just two little chinks, two minor details in=
C++ that we could have done better. They're not deal-breaking, or anyt=
hing. We can adapt to this, and live with this.</div><div><br></div><div>Bu=
t each little shortcoming like this is a brick. And lots of these bricks ma=
ke a wall. And if we don't work to continually dissolve these bricks; i=
f we don't continually strive to make the language the best that it <em=
>can </em>be -=C2=A0instead of what compatibility dictates;</div><div><br><=
/div><div>.. then eventually we will build up a wall; and this wall will ke=
ep out new users; and the new users will use some more elegant language.</d=
iv><div><br></div><div>These two little bricks do not matter so much if we =
address others. We can select any arbitrary problem, and fix it in place, t=
o keep it around indefinitely.=C2=A0It=C2=A0comes at a long term cost, but =
we can=C2=A0do this=C2=A0as long as other problems are being fixed.</div><d=
iv><br></div><div>But... these are two little bricks.</div><div><br></div><=
div>Everything must evolve, or be replaced,=C2=A0eventually. I don't th=
ink it's viable to maintain backward compatibility indefinitely.</div><=
div><br><br>On Friday, July 24, 2015 at 7:43:51 AM UTC-6, David Rodr=C3=ADg=
uez Ibeas wrote:</div><blockquote class=3D"gmail_quote" style=3D"margin: 0p=
x 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); =
border-left-width: 1px; border-left-style: solid;"><div dir=3D"ltr">Answeri=
ng to Howard's message, but really aimed at Denis:<br><div><br><div cla=
ss=3D"gmail_quote">On Fri, Jul 24, 2015 at 12:41 PM, Howard Hinnant <span d=
ir=3D"ltr"><<a onmousedown=3D"this.href=3D'javascript:';return t=
rue;" onclick=3D"this.href=3D'javascript:';return true;" href=3D"ja=
vascript:" target=3D"_blank" rel=3D"nofollow">howard....@gmail.com</a>><=
/span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px=
0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); borde=
r-left-width: 1px; border-left-style: solid;">For four years now we=E2=80=
=99ve had:<br>
<br>
=C2=A0 =C2=A0 template <class T, class... Args> struct is_trivially_c=
onstructible;<br>
=C2=A0 =C2=A0 template <class T>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 struct is_trivially_default_constructible;<br>
=C2=A0 =C2=A0 template <class T>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 struct is_trivially_copy_constructible;<br>
=C2=A0 =C2=A0 template <class T>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 struct is_trivially_move_constructible;<br>
=C2=A0 =C2=A0 template <class T, class U>=C2=A0 =C2=A0 =C2=A0 =C2=A0s=
truct is_trivially_assignable;<br>
=C2=A0 =C2=A0 template <class T>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 struct is_trivially_copy_assignable;<br>
=C2=A0 =C2=A0 template <class T>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 struct is_trivially_move_assignable;<br>
=C2=A0 =C2=A0 template <class T>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 struct is_trivially_destructible;<br></blockquote><div=
><br>And beyond that, some libraries provide traits that indicate when an o=
bject can be "moved" by memcpy by not calling the destructor on t=
he source object. I am not sure if that is the case of Q_MOVABLE_TYPE (quic=
k google search failed me), but it is in EASTL (has_trivial_relocate), BSL =
(IsBitwiseMovable), Folly (IsRelocatable). The trait indicates that a destr=
uctive move can be implemented by blasting bits from the source to the dest=
ination and making sure that the destructor is not run over the source.=C2=
=A0 The destructive move is trivially noexcept and can be used even with ty=
pes for which move constructors cannot be noexcept (for example Dinkumware&=
#39;s or BSL list implementations).<br><br>Implementations can use this to =
efficiently implement capacity grows in vectors through memcpy (and releasi=
ng the source buffer's memory without running the destructors) or to im=
plement insertions/removals from the middle of a vector through memmove.<br=
><br>Now, this cannot be inferred in any way by a compiler, and the trait h=
as to be explicitly reported by the implementor of the type.<br><br>On the =
exception part of the thread... I am not sure how the proposal is really he=
lping. Users that want to run multiple destructors (assuming a container im=
plementation) need to write roughly the same amount of code that they would=
write now (try block), maybe slightly simpler code (no need to handle manu=
ally nesting exceptions), but this should be rare. =C2=A0<br><br>So the mai=
n advantage is for compiler-generated destructors what would do this implic=
itly over the members at the cost of additional generated code for the case=
s where nested exceptions won't happen (the proposal makes destructors =
default to noexcept(false), so the compiler can only assume that they may t=
hrow). Additionally this increases the complexity of the language for all u=
sers: anyone that wants to handle exceptions needs to handle just one excep=
tion in flight today, all that code would have to be adjusted to handle pos=
sibly multiple exceptions in flight.=C2=A0 Note that the proposal does not =
just turn something that may terminate into multiple exceptions, it also ca=
uses multiple exceptions to appear in situations that are not possible toda=
y as an exception flying over a destructor won't exit the destructor bu=
t continue to destroy the rest of the members.=C2=A0 I am not sure, but if =
I understood it right, code that handles only one exception (i.e. all code =
today) could 'std::terminate'<br><br>On this note, most of the dest=
ructors that I have ever seen "failing" did not fail while destru=
cting members, but inside the destructor body, similar to Thiago's '=
;dispose', and there you would have to do basically the same that you d=
o today: wrap every operation that can fail into a 'try+' block<br>=
<br>I would suggest that you create some non-trivial real-world example tha=
t shows this as a big improvement over the current state of affairs, I fear=
that in most real world examples the proposal would not be that different =
from today's implementations (where 'try*' and 'try+' a=
re replaced by a slightly more complex 'try/catch' that transforms =
into a nested exception, and the 'catch-any' construct replaces a c=
atch with the nested exceptions, or a 'exception_list' (which I ima=
gine not that hard to implement in user code).<br><br>I don't think the=
potential advantage in code is worth the additional complexity for all use=
rs that don't care today.<br><br>=C2=A0 =C2=A0 David<br><br>P.S. Some a=
ssumptions you have which I don't think are correct:<br><br>- Exception=
s cannot cross thread boundaries<br><br>=C2=A0 I am pretty sure that they c=
an, it is already done in 'std::future' for example. The compiler w=
on't aggregate them for you, but the library could without having to ch=
ange the core language.<br><br>- The solution makes managing exceptions eas=
ier<br><br>=C2=A0 It does not. It raises the complexity of most uses and it=
lowers the complexity of a different subset of users. The increase in comp=
lexity is not huge, but it is broad. The lower complexity is deeper, but mo=
re niche.<br><br><br></div></div></div></div>
</blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_778_991131206.1437763623996--
------=_Part_777_365915674.1437763623996--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Fri, 24 Jul 2015 12:17:55 -0700 (PDT)
Raw View
------=_Part_1121_1936796045.1437765475487
Content-Type: multipart/alternative;
boundary="----=_Part_1122_1208622880.1437765475488"
------=_Part_1122_1208622880.1437765475488
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Howard:
> For four years now we=E2=80=99ve had:=20
> template <class T, class... Args> struct is_trivially_constructible;=20
> template <class T> struct=20
is_trivially_default_constructible;
> template <class T> struct is_trivially_copy_constructible;=
=20
> template <class T> struct is_trivially_move_constructible;=
=20
> template <class T, class U> struct is_trivially_assignable;=20
> template <class T> struct is_trivially_copy_assignable;=20
> template <class T> struct is_trivially_move_assignable;=20
> template <class T> struct is_trivially_destructible;=20
Which one of these - or which combination of them - would you then suggest=
=20
a container can use to deduce that it's safe to memcpy an object, and not=
=20
call its destructor in the previous location?
I would argue that none of these accurately reflect what the container is=
=20
trying to do.
It seems to me the container needs a combination of these properties:
is_trivially_move_constructible
is_trivially_destructible // but only after trivial move construction
Most classes that have any kind of strings or resources in them are *not*=
=20
trivially destructible. However, they *are* trivially destructible after=20
they have been used to trivially move construct another object.
It seems to me there's no combination of the above that accurately reflects=
=20
that.
On Friday, July 24, 2015 at 5:41:33 AM UTC-6, Howard Hinnant wrote:
> On Jul 23, 2015, at 5:18 PM, denis bider <isocp...@denisbider.com=20
> <javascript:>> wrote:=20
> >=20
> > Preliminary thought:=20
> >=20
> > A huge amount of issues arise from the fact that we're not recognizing=
=20
> that the vast majority of C++ objects are trivially movable using memcpy,=
=20
> regardless of the objects' internal complexity.=20
> >=20
> > The original mistake in C++ language design was assuming that copying,=
=20
> rather than moving, is the primary operation. Moving is, by far, the more=
=20
> primary. The fact that we spent 20 years aping move operations via copy +=
=20
> destruct is insane.=20
> >=20
> > We have fixed this somewhat by adopting move semantics, but we're still=
=20
> doing them in a way that is somewhat insane. When using standard library=
=20
> conventions, moving a container involves loops that do this:=20
> >=20
> > new (newPtr) T(std::move(*oldPtr));=20
> > oldPtr->~T();=20
> >=20
> > Instead of doing this:=20
> >=20
> > memcpy(newPtr, oldPtr, sizeof(T));=20
> >=20
> > In almost all cases; for almost all objects; we could just do the=20
> memcpy, without informing the object, and without calling any destructors=
=20
> for the old memory location.=20
>
> Actually you might be surprised at the number of classes where this won=
=E2=80=99t=20
> work. Examples include most of the std node-based containers as=20
> implemented by libstdc++ and libc++.=20
>
> >=20
> > Even though this would be safe to do for nearly all objects, the librar=
y=20
> doesn't expose a trait to indicate this.=20
>
> Yes it does.=20
>
> >=20
> > Instead, we focus on assuring that the move constructor and the=20
> destructor are noexcept.=20
>
> Trivial special members get focus roughly equal to that of noexcept=20
> special members.=20
>
> >=20
> > It's stupid.=20
> >=20
> > We spent 20 years deep copying objects when we want to move them.=20
> >=20
> > Are we going to spend another 20 years before we're smart enough to=20
> expose an "is trivially movable" trait, and then just perform memcpy?=20
>
> For four years now we=E2=80=99ve had:=20
>
> template <class T, class... Args> struct is_trivially_constructible;=
=20
> template <class T> struct=20
> is_trivially_default_constructible;=20
> template <class T> struct=20
> is_trivially_copy_constructible;=20
> template <class T> struct=20
> is_trivially_move_constructible;=20
> template <class T, class U> struct is_trivially_assignable;=20
> template <class T> struct is_trivially_copy_assignable=
;=20
> template <class T> struct is_trivially_move_assignable=
;=20
> template <class T> struct is_trivially_destructible;=
=20
>
> Howard=20
>
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1122_1208622880.1437765475488
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Howard:</div><div><br></div><div>> For four years =
now we=E2=80=99ve had:=C2=A0<br>> template <class T, class... Args>=
; struct is_trivially_constructible;=C2=A0<br>> template <class T>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0struct is_trivially=
_default_constructible;<br> > template <class T> =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0struct is_trivially_copy_constructibl=
e;=C2=A0<br>> template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0struct is_trivially_move_constructible;=C2=A0<br>&g=
t; template <class T, class U> =C2=A0 =C2=A0 =C2=A0 struct is_trivial=
ly_assignable;=C2=A0<br>> template <class T> =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0struct is_trivially_copy_assignable;=C2=
=A0<br>> template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0struct is_trivially_move_assignable;=C2=A0<br>> templat=
e <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0st=
ruct is_trivially_destructible; <br></div><div><br></div><div>Which one=C2=
=A0of these - or which combination of them - would you then suggest a conta=
iner can use to deduce that it's safe to memcpy an object, and not call=
its destructor in the previous location?</div><div><br></div><div>I would =
argue that none of these accurately reflect what the container is trying to=
do.</div><div><br></div><div>It seems to me the container needs a combinat=
ion of these properties:</div><div><br></div><div>is_trivially_move_constru=
ctible</div><div>is_trivially_destructible=C2=A0=C2=A0// but only after tri=
vial move construction</div><div><br></div><div>Most classes that have any =
kind of strings or resources in them are <em>not</em> trivially destructibl=
e.=C2=A0However, they=C2=A0<em>are</em> trivially destructible after they h=
ave been used to trivially move construct another object.</div><div><br></d=
iv><div>It seems to me there's no combination of the above that accurat=
ely reflects that.<br></div><div><br></div><div><br>On Friday, July 24, 201=
5 at 5:41:33 AM UTC-6, Howard Hinnant wrote:</div><blockquote class=3D"gmai=
l_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left=
-color: rgb(204, 204, 204); border-left-width: 1px; border-left-style: soli=
d;">On Jul 23, 2015, at 5:18 PM, denis bider <<a onmousedown=3D"this.hre=
f=3D'javascript:';return true;" onclick=3D"this.href=3D'javascr=
ipt:';return true;" href=3D"javascript:" target=3D"_blank" rel=3D"nofol=
low">isocp...@denisbider.com</a>> wrote:
<br>>=20
<br>> Preliminary thought:
<br>>=20
<br>> A huge amount of issues arise from the fact that we're not rec=
ognizing that the vast majority of C++ objects are trivially movable using =
memcpy, regardless of the objects' internal complexity.
<br>>=20
<br>> The original mistake in C++ language design was assuming that copy=
ing, rather than moving, is the primary operation. Moving is, by far, the m=
ore primary. The fact that we spent 20 years aping move operations via copy=
+ destruct is insane.
<br>>=20
<br>> We have fixed this somewhat by adopting move semantics, but we'=
;re still doing them in a way that is somewhat insane. When using standard =
library conventions, moving a container involves loops that do this:
<br>>=20
<br>> new (newPtr) T(std::move(*oldPtr));
<br>> oldPtr->~T();
<br>>=20
<br>> Instead of doing this:
<br>>=20
<br>> memcpy(newPtr, oldPtr, sizeof(T));
<br>>=20
<br>> In almost all cases; for almost all objects; we could just do the =
memcpy, without informing the object, and without calling any destructors f=
or the old memory location.
<br>
<br>Actually you might be surprised at the number of classes where this won=
=E2=80=99t work. =C2=A0Examples include most of the std node-based containe=
rs as implemented by libstdc++ and libc++.
<br>
<br>>=20
<br>> Even though this would be safe to do for nearly all objects, the l=
ibrary doesn't expose a trait to indicate this.
<br>
<br>Yes it does.
<br>
<br>>=20
<br>> Instead, we focus on assuring that the move constructor and the de=
structor are noexcept.
<br>
<br>Trivial special members get focus roughly equal to that of noexcept spe=
cial members.
<br>
<br>>=20
<br>> It's stupid.
<br>>=20
<br>> We spent 20 years deep copying objects when we want to move them.
<br>>=20
<br>> Are we going to spend another 20 years before we're smart enou=
gh to expose an "is trivially movable" trait, and then just perfo=
rm memcpy?
<br>
<br>For four years now we=E2=80=99ve had:
<br>
<br>=C2=A0 =C2=A0 template <class T, class... Args> struct is_trivial=
ly_constructible;
<br>=C2=A0 =C2=A0 template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0struct is_trivially_default_constructible;
<br>=C2=A0 =C2=A0 template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0struct is_trivially_copy_constructible;
<br>=C2=A0 =C2=A0 template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0struct is_trivially_move_constructible;
<br>=C2=A0 =C2=A0 template <class T, class U> =C2=A0 =C2=A0 =C2=A0 st=
ruct is_trivially_assignable;
<br>=C2=A0 =C2=A0 template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0struct is_trivially_copy_assignable;
<br>=C2=A0 =C2=A0 template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0struct is_trivially_move_assignable;
<br>=C2=A0 =C2=A0 template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0struct is_trivially_destructible;
<br>
<br>Howard
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1122_1208622880.1437765475488--
------=_Part_1121_1936796045.1437765475487--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Fri, 24 Jul 2015 12:23:34 -0700 (PDT)
Raw View
------=_Part_1041_1319456658.1437765814603
Content-Type: multipart/alternative;
boundary="----=_Part_1042_1264922424.1437765814603"
------=_Part_1042_1264922424.1437765814603
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
David - with respect to this part:
> And beyond that, some libraries provide traits that indicate
> when an object can be "moved" by memcpy by not calling
> the destructor on the source object. I am not sure if that is
> the case of Q_MOVABLE_TYPE (quick google search
> failed me), but it is in EASTL (has_trivial_relocate),
> BSL (IsBitwiseMovable), Folly (IsRelocatable).
Given the number of libraries that:
- see the need to express this concept;
- don't find existing standard type_traits suitable;
.... this seems to me a strong suggestion that the language needs to=20
standardize this concept.
On Friday, July 24, 2015 at 7:43:51 AM UTC-6, David Rodr=C3=ADguez Ibeas wr=
ote:
> Answering to Howard's message, but really aimed at Denis:
>
> On Fri, Jul 24, 2015 at 12:41 PM, Howard Hinnant <howard....@gmail.com=20
> <javascript:>> wrote:
>
>> For four years now we=E2=80=99ve had:
>>
>> template <class T, class... Args> struct is_trivially_constructible;
>> template <class T> struct=20
>> is_trivially_default_constructible;
>> template <class T> struct=20
>> is_trivially_copy_constructible;
>> template <class T> struct=20
>> is_trivially_move_constructible;
>> template <class T, class U> struct is_trivially_assignable;
>> template <class T> struct is_trivially_copy_assignabl=
e;
>> template <class T> struct is_trivially_move_assignabl=
e;
>> template <class T> struct is_trivially_destructible;
>>
>
> And beyond that, some libraries provide traits that indicate when an=20
> object can be "moved" by memcpy by not calling the destructor on the sour=
ce=20
> object. I am not sure if that is the case of Q_MOVABLE_TYPE (quick google=
=20
> search failed me), but it is in EASTL (has_trivial_relocate), BSL=20
> (IsBitwiseMovable), Folly (IsRelocatable). The trait indicates that a=20
> destructive move can be implemented by blasting bits from the source to t=
he=20
> destination and making sure that the destructor is not run over the=20
> source. The destructive move is trivially noexcept and can be used even=
=20
> with types for which move constructors cannot be noexcept (for example=20
> Dinkumware's or BSL list implementations).
>
> Implementations can use this to efficiently implement capacity grows in=
=20
> vectors through memcpy (and releasing the source buffer's memory without=
=20
> running the destructors) or to implement insertions/removals from the=20
> middle of a vector through memmove.
>
> Now, this cannot be inferred in any way by a compiler, and the trait has=
=20
> to be explicitly reported by the implementor of the type.
>
> On the exception part of the thread... I am not sure how the proposal is=
=20
> really helping. Users that want to run multiple destructors (assuming a=
=20
> container implementation) need to write roughly the same amount of code=
=20
> that they would write now (try block), maybe slightly simpler code (no ne=
ed=20
> to handle manually nesting exceptions), but this should be rare. =20
>
> So the main advantage is for compiler-generated destructors what would do=
=20
> this implicitly over the members at the cost of additional generated code=
=20
> for the cases where nested exceptions won't happen (the proposal makes=20
> destructors default to noexcept(false), so the compiler can only assume=
=20
> that they may throw). Additionally this increases the complexity of the=
=20
> language for all users: anyone that wants to handle exceptions needs to=
=20
> handle just one exception in flight today, all that code would have to be=
=20
> adjusted to handle possibly multiple exceptions in flight. Note that the=
=20
> proposal does not just turn something that may terminate into multiple=20
> exceptions, it also causes multiple exceptions to appear in situations th=
at=20
> are not possible today as an exception flying over a destructor won't exi=
t=20
> the destructor but continue to destroy the rest of the members. I am not=
=20
> sure, but if I understood it right, code that handles only one exception=
=20
> (i.e. all code today) could 'std::terminate'
>
> On this note, most of the destructors that I have ever seen "failing" did=
=20
> not fail while destructing members, but inside the destructor body, simil=
ar=20
> to Thiago's 'dispose', and there you would have to do basically the same=
=20
> that you do today: wrap every operation that can fail into a 'try+' block
>
> I would suggest that you create some non-trivial real-world example that=
=20
> shows this as a big improvement over the current state of affairs, I fear=
=20
> that in most real world examples the proposal would not be that different=
=20
> from today's implementations (where 'try*' and 'try+' are replaced by a=
=20
> slightly more complex 'try/catch' that transforms into a nested exception=
,=20
> and the 'catch-any' construct replaces a catch with the nested exceptions=
,=20
> or a 'exception_list' (which I imagine not that hard to implement in user=
=20
> code).
>
> I don't think the potential advantage in code is worth the additional=20
> complexity for all users that don't care today.
>
> David
>
> P.S. Some assumptions you have which I don't think are correct:
>
> - Exceptions cannot cross thread boundaries
>
> I am pretty sure that they can, it is already done in 'std::future' for=
=20
> example. The compiler won't aggregate them for you, but the library could=
=20
> without having to change the core language.
>
> - The solution makes managing exceptions easier
>
> It does not. It raises the complexity of most uses and it lowers the=20
> complexity of a different subset of users. The increase in complexity is=
=20
> not huge, but it is broad. The lower complexity is deeper, but more niche=
..
>
>
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1042_1264922424.1437765814603
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>David - with respect to this part:</div><div><br></di=
v><div>> And beyond that, some libraries provide traits that indicate</d=
iv><div>> when an object can be "moved" by memcpy by not calli=
ng</div><div>> the destructor on the source object. I am not sure if tha=
t is</div><div>> the case of Q_MOVABLE_TYPE (quick google search</div><d=
iv>> failed me), but it is in EASTL (has_trivial_relocate),</div><div>&g=
t; BSL (IsBitwiseMovable), Folly (IsRelocatable).</div><div><br></div><div>=
Given the number of libraries that:</div><div><br></div><div>- see the need=
to express this concept;</div><div><br></div><div>- don't find existin=
g standard type_traits suitable;</div><div><br></div><div>... this seems to=
me=C2=A0a strong suggestion that the=C2=A0language needs to standardize th=
is concept.</div><div><br><br>On Friday, July 24, 2015 at 7:43:51 AM UTC-6,=
David Rodr=C3=ADguez Ibeas wrote:</div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rg=
b(204, 204, 204); border-left-width: 1px; border-left-style: solid;"><div d=
ir=3D"ltr">Answering to Howard's message, but really aimed at Denis:<br=
><div><br><div class=3D"gmail_quote">On Fri, Jul 24, 2015 at 12:41 PM, Howa=
rd Hinnant <span dir=3D"ltr"><<a onmousedown=3D"this.href=3D'javascr=
ipt:';return true;" onclick=3D"this.href=3D'javascript:';return=
true;" href=3D"javascript:" target=3D"_blank" rel=3D"nofollow">howard....@=
gmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=
=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(20=
4, 204, 204); border-left-width: 1px; border-left-style: solid;">For four y=
ears now we=E2=80=99ve had:<br>
<br>
=C2=A0 =C2=A0 template <class T, class... Args> struct is_trivially_c=
onstructible;<br>
=C2=A0 =C2=A0 template <class T>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 struct is_trivially_default_constructible;<br>
=C2=A0 =C2=A0 template <class T>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 struct is_trivially_copy_constructible;<br>
=C2=A0 =C2=A0 template <class T>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 struct is_trivially_move_constructible;<br>
=C2=A0 =C2=A0 template <class T, class U>=C2=A0 =C2=A0 =C2=A0 =C2=A0s=
truct is_trivially_assignable;<br>
=C2=A0 =C2=A0 template <class T>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 struct is_trivially_copy_assignable;<br>
=C2=A0 =C2=A0 template <class T>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 struct is_trivially_move_assignable;<br>
=C2=A0 =C2=A0 template <class T>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 struct is_trivially_destructible;<br></blockquote><div=
><br>And beyond that, some libraries provide traits that indicate when an o=
bject can be "moved" by memcpy by not calling the destructor on t=
he source object. I am not sure if that is the case of Q_MOVABLE_TYPE (quic=
k google search failed me), but it is in EASTL (has_trivial_relocate), BSL =
(IsBitwiseMovable), Folly (IsRelocatable). The trait indicates that a destr=
uctive move can be implemented by blasting bits from the source to the dest=
ination and making sure that the destructor is not run over the source.=C2=
=A0 The destructive move is trivially noexcept and can be used even with ty=
pes for which move constructors cannot be noexcept (for example Dinkumware&=
#39;s or BSL list implementations).<br><br>Implementations can use this to =
efficiently implement capacity grows in vectors through memcpy (and releasi=
ng the source buffer's memory without running the destructors) or to im=
plement insertions/removals from the middle of a vector through memmove.<br=
><br>Now, this cannot be inferred in any way by a compiler, and the trait h=
as to be explicitly reported by the implementor of the type.<br><br>On the =
exception part of the thread... I am not sure how the proposal is really he=
lping. Users that want to run multiple destructors (assuming a container im=
plementation) need to write roughly the same amount of code that they would=
write now (try block), maybe slightly simpler code (no need to handle manu=
ally nesting exceptions), but this should be rare. =C2=A0<br><br>So the mai=
n advantage is for compiler-generated destructors what would do this implic=
itly over the members at the cost of additional generated code for the case=
s where nested exceptions won't happen (the proposal makes destructors =
default to noexcept(false), so the compiler can only assume that they may t=
hrow). Additionally this increases the complexity of the language for all u=
sers: anyone that wants to handle exceptions needs to handle just one excep=
tion in flight today, all that code would have to be adjusted to handle pos=
sibly multiple exceptions in flight.=C2=A0 Note that the proposal does not =
just turn something that may terminate into multiple exceptions, it also ca=
uses multiple exceptions to appear in situations that are not possible toda=
y as an exception flying over a destructor won't exit the destructor bu=
t continue to destroy the rest of the members.=C2=A0 I am not sure, but if =
I understood it right, code that handles only one exception (i.e. all code =
today) could 'std::terminate'<br><br>On this note, most of the dest=
ructors that I have ever seen "failing" did not fail while destru=
cting members, but inside the destructor body, similar to Thiago's '=
;dispose', and there you would have to do basically the same that you d=
o today: wrap every operation that can fail into a 'try+' block<br>=
<br>I would suggest that you create some non-trivial real-world example tha=
t shows this as a big improvement over the current state of affairs, I fear=
that in most real world examples the proposal would not be that different =
from today's implementations (where 'try*' and 'try+' a=
re replaced by a slightly more complex 'try/catch' that transforms =
into a nested exception, and the 'catch-any' construct replaces a c=
atch with the nested exceptions, or a 'exception_list' (which I ima=
gine not that hard to implement in user code).<br><br>I don't think the=
potential advantage in code is worth the additional complexity for all use=
rs that don't care today.<br><br>=C2=A0 =C2=A0 David<br><br>P.S. Some a=
ssumptions you have which I don't think are correct:<br><br>- Exception=
s cannot cross thread boundaries<br><br>=C2=A0 I am pretty sure that they c=
an, it is already done in 'std::future' for example. The compiler w=
on't aggregate them for you, but the library could without having to ch=
ange the core language.<br><br>- The solution makes managing exceptions eas=
ier<br><br>=C2=A0 It does not. It raises the complexity of most uses and it=
lowers the complexity of a different subset of users. The increase in comp=
lexity is not huge, but it is broad. The lower complexity is deeper, but mo=
re niche.<br><br><br></div></div></div></div>
</blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1042_1264922424.1437765814603--
------=_Part_1041_1319456658.1437765814603--
.
Author: Howard Hinnant <howard.hinnant@gmail.com>
Date: Fri, 24 Jul 2015 15:30:30 -0400
Raw View
On Jul 24, 2015, at 3:17 PM, denis bider <isocppgroup@denisbider.com> wrote=
:
>=20
> Howard:
>=20
> > For four years now we=E2=80=99ve had:=20
> > template <class T, class... Args> struct is_trivially_constructible;=20
> > template <class T> struct is_trivially_default_construct=
ible;
> > template <class T> struct is_trivially_copy_constructibl=
e;=20
> > template <class T> struct is_trivially_move_constructibl=
e;=20
> > template <class T, class U> struct is_trivially_assignable;=20
> > template <class T> struct is_trivially_copy_assignable;=
=20
> > template <class T> struct is_trivially_move_assignable;=
=20
> > template <class T> struct is_trivially_destructible;=20
>=20
> Which one of these - or which combination of them - would you then sugges=
t a container can use to deduce that it's safe to memcpy an object, and not=
call its destructor in the previous location?
>=20
> I would argue that none of these accurately reflect what the container is=
trying to do.
>=20
> It seems to me the container needs a combination of these properties:
>=20
> is_trivially_move_constructible
> is_trivially_destructible // but only after trivial move construction
Agreed, this is what I would use too for a trivial destructive move constru=
ction, except without the comment. A trivial move constructor doesn=E2=80=
=99t alter the source (else it would not be trivial). So the source has to=
be trivially destructible from an arbitrary state (assuming current langua=
ge rules).
>=20
> Most classes that have any kind of strings or resources in them are not t=
rivially destructible. However, they are trivially destructible after they =
have been used to trivially move construct another object.
There is interest in creating destructive move semantics. For example see:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4158.pdf
See also the section "Destructive move semantics=E2=80=9D here:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm#Alternati=
ve%20move%20designs
for issues I would like to see addressed in any destructive move proposal.
Howard
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Fri, 24 Jul 2015 12:57:26 -0700 (PDT)
Raw View
------=_Part_1120_1486384034.1437767846938
Content-Type: multipart/alternative;
boundary="----=_Part_1121_1903732358.1437767846938"
------=_Part_1121_1903732358.1437767846938
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
> Agreed, this is what I would use too for a trivial destructive
> move construction, except without the comment.
> A trivial move constructor doesn=E2=80=99t alter the source
> (else it would not be trivial). So the source has to be
> trivially destructible from an arbitrary state
> (assuming current language rules).
But the comment does not imply that the source is not trivially=20
destructible from an arbitrary state.
What the comment implies is that the source is trivially destructible, if=
=20
and only if it has just been used to trivially move construct another=20
object.
There should be another comment next to is_trivially_move_constructible, as=
=20
well. Many objects may be trivially move constructible, but *only *if this=
=20
is followed by trivial destruction of the source. It's a contract.
On Friday, July 24, 2015 at 1:30:31 PM UTC-6, Howard Hinnant wrote:
> On Jul 24, 2015, at 3:17 PM, denis bider <isocp...@denisbider.com=20
> <javascript:>> wrote:=20
> >=20
> > Howard:=20
> >=20
> > > For four years now we=E2=80=99ve had:=20
> > > template <class T, class... Args> struct is_trivially_constructible;=
=20
> > > template <class T> struct=20
> is_trivially_default_constructible;=20
> > > template <class T> struct=20
> is_trivially_copy_constructible;=20
> > > template <class T> struct=20
> is_trivially_move_constructible;=20
> > > template <class T, class U> struct is_trivially_assignable;=20
> > > template <class T> struct is_trivially_copy_assignable=
;=20
> > > template <class T> struct is_trivially_move_assignable=
;=20
> > > template <class T> struct is_trivially_destructible;=
=20
> >=20
> > Which one of these - or which combination of them - would you then=20
> suggest a container can use to deduce that it's safe to memcpy an object,=
=20
> and not call its destructor in the previous location?=20
> >=20
> > I would argue that none of these accurately reflect what the container=
=20
> is trying to do.=20
> >=20
> > It seems to me the container needs a combination of these properties:=
=20
> >=20
> > is_trivially_move_constructible=20
> > is_trivially_destructible // but only after trivial move construction=
=20
>
> Agreed, this is what I would use too for a trivial destructive move=20
> construction, except without the comment. A trivial move constructor=20
> doesn=E2=80=99t alter the source (else it would not be trivial). So the =
source has=20
> to be trivially destructible from an arbitrary state (assuming current=20
> language rules).=20
>
> >=20
> > Most classes that have any kind of strings or resources in them are not=
=20
> trivially destructible. However, they are trivially destructible after th=
ey=20
> have been used to trivially move construct another object.=20
>
> There is interest in creating destructive move semantics. For example=20
> see:=20
>
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4158.pdf=20
>
> See also the section "Destructive move semantics=E2=80=9D here:=20
>
>
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm#Alterna=
tive%20move%20designs=20
>
> for issues I would like to see addressed in any destructive move proposal=
..=20
>
> Howard=20
>
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1121_1903732358.1437767846938
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>> Agreed, this is what I would use too for a trivi=
al destructive</div><div>> move construction, except without the comment=
..</div><div>> A trivial move constructor doesn=E2=80=99t alter the sourc=
e</div><div>> (else it would not be trivial). =C2=A0So the source has to=
be</div><div>> trivially destructible from an arbitrary state</div><div=
>> (assuming current language rules).</div><div><br></div><div>But the c=
omment does not imply that the source is not trivially destructible from an=
arbitrary state.</div><div><br></div><div>What the comment implies is that=
the source is trivially destructible, if and only if it has just been used=
to trivially move construct another object.</div><div><br></div><div>There=
should be another comment next to is_trivially_move_constructible, as well=
.. Many objects may be trivially move constructible, but <em>only </em>if th=
is is followed by trivial destruction of the source. It's a contract.<b=
r><br><br>On Friday, July 24, 2015 at 1:30:31 PM UTC-6, Howard Hinnant wrot=
e:</div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8e=
x; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-wi=
dth: 1px; border-left-style: solid;">On Jul 24, 2015, at 3:17 PM, denis bid=
er <<a onmousedown=3D"this.href=3D'javascript:';return true;" on=
click=3D"this.href=3D'javascript:';return true;" href=3D"javascript=
:" target=3D"_blank" rel=3D"nofollow">isocp...@denisbider.com</a>> wrote=
:
<br>>=20
<br>> Howard:
<br>>=20
<br>> > For four years now we=E2=80=99ve had:=20
<br>> > template <class T, class... Args> struct is_trivially_c=
onstructible;=20
<br>> > template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0struct is_trivially_default_constructible;
<br>> > template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0struct is_trivially_copy_constructible;=20
<br>> > template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0struct is_trivially_move_constructible;=20
<br>> > template <class T, class U> =C2=A0 =C2=A0 =C2=A0 struct=
is_trivially_assignable;=20
<br>> > template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0struct is_trivially_copy_assignable;=20
<br>> > template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0struct is_trivially_move_assignable;=20
<br>> > template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0struct is_trivially_destructible;=20
<br>>=20
<br>> Which one of these - or which combination of them - would you then=
suggest a container can use to deduce that it's safe to memcpy an obje=
ct, and not call its destructor in the previous location?
<br>>=20
<br>> I would argue that none of these accurately reflect what the conta=
iner is trying to do.
<br>>=20
<br>> It seems to me the container needs a combination of these properti=
es:
<br>>=20
<br>> is_trivially_move_constructible
<br>> is_trivially_destructible =C2=A0// but only after trivial move con=
struction
<br>
<br>Agreed, this is what I would use too for a trivial destructive move con=
struction, except without the comment. =C2=A0A trivial move constructor doe=
sn=E2=80=99t alter the source (else it would not be trivial). =C2=A0So the =
source has to be trivially destructible from an arbitrary state (assuming c=
urrent language rules).
<br>
<br>>=20
<br>> Most classes that have any kind of strings or resources in them ar=
e not trivially destructible. However, they are trivially destructible afte=
r they have been used to trivially move construct another object.
<br>
<br>There is interest in creating destructive move semantics. =C2=A0For exa=
mple see:
<br>
<br><a onmousedown=3D"this.href=3D'http://www.google.com/url?q\75http%3=
A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2014%2Fn4158=
..pdf\46sa\75D\46sntz\0751\46usg\75AFQjCNFSMQjXX1FT4QHQxCpy1JdEdqJMdg';r=
eturn true;" onclick=3D"this.href=3D'http://www.google.com/url?q\75http=
%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2014%2Fn41=
58.pdf\46sa\75D\46sntz\0751\46usg\75AFQjCNFSMQjXX1FT4QHQxCpy1JdEdqJMdg'=
;return true;" href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2=
014/n4158.pdf" target=3D"_blank" rel=3D"nofollow">http://www.open-std.org/j=
tc1/sc22/wg21/docs/papers/2014/n4158.pdf</a>
<br>
<br>See also the section "Destructive move semantics=E2=80=9D here:
<br>
<br><a onmousedown=3D"this.href=3D'http://www.google.com/url?q\75http%3=
A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2002%2Fn1377=
..htm%23Alternative%2520move%2520designs\46sa\75D\46sntz\0751\46usg\75AFQjCN=
Gt0VU-QXvmQUWducammjz-p0o-Dg';return true;" onclick=3D"this.href=3D'=
;http://www.google.com/url?q\75http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%=
2Fwg21%2Fdocs%2Fpapers%2F2002%2Fn1377.htm%23Alternative%2520move%2520design=
s\46sa\75D\46sntz\0751\46usg\75AFQjCNGt0VU-QXvmQUWducammjz-p0o-Dg';retu=
rn true;" href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n=
1377.htm#Alternative%20move%20designs" target=3D"_blank" rel=3D"nofollow">h=
ttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm#Alternativ=
e%20move%20designs</a>
<br>
<br>for issues I would like to see addressed in any destructive move propos=
al.
<br>
<br>Howard
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1121_1903732358.1437767846938--
------=_Part_1120_1486384034.1437767846938--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Fri, 24 Jul 2015 13:21:42 -0700 (PDT)
Raw View
------=_Part_1115_1202617170.1437769302976
Content-Type: multipart/alternative;
boundary="----=_Part_1116_1146825473.1437769302976"
------=_Part_1116_1146825473.1437769302976
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
> There is interest in creating destructive move semantics. For example=20
see:=20
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4158.pdf=20
Thank you for the link. I have now read this.
I like this proposal as far as it goes, but I think we need to go further.
This proposal is essentially standardization of current third-party library=
=20
concepts: Q_MOVABLE_TYPE, has_trivial_relocate, IsBitwiseMovable,=20
IsRelocatable.
This is good as far as it goes. It's better than nothing. It's better to=20
have one of these concepts than 10.
But what I *really* want is for the compiler to automatically flag my types=
=20
as trivially-destructive-movable, based on satisfying certain conditions.
As far as I can tell, *all* instances of classes not being=20
trivially-destructive-movable involve the class containing raw pointers.=20
(As opposed to references; except for classes that aren't copyable or=20
movable, at all.)
Therefore, we can come up with the following rules:
- If a type contains only integers and floats, and derives only from types=
=20
that are movable, and aggregates only types that are movable: it's movable.
- Otherwise: if the type contains pointers or references; or aggregates or=
=20
derives from types that aren't movable: it is movable if and only if it's=
=20
explicitly declared so: "class A movable".
I would really like the compiler's assistance in this. Otherwise, I have to=
=20
declare
every
type
that
I
will
ever
use
explicitly as movable.
And this is not nice.
On Friday, July 24, 2015 at 1:30:31 PM UTC-6, Howard Hinnant wrote:
> On Jul 24, 2015, at 3:17 PM, denis bider <isocp...@denisbider.com=20
> <javascript:>> wrote:=20
> >=20
> > Howard:=20
> >=20
> > > For four years now we=E2=80=99ve had:=20
> > > template <class T, class... Args> struct is_trivially_constructible;=
=20
> > > template <class T> struct=20
> is_trivially_default_constructible;=20
> > > template <class T> struct=20
> is_trivially_copy_constructible;=20
> > > template <class T> struct=20
> is_trivially_move_constructible;=20
> > > template <class T, class U> struct is_trivially_assignable;=20
> > > template <class T> struct is_trivially_copy_assignable=
;=20
> > > template <class T> struct is_trivially_move_assignable=
;=20
> > > template <class T> struct is_trivially_destructible;=
=20
> >=20
> > Which one of these - or which combination of them - would you then=20
> suggest a container can use to deduce that it's safe to memcpy an object,=
=20
> and not call its destructor in the previous location?=20
> >=20
> > I would argue that none of these accurately reflect what the container=
=20
> is trying to do.=20
> >=20
> > It seems to me the container needs a combination of these properties:=
=20
> >=20
> > is_trivially_move_constructible=20
> > is_trivially_destructible // but only after trivial move construction=
=20
>
> Agreed, this is what I would use too for a trivial destructive move=20
> construction, except without the comment. A trivial move constructor=20
> doesn=E2=80=99t alter the source (else it would not be trivial). So the =
source has=20
> to be trivially destructible from an arbitrary state (assuming current=20
> language rules).=20
>
> >=20
> > Most classes that have any kind of strings or resources in them are not=
=20
> trivially destructible. However, they are trivially destructible after th=
ey=20
> have been used to trivially move construct another object.=20
>
> There is interest in creating destructive move semantics. For example=20
> see:=20
>
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4158.pdf=20
>
> See also the section "Destructive move semantics=E2=80=9D here:=20
>
>
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm#Alterna=
tive%20move%20designs=20
>
> for issues I would like to see addressed in any destructive move proposal=
..=20
>
> Howard=20
>
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1116_1146825473.1437769302976
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>> There is interest in creating destructive move s=
emantics. =C2=A0For example see: <br>> <a onmousedown=3D"this.href=3D=
9;http://www.google.com/url?q\75http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22=
%2Fwg21%2Fdocs%2Fpapers%2F2014%2Fn4158.pdf\46sa\75D\46sntz\0751\46usg\75AFQ=
jCNFSMQjXX1FT4QHQxCpy1JdEdqJMdg';return true;" onclick=3D"this.href=3D&=
#39;http://www.google.com/url?q\75http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc=
22%2Fwg21%2Fdocs%2Fpapers%2F2014%2Fn4158.pdf\46sa\75D\46sntz\0751\46usg\75A=
FQjCNFSMQjXX1FT4QHQxCpy1JdEdqJMdg';return true;" href=3D"http://www.ope=
n-std.org/jtc1/sc22/wg21/docs/papers/2014/n4158.pdf" target=3D"_blank" rel=
=3D"nofollow">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4158=
..pdf</a> </div><div><br></div><div>Thank you for the link. I have now=C2=A0=
read this.</div><div><br></div><div>I like this proposal as far as it goes,=
but I think we need to go further.</div><div><br></div><div>This proposal =
is essentially standardization of current third-party library concepts: Q_M=
OVABLE_TYPE, has_trivial_relocate, IsBitwiseMovable, IsRelocatable.</div><d=
iv><br></div><div>This is good as far as it goes. It's better than noth=
ing. It's better to have one=C2=A0of these concepts than 10.</div><div>=
<br></div><div>But what I <em>really</em> want is for the compiler to autom=
atically flag my types as trivially-destructive-movable, based on satisfyin=
g certain conditions.</div><div><br></div><div>As far as I can tell, <em>al=
l</em> instances of classes not being trivially-destructive-movable involve=
the class containing raw pointers. (As opposed to=C2=A0references; except =
for classes that aren't=C2=A0copyable or movable, at all.)</div><div><b=
r></div><div>Therefore, we can come up with the following rules:</div><div>=
<br></div><div>- If a type contains only integers and floats, and derives o=
nly from=C2=A0types that are movable, and aggregates only types that are mo=
vable:=C2=A0it's movable.</div><div><br></div><div>-=C2=A0Otherwise: if=
the type contains pointers or references;=C2=A0or=C2=A0aggregates or deriv=
es from types that aren't movable: it is movable if and only if it'=
s explicitly declared so: "class A movable".</div><div><br></div>=
<div>I would really like the compiler's assistance in this. Otherwise, =
I have to declare</div><div><br></div><div>every</div><div><br></div><div>t=
ype</div><div><br></div><div>that</div><div><br></div><div>I</div><div><br>=
</div><div>will</div><div><br></div><div>ever</div><div><br></div><div>use<=
/div><div><br></div><div>explicitly as movable.</div><div><br></div><div>An=
d this is not nice.</div><div><br><br>On Friday, July 24, 2015 at 1:30:31 P=
M UTC-6, Howard Hinnant wrote:</div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(20=
4, 204, 204); border-left-width: 1px; border-left-style: solid;">On Jul 24,=
2015, at 3:17 PM, denis bider <<a onmousedown=3D"this.href=3D'javas=
cript:';return true;" onclick=3D"this.href=3D'javascript:';retu=
rn true;" href=3D"javascript:" target=3D"_blank" rel=3D"nofollow">isocp...@=
denisbider.com</a>> wrote:
<br>>=20
<br>> Howard:
<br>>=20
<br>> > For four years now we=E2=80=99ve had:=20
<br>> > template <class T, class... Args> struct is_trivially_c=
onstructible;=20
<br>> > template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0struct is_trivially_default_constructible;
<br>> > template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0struct is_trivially_copy_constructible;=20
<br>> > template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0struct is_trivially_move_constructible;=20
<br>> > template <class T, class U> =C2=A0 =C2=A0 =C2=A0 struct=
is_trivially_assignable;=20
<br>> > template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0struct is_trivially_copy_assignable;=20
<br>> > template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0struct is_trivially_move_assignable;=20
<br>> > template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0struct is_trivially_destructible;=20
<br>>=20
<br>> Which one of these - or which combination of them - would you then=
suggest a container can use to deduce that it's safe to memcpy an obje=
ct, and not call its destructor in the previous location?
<br>>=20
<br>> I would argue that none of these accurately reflect what the conta=
iner is trying to do.
<br>>=20
<br>> It seems to me the container needs a combination of these properti=
es:
<br>>=20
<br>> is_trivially_move_constructible
<br>> is_trivially_destructible =C2=A0// but only after trivial move con=
struction
<br>
<br>Agreed, this is what I would use too for a trivial destructive move con=
struction, except without the comment. =C2=A0A trivial move constructor doe=
sn=E2=80=99t alter the source (else it would not be trivial). =C2=A0So the =
source has to be trivially destructible from an arbitrary state (assuming c=
urrent language rules).
<br>
<br>>=20
<br>> Most classes that have any kind of strings or resources in them ar=
e not trivially destructible. However, they are trivially destructible afte=
r they have been used to trivially move construct another object.
<br>
<br>There is interest in creating destructive move semantics. =C2=A0For exa=
mple see:
<br>
<br><a onmousedown=3D"this.href=3D'http://www.google.com/url?q\75http%3=
A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2014%2Fn4158=
..pdf\46sa\75D\46sntz\0751\46usg\75AFQjCNFSMQjXX1FT4QHQxCpy1JdEdqJMdg';r=
eturn true;" onclick=3D"this.href=3D'http://www.google.com/url?q\75http=
%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2014%2Fn41=
58.pdf\46sa\75D\46sntz\0751\46usg\75AFQjCNFSMQjXX1FT4QHQxCpy1JdEdqJMdg'=
;return true;" href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2=
014/n4158.pdf" target=3D"_blank" rel=3D"nofollow">http://www.open-std.org/j=
tc1/sc22/wg21/docs/papers/2014/n4158.pdf</a>
<br>
<br>See also the section "Destructive move semantics=E2=80=9D here:
<br>
<br><a onmousedown=3D"this.href=3D'http://www.google.com/url?q\75http%3=
A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2002%2Fn1377=
..htm%23Alternative%2520move%2520designs\46sa\75D\46sntz\0751\46usg\75AFQjCN=
Gt0VU-QXvmQUWducammjz-p0o-Dg';return true;" onclick=3D"this.href=3D'=
;http://www.google.com/url?q\75http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%=
2Fwg21%2Fdocs%2Fpapers%2F2002%2Fn1377.htm%23Alternative%2520move%2520design=
s\46sa\75D\46sntz\0751\46usg\75AFQjCNGt0VU-QXvmQUWducammjz-p0o-Dg';retu=
rn true;" href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n=
1377.htm#Alternative%20move%20designs" target=3D"_blank" rel=3D"nofollow">h=
ttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm#Alternativ=
e%20move%20designs</a>
<br>
<br>for issues I would like to see addressed in any destructive move propos=
al.
<br>
<br>Howard
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1116_1146825473.1437769302976--
------=_Part_1115_1202617170.1437769302976--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Fri, 24 Jul 2015 13:33:12 -0700 (PDT)
Raw View
------=_Part_1246_1815815268.1437769992862
Content-Type: multipart/alternative;
boundary="----=_Part_1247_636474429.1437769992863"
------=_Part_1247_636474429.1437769992863
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
In FACT, this is not all.
What I want in addition is for the compiler to warn me if I have=20
accidentally made a class not movable.
In order to avoid this diagnostic, every class that isn't movable *should*=
=20
be explicitly declared "class A movable(false)".
Examples:
struct A { int x; }; // OK, movable
struct B { B* x; }; // *Warning:* not declared non-movable
struct C movable(false) { C* x; }; // OK, explicitly declared
struct D : A { }; // OK, movable
struct E : C { }; // *Warning:* not declared non-movable
struct E movable(false) : C { }; // OK, explicitly declared
Also - with respect to this proposed rule:
> If a type contains only integers and floats,
> and derives only from types that are movable,
> and aggregates only types that are movable:
> it's movable.
It strikes me that a class with pointers to only built-in types (bool*,=20
char*, int*, int**) can be assumed movable as well. The point where the=20
compiler needs help is with classes containing pointers to user-defined=20
types.
On Friday, July 24, 2015 at 2:21:43 PM UTC-6, denis bider wrote:
> > There is interest in creating destructive move semantics. For example=
=20
> see:=20
> > http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4158.pdf=20
>
> Thank you for the link. I have now read this.
>
> I like this proposal as far as it goes, but I think we need to go further=
..
>
> This proposal is essentially standardization of current third-party=20
> library concepts: Q_MOVABLE_TYPE, has_trivial_relocate, IsBitwiseMovable,=
=20
> IsRelocatable.
>
> This is good as far as it goes. It's better than nothing. It's better to=
=20
> have one of these concepts than 10.
>
> But what I *really* want is for the compiler to automatically flag my=20
> types as trivially-destructive-movable, based on satisfying certain=20
> conditions.
>
> As far as I can tell, *all* instances of classes not being=20
> trivially-destructive-movable involve the class containing raw pointers.=
=20
> (As opposed to references; except for classes that aren't copyable or=20
> movable, at all.)
>
> Therefore, we can come up with the following rules:
>
> - If a type contains only integers and floats, and derives only from type=
s=20
> that are movable, and aggregates only types that are movable: it's movabl=
e.
>
> - Otherwise: if the type contains pointers or references; or aggregates o=
r=20
> derives from types that aren't movable: it is movable if and only if it's=
=20
> explicitly declared so: "class A movable".
>
> I would really like the compiler's assistance in this. Otherwise, I have=
=20
> to declare
>
> every
>
> type
>
> that
>
> I
>
> will
>
> ever
>
> use
>
> explicitly as movable.
>
> And this is not nice.
>
>
> On Friday, July 24, 2015 at 1:30:31 PM UTC-6, Howard Hinnant wrote:
>
>> On Jul 24, 2015, at 3:17 PM, denis bider <isocp...@denisbider.com>=20
>> wrote:=20
>> >=20
>> > Howard:=20
>> >=20
>> > > For four years now we=E2=80=99ve had:=20
>> > > template <class T, class... Args> struct is_trivially_constructible;=
=20
>> > > template <class T> struct=20
>> is_trivially_default_constructible;=20
>> > > template <class T> struct=20
>> is_trivially_copy_constructible;=20
>> > > template <class T> struct=20
>> is_trivially_move_constructible;=20
>> > > template <class T, class U> struct is_trivially_assignable;=20
>> > > template <class T> struct=20
>> is_trivially_copy_assignable;=20
>> > > template <class T> struct=20
>> is_trivially_move_assignable;=20
>> > > template <class T> struct is_trivially_destructible;=
=20
>> >=20
>> > Which one of these - or which combination of them - would you then=20
>> suggest a container can use to deduce that it's safe to memcpy an object=
,=20
>> and not call its destructor in the previous location?=20
>> >=20
>> > I would argue that none of these accurately reflect what the container=
=20
>> is trying to do.=20
>> >=20
>> > It seems to me the container needs a combination of these properties:=
=20
>> >=20
>> > is_trivially_move_constructible=20
>> > is_trivially_destructible // but only after trivial move construction=
=20
>>
>> Agreed, this is what I would use too for a trivial destructive move=20
>> construction, except without the comment. A trivial move constructor=20
>> doesn=E2=80=99t alter the source (else it would not be trivial). So the=
source has=20
>> to be trivially destructible from an arbitrary state (assuming current=
=20
>> language rules).=20
>>
>> >=20
>> > Most classes that have any kind of strings or resources in them are no=
t=20
>> trivially destructible. However, they are trivially destructible after t=
hey=20
>> have been used to trivially move construct another object.=20
>>
>> There is interest in creating destructive move semantics. For example=
=20
>> see:=20
>>
>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4158.pdf=20
>>
>> See also the section "Destructive move semantics=E2=80=9D here:=20
>>
>>
>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm#Altern=
ative%20move%20designs=20
>>
>> for issues I would like to see addressed in any destructive move=20
>> proposal.=20
>>
>> Howard=20
>>
>>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1247_636474429.1437769992863
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>In FACT, this is not all.</div><div><br></div><div>Wh=
at I want in addition is for the compiler to warn me if I have accidentally=
made a class not movable.</div><div><br></div><div>In order to avoid this =
diagnostic, every class that isn't movable <em>should</em> be explicitl=
y declared "class A movable(false)".</div><div><br></div><div>Exa=
mples:</div><div><br></div><div><font face=3D"courier new,monospace">struct=
A { int x; };=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 // OK, movable<br>struct B { B* x; };=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 // <strong>Warning:</strong> not declared non-movable<br>st=
ruct C movable(false) { C* x; };=C2=A0 // OK, explicitly declared<br>struct=
D : A { };=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 // OK, movable<br>struct E : =
C { };=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 // <strong>Warning:</strong> not de=
clared non-movable<br>struct E movable(false) : C { };=C2=A0=C2=A0=C2=A0 //=
OK, explicitly declared<br></font></div><div><br></div><div><br></div><div=
>Also - with respect to this proposed rule:</div><div><br></div><div>> I=
f a type contains only integers and floats,</div><div>> and derives only=
from=C2=A0types that are movable,</div><div>> and aggregates only types=
that are movable:</div><div>> it's movable.</div><div><br></div><di=
v>It strikes me that a class with pointers to only built-in types (bool*, c=
har*, int*, int**) can be assumed=C2=A0movable as well. The point where the=
compiler needs help is with classes containing pointers to user-defined ty=
pes.</div><div><br></div><div><br>On Friday, July 24, 2015 at 2:21:43 PM UT=
C-6, denis bider wrote:</div><blockquote class=3D"gmail_quote" style=3D"mar=
gin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204,=
204); border-left-width: 1px; border-left-style: solid;"><div dir=3D"ltr">=
<div>> There is interest in creating destructive move semantics. =C2=A0F=
or example see: <br>> <a onmousedown=3D"this.href=3D'http://www.goog=
le.com/url?q\75http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2F=
papers%2F2014%2Fn4158.pdf\46sa\75D\46sntz\0751\46usg\75AFQjCNFSMQjXX1FT4QHQ=
xCpy1JdEdqJMdg';return true;" onclick=3D"this.href=3D'http://www.go=
ogle.com/url?q\75http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%=
2Fpapers%2F2014%2Fn4158.pdf\46sa\75D\46sntz\0751\46usg\75AFQjCNFSMQjXX1FT4Q=
HQxCpy1JdEdqJMdg';return true;" href=3D"http://www.open-std.org/jtc1/sc=
22/wg21/docs/papers/2014/n4158.pdf" target=3D"_blank" rel=3D"nofollow">http=
://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4158.pdf</a> </div><di=
v><br></div><div>Thank you for the link. I have now=C2=A0read this.</div><d=
iv><br></div><div>I like this proposal as far as it goes, but I think we ne=
ed to go further.</div><div><br></div><div>This proposal is essentially sta=
ndardization of current third-party library concepts: Q_MOVABLE_TYPE, has_t=
rivial_relocate, IsBitwiseMovable, IsRelocatable.</div><div><br></div><div>=
This is good as far as it goes. It's better than nothing. It's bett=
er to have one=C2=A0of these concepts than 10.</div><div><br></div><div>But=
what I <em>really</em> want is for the compiler to automatically flag my t=
ypes as trivially-destructive-movable, based on satisfying certain conditio=
ns.</div><div><br></div><div>As far as I can tell, <em>all</em> instances o=
f classes not being trivially-destructive-movable involve the class contain=
ing raw pointers. (As opposed to=C2=A0references; except for classes that a=
ren't=C2=A0copyable or movable, at all.)</div><div><br></div><div>There=
fore, we can come up with the following rules:</div><div><br></div><div>- I=
f a type contains only integers and floats, and derives only from=C2=A0type=
s that are movable, and aggregates only types that are movable:=C2=A0it'=
;s movable.</div><div><br></div><div>-=C2=A0Otherwise: if the type contains=
pointers or references;=C2=A0or=C2=A0aggregates or derives from types that=
aren't movable: it is movable if and only if it's explicitly decla=
red so: "class A movable".</div><div><br></div><div>I would reall=
y like the compiler's assistance in this. Otherwise, I have to declare<=
/div><div><br></div><div>every</div><div><br></div><div>type</div><div><br>=
</div><div>that</div><div><br></div><div>I</div><div><br></div><div>will</d=
iv><div><br></div><div>ever</div><div><br></div><div>use</div><div><br></di=
v><div>explicitly as movable.</div><div><br></div><div>And this is not nice=
..</div><div><br><br>On Friday, July 24, 2015 at 1:30:31 PM UTC-6, Howard Hi=
nnant wrote:</div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0p=
x 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); bord=
er-left-width: 1px; border-left-style: solid;">On Jul 24, 2015, at 3:17 PM,=
denis bider <<a rel=3D"nofollow">isocp...@denisbider.com</a>> wrote:
<br>>=20
<br>> Howard:
<br>>=20
<br>> > For four years now we=E2=80=99ve had:=20
<br>> > template <class T, class... Args> struct is_trivially_c=
onstructible;=20
<br>> > template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0struct is_trivially_default_constructible;
<br>> > template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0struct is_trivially_copy_constructible;=20
<br>> > template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0struct is_trivially_move_constructible;=20
<br>> > template <class T, class U> =C2=A0 =C2=A0 =C2=A0 struct=
is_trivially_assignable;=20
<br>> > template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0struct is_trivially_copy_assignable;=20
<br>> > template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0struct is_trivially_move_assignable;=20
<br>> > template <class T> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0struct is_trivially_destructible;=20
<br>>=20
<br>> Which one of these - or which combination of them - would you then=
suggest a container can use to deduce that it's safe to memcpy an obje=
ct, and not call its destructor in the previous location?
<br>>=20
<br>> I would argue that none of these accurately reflect what the conta=
iner is trying to do.
<br>>=20
<br>> It seems to me the container needs a combination of these properti=
es:
<br>>=20
<br>> is_trivially_move_constructible
<br>> is_trivially_destructible =C2=A0// but only after trivial move con=
struction
<br>
<br>Agreed, this is what I would use too for a trivial destructive move con=
struction, except without the comment. =C2=A0A trivial move constructor doe=
sn=E2=80=99t alter the source (else it would not be trivial). =C2=A0So the =
source has to be trivially destructible from an arbitrary state (assuming c=
urrent language rules).
<br>
<br>>=20
<br>> Most classes that have any kind of strings or resources in them ar=
e not trivially destructible. However, they are trivially destructible afte=
r they have been used to trivially move construct another object.
<br>
<br>There is interest in creating destructive move semantics. =C2=A0For exa=
mple see:
<br>
<br><a onmousedown=3D"this.href=3D'http://www.google.com/url?q\75http%3=
A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2014%2Fn4158=
..pdf\46sa\75D\46sntz\0751\46usg\75AFQjCNFSMQjXX1FT4QHQxCpy1JdEdqJMdg';r=
eturn true;" onclick=3D"this.href=3D'http://www.google.com/url?q\75http=
%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2014%2Fn41=
58.pdf\46sa\75D\46sntz\0751\46usg\75AFQjCNFSMQjXX1FT4QHQxCpy1JdEdqJMdg'=
;return true;" href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2=
014/n4158.pdf" target=3D"_blank" rel=3D"nofollow">http://www.open-std.org/j=
tc1/sc22/wg21/docs/papers/2014/n4158.pdf</a>
<br>
<br>See also the section "Destructive move semantics=E2=80=9D here:
<br>
<br><a onmousedown=3D"this.href=3D'http://www.google.com/url?q\75http%3=
A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2002%2Fn1377=
..htm%23Alternative%2520move%2520designs\46sa\75D\46sntz\0751\46usg\75AFQjCN=
Gt0VU-QXvmQUWducammjz-p0o-Dg';return true;" onclick=3D"this.href=3D'=
;http://www.google.com/url?q\75http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%=
2Fwg21%2Fdocs%2Fpapers%2F2002%2Fn1377.htm%23Alternative%2520move%2520design=
s\46sa\75D\46sntz\0751\46usg\75AFQjCNGt0VU-QXvmQUWducammjz-p0o-Dg';retu=
rn true;" href=3D"http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n=
1377.htm#Alternative%20move%20designs" target=3D"_blank" rel=3D"nofollow">h=
ttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm#Alternativ=
e%20move%20designs</a>
<br>
<br>for issues I would like to see addressed in any destructive move propos=
al.
<br>
<br>Howard
<br>
<br></blockquote></div></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1247_636474429.1437769992863--
------=_Part_1246_1815815268.1437769992862--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Fri, 24 Jul 2015 14:37:35 -0700
Raw View
On Friday 24 July 2015 13:21:42 denis bider wrote:
> Therefore, we can come up with the following rules:
>
> - If a type contains only integers and floats, and derives only from types
> that are movable, and aggregates only types that are movable: it's movable.
You've just described trivial types. Yes, all trivial types are movable.
> - Otherwise: if the type contains pointers or references; or aggregates or
> derives from types that aren't movable: it is movable if and only if it's
> explicitly declared so: "class A movable".
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Fri, 24 Jul 2015 15:04:17 -0700 (PDT)
Raw View
------=_Part_1073_1307218595.1437775457981
Content-Type: multipart/alternative;
boundary="----=_Part_1074_575224709.1437775457981"
------=_Part_1074_575224709.1437775457981
Content-Type: text/plain; charset=UTF-8
I intentionally avoided "trivial" because that might then also include
structured types that a developer has declared trivial.
But arguably, including such types would be fine, too.
On Friday, July 24, 2015 at 3:37:41 PM UTC-6, Thiago Macieira wrote:
> On Friday 24 July 2015 13:21:42 denis bider wrote:
> > Therefore, we can come up with the following rules:
> >
> > - If a type contains only integers and floats, and derives only from
> types
> > that are movable, and aggregates only types that are movable: it's
> movable.
>
> You've just described trivial types. Yes, all trivial types are movable.
>
> > - Otherwise: if the type contains pointers or references; or aggregates
> or
> > derives from types that aren't movable: it is movable if and only if
> it's
> > explicitly declared so: "class A movable".
>
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
> PGP/GPG: 0x6EF45358; fingerprint:
> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
>
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1074_575224709.1437775457981
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>I intentionally avoided "trivial" because t=
hat might then also include structured types that a developer has declared =
trivial.</div><div><br></div><div>But arguably, including such types would =
be fine, too.</div><div><br><br>On Friday, July 24, 2015 at 3:37:41 PM UTC-=
6, Thiago Macieira wrote:</div><blockquote class=3D"gmail_quote" style=3D"m=
argin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 20=
4, 204); border-left-width: 1px; border-left-style: solid;">On Friday 24 Ju=
ly 2015 13:21:42 denis bider wrote:
<br>> Therefore, we can come up with the following rules:
<br>>=20
<br>> - If a type contains only integers and floats, and derives only fr=
om types
<br>> that are movable, and aggregates only types that are movable: it&#=
39;s movable.
<br>
<br>You've just described trivial types. Yes, all trivial types are mov=
able.
<br>
<br>> - Otherwise: if the type contains pointers or references; or aggre=
gates or
<br>> derives from types that aren't movable: it is movable if and o=
nly if it's
<br>> explicitly declared so: "class A movable".
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a onmousedown=3D"this.href=3D'http:/=
/www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\75D\46sntz\0751\46u=
sg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.=
href=3D'http://www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\7=
5D\46sntz\0751\46usg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;=
" href=3D"http://macieira.info" target=3D"_blank" rel=3D"nofollow">macieira=
..info</a> - thiago (AT) <a onmousedown=3D"this.href=3D'http://www.googl=
e.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\75AFQjCNHGRJd=
o5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'http=
://www.google.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\7=
5AFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;" href=3D"http://kde.o=
rg" target=3D"_blank" rel=3D"nofollow">kde.org</a>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>=C2=A0 =C2=A0 =C2=A0 PGP/GPG: 0x6EF45358; fingerprint:
<br>=C2=A0 =C2=A0 =C2=A0 E067 918B B660 DBD1 105C =C2=A0966C 33F5 F005 6EF4=
5358
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1074_575224709.1437775457981--
------=_Part_1073_1307218595.1437775457981--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Fri, 24 Jul 2015 15:07:52 -0700 (PDT)
Raw View
------=_Part_1213_1431303191.1437775672443
Content-Type: multipart/alternative;
boundary="----=_Part_1214_1390620307.1437775672443"
------=_Part_1214_1390620307.1437775672443
Content-Type: text/plain; charset=UTF-8
Also, you are in fact incorrect:
#include <type_traits>
struct A {};
static_assert(std::is_trivial<A*>::value, "");
A* is a trivial type, but this:
struct B { A* x; };
cannot be assumed to be a movable.
On Friday, July 24, 2015 at 4:04:18 PM UTC-6, denis bider wrote:
> I intentionally avoided "trivial" because that might then also include
> structured types that a developer has declared trivial.
>
> But arguably, including such types would be fine, too.
>
>
> On Friday, July 24, 2015 at 3:37:41 PM UTC-6, Thiago Macieira wrote:
>
>> On Friday 24 July 2015 13:21:42 denis bider wrote:
>> > Therefore, we can come up with the following rules:
>> >
>> > - If a type contains only integers and floats, and derives only from
>> types
>> > that are movable, and aggregates only types that are movable: it's
>> movable.
>>
>> You've just described trivial types. Yes, all trivial types are movable.
>>
>> > - Otherwise: if the type contains pointers or references; or aggregates
>> or
>> > derives from types that aren't movable: it is movable if and only if
>> it's
>> > explicitly declared so: "class A movable".
>>
>> --
>> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
>> Software Architect - Intel Open Source Technology Center
>> PGP/GPG: 0x6EF45358; fingerprint:
>> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
>>
>>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1214_1390620307.1437775672443
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Also, you are in fact incorrect:</div><div><br></div>=
<div><font face=3D"courier new,monospace">#include <type_traits><br>s=
truct A {};<br>static_assert(std::is_trivial<A*>::value, ""=
);<br></font></div><div><br></div><div>A* is a trivial type, but this:</div=
><div><br></div><div><font face=3D"courier new,monospace">struct B { A* x; =
};</font></div><div><br></div><div>cannot be assumed to be a movable.</div>=
<div><br><br>On Friday, July 24, 2015 at 4:04:18 PM UTC-6, denis bider wrot=
e:</div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8e=
x; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-wi=
dth: 1px; border-left-style: solid;"><div dir=3D"ltr"><div>I intentionally =
avoided "trivial" because that might then also include structured=
types that a developer has declared trivial.</div><div><br></div><div>But =
arguably, including such types would be fine, too.</div><div><br><br>On Fri=
day, July 24, 2015 at 3:37:41 PM UTC-6, Thiago Macieira wrote:</div><blockq=
uote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left=
: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px; borde=
r-left-style: solid;">On Friday 24 July 2015 13:21:42 denis bider wrote:
<br>> Therefore, we can come up with the following rules:
<br>>=20
<br>> - If a type contains only integers and floats, and derives only fr=
om types
<br>> that are movable, and aggregates only types that are movable: it&#=
39;s movable.
<br>
<br>You've just described trivial types. Yes, all trivial types are mov=
able.
<br>
<br>> - Otherwise: if the type contains pointers or references; or aggre=
gates or
<br>> derives from types that aren't movable: it is movable if and o=
nly if it's
<br>> explicitly declared so: "class A movable".
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a onmousedown=3D"this.href=3D'http:/=
/www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\75D\46sntz\0751\46u=
sg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.=
href=3D'http://www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\7=
5D\46sntz\0751\46usg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;=
" href=3D"http://macieira.info" target=3D"_blank" rel=3D"nofollow">macieira=
..info</a> - thiago (AT) <a onmousedown=3D"this.href=3D'http://www.googl=
e.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\75AFQjCNHGRJd=
o5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'http=
://www.google.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\7=
5AFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;" href=3D"http://kde.o=
rg" target=3D"_blank" rel=3D"nofollow">kde.org</a>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>=C2=A0 =C2=A0 =C2=A0 PGP/GPG: 0x6EF45358; fingerprint:
<br>=C2=A0 =C2=A0 =C2=A0 E067 918B B660 DBD1 105C =C2=A0966C 33F5 F005 6EF4=
5358
<br>
<br></blockquote></div></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1214_1390620307.1437775672443--
------=_Part_1213_1431303191.1437775672443--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Fri, 24 Jul 2015 15:44:27 -0700
Raw View
On Friday 24 July 2015 15:07:52 denis bider wrote:
> Also, you are in fact incorrect:
>
> #include <type_traits>
> struct A {};
> static_assert(std::is_trivial<A*>::value, "");
>
> A* is a trivial type, but this:
>
> struct B { A* x; };
>
> cannot be assumed to be a movable.
Yes, it can. The type B above *is* movable because the destructible move via
memcpy is identical to:
new (dst) B(*src)
src->~B();
If you meant to add a copy constructor, then it would cease being trivial.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Fri, 24 Jul 2015 15:46:47 -0700
Raw View
On Friday 24 July 2015 11:47:03 denis bider wrote:
> - If the exception mechanism was designed from scratch, it *should* handle
> multi-exceptions. It seems to me that the mechanism I proposed would be a
> general way to do this.
Not sure. The exception mechanism was designed the way it was so it would work
without dynamic memory allocation. That problem hasn't been solved yet.
> - If classes were designed from scratch, they *should* be movable by
> default - removing a lot of destructor use in containers that's in fact
> unnecessary.
This is a more-or-less recent development. Before the standard template
library came long, code most often stored pointers to the elements, not the
elements themselves. Copying/moving those is trivial. That's also what higher
level languages do.
Indeed C++98 made this difficult, but C++11 is a long way towards the right way.
With a trait like is_trivial_type and its derivatives, classes are by default
movable, unless you take an action that hides its movability from the
compiler. Like adding a copy constructor.
> - If we do not move towards better design decisions gradually, over time;
> then another language will do this in a more revolutionary manner.
While that may be true, it does not guarantee the success of that language. In
fact, C and C++ still are the de-facto solutions for portable, high-
performance code, despite Java in the 90s, scripting languages of the
noughties and Go and Rust from the 2010s.
> - If we allow a sufficient number of suboptimal design choices to be
> accumulated in our language, which are solved by another language, then
> users writing new software will migrate to that new language.
Again, only if that new language does not in the process add a sufficient number
of suboptimal designs of their own. See above.
> It seems to me that:
>
> - the single-exception policy;
>
> - a related issue - that we don't assume classes to be bitwise movable *as
> default*, and therefore call destructors too much;
I disagree. In most languages, move semantics does not even come into
discussion. C++ is already much ahead of anything else by having move
semantics at all.
Let's build on it.
[And, like I said, looking at it from a different point of view, classes are
bitwise movable by default already]
> But each little shortcoming like this is a brick. And lots of these bricks
> make a wall. And if we don't work to continually dissolve these bricks; if
> we don't continually strive to make the language the best that it *can *be
> - instead of what compatibility dictates;
I again disagree. We don't want to remove a brick in a support column that
would cause the column to crumble and cause the whole castle to fall.
Certain things cannot be removed because they'd break way too much code and
cause bigger problems than the issue being fixed.
> Everything must evolve, or be replaced, eventually. I don't think it's
> viable to maintain backward compatibility indefinitely.
I disagree on both sentences.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Fri, 24 Jul 2015 16:16:12 -0700 (PDT)
Raw View
------=_Part_1253_1901649817.1437779772886
Content-Type: multipart/alternative;
boundary="----=_Part_1254_654986233.1437779772886"
------=_Part_1254_654986233.1437779772886
Content-Type: text/plain; charset=UTF-8
> The type B above *is* movable because the destructible
> move via memcpy is identical to: If you meant to add a
> copy constructor, then it would cease being trivial.
True, I should have added one.
> The exception mechanism was designed the way it was
> so it would work without dynamic memory allocation.
> That problem hasn't been solved yet.
I think that's an imagined problem.
As if the stack magically provides unlimited memory.
It doesn't. A program can run out of stack *any time*.
Why is it that, when it comes to the stack, somehow this isn't an issue?
> With a trait like is_trivial_type and its derivatives, classes
> are by default movable, unless you take an action that
> hides its movability from the compiler.
> Like adding a copy constructor.
However, the whole trivially-destructive-movable issue revolves around
types with copy constructors.
I cannot declare my StringType is_trivial. But I need this:
struct A { StringType x; };
.... to be movable, without having to *say* that it is.
> Again, only if that new language does not
> in the process add a sufficient number of
> suboptimal designs of their own.
Indeed. Rust has some ingenious ideas, but then I look at its error
handling, and there's either explicit checking of results, or "panic!".
Ooookay.
But that's why I'm pushing for improvement here, instead of moving to Rust.
> We don't want to remove a brick in a support column that
> would cause the column to crumble and cause the whole
> castle to fall.
That's why you transition over time.
How do we walk? You don't move the leg you stand on. You put your weight on
one leg; you move the other leg; then you switch.
That's how systems evolve, too. You provide new behavior; allow ample time
for users to migrate - in the case of C++, this is on the order of 20 years
- then you deprecate the old behavior; and then you remove it.
> > Everything must evolve, or be replaced, eventually.
> > I don't think it's viable to maintain backward
> > compatibility indefinitely.
>
> I disagree on both sentences.
You've said before you hate macros. You don't want the language to evolve
in a way that they can eventually be removed?
Or *at least *replaced with namespace-aware macros?
In 20 years? In 50 years? 100?
A hundred years from now, in 2115, do you *really* want C++ to *still *implement
macros that aren't even namespace aware?
On Friday, July 24, 2015 at 4:46:50 PM UTC-6, Thiago Macieira wrote:
> On Friday 24 July 2015 11:47:03 denis bider wrote:
> > - If the exception mechanism was designed from scratch, it *should*
> handle
> > multi-exceptions. It seems to me that the mechanism I proposed would be
> a
> > general way to do this.
>
> Not sure. The exception mechanism was designed the way it was so it would
> work
> without dynamic memory allocation. That problem hasn't been solved yet.
>
> > - If classes were designed from scratch, they *should* be movable by
> > default - removing a lot of destructor use in containers that's in fact
> > unnecessary.
>
> This is a more-or-less recent development. Before the standard template
> library came long, code most often stored pointers to the elements, not
> the
> elements themselves. Copying/moving those is trivial. That's also what
> higher
> level languages do.
>
> Indeed C++98 made this difficult, but C++11 is a long way towards the
> right way.
>
> With a trait like is_trivial_type and its derivatives, classes are by
> default
> movable, unless you take an action that hides its movability from the
> compiler. Like adding a copy constructor.
>
> > - If we do not move towards better design decisions gradually, over
> time;
> > then another language will do this in a more revolutionary manner.
>
> While that may be true, it does not guarantee the success of that
> language. In
> fact, C and C++ still are the de-facto solutions for portable, high-
> performance code, despite Java in the 90s, scripting languages of the
> noughties and Go and Rust from the 2010s.
>
> > - If we allow a sufficient number of suboptimal design choices to be
> > accumulated in our language, which are solved by another language, then
> > users writing new software will migrate to that new language.
>
> Again, only if that new language does not in the process add a sufficient
> number
> of suboptimal designs of their own. See above.
>
> > It seems to me that:
> >
> > - the single-exception policy;
> >
> > - a related issue - that we don't assume classes to be bitwise movable
> *as
> > default*, and therefore call destructors too much;
>
> I disagree. In most languages, move semantics does not even come into
> discussion. C++ is already much ahead of anything else by having move
> semantics at all.
>
> Let's build on it.
>
> [And, like I said, looking at it from a different point of view, classes
> are
> bitwise movable by default already]
>
> > But each little shortcoming like this is a brick. And lots of these
> bricks
> > make a wall. And if we don't work to continually dissolve these bricks;
> if
> > we don't continually strive to make the language the best that it *can
> *be
> > - instead of what compatibility dictates;
>
> I again disagree. We don't want to remove a brick in a support column that
> would cause the column to crumble and cause the whole castle to fall.
>
> Certain things cannot be removed because they'd break way too much code
> and
> cause bigger problems than the issue being fixed.
>
> > Everything must evolve, or be replaced, eventually. I don't think it's
> > viable to maintain backward compatibility indefinitely.
>
> I disagree on both sentences.
>
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
> PGP/GPG: 0x6EF45358; fingerprint:
> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
>
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1254_654986233.1437779772886
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>> The type B above *is* movable because the destru=
ctible</div><div>> move via=C2=A0memcpy is identical to:=C2=A0If you mea=
nt to add a</div><div>> copy constructor, then it would cease being triv=
ial.<br></div><div><br></div><div>True, I should have added one.</div><div>=
<br></div><div><br></div><div>>=C2=A0The exception mechanism was designe=
d the way it was</div><div>> so it would work=C2=A0without dynamic memor=
y allocation.</div><div>> That problem hasn't been solved yet. </div=
><div><br></div><div>I think that's an imagined problem.</div><div><br>=
As if the stack magically provides unlimited memory.</div><div><br></div><d=
iv>It doesn't. A program can run out of stack <em>any time</em>.</div><=
div><br></div><div>Why is it that, when it comes to the stack, somehow this=
isn't an issue?<br></div><div><br></div><div><br></div><div>> With =
a trait like is_trivial_type and its derivatives, classes</div><div>> ar=
e by default=C2=A0movable, unless you take an action that</div><div>> hi=
des its movability from the=C2=A0=C2=A0compiler.</div><div>> Like adding=
a copy constructor. <br></div><div><br></div><div><div>However, the whole =
trivially-destructive-movable issue revolves around types with copy constru=
ctors.</div><div><br></div><div>I cannot declare my=C2=A0StringType is_triv=
ial. But I need this:</div><div><br></div><div>struct A { StringType x; };<=
/div><div><br></div><div>... to be movable, without having to <em>say</em> =
that it is.</div></div><div><br></div><div><br></div><div>> Again, only =
if that new language does not</div><div>> in the process add a sufficien=
t number=C2=A0of</div><div>> suboptimal designs of their own.</div><div>=
<br></div><div>Indeed. Rust has some ingenious ideas, but then I look at it=
s error handling, and=C2=A0there's either=C2=A0explicit checking of res=
ults, or "panic!". Ooookay.</div><div><br></div><div>But that'=
;s why I'm pushing for improvement here, instead of=C2=A0moving to Rust=
..</div><div><br></div><div><br></div><div>> We don't want to remove =
a brick in a support column that</div><div>> would cause the column to c=
rumble and cause the whole</div><div>> castle to fall. </div><div><br></=
div><div>That's why you transition over time.</div><div><br></div><div>=
How do we walk? You don't move the leg you stand on. You put your weigh=
t on one leg; you move the other leg; then you switch.</div><div><br></div>=
<div>That's how systems evolve, too. You provide new behavior; allow am=
ple time for users to migrate - in the case of C++, this is on the order of=
20 years - then you deprecate the old behavior; and then you remove it.<br=
></div><div><br></div><div><br></div><div>> > Everything must evolve,=
or be replaced, eventually.</div><div>> > I don't think it's=
=C2=A0viable to maintain backward</div><div>> > compatibility indefin=
itely. </div><div>> <br></div><div>> I disagree on both sentences. </=
div><div><br></div><div>You've said before you hate macros. You don'=
;t want the language to evolve in a way that they can eventually be removed=
?</div><div><br></div><div>Or <em>at least </em>replaced with namespace-awa=
re macros?</div><div><br></div><div>In 20 years? In 50 years? 100?</div><di=
v><br></div><div>A hundred years from now, in 2115, do you <em>really</em> =
want C++ to <em>still=C2=A0</em>implement macros that aren't=C2=A0even =
namespace aware?</div><div><br></div><div><br>On Friday, July 24, 2015 at 4=
:46:50 PM UTC-6, Thiago Macieira wrote:</div><blockquote class=3D"gmail_quo=
te" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-colo=
r: rgb(204, 204, 204); border-left-width: 1px; border-left-style: solid;">O=
n Friday 24 July 2015 11:47:03 denis bider wrote:
<br>> - If the exception mechanism was designed from scratch, it *should=
* handle
<br>> multi-exceptions. It seems to me that the mechanism I proposed wou=
ld be a
<br>> general way to do this.
<br>
<br>Not sure. The exception mechanism was designed the way it was so it wou=
ld work=20
<br>without dynamic memory allocation. That problem hasn't been solved =
yet.
<br>
<br>> - If classes were designed from scratch, they *should* be movable =
by
<br>> default - removing a lot of destructor use in containers that'=
s in fact
<br>> unnecessary.
<br>
<br>This is a more-or-less recent development. Before the standard template=
=20
<br>library came long, code most often stored pointers to the elements, not=
the=20
<br>elements themselves. Copying/moving those is trivial. That's also w=
hat higher=20
<br>level languages do.
<br>
<br>Indeed C++98 made this difficult, but C++11 is a long way towards the r=
ight way.
<br>
<br>With a trait like is_trivial_type and its derivatives, classes are by d=
efault=20
<br>movable, unless you take an action that hides its movability from the=
=20
<br>compiler. Like adding a copy constructor.
<br>
<br>> - If we do not move towards better design decisions gradually, ove=
r time;
<br>> then another language will do this in a more revolutionary manner.
<br>
<br>While that may be true, it does not guarantee the success of that langu=
age. In=20
<br>fact, C and C++ still are the de-facto solutions for portable, high-
<br>performance code, despite Java in the 90s, scripting languages of the=
=20
<br>noughties and Go and Rust from the 2010s.
<br>
<br>> - If we allow a sufficient number of suboptimal design choices to =
be
<br>> accumulated in our language, which are solved by another language,=
then
<br>> users writing new software will migrate to that new language.
<br>
<br>Again, only if that new language does not in the process add a sufficie=
nt number=20
<br>of suboptimal designs of their own. See above.
<br>
<br>> It seems to me that:
<br>>=20
<br>> - the single-exception policy;
<br>>=20
<br>> - a related issue - that we don't assume classes to be bitwise=
movable *as
<br>> default*, and therefore call destructors too much;
<br>
<br>I disagree. In most languages, move semantics does not even come into=
=20
<br>discussion. C++ is already much ahead of anything else by having move=
=20
<br>semantics at all.
<br>
<br>Let's build on it.
<br>
<br>[And, like I said, looking at it from a different point of view, classe=
s are=20
<br>bitwise movable by default already]
<br>
<br>> But each little shortcoming like this is a brick. And lots of thes=
e bricks
<br>> make a wall. And if we don't work to continually dissolve thes=
e bricks; if
<br>> we don't continually strive to make the language the best that=
it *can *be
<br>> - instead of what compatibility dictates;
<br>
<br>I again disagree. We don't want to remove a brick in a support colu=
mn that=20
<br>would cause the column to crumble and cause the whole castle to fall.
<br>
<br>Certain things cannot be removed because they'd break way too much =
code and=20
<br>cause bigger problems than the issue being fixed.
<br>
<br>> Everything must evolve, or be replaced, eventually. I don't th=
ink it's
<br>> viable to maintain backward compatibility indefinitely.
<br>
<br>I disagree on both sentences.
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a onmousedown=3D"this.href=3D'http:/=
/www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\75D\46sntz\0751\46u=
sg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.=
href=3D'http://www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\7=
5D\46sntz\0751\46usg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;=
" href=3D"http://macieira.info" target=3D"_blank" rel=3D"nofollow">macieira=
..info</a> - thiago (AT) <a onmousedown=3D"this.href=3D'http://www.googl=
e.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\75AFQjCNHGRJd=
o5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'http=
://www.google.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\7=
5AFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;" href=3D"http://kde.o=
rg" target=3D"_blank" rel=3D"nofollow">kde.org</a>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>=C2=A0 =C2=A0 =C2=A0 PGP/GPG: 0x6EF45358; fingerprint:
<br>=C2=A0 =C2=A0 =C2=A0 E067 918B B660 DBD1 105C =C2=A0966C 33F5 F005 6EF4=
5358
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1254_654986233.1437779772886--
------=_Part_1253_1901649817.1437779772886--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Fri, 24 Jul 2015 16:57:33 -0700
Raw View
On Friday 24 July 2015 16:16:12 denis bider wrote:
> > The exception mechanism was designed the way it was
> > so it would work without dynamic memory allocation.
> > That problem hasn't been solved yet.
>
> I think that's an imagined problem.
>
> As if the stack magically provides unlimited memory.
>
> It doesn't. A program can run out of stack *any time*.
>
> Why is it that, when it comes to the stack, somehow this isn't an issue?
It sure is. That's one of the reason why VLAs were dropped from C++14: we
couldn't get a proper error reporting in case of stack exhaustion. There were
other issues, but this was a big one.
Stack space has grown more in-line with our stack needs compared to the heap,
to the point that most stack exhaustion cases are a symptom of a different bug
(infinite recursion) than caused by the managing of a reasonable data set. Heap
exhaustion is often a problem of its own.
And yet you're also right that it's a problem less frequently managed. Careful
code regularly deals with memory allocation failures -- let's ignore the fact
of whether the failures are reliably reported -- but often does not deal with
stack exhaustion. I've seen a lot of defensive-programming guidelines deal
with memory allocation and validating user input, but I don't remember ever
seeing them talk about stack overflow defence.
An algorithm that occupies a small stack frame size (let's say 64 bytes) could
recurse roughly 130000 times before exhausting the default stack on Linux,
while 130000 items is not an unreasonable number of items in a data set. After
all, a vector of 131072 items of 1024 bytes occupies 128 MB, something readily
available to most applications.
> > With a trait like is_trivial_type and its derivatives, classes
> > are by default movable, unless you take an action that
> > hides its movability from the compiler.
> > Like adding a copy constructor.
>
> However, the whole trivially-destructive-movable issue revolves around
> types with copy constructors.
I know. I am agreeing with you we need a trait that the class author can
specify. I was just nitpicking on your wording.
> I cannot declare my StringType is_trivial. But I need this:
>
> struct A { StringType x; };
>
> ... to be movable, without having to *say* that it is.
Hmm... interesting.
You're saying that an aggregate with public, implicit copy constructors and
destructors (though not necessarily trivial) should automatically be marked
movable if it is composed only of movable sub-objects?
Makes sense.
> > We don't want to remove a brick in a support column that
> > would cause the column to crumble and cause the whole
> > castle to fall.
>
> That's why you transition over time.
>
> How do we walk? You don't move the leg you stand on. You put your weight on
> one leg; you move the other leg; then you switch.
>
> That's how systems evolve, too. You provide new behavior; allow ample time
> for users to migrate - in the case of C++, this is on the order of 20 years
> - then you deprecate the old behavior; and then you remove it.
Indeed, but only if people have actually migrated.
For example, typedefs will never go away, no matter how much we make an
incentive to use the new using declaration, unless C also does it.
Compatibility with C headers is very important.
> > > Everything must evolve, or be replaced, eventually.
> > > I don't think it's viable to maintain backward
> > > compatibility indefinitely.
> >
> > I disagree on both sentences.
>
> You've said before you hate macros. You don't want the language to evolve
> in a way that they can eventually be removed?
That's another thing that will never be removed, unless we also convince C to
do it too.
> Or *at least *replaced with namespace-aware macros?
I'm not convinced namespace-aware macros will work or that they solve the
right problem.
> A hundred years from now, in 2115, do you *really* want C++ to *still
> *implement macros that aren't even namespace aware?
If C2111 still has namespace-unaware macros and there's a large codebase using
them, then yes, C++2114 should still support them.
Anyway, I was disagreeing with the sentences themselves.
"Everything must evolve or be replaced": it will be replaced only if something
better comes along, solving problems that the current solution didn't solve,
without unduly creating new problems.
"Maintain backwards compatibility indefinitely": see above on one particular
case, that of C compatibility, which is a fundamental strength of C++, not a
weakness. There are others. Legacy is not always a bad thing: being familiar,
with a large pool of developers who understand it, is a positive aspect.
Breaking compatibility is a compromise and you can't expect to win every time.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: =?UTF-8?Q?David_Rodr=C3=ADguez_Ibeas?= <dibeas@ieee.org>
Date: Sat, 25 Jul 2015 01:07:54 +0100
Raw View
--089e0149420a839ec2051ba7e919
Content-Type: text/plain; charset=UTF-8
On Fri, Jul 24, 2015 at 9:33 PM, denis bider <isocppgroup@denisbider.com>
wrote:
> It strikes me that a class with pointers to only built-in types (bool*,
> char*, int*, int**) can be assumed movable as well. The point where the
> compiler needs help is with classes containing pointers to user-defined
> types.
>
>
Not really. The core property of a type that is *not* bitwise movable is
that it contains pointers or references to a member that is not dynamically
allocated. I am using "contains" here in a broad sense that includes not
only pointers held directly in this object, but additionally pointers in
other objects that refer to it.
The first case would be:
struct A {
int value;
int *ptr;
A() : value(), ptr(&value) {}
}; // not bitwise movable
The second case includes the implementation of std::list in stdc++, where
the first and last nodes in the list contain pointers to the std::list
object (the std::list object serves as a "sentry" node in both the forward
and backwards directions).
If a type does not contain pointers [*] it fair to assume that it is not
self-referencing and it is bitwise movable, even if the constructors and
possibly the destructor are not trivial (say a destructor that is user
provided to validate the invariants).
For anything else, the compiler could, as QoI, hint you about the trait,
but I would not like a compiler flagging the type as bitwise movable
aggresively: if it is not marked as bitwise movable and it is, you miss a
performance gain; if it is not bitwise movable and it is incorrectly marked
so you have a correctness issue. As they say, those willing to sacrifice
correctness for performance deserve neither.
David
[*] --> or integral values that might represent a pointer, as in
'reinterpret_cast<size_t>(ptr)', but if your type has these, it is up to
you to flag the type.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--089e0149420a839ec2051ba7e919
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><div class=3D"gmail_quote">=
On Fri, Jul 24, 2015 at 9:33 PM, denis bider <span dir=3D"ltr"><<a href=
=3D"mailto:isocppgroup@denisbider.com" target=3D"_blank">isocppgroup@denisb=
ider.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=
=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><div>It strikes me that a class with pointers to only built-in typ=
es (bool*, char*, int*, int**) can be assumed=C2=A0movable as well. The poi=
nt where the compiler needs help is with classes containing pointers to use=
r-defined types.<br></div><div><div class=3D"h5"><div><br></div></div></div=
></div></blockquote><div><br></div><div>Not really. The core property of a =
type that is *not* bitwise movable is that it contains pointers or referenc=
es to a member that is not dynamically allocated. I am using "contains=
" here in a broad sense that includes not only pointers held directly =
in this object, but additionally pointers in other objects that refer to it=
..</div><div><br></div><div>The first case would be:</div><div><br></div><di=
v>struct A {</div><div>=C2=A0 =C2=A0int value;</div><div>=C2=A0 =C2=A0int *=
ptr;</div><div>=C2=A0 =C2=A0A() : value(), ptr(&value) {}</div><div>}; =
// not bitwise movable</div><div><br></div><div>The second case includes th=
e implementation of std::list in stdc++, where the first and last nodes in =
the list contain pointers to the std::list object (the std::list object ser=
ves as a "sentry" node in both the forward and backwards directio=
ns).</div><div><br></div><div>If a type does not contain pointers [*] it fa=
ir to assume that it is not self-referencing and it is bitwise movable, eve=
n if the constructors and possibly the destructor are not trivial (say a de=
structor that is user provided to validate the invariants).</div><div><br><=
/div><div>For anything else, the compiler could, as QoI, hint you about the=
trait, but I would not like a compiler flagging the type as bitwise movabl=
e aggresively: if it is not marked as bitwise movable and it is, you miss a=
performance gain; if it is not bitwise movable and it is incorrectly marke=
d so you have a correctness issue. As they say, those willing to sacrifice =
correctness for performance deserve neither.</div><div><br></div><div>=C2=
=A0 =C2=A0David</div><div><br></div><div>[*] --> or integral values that=
might represent a pointer, as in 'reinterpret_cast<size_t>(ptr)&=
#39;, but if your type has these, it is up to you to flag the type.</div></=
div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--089e0149420a839ec2051ba7e919--
.
Author: Howard Hinnant <howard.hinnant@gmail.com>
Date: Fri, 24 Jul 2015 20:28:38 -0400
Raw View
I came in on this thread late, and missed a lot of the initial context. I =
came into it because I saw statements like the one I quote below, and read =
them out of context:
On Jul 24, 2015, at 7:16 PM, denis bider <isocppgroup@denisbider.com> wrote=
:
>=20
> I cannot declare my StringType is_trivial. But I need this:
>=20
> struct A { StringType x; };
>=20
> ... to be movable, without having to say that it is.
>=20
Out of context, this is a blatantly false statement.
My sincere suggestion is that you adopt some other terminology that won=E2=
=80=99t be mistaken for C++11/14 move semantics. Perhaps =E2=80=9Ctriviall=
y destructive movable=E2=80=9D or whatever. Just something so that when so=
mebody (like me) reads a snippet as they cruise through the 100=E2=80=99s o=
f unread emails in their inbox, this doesn=E2=80=99t catch their eye and ma=
ke them believe you don=E2=80=99t know what you=E2=80=99re talking about.
Just a friendly suggestion.
Howard
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
Date: Fri, 24 Jul 2015 17:39:35 -0700 (PDT)
Raw View
------=_Part_19_256387369.1437784775257
Content-Type: multipart/alternative;
boundary="----=_Part_20_335458135.1437784775258"
------=_Part_20_335458135.1437784775258
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Friday, July 24, 2015 at 12:57:27 PM UTC-7, denis bider wrote:
>
> > Agreed, this is what I would use too for a trivial destructive
> > move construction, except without the comment.
> > A trivial move constructor doesn=E2=80=99t alter the source
> > (else it would not be trivial). So the source has to be
> > trivially destructible from an arbitrary state
> > (assuming current language rules).
>
> But the comment does not imply that the source is not trivially=20
> destructible from an arbitrary state.
>
> What the comment implies is that the source is trivially destructible, if=
=20
> and only if it has just been used to trivially move construct another=20
> object.
>
> There should be another comment next to is_trivially_move_constructible,=
=20
> as well. Many objects may be trivially move constructible, but *only *if=
=20
> this is followed by trivial destruction of the source. It's a contract.
>
Yes, as Denis says, it appears to me that if I really wanted to implement a=
=20
blazingly fast std::vector, I would want the user to provide me with a=20
specialization of
template<class T> struct is_trivially_destructively_move_constructible;
whose value is true iff
new (&t2) T(std::move(t1));
t1->~T();
is logically equivalent to
// never attempt to construct t2
memcpy(t2, t1, sizeof(T));
// never attempt to destroy t1
This trait would be true of a lot of library types; for example, it would=
=20
be true of std::string and std::vector<int>, *even though* (as Howard very=
=20
correctly said) neither of these types is trivially move-constructible.
I skimmed N4158 and N1377 and didn't see anything that looked similar to=20
is_trivially_destructively_move_constructible.
Has such a type-trait ever been proposed? Might one be, soon? I'd be happy=
=20
to write up the wording...
Thanks,
Arthur
There is interest in creating destructive move semantics. For example see:=
=20
>>
>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4158.pdf=20
>> <http://www.google.com/url?q=3Dhttp%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc=
22%2Fwg21%2Fdocs%2Fpapers%2F2014%2Fn4158.pdf&sa=3DD&sntz=3D1&usg=3DAFQjCNFS=
MQjXX1FT4QHQxCpy1JdEdqJMdg>=20
>>
>> See also the section "Destructive move semantics=E2=80=9D here:=20
>>
>>
>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm#Altern=
ative%20move%20designs=20
>> <http://www.google.com/url?q=3Dhttp%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc=
22%2Fwg21%2Fdocs%2Fpapers%2F2002%2Fn1377.htm%23Alternative%2520move%2520des=
igns&sa=3DD&sntz=3D1&usg=3DAFQjCNGt0VU-QXvmQUWducammjz-p0o-Dg>=20
>>
>> for issues I would like to see addressed in any destructive move=20
>> proposal.=20
>>
>> Howard=20
>>
>>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_20_335458135.1437784775258
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Friday, July 24, 2015 at 12:57:27 PM UTC-7, denis bider wrote:<blockquot=
e class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: =
1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>> Agreed, this =
is what I would use too for a trivial destructive</div><div>> move const=
ruction, except without the comment.</div><div>> A trivial move construc=
tor doesn=E2=80=99t alter the source</div><div>> (else it would not be t=
rivial). =C2=A0So the source has to be</div><div>> trivially destructibl=
e from an arbitrary state</div><div>> (assuming current language rules).=
</div><div><br></div><div>But the comment does not imply that the source is=
not trivially destructible from an arbitrary state.</div><div><br></div><d=
iv>What the comment implies is that the source is trivially destructible, i=
f and only if it has just been used to trivially move construct another obj=
ect.</div><div><br></div><div>There should be another comment next to is_tr=
ivially_move_constructible, as well. Many objects may be trivially move con=
structible, but <em>only </em>if this is followed by trivial destruction of=
the source. It's a contract.<br></div></div></blockquote><div><br></di=
v><div>Yes, as Denis says, it appears to me that if I really wanted to impl=
ement a blazingly fast std::vector, I would want the user to provide me wit=
h a specialization of</div><div><br></div><div>=C2=A0 =C2=A0 template<cl=
ass T> struct is_trivially_destructively_move_constructible;</div><div><=
br></div><div>whose value is true iff</div><div><br></div><div>=C2=A0 =C2=
=A0 new (&t2) T(std::move(t1));</div><div>=C2=A0 =C2=A0 t1->~T();</d=
iv><div><br></div><div>is logically equivalent to</div><div><br></div><div>=
=C2=A0 =C2=A0 // never attempt to construct t2</div><div>=C2=A0 =C2=A0 memc=
py(t2, t1, sizeof(T));</div><div>=C2=A0 =C2=A0 // never attempt to destroy =
t1</div><div><br></div><div>This trait would be true of a lot of library ty=
pes; for example, it would be true of std::string and std::vector<int>=
;, <i>even though</i> (as Howard very correctly said) neither of these type=
s is trivially move-constructible.</div><div><br></div><div>I skimmed N4158=
and N1377 and didn't see anything that looked similar to is_trivially_=
destructively_move_constructible.</div><div>Has such a type-trait ever been=
proposed? Might one be, soon? I'd be happy to write up the wording...<=
/div><div><br></div><div>Thanks,</div><div>Arthur</div><div><br></div><div>=
<br></div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margin:=
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div =
dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0=
..8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:=
1px;border-left-style:solid">There is interest in creating destructive move=
semantics. =C2=A0For example see:
<br>
<br><a href=3D"http://www.google.com/url?q=3Dhttp%3A%2F%2Fwww.open-std.org%=
2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2014%2Fn4158.pdf&sa=3DD&sntz=
=3D1&usg=3DAFQjCNFSMQjXX1FT4QHQxCpy1JdEdqJMdg" rel=3D"nofollow" target=
=3D"_blank" onmousedown=3D"this.href=3D'http://www.google.com/url?q\75h=
ttp%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2014%2F=
n4158.pdf\46sa\75D\46sntz\0751\46usg\75AFQjCNFSMQjXX1FT4QHQxCpy1JdEdqJMdg&#=
39;;return true;" onclick=3D"this.href=3D'http://www.google.com/url?q\7=
5http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2014%=
2Fn4158.pdf\46sa\75D\46sntz\0751\46usg\75AFQjCNFSMQjXX1FT4QHQxCpy1JdEdqJMdg=
';return true;">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014=
/n4158.pdf</a>
<br>
<br>See also the section "Destructive move semantics=E2=80=9D here:
<br>
<br><a href=3D"http://www.google.com/url?q=3Dhttp%3A%2F%2Fwww.open-std.org%=
2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2002%2Fn1377.htm%23Alternative%2520m=
ove%2520designs&sa=3DD&sntz=3D1&usg=3DAFQjCNGt0VU-QXvmQUWducamm=
jz-p0o-Dg" rel=3D"nofollow" target=3D"_blank" onmousedown=3D"this.href=3D&#=
39;http://www.google.com/url?q\75http%3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc2=
2%2Fwg21%2Fdocs%2Fpapers%2F2002%2Fn1377.htm%23Alternative%2520move%2520desi=
gns\46sa\75D\46sntz\0751\46usg\75AFQjCNGt0VU-QXvmQUWducammjz-p0o-Dg';re=
turn true;" onclick=3D"this.href=3D'http://www.google.com/url?q\75http%=
3A%2F%2Fwww.open-std.org%2Fjtc1%2Fsc22%2Fwg21%2Fdocs%2Fpapers%2F2002%2Fn137=
7.htm%23Alternative%2520move%2520designs\46sa\75D\46sntz\0751\46usg\75AFQjC=
NGt0VU-QXvmQUWducammjz-p0o-Dg';return true;">http://www.open-std.org/jt=
c1/sc22/wg21/docs/papers/2002/n1377.htm#Alternative%20move%20designs</a>
<br>
<br>for issues I would like to see addressed in any destructive move propos=
al.
<br>
<br>Howard
<br>
<br></blockquote></div></blockquote>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_20_335458135.1437784775258--
------=_Part_19_256387369.1437784775257--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Fri, 24 Jul 2015 17:52:42 -0700
Raw View
On Saturday 25 July 2015 01:07:54 David Rodr=C3=ADguez Ibeas wrote:
> If a type does not contain pointers [*] it fair to assume that it is not
> self-referencing and it is bitwise movable, even if the constructors and
> possibly the destructor are not trivial (say a destructor that is user
> provided to validate the invariants).
A non-trivial non-implicit constructor could do crazy things, like add the=
=20
object's address to a global list.
--=20
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Fri, 24 Jul 2015 18:09:31 -0700 (PDT)
Raw View
------=_Part_1336_62012893.1437786571913
Content-Type: multipart/alternative;
boundary="----=_Part_1337_177504529.1437786571913"
------=_Part_1337_177504529.1437786571913
Content-Type: text/plain; charset=UTF-8
> That's one of the reason why VLAs were dropped from C++14:
> we couldn't get a proper error reporting in case of stack
> exhaustion. There were other issues, but this was a big one.
Fair point.
> You're saying that an aggregate with public, implicit copy
> constructors and destructors (though not necessarily trivial)
> should automatically be marked movable if it is composed
> only of movable sub-objects?
Yes! :-)
I appreciate the phrasing. I believe this is accurate.
*(Please make this happen; please please... :)*
> C compatibility, which is a fundamental strength of C++,
The problem is that the C community may hate this.
It seems to me that the people who are active in, and passionate about, C,
tend to also be people who hold grudges against C++, and want to develop C
in an independent direction.
Examples of existing divergence:
In C99:
- flexible array members
- designated initializers
In C11:
- a stupid version of overloading via type-generic macros
- _Noreturn instead of C++ [[ noreturn ]], _Alignas instead of alignas, ...
To some extent, C++ has been able to bridge differences by adopting same
syntax as C where it makes sense (static_assert, variadic macros), but it
cannot do this where C has decided to do something insane (like
type-generic macros instead of overloading).
Consider then what happens when C++ adopts modules, and they're different
than what C adopts.
End of compatibility, right there.
On Friday, July 24, 2015 at 5:57:39 PM UTC-6, Thiago Macieira wrote:
> On Friday 24 July 2015 16:16:12 denis bider wrote:
> > > The exception mechanism was designed the way it was
> > > so it would work without dynamic memory allocation.
> > > That problem hasn't been solved yet.
> >
> > I think that's an imagined problem.
> >
> > As if the stack magically provides unlimited memory.
> >
> > It doesn't. A program can run out of stack *any time*.
> >
> > Why is it that, when it comes to the stack, somehow this isn't an issue?
>
> It sure is. That's one of the reason why VLAs were dropped from C++14: we
> couldn't get a proper error reporting in case of stack exhaustion. There
> were
> other issues, but this was a big one.
>
> Stack space has grown more in-line with our stack needs compared to the
> heap,
> to the point that most stack exhaustion cases are a symptom of a different
> bug
> (infinite recursion) than caused by the managing of a reasonable data set.
> Heap
> exhaustion is often a problem of its own.
>
> And yet you're also right that it's a problem less frequently managed.
> Careful
> code regularly deals with memory allocation failures -- let's ignore the
> fact
> of whether the failures are reliably reported -- but often does not deal
> with
> stack exhaustion. I've seen a lot of defensive-programming guidelines deal
> with memory allocation and validating user input, but I don't remember
> ever
> seeing them talk about stack overflow defence.
>
> An algorithm that occupies a small stack frame size (let's say 64 bytes)
> could
> recurse roughly 130000 times before exhausting the default stack on Linux,
> while 130000 items is not an unreasonable number of items in a data set.
> After
> all, a vector of 131072 items of 1024 bytes occupies 128 MB, something
> readily
> available to most applications.
>
> > > With a trait like is_trivial_type and its derivatives, classes
> > > are by default movable, unless you take an action that
> > > hides its movability from the compiler.
> > > Like adding a copy constructor.
> >
> > However, the whole trivially-destructive-movable issue revolves around
> > types with copy constructors.
>
> I know. I am agreeing with you we need a trait that the class author can
> specify. I was just nitpicking on your wording.
>
> > I cannot declare my StringType is_trivial. But I need this:
> >
> > struct A { StringType x; };
> >
> > ... to be movable, without having to *say* that it is.
>
> Hmm... interesting.
>
> You're saying that an aggregate with public, implicit copy constructors
> and
> destructors (though not necessarily trivial) should automatically be
> marked
> movable if it is composed only of movable sub-objects?
>
> Makes sense.
>
> > > We don't want to remove a brick in a support column that
> > > would cause the column to crumble and cause the whole
> > > castle to fall.
> >
> > That's why you transition over time.
> >
> > How do we walk? You don't move the leg you stand on. You put your weight
> on
> > one leg; you move the other leg; then you switch.
> >
> > That's how systems evolve, too. You provide new behavior; allow ample
> time
> > for users to migrate - in the case of C++, this is on the order of 20
> years
> > - then you deprecate the old behavior; and then you remove it.
>
> Indeed, but only if people have actually migrated.
>
> For example, typedefs will never go away, no matter how much we make an
> incentive to use the new using declaration, unless C also does it.
> Compatibility with C headers is very important.
>
> > > > Everything must evolve, or be replaced, eventually.
> > > > I don't think it's viable to maintain backward
> > > > compatibility indefinitely.
> > >
> > > I disagree on both sentences.
> >
> > You've said before you hate macros. You don't want the language to
> evolve
> > in a way that they can eventually be removed?
>
> That's another thing that will never be removed, unless we also convince C
> to
> do it too.
>
> > Or *at least *replaced with namespace-aware macros?
>
> I'm not convinced namespace-aware macros will work or that they solve the
> right problem.
>
> > A hundred years from now, in 2115, do you *really* want C++ to *still
> > *implement macros that aren't even namespace aware?
>
> If C2111 still has namespace-unaware macros and there's a large codebase
> using
> them, then yes, C++2114 should still support them.
>
> Anyway, I was disagreeing with the sentences themselves.
>
> "Everything must evolve or be replaced": it will be replaced only if
> something
> better comes along, solving problems that the current solution didn't
> solve,
> without unduly creating new problems.
>
> "Maintain backwards compatibility indefinitely": see above on one
> particular
> case, that of C compatibility, which is a fundamental strength of C++, not
> a
> weakness. There are others. Legacy is not always a bad thing: being
> familiar,
> with a large pool of developers who understand it, is a positive aspect.
>
> Breaking compatibility is a compromise and you can't expect to win every
> time.
>
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
> PGP/GPG: 0x6EF45358; fingerprint:
> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
>
>
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_1337_177504529.1437786571913
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>> That's one of the reason why VLAs were dropp=
ed from C++14:</div><div>> we=C2=A0couldn't get a proper error repor=
ting in case of stack</div><div>> exhaustion. There were=C2=A0other issu=
es, but this was a big one. <br></div><div><br></div><div>Fair point.</div>=
<div><br></div><div><br></div><div>> You're saying that an aggregate=
with public, implicit copy</div><div>> constructors and=C2=A0destructor=
s (though not necessarily trivial)</div><div>> should automatically be m=
arked=C2=A0movable if it is composed</div><div>> only of movable sub-obj=
ects? </div><div><br></div><div>Yes! :-)</div><div><br></div><div>I appreci=
ate the phrasing.=C2=A0I believe=C2=A0this is=C2=A0accurate.</div><div><br>=
</div><div><em>(Please make this happen; please please... :)</em></div><div=
><br></div><div><br></div><div>> C compatibility, which is a fundamental=
strength of C++,</div><div><br></div><div>The problem is that the C commun=
ity may hate this.</div><div><br></div><div>It seems to me that the people =
who are active in, and passionate about, C, tend to also be people who hold=
grudges against C++, and want to develop C in an independent=C2=A0directio=
n.</div><div><br></div><div>Examples of existing divergence:</div><div><br>=
</div><div>In C99:</div><div><br></div><div>- flexible array members</div><=
div><br></div><div>- designated initializers</div><div><br></div><div>In C1=
1:</div><div><br></div><div>- a stupid version of overloading via type-gene=
ric macros</div><div><br></div><div>- _Noreturn instead of C++ [[ noreturn =
]], _Alignas instead of alignas, ...</div><div><div><br></div><div>To some =
extent, C++=C2=A0has been able=C2=A0to bridge differences by adopting=C2=A0=
same syntax as C where it makes sense (static_assert, variadic macros), but=
it cannot do this where C has decided to do something insane (like type-ge=
neric macros instead of overloading).</div><div><br></div><div>Consider the=
n what happens when C++ adopts modules, and they're different than what=
C adopts.</div><div><br></div><div>End of compatibility, right there.</div=
><div><br></div><div><br>On Friday, July 24, 2015 at 5:57:39 PM UTC-6, Thia=
go Macieira wrote:</div></div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204=
, 204); border-left-width: 1px; border-left-style: solid;">On Friday 24 Jul=
y 2015 16:16:12 denis bider wrote:
<br>> > The exception mechanism was designed the way it was
<br>> > so it would work without dynamic memory allocation.
<br>> > That problem hasn't been solved yet.
<br>>=20
<br>> I think that's an imagined problem.
<br>>=20
<br>> As if the stack magically provides unlimited memory.
<br>>=20
<br>> It doesn't. A program can run out of stack *any time*.
<br>>=20
<br>> Why is it that, when it comes to the stack, somehow this isn't=
an issue?
<br>
<br>It sure is. That's one of the reason why VLAs were dropped from C++=
14: we=20
<br>couldn't get a proper error reporting in case of stack exhaustion. =
There were=20
<br>other issues, but this was a big one.
<br>
<br>Stack space has grown more in-line with our stack needs compared to the=
heap,=20
<br>to the point that most stack exhaustion cases are a symptom of a differ=
ent bug=20
<br>(infinite recursion) than caused by the managing of a reasonable data s=
et. Heap=20
<br>exhaustion is often a problem of its own.
<br>
<br>And yet you're also right that it's a problem less frequently m=
anaged. Careful=20
<br>code regularly deals with memory allocation failures -- let's ignor=
e the fact=20
<br>of whether the failures are reliably reported -- but often does not dea=
l with=20
<br>stack exhaustion. I've seen a lot of defensive-programming guidelin=
es deal=20
<br>with memory allocation and validating user input, but I don't remem=
ber ever=20
<br>seeing them talk about stack overflow defence.
<br>
<br>An algorithm that occupies a small stack frame size (let's say 64 b=
ytes) could=20
<br>recurse roughly 130000 times before exhausting the default stack on Lin=
ux,=20
<br>while 130000 items is not an unreasonable number of items in a data set=
.. After=20
<br>all, a vector of 131072 items of 1024 bytes occupies 128 MB, something =
readily=20
<br>available to most applications.
<br>
<br>> > With a trait like is_trivial_type and its derivatives, classe=
s
<br>> > are by default movable, unless you take an action that
<br>> > hides its movability from the =C2=A0compiler.
<br>> > Like adding a copy constructor.
<br>>=20
<br>> However, the whole trivially-destructive-movable issue revolves ar=
ound
<br>> types with copy constructors.
<br>
<br>I know. I am agreeing with you we need a trait that the class author ca=
n=20
<br>specify. I was just nitpicking on your wording.
<br>
<br>> I cannot declare my StringType is_trivial. But I need this:
<br>>=20
<br>> struct A { StringType x; };
<br>>=20
<br>> ... to be movable, without having to *say* that it is.
<br>
<br>Hmm... interesting.
<br>
<br>You're saying that an aggregate with public, implicit copy construc=
tors and=20
<br>destructors (though not necessarily trivial) should automatically be ma=
rked=20
<br>movable if it is composed only of movable sub-objects?
<br>
<br>Makes sense.
<br>
<br>> > We don't want to remove a brick in a support column that
<br>> > would cause the column to crumble and cause the whole
<br>> > castle to fall.
<br>>=20
<br>> That's why you transition over time.
<br>>=20
<br>> How do we walk? You don't move the leg you stand on. You put y=
our weight on
<br>> one leg; you move the other leg; then you switch.
<br>>=20
<br>> That's how systems evolve, too. You provide new behavior; allo=
w ample time
<br>> for users to migrate - in the case of C++, this is on the order of=
20 years
<br>> - then you deprecate the old behavior; and then you remove it.
<br>
<br>Indeed, but only if people have actually migrated.
<br>
<br>For example, typedefs will never go away, no matter how much we make an=
=20
<br>incentive to use the new using declaration, unless C also does it.=20
<br>Compatibility with C headers is very important.
<br>
<br>> > > Everything must evolve, or be replaced, eventually.
<br>> > > I don't think it's viable to maintain backward
<br>> > > compatibility indefinitely.
<br>> >=20
<br>> > I disagree on both sentences.
<br>>=20
<br>> You've said before you hate macros. You don't want the lan=
guage to evolve
<br>> in a way that they can eventually be removed?
<br>
<br>That's another thing that will never be removed, unless we also con=
vince C to=20
<br>do it too.
<br>
<br>> Or *at least *replaced with namespace-aware macros?
<br>
<br>I'm not convinced namespace-aware macros will work or that they sol=
ve the=20
<br>right problem.
<br>
<br>> A hundred years from now, in 2115, do you *really* want C++ to *st=
ill
<br>> *implement macros that aren't even namespace aware?
<br>
<br>If C2111 still has namespace-unaware macros and there's a large cod=
ebase using=20
<br>them, then yes, C++2114 should still support them.
<br>
<br>Anyway, I was disagreeing with the sentences themselves.
<br>
<br>"Everything must evolve or be replaced": it will be replaced =
only if something=20
<br>better comes along, solving problems that the current solution didn'=
;t solve,=20
<br>without unduly creating new problems.
<br>
<br>"Maintain backwards compatibility indefinitely": see above on=
one particular=20
<br>case, that of C compatibility, which is a fundamental strength of C++, =
not a=20
<br>weakness. There are others. Legacy is not always a bad thing: being fam=
iliar,=20
<br>with a large pool of developers who understand it, is a positive aspect=
..
<br>
<br>Breaking compatibility is a compromise and you can't expect to win =
every time.
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a onmousedown=3D"this.href=3D'http:/=
/www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\75D\46sntz\0751\46u=
sg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.=
href=3D'http://www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\7=
5D\46sntz\0751\46usg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;=
" href=3D"http://macieira.info" target=3D"_blank" rel=3D"nofollow">macieira=
..info</a> - thiago (AT) <a onmousedown=3D"this.href=3D'http://www.googl=
e.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\75AFQjCNHGRJd=
o5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'http=
://www.google.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\7=
5AFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;" href=3D"http://kde.o=
rg" target=3D"_blank" rel=3D"nofollow">kde.org</a>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>=C2=A0 =C2=A0 =C2=A0 PGP/GPG: 0x6EF45358; fingerprint:
<br>=C2=A0 =C2=A0 =C2=A0 E067 918B B660 DBD1 105C =C2=A0966C 33F5 F005 6EF4=
5358
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1337_177504529.1437786571913--
------=_Part_1336_62012893.1437786571913--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Fri, 24 Jul 2015 18:18:32 -0700 (PDT)
Raw View
------=_Part_1354_1034438921.1437787112505
Content-Type: multipart/alternative;
boundary="----=_Part_1355_874878994.1437787112505"
------=_Part_1355_874878994.1437787112505
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
I agree this nomenclature confusion is an issue.
Can we adopt "relocatable" as an alias for "trivially destructive movable",=
=20
or does that already mean something else?
"Trivially destructive movable" has 10 syllables. People will shorten it to=
=20
"movable" unless we settle on something practical.
On Friday, July 24, 2015 at 6:28:39 PM UTC-6, Howard Hinnant wrote:
> I came in on this thread late, and missed a lot of the initial context. =
I=20
> came into it because I saw statements like the one I quote below, and rea=
d=20
> them out of context:=20
>
> On Jul 24, 2015, at 7:16 PM, denis bider <isocp...@denisbider.com=20
> <javascript:>> wrote:=20
> >=20
> > I cannot declare my StringType is_trivial. But I need this:=20
> >=20
> > struct A { StringType x; };=20
> >=20
> > ... to be movable, without having to say that it is.=20
> >=20
>
> Out of context, this is a blatantly false statement.=20
>
> My sincere suggestion is that you adopt some other terminology that won=
=E2=80=99t=20
> be mistaken for C++11/14 move semantics. Perhaps =E2=80=9Ctrivially dest=
ructive=20
> movable=E2=80=9D or whatever. Just something so that when somebody (like=
me) reads=20
> a snippet as they cruise through the 100=E2=80=99s of unread emails in th=
eir inbox,=20
> this doesn=E2=80=99t catch their eye and make them believe you don=E2=80=
=99t know what=20
> you=E2=80=99re talking about.=20
>
> Just a friendly suggestion.=20
>
> Howard=20
>
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_1355_874878994.1437787112505
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>I agree this nomenclature=C2=A0confusion is an issue.=
</div><div><br></div><div>Can we adopt "relocatable" as an alias =
for "trivially destructive movable", or does that already mean so=
mething else?</div><div><br></div><div>"Trivially destructive movable&=
quot; has 10 syllables. People will shorten it to "movable" unles=
s we settle on something practical.</div><div><br><br>On Friday, July 24, 2=
015 at 6:28:39 PM UTC-6, Howard Hinnant wrote:</div><blockquote class=3D"gm=
ail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-le=
ft-color: rgb(204, 204, 204); border-left-width: 1px; border-left-style: so=
lid;">I came in on this thread late, and missed a lot of the initial contex=
t. =C2=A0I came into it because I saw statements like the one I quote below=
, and read them out of context:
<br>
<br>On Jul 24, 2015, at 7:16 PM, denis bider <<a onmousedown=3D"this.hre=
f=3D'javascript:';return true;" onclick=3D"this.href=3D'javascr=
ipt:';return true;" href=3D"javascript:" target=3D"_blank" rel=3D"nofol=
low">isocp...@denisbider.com</a>> wrote:
<br>>=20
<br>> I cannot declare my StringType is_trivial. But I need this:
<br>>=20
<br>> struct A { StringType x; };
<br>>=20
<br>> ... to be movable, without having to say that it is.
<br>>=20
<br>
<br>Out of context, this is a blatantly false statement.
<br>
<br>My sincere suggestion is that you adopt some other terminology that won=
=E2=80=99t be mistaken for C++11/14 move semantics. =C2=A0Perhaps =E2=80=9C=
trivially destructive movable=E2=80=9D or whatever. =C2=A0Just something so=
that when somebody (like me) reads a snippet as they cruise through the 10=
0=E2=80=99s of unread emails in their inbox, this doesn=E2=80=99t catch the=
ir eye and make them believe you don=E2=80=99t know what you=E2=80=99re tal=
king about.
<br>
<br>Just a friendly suggestion.
<br>
<br>Howard
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_1355_874878994.1437787112505--
------=_Part_1354_1034438921.1437787112505--
.
Author: Howard Hinnant <howard.hinnant@gmail.com>
Date: Fri, 24 Jul 2015 21:23:48 -0400
Raw View
Random fact tangentially relevant:
I=E2=80=99ve scanned the gcc-5.2.0 std::string implementation, and if I=E2=
=80=99m reading it correctly, it is not relocatable (good choice of termino=
logy).
I believe it contains a pointer that points into itself when the short stri=
ng optimization is enabled (anyone =E2=80=94Jonathan? =E2=80=94 please corr=
ect me if I am misreading). Self-referencing data structures are both surp=
risingly common and frequently used in both libstdc++ and libc++. Self-ref=
erencing data structures can never be relocatable. When you memcpy them, t=
he self-referencing pointer still references the old (now destructed) sourc=
e.
Howard
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Fri, 24 Jul 2015 21:49:51 -0700
Raw View
On Friday 24 July 2015 18:18:32 denis bider wrote:
> I agree this nomenclature confusion is an issue.
>
> Can we adopt "relocatable" as an alias for "trivially destructive movable",
> or does that already mean something else?
>
> "Trivially destructive movable" has 10 syllables. People will shorten it to
> "movable" unless we settle on something practical.
We're also switching the Qt trait to isRelocatable because isMovable has this
incorrect understanding (even though we were there first). And because QList
makes a horrible option when isMovable == true...
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: =?UTF-8?Q?David_Rodr=C3=ADguez_Ibeas?= <dibeas@ieee.org>
Date: Sat, 25 Jul 2015 10:24:49 +0100
Raw View
--001a11c3cc6e32e1ec051bafb163
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
I have not looked at the implementation of std::string in gcc 5, but it
seems as a natural choice. When you want to support small object
optimization you have to choose your poison: either you penalize every
access with an 'if' to determine which way to go (small buffer, heap) or
you have a self-referencing data structure.
One interesting note, though, is that the trait does provide a great
advantage in some other circumstances. In particular the two common
implementations of std::list are either nothrow move constructible (stdc++)
or relocatable (dinkumware) [using just one library name as representative
of the families], thus having the trait would enable std::vector to always
*move* lists.
I am not sure how often this is the case, but I have the feeling that most
types that are not nothrow move constructible may be relocatable.
One point that was not mentioned, and I feel is much harder to resolve, is
whether this kind of approach can be done for objects live in the stack
(destructively moving something in the stack somewhere else), I have seen
suggestions in the past, but there are quite a few problems due to the fact
that the compiler needs to be able to determine whether the destructor is
to be run or not. I am mentioning this only to see if someone smarter than
me can come up with some ideas.
Arthur, if you are interested in writing a proposal for a std::relocatable
trait I could help. Otherwise, if I find the time I may attempt to write
one myself.
David
On Sat, Jul 25, 2015 at 2:23 AM, Howard Hinnant <howard.hinnant@gmail.com>
wrote:
> Random fact tangentially relevant:
>
> I=E2=80=99ve scanned the gcc-5.2.0 std::string implementation, and if I=
=E2=80=99m reading
> it correctly, it is not relocatable (good choice of terminology).
>
> I believe it contains a pointer that points into itself when the short
> string optimization is enabled (anyone =E2=80=94Jonathan? =E2=80=94 pleas=
e correct me if I
> am misreading). Self-referencing data structures are both surprisingly
> common and frequently used in both libstdc++ and libc++. Self-referencin=
g
> data structures can never be relocatable. When you memcpy them, the
> self-referencing pointer still references the old (now destructed) source=
..
>
> Howard
>
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--001a11c3cc6e32e1ec051bafb163
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I have not looked at the implementation of std::string in =
gcc 5, but it seems as a natural choice. When you want to support small obj=
ect optimization you have to choose your poison: either you penalize every =
access with an 'if' to determine which way to go (small buffer, hea=
p) or you have a self-referencing data structure.<div><br></div><div>One in=
teresting note, though, is that the trait does provide a great advantage in=
some other circumstances. In particular the two common implementations of =
std::list are either nothrow move constructible (stdc++) or relocatable (di=
nkumware) [using just one library name as representative of the families], =
thus having the trait would enable std::vector to always *move* lists.</div=
><div><br></div><div>I am not sure how often this is the case, but I have t=
he feeling that most types that are not nothrow move constructible may be r=
elocatable.</div><div><br></div><div>One point that was not mentioned, and =
I feel is much harder to resolve, is whether this kind of approach can be d=
one for objects live in the stack (destructively moving something in the st=
ack somewhere else), I have seen suggestions in the past, but there are qui=
te a few problems due to the fact that the compiler needs to be able to det=
ermine whether the destructor is to be run or not.=C2=A0 I am mentioning th=
is only to see if someone smarter than me can come up with some ideas.</div=
><div><br></div><div>Arthur, if you are interested in writing a proposal fo=
r a std::relocatable trait I could help. Otherwise, if I find the time I ma=
y attempt to write one myself.</div><div><br></div><div>=C2=A0 =C2=A0 =C2=
=A0David</div></div><div class=3D"gmail_extra"><br><div class=3D"gmail_quot=
e">On Sat, Jul 25, 2015 at 2:23 AM, Howard Hinnant <span dir=3D"ltr"><<a=
href=3D"mailto:howard.hinnant@gmail.com" target=3D"_blank">howard.hinnant@=
gmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=
=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Random f=
act tangentially relevant:<br>
<br>
I=E2=80=99ve scanned the gcc-5.2.0 std::string implementation, and if I=E2=
=80=99m reading it correctly, it is not relocatable (good choice of termino=
logy).<br>
<br>
I believe it contains a pointer that points into itself when the short stri=
ng optimization is enabled (anyone =E2=80=94Jonathan? =E2=80=94 please corr=
ect me if I am misreading).=C2=A0 Self-referencing data structures are both=
surprisingly common and frequently used in both libstdc++ and libc++.=C2=
=A0 Self-referencing data structures can never be relocatable.=C2=A0 When y=
ou memcpy them, the self-referencing pointer still references the old (now =
destructed) source.<br>
<br>
Howard<br>
<span class=3D""><br>
--<br>
<br>
---<br>
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br>
</span>To unsubscribe from this group and stop receiving emails from it, se=
nd an email to <a href=3D"mailto:std-proposals%2Bunsubscribe@isocpp.org">st=
d-proposals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" rel=3D"noreferrer" target=3D"_blank">http://groups.google.c=
om/a/isocpp.org/group/std-proposals/</a>.<br>
</blockquote></div><br></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c3cc6e32e1ec051bafb163--
.
Author: =?UTF-8?Q?David_Rodr=C3=ADguez_Ibeas?= <dibeas@ieee.org>
Date: Sat, 25 Jul 2015 11:14:42 +0100
Raw View
--001a11c33ffaa12241051bb06346
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
By the way...
On Sat, Jul 25, 2015 at 10:24 AM, David Rodr=C3=ADguez Ibeas <dibeas@ieee.o=
rg>
wrote:
> Arthur, if you are interested in writing a proposal for a std::relocatabl=
e
> trait I could help. Otherwise, if I find the time I may attempt to write
> one myself.
>
> The complicated part is not the wording of the trait, but having to deal
with lifetime issues. Objects are not *moved*, but the contents of the
objects are moved from one object to another. The identity of objects
(AFAIK) is pinned by the memory location, and the relocate operation could
be considered as either shifting the "identity" (same object now lives in a
different location) or as the creation of a new object and disappearance of
the old object (without running the destructor). The first alternative is
probably impossible to adopt, the second would require the standard
blessing memmove/memcpy as "creators" of object lifetime.
There was a proposal by Pablo Halpern some time back about a
destructive-move function (don't recall the details, and not being in the
standard meetings I don't know how the proposal fared=E2=80=A6 but I imagin=
e it was
taken down). That proposal and the proposal of a relocatable trait go hand
in hand. My guess is that Pablo's proposal was really about allowing this
trait in the language.
As of today, all the libraries that provide this trait are strictly
speaking built on undefined behavior, it is just that the compiler's
provide the expected behavior in these cases --but that does not make them
correct from the point of view of the language.
David
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--001a11c33ffaa12241051bb06346
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">By the way...<br><div class=3D"gmail_extra"><br><div class=
=3D"gmail_quote">On Sat, Jul 25, 2015 at 10:24 AM, David Rodr=C3=ADguez Ibe=
as <span dir=3D"ltr"><<a href=3D"mailto:dibeas@ieee.org" target=3D"_blan=
k">dibeas@ieee.org</a>></span> wrote:<br><blockquote class=3D"gmail_quot=
e" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">=
<div dir=3D"ltr"><div>Arthur, if you are interested in writing a proposal f=
or a std::relocatable trait I could help. Otherwise, if I find the time I m=
ay attempt to write one myself.</div><div><br></div></div></blockquote><div=
>The complicated part is not the wording of the trait, but having to deal w=
ith lifetime issues. Objects are not *moved*, but the contents of the objec=
ts are moved from one object to another. The identity of objects (AFAIK) is=
pinned by the memory location, and the relocate operation could be conside=
red as either shifting the "identity" (same object now lives in a=
different location) or as the creation of a new object and disappearance o=
f the old object (without running the destructor).=C2=A0 The first alternat=
ive is probably impossible to adopt, the second would require the standard =
blessing memmove/memcpy as "creators" of object lifetime.</div><d=
iv><br></div><div>There was a proposal by Pablo Halpern some time back abou=
t a destructive-move function (don't recall the details, and not being =
in the standard meetings I don't know how the proposal fared=E2=80=A6 b=
ut I imagine it was taken down). That proposal and the proposal of a reloca=
table trait go hand in hand.=C2=A0 My guess is that Pablo's proposal wa=
s really about allowing this trait in the language.</div><div><br></div><di=
v>As of today, all the libraries that provide this trait are strictly speak=
ing built on undefined behavior, it is just that the compiler's provide=
the expected behavior in these cases --but that does not make them correct=
from the point of view of the language.</div><div><br></div><div>=C2=A0 =
=C2=A0 David</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--001a11c33ffaa12241051bb06346--
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Sat, 25 Jul 2015 07:43:08 -0700 (PDT)
Raw View
------=_Part_38_1596534904.1437835388791
Content-Type: multipart/alternative;
boundary="----=_Part_39_854206507.1437835388791"
------=_Part_39_854206507.1437835388791
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
A while ago, I saw this interesting comment about exotic treatment of=20
pointers on a particular IBM platform. It seems that a system like this *ma=
y=20
or may not* have issues if objects are relocated by memcpy, depending on=20
the memcpy implementation:
http://stackoverflow.com/questions/12645647/what-happens-in-os-when-we-dere=
ference-a-null-pointer-in-c/12646182#12646182
On this system, a pointer may have to be moved: (1) in a 128-bit load and=
=20
store operation as a whole; and (2) to a 128-bit aligned memory location;=
=20
in order for the system to properly update the underlying valid pointers=20
table. Otherwise, future attempts to access the moved pointer may result in=
=20
null pointer access, instead.
It seems that a platform-specific implementation of memcpy could=20
accommodate such moves, by ensuring use of pointer-compatible loads and=20
stores.
I'm not sure if there are platforms that genuinely *cannot* relocate=20
objects. If there are, it seems it would be more useful to expose this via=
=20
some compiler-provided property (std::platform_supports_relocate?) than to=
=20
deny this ability to a (probably large) majority of platforms where it's=20
supported.
On Saturday, July 25, 2015 at 4:14:46 AM UTC-6, David Rodr=C3=ADguez Ibeas =
wrote:
> By the way...
>
> On Sat, Jul 25, 2015 at 10:24 AM, David Rodr=C3=ADguez Ibeas <dib...@ieee=
..org=20
> <javascript:>> wrote:
>
>> Arthur, if you are interested in writing a proposal for a=20
>> std::relocatable trait I could help. Otherwise, if I find the time I may=
=20
>> attempt to write one myself.
>>
>> The complicated part is not the wording of the trait, but having to deal=
=20
> with lifetime issues. Objects are not *moved*, but the contents of the=20
> objects are moved from one object to another. The identity of objects=20
> (AFAIK) is pinned by the memory location, and the relocate operation coul=
d=20
> be considered as either shifting the "identity" (same object now lives in=
a=20
> different location) or as the creation of a new object and disappearance =
of=20
> the old object (without running the destructor). The first alternative i=
s=20
> probably impossible to adopt, the second would require the standard=20
> blessing memmove/memcpy as "creators" of object lifetime.
>
> There was a proposal by Pablo Halpern some time back about a=20
> destructive-move function (don't recall the details, and not being in the=
=20
> standard meetings I don't know how the proposal fared=E2=80=A6 but I imag=
ine it was=20
> taken down). That proposal and the proposal of a relocatable trait go han=
d=20
> in hand. My guess is that Pablo's proposal was really about allowing thi=
s=20
> trait in the language.
>
> As of today, all the libraries that provide this trait are strictly=20
> speaking built on undefined behavior, it is just that the compiler's=20
> provide the expected behavior in these cases --but that does not make the=
m=20
> correct from the point of view of the language.
>
> David
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_39_854206507.1437835388791
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>A while ago, I saw this interesting comment about exo=
tic treatment of pointers on a particular IBM platform.=C2=A0It seems that =
a system like this=C2=A0<em>may or may not</em> have issues if objects are =
relocated by <font face=3D"courier new,monospace">memcpy</font>, depending =
on the <font face=3D"courier new,monospace">memcpy</font> implementation:</=
div><div><br></div><div><a href=3D"http://stackoverflow.com/questions/12645=
647/what-happens-in-os-when-we-dereference-a-null-pointer-in-c/12646182#126=
46182">http://stackoverflow.com/questions/12645647/what-happens-in-os-when-=
we-dereference-a-null-pointer-in-c/12646182#12646182</a></div><div><br></di=
v><div>On this system, a pointer may have to be moved: (1) in a 128-bit loa=
d and store operation as a whole; and (2) to a 128-bit aligned memory locat=
ion; in order for the system to properly update the underlying valid pointe=
rs table. Otherwise, future attempts to access the moved pointer may result=
in null pointer access, instead.</div><div><br></div><div>It seems that a =
platform-specific implementation of <font face=3D"courier new,monospace">me=
mcpy</font> could accommodate such moves, by ensuring use of pointer-compat=
ible loads and stores.</div><div><br></div><div>I'm not sure if there a=
re platforms that genuinely <em>cannot</em> relocate objects. If there are,=
it seems it would be more useful to expose this via some compiler-provided=
property (<font face=3D"courier new,monospace">std::platform_supports_relo=
cate?</font>) than to deny this ability to a (probably large) majority of p=
latforms where it's supported.</div><div><br><br>On Saturday, July 25, =
2015 at 4:14:46 AM UTC-6, David Rodr=C3=ADguez Ibeas wrote:</div><blockquot=
e class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1=
ex; border-left-color: rgb(204, 204, 204); border-left-width: 1px; border-l=
eft-style: solid;"><div dir=3D"ltr">By the way...<br><div><br><div class=3D=
"gmail_quote">On Sat, Jul 25, 2015 at 10:24 AM, David Rodr=C3=ADguez Ibeas =
<span dir=3D"ltr"><<a onmousedown=3D"this.href=3D'javascript:';r=
eturn true;" onclick=3D"this.href=3D'javascript:';return true;" hre=
f=3D"javascript:" target=3D"_blank" rel=3D"nofollow">dib...@ieee.org</a>>=
;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0=
px 0px 0.8ex; padding-left: 1ex; border-left-color: rgb(204, 204, 204); bor=
der-left-width: 1px; border-left-style: solid;"><div dir=3D"ltr"><div>Arthu=
r, if you are interested in writing a proposal for a std::relocatable trait=
I could help. Otherwise, if I find the time I may attempt to write one mys=
elf.</div><div><br></div></div></blockquote><div>The complicated part is no=
t the wording of the trait, but having to deal with lifetime issues. Object=
s are not *moved*, but the contents of the objects are moved from one objec=
t to another. The identity of objects (AFAIK) is pinned by the memory locat=
ion, and the relocate operation could be considered as either shifting the =
"identity" (same object now lives in a different location) or as =
the creation of a new object and disappearance of the old object (without r=
unning the destructor).=C2=A0 The first alternative is probably impossible =
to adopt, the second would require the standard blessing memmove/memcpy as =
"creators" of object lifetime.</div><div><br></div><div>There was=
a proposal by Pablo Halpern some time back about a destructive-move functi=
on (don't recall the details, and not being in the standard meetings I =
don't know how the proposal fared=E2=80=A6 but I imagine it was taken d=
own). That proposal and the proposal of a relocatable trait go hand in hand=
..=C2=A0 My guess is that Pablo's proposal was really about allowing thi=
s trait in the language.</div><div><br></div><div>As of today, all the libr=
aries that provide this trait are strictly speaking built on undefined beha=
vior, it is just that the compiler's provide the expected behavior in t=
hese cases --but that does not make them correct from the point of view of =
the language.</div><div><br></div><div>=C2=A0 =C2=A0 David</div></div></div=
></div>
</blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_39_854206507.1437835388791--
------=_Part_38_1596534904.1437835388791--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Sat, 25 Jul 2015 10:36:36 -0700
Raw View
On Saturday 25 July 2015 10:24:49 David Rodr=C3=ADguez Ibeas wrote:
> I have not looked at the implementation of std::string in gcc 5, but it
> seems as a natural choice. When you want to support small object
> optimization you have to choose your poison: either you penalize every
> access with an 'if' to determine which way to go (small buffer, heap) or
> you have a self-referencing data structure.
Yeah, but you're paying an overhead penalty for using the self-referencing=
=20
solution. You're keeping a pointer to a location you already know about and=
=20
you're keeping far too many bytes for the size. That's at least 15 more byt=
es=20
you could use for the data on a 64-bit machine.
On a typical string object of {begin, size, alloc}, that means your SSO=20
optimises for 8-byte strings (incl. NUL) with an overhead of 200%. The=20
equivalent 1-bit solution would allow for 23 bytes and an overhead of 4.3%.=
=20
> One point that was not mentioned, and I feel is much harder to resolve, i=
s
> whether this kind of approach can be done for objects live in the stack
> (destructively moving something in the stack somewhere else), I have seen
> suggestions in the past, but there are quite a few problems due to the fa=
ct
> that the compiler needs to be able to determine whether the destructor is
> to be run or not. I am mentioning this only to see if someone smarter th=
an
> me can come up with some ideas.
It cannot be used.
The trait can only be used if you can guarantee the destructor will not get=
=20
called for the original object. You can't guarantee that for on-stack objec=
ts.
Well... you could with assembly by doing an early exit or by relocating the=
=20
stack. At that point, you're ABI-dependent and writing assembly anyway.
--=20
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: denis bider <isocppgroup@denisbider.com>
Date: Sun, 26 Jul 2015 06:24:31 -0700 (PDT)
Raw View
------=_Part_2253_1819751322.1437917071623
Content-Type: multipart/alternative;
boundary="----=_Part_2254_278656856.1437917071623"
------=_Part_2254_278656856.1437917071623
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
> It cannot be used. The trait can only be used if you can
> guarantee the destructor will not get called for the original
> object. You can't guarantee that for on-stack objects.=20
It seems possible the compiler might be able to optimize this:
struct B relocatable {
B();
B(B const&);
~B();
// no move semantics
};
B f() {
B b;
if (condition)
(use b)
return b; // can't use RVO
}
int main() {
B x =3D f(); // memcpy?
}
.... to relocate, instead of copy constructing the return.
I'm not sure how that would mesh with exceptions in f(), but perhaps it may=
=20
be possible for the compiler to guarantee that, post return, the destructor=
=20
will not be called.
On Saturday, July 25, 2015 at 11:36:42 AM UTC-6, Thiago Macieira wrote:
> On Saturday 25 July 2015 10:24:49 David Rodr=C3=ADguez Ibeas wrote:=20
> > I have not looked at the implementation of std::string in gcc 5, but it=
=20
> > seems as a natural choice. When you want to support small object=20
> > optimization you have to choose your poison: either you penalize every=
=20
> > access with an 'if' to determine which way to go (small buffer, heap) o=
r=20
> > you have a self-referencing data structure.=20
>
> Yeah, but you're paying an overhead penalty for using the self-referencin=
g=20
> solution. You're keeping a pointer to a location you already know about=
=20
> and=20
> you're keeping far too many bytes for the size. That's at least 15 more=
=20
> bytes=20
> you could use for the data on a 64-bit machine.=20
>
> On a typical string object of {begin, size, alloc}, that means your SSO=
=20
> optimises for 8-byte strings (incl. NUL) with an overhead of 200%. The=20
> equivalent 1-bit solution would allow for 23 bytes and an overhead of=20
> 4.3%.=20
>
> > One point that was not mentioned, and I feel is much harder to resolve,=
=20
> is=20
> > whether this kind of approach can be done for objects live in the stack=
=20
> > (destructively moving something in the stack somewhere else), I have=20
> seen=20
> > suggestions in the past, but there are quite a few problems due to the=
=20
> fact=20
> > that the compiler needs to be able to determine whether the destructor=
=20
> is=20
> > to be run or not. I am mentioning this only to see if someone smarter=
=20
> than=20
> > me can come up with some ideas.=20
>
> It cannot be used.=20
>
> The trait can only be used if you can guarantee the destructor will not=
=20
> get=20
> called for the original object. You can't guarantee that for on-stack=20
> objects.=20
>
> Well... you could with assembly by doing an early exit or by relocating=
=20
> the=20
> stack. At that point, you're ABI-dependent and writing assembly anyway.=
=20
>
> --=20
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org=20
> Software Architect - Intel Open Source Technology Center=20
> PGP/GPG: 0x6EF45358; fingerprint:=20
> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358=20
>
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_2254_278656856.1437917071623
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>> It cannot be used.=C2=A0The trait can only be us=
ed if you can</div><div>> guarantee the destructor will not get=C2=A0cal=
led for the original</div><div>> object. You can't guarantee that fo=
r on-stack objects. <br></div><div><br></div><div>It seems possible the com=
piler might be able to optimize this:</div><div><br></div><div><font face=
=3D"courier new,monospace">struct B relocatable </font><font face=3D"Courie=
r New">{</font></div><div><font face=3D"Courier New">=C2=A0=C2=A0=C2=A0 B()=
;</font></div><div><font face=3D"Courier New">=C2=A0=C2=A0=C2=A0 B(B const&=
amp;);</font></div><div><font face=3D"Courier New">=C2=A0=C2=A0=C2=A0 ~B();=
</font></div><div><font face=3D"Courier New">=C2=A0=C2=A0=C2=A0 // no move =
semantics</font></div><div><font face=3D"Courier New">};</font></div><div><=
font face=3D"Courier New"><br></font></div><div><font face=3D"Courier New">=
B f() {</font></div><div><font face=3D"Courier New">=C2=A0=C2=A0=C2=A0 B b;=
</font></div><div><font face=3D"Courier New">=C2=A0=C2=A0=C2=A0 if (conditi=
on)</font></div><div><font face=3D"Courier New">=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 (use b)</font></div><div><font face=3D"Courier New">=C2=A0=
=C2=A0=C2=A0 return b;=C2=A0 // can't use RVO</font></div><div><font fa=
ce=3D"Courier New">}</font></div><div><font face=3D"Courier New"><br></font=
></div><div><font face=3D"Courier New">int main() {</font></div><div><font =
face=3D"Courier New">=C2=A0=C2=A0=C2=A0 B=C2=A0x =3D f();=C2=A0=C2=A0=C2=A0=
// memcpy?</font></div><div><font face=3D"Courier New">}</font></div><div>=
<br></div><div>... to relocate, instead of copy constructing the return.</d=
iv><div><br></div><div>I'm not sure how that would mesh with exceptions=
in f(), but perhaps it may be possible for the compiler to guarantee that,=
=C2=A0post return,=C2=A0the destructor will not be called.</div><div><br><b=
r>On Saturday, July 25, 2015 at 11:36:42 AM UTC-6, Thiago Macieira wrote:</=
div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; p=
adding-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-width:=
1px; border-left-style: solid;">On Saturday 25 July 2015 10:24:49 David Ro=
dr=C3=ADguez Ibeas wrote:
<br>> I have not looked at the implementation of std::string in gcc 5, b=
ut it
<br>> seems as a natural choice. When you want to support small object
<br>> optimization you have to choose your poison: either you penalize e=
very
<br>> access with an 'if' to determine which way to go (small bu=
ffer, heap) or
<br>> you have a self-referencing data structure.
<br>
<br>Yeah, but you're paying an overhead penalty for using the self-refe=
rencing=20
<br>solution. You're keeping a pointer to a location you already know a=
bout and=20
<br>you're keeping far too many bytes for the size. That's at least=
15 more bytes=20
<br>you could use for the data on a 64-bit machine.
<br>
<br>On a typical string object of {begin, size, alloc}, that means your SSO=
=20
<br>optimises for 8-byte strings (incl. NUL) with an overhead of 200%. The=
=20
<br>equivalent 1-bit solution would allow for 23 bytes and an overhead of 4=
..3%.=20
<br>
<br>> One point that was not mentioned, and I feel is much harder to res=
olve, is
<br>> whether this kind of approach can be done for objects live in the =
stack
<br>> (destructively moving something in the stack somewhere else), I ha=
ve seen
<br>> suggestions in the past, but there are quite a few problems due to=
the fact
<br>> that the compiler needs to be able to determine whether the destru=
ctor is
<br>> to be run or not. =C2=A0I am mentioning this only to see if someon=
e smarter than
<br>> me can come up with some ideas.
<br>
<br>It cannot be used.
<br>
<br>The trait can only be used if you can guarantee the destructor will not=
get=20
<br>called for the original object. You can't guarantee that for on-sta=
ck objects.
<br>
<br>Well... you could with assembly by doing an early exit or by relocating=
the=20
<br>stack. At that point, you're ABI-dependent and writing assembly any=
way.
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a onmousedown=3D"this.href=3D'http:/=
/www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\75D\46sntz\0751\46u=
sg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.=
href=3D'http://www.google.com/url?q\75http%3A%2F%2Fmacieira.info\46sa\7=
5D\46sntz\0751\46usg\75AFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;=
" href=3D"http://macieira.info" target=3D"_blank" rel=3D"nofollow">macieira=
..info</a> - thiago (AT) <a onmousedown=3D"this.href=3D'http://www.googl=
e.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\75AFQjCNHGRJd=
o5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'http=
://www.google.com/url?q\75http%3A%2F%2Fkde.org\46sa\75D\46sntz\0751\46usg\7=
5AFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;" href=3D"http://kde.o=
rg" target=3D"_blank" rel=3D"nofollow">kde.org</a>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>=C2=A0 =C2=A0 =C2=A0 PGP/GPG: 0x6EF45358; fingerprint:
<br>=C2=A0 =C2=A0 =C2=A0 E067 918B B660 DBD1 105C =C2=A0966C 33F5 F005 6EF4=
5358
<br>
<br></blockquote></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2254_278656856.1437917071623--
------=_Part_2253_1819751322.1437917071623--
.
Author: "Arthur O'Dwyer" <arthur.j.odwyer@gmail.com>
Date: Sun, 26 Jul 2015 22:42:16 -0700
Raw View
--f46d043c7c54f339ec051bd4d01a
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
On Sun, Jul 26, 2015 at 6:24 AM, denis bider <isocppgroup@denisbider.com>
wrote:
> > It cannot be used. The trait can only be used if you can
> > guarantee the destructor will not get called for the original
> > object. You can't guarantee that for on-stack objects.
>
> It seems possible the compiler might be able to optimize this:
>
> struct B relocatable {
> B();
> B(B const&);
> ~B();
> // no move semantics
> };
>
> B f() {
> B b;
> if (condition)
> (use b)
> return b; // can't use RVO
> }
>
Huh? Isn't this the poster child for RVO? The return-by-move turns into a
return-by-copy (because B lacks a move constructor); and then the
return-by-copy is elided (via NRVO).
However, your idea seems to fall under the as-if rule. I'm not interested
in smart things the compiler can do under the as-if rule, because compilers
generally *do* do such things, already, today. I'm talking strictly about
things that the library implementor can do to improve performance in cases
where it's inappropriate for the compiler to intervene. For example, given:
template<class T>
void Vector<T>::resize(size_t n) {
while (this->length > n) {
this->data[--this->length].~T();
}
if (n > this->capacity) {
char *newdata =3D new char[n * sizeof(T)]; // modulo alignment
for (size_t i =3D 0; i < this->length; ++i) {
new ((void*)&newdata[i * sizeof(T)]) T{
std::move(this->data[i]) };
this->data[i].~T();
}
for (size_t i =3D this->length; i < n; ++i) {
new ((void*)&newdata[i * sizeof(T)]) T{};
}
delete [] (char *)this->data;
this->data =3D (T *)newdata;
}
}
the library implementor could try to improve performance by adding a
specialization:
template<class T>
void Vector<T>::resize(size_t n,
std::enable_if_t<std::is_trivially_relocatable_v<T>, int> =3D 0) {
while (this->length > n) {
this->data[--this->length].~T();
}
if (n > this->capacity) {
char *newdata =3D new char[n * sizeof(T)]; // modulo alignment
memcpy(newdata, this->data, this->length * sizeof(T)); // relocate
instead of move-constructing + destructing
for (size_t i =3D this->length; i < n; ++i) {
new ((void*)&newdata[i * sizeof(T)]) T{};
}
delete [] (char *)this->data;
this->data =3D (T *)newdata;
}
}
Although, having written that out, I'm not convinced that a smart compiler
such as GCC or Clang couldn't still optimize my first code sample into the
moral equivalent of memcpy, *under the as-if rule,* via a combination of
inlining and constant-propagating. (For example, inlining the part of T's
move-constructor that sets rhs->ptr =3D nullptr, and then
constant-propagating that nullptr down into the part of ~T that does delete
ptr to prove that the destructor is a no-op.)
Clang 3.5 does a certain amount of constant-propagation on
using T =3D std::vector<int>;
void relocate(T& dst, T src) {
new (&dst) T { std::move(src) };
}
although not as much as I had hoped (it elides the destructor, but still
pointlessly zeroes src before returning). I don't know if Clang 3.7 does
better.
The problem with my second code sample, as David Rodr=C3=ADguez Ibeas point=
ed out
<https://groups.google.com/a/isocpp.org/d/msg/std-proposals/Y6gjtmVyzBo/J0M=
dKDePDboJ>,
is that memcpy'ing a bunch of bytes into a char buffer doesn't magically
create a new T object as far as the runtime semantics are concerned. The
implementation would be within its rights to detect subsequent uses of
this->data[0] as undefined behavior (e.g. by using type-based alias
analysis to prove that that memory address currently holds a char, so it
cannot possibly hold a T).
I believe I've seen some proposals in-flight regarding standard library
hooks to "bless" a memory region as a given type. I don't know enough about
these issues to say whether the proposals are good ideas or bad ideas, or
whether they'd save this "is_trivially_relocatable" idea. IIUC, the
intended usage would be something like
template<class T>
void Vector<T>::resize(size_t n,
std::enable_if_t<std::is_trivially_relocatable_v<T>, int> =3D 0) {
while (this->length > n) {
this->data[--this->length].~T();
}
if (n > this->capacity) {
char *newdata =3D new char[n * sizeof(T)]; // modulo alignment
for (size_t i =3D 0; i < this->length; ++i)
std::unbless<T>(this->data[i]);
memcpy(newdata, this->data, this->length * sizeof(T)); // relocate
instead of move-constructing + destructing
for (size_t i =3D 0; i < this->length; ++i) std::bless<T>(newdata[i=
*
sizeof(T)]);
for (size_t i =3D this->length; i < n; ++i) {
new ((void*)&newdata[i * sizeof(T)]) T{};
}
delete [] (char *)this->data;
this->data =3D (T *)newdata;
}
}
=E2=80=93Arthur
> On Saturday, July 25, 2015 at 11:36:42 AM UTC-6, Thiago Macieira wrote:
>
>> On Saturday 25 July 2015 10:24:49 David Rodr=C3=ADguez Ibeas wrote:
>> > I have not looked at the implementation of std::string in gcc 5, but i=
t
>> > seems as a natural choice. When you want to support small object
>> > optimization you have to choose your poison: either you penalize every
>> > access with an 'if' to determine which way to go (small buffer, heap)
>> or
>> > you have a self-referencing data structure.
>>
>> Yeah, but you're paying an overhead penalty for using the
>> self-referencing
>> solution. You're keeping a pointer to a location you already know about
>> and
>> you're keeping far too many bytes for the size. That's at least 15 more
>> bytes
>> you could use for the data on a 64-bit machine.
>>
>> On a typical string object of {begin, size, alloc}, that means your SSO
>> optimises for 8-byte strings (incl. NUL) with an overhead of 200%. The
>> equivalent 1-bit solution would allow for 23 bytes and an overhead of
>> 4.3%.
>>
>> > One point that was not mentioned, and I feel is much harder to resolve=
,
>> is
>> > whether this kind of approach can be done for objects live in the stac=
k
>> > (destructively moving something in the stack somewhere else), I have
>> seen
>> > suggestions in the past, but there are quite a few problems due to the
>> fact
>> > that the compiler needs to be able to determine whether the destructor
>> is
>> > to be run or not. I am mentioning this only to see if someone smarter
>> than
>> > me can come up with some ideas.
>>
>> It cannot be used.
>>
>> The trait can only be used if you can guarantee the destructor will not
>> get
>> called for the original object. You can't guarantee that for on-stack
>> objects.
>>
>> Well... you could with assembly by doing an early exit or by relocating
>> the
>> stack. At that point, you're ABI-dependent and writing assembly anyway.
>>
>> --
>> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
>> Software Architect - Intel Open Source Technology Center
>> PGP/GPG: 0x6EF45358; fingerprint:
>> E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
>>
>> --
>
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/a/isocpp.org/d/topic/std-proposals/Y6gjtmVyzBo/=
unsubscribe
> .
> To unsubscribe from this group and all its topics, send an email to
> std-proposals+unsubscribe@isocpp.org.
> To post to this group, send email to std-proposals@isocpp.org.
> Visit this group at
> http://groups.google.com/a/isocpp.org/group/std-proposals/.
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
--f46d043c7c54f339ec051bd4d01a
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Sun, Jul 26, 2015 at 6:24 AM, denis bider <span dir=3D"=
ltr"><<a href=3D"mailto:isocppgroup@denisbider.com" target=3D"_blank">is=
ocppgroup@denisbider.com</a>></span> wrote:<br><div class=3D"gmail_extra=
"><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr=
"><div>> It cannot be used.=C2=A0The trait can only be used if you can</=
div><div>> guarantee the destructor will not get=C2=A0called for the ori=
ginal</div><div>> object. You can't guarantee that for on-stack obje=
cts. <br></div><div><br></div><div>It seems possible the compiler might be =
able to optimize this:</div><div><br></div><div><font face=3D"courier new,m=
onospace">struct B relocatable </font><font face=3D"Courier New">{</font></=
div><div><font face=3D"Courier New">=C2=A0=C2=A0=C2=A0 B();</font></div><di=
v><font face=3D"Courier New">=C2=A0=C2=A0=C2=A0 B(B const&);</font></di=
v><div><font face=3D"Courier New">=C2=A0=C2=A0=C2=A0 ~B();</font></div><div=
><font face=3D"Courier New">=C2=A0=C2=A0=C2=A0 // no move semantics</font><=
/div><div><font face=3D"Courier New">};</font></div><div><font face=3D"Cour=
ier New"><br></font></div><div><font face=3D"Courier New">B f() {</font></d=
iv><div><font face=3D"Courier New">=C2=A0=C2=A0=C2=A0 B b;</font></div><div=
><font face=3D"Courier New">=C2=A0=C2=A0=C2=A0 if (condition)</font></div><=
div><font face=3D"Courier New">=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (=
use b)</font></div><div><font face=3D"Courier New">=C2=A0=C2=A0=C2=A0 retur=
n b;=C2=A0 // can't use RVO</font></div><div><font face=3D"Courier New"=
>}</font></div></div></blockquote><div><br></div><div>Huh? Isn't this t=
he poster child for RVO? The return-by-move turns into a return-by-copy (be=
cause B lacks a move constructor); and then the return-by-copy is elided (v=
ia NRVO).</div><div><br></div><div>However, your idea seems to fall under t=
he as-if rule. I'm not interested in smart things the compiler can do u=
nder the as-if rule, because compilers generally <i>do</i> do such things, =
already, today. I'm talking strictly about things that the library impl=
ementor can do to improve performance in cases where it's inappropriate=
for the compiler to intervene. For example, given:</div><div><br></div><di=
v><font face=3D"monospace, monospace">template<class T></font></div><=
div><font face=3D"monospace, monospace">void Vector<T>::resize(size_t=
n) {</font></div><div><font face=3D"monospace, monospace">=C2=A0 =C2=A0 wh=
ile (this->length > n) {</font></div><div><font face=3D"monospace, mo=
nospace">=C2=A0 =C2=A0 =C2=A0 =C2=A0 this->data[--this->length].~T();=
</font></div><div><font face=3D"monospace, monospace">=C2=A0 =C2=A0 }</font=
></div><div><font face=3D"monospace, monospace">=C2=A0 =C2=A0 if (n > th=
is->capacity) {</font></div><div><font face=3D"monospace, monospace">=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 char *newdata =3D new char[n * sizeof(T)]; =C2=A0/=
/ modulo alignment</font></div><div><font face=3D"monospace, monospace">=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 <font color=3D"#ff0000">for (size_t i =3D 0; i <=
; this->length; ++i) {</font></font></div><div><font face=3D"monospace, =
monospace" color=3D"#ff0000">=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 new =
((void*)&newdata[i * sizeof(T)]) T{ std::move(this->data[i]) };</fon=
t></div><div><font face=3D"monospace, monospace" color=3D"#ff0000">=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 this->data[i].~T();</font></div><div>=
<font face=3D"monospace, monospace"><font color=3D"#ff0000">=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 }</font><br></font></div><div><font face=3D"monospace, monosp=
ace">=C2=A0 =C2=A0 =C2=A0 =C2=A0 for (size_t i =3D this->length; i < =
n; ++i) {</font></div><div><font face=3D"monospace, monospace">=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 new ((void*)&newdata[i * sizeof(T)]) T{=
};</font></div><div><font face=3D"monospace, monospace">=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 }<br></font></div><div><font face=3D"monospace, monospace">=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 delete [] (char *)this->data;<br></font></div><=
div><font face=3D"monospace, monospace">=C2=A0 =C2=A0 =C2=A0 =C2=A0 this-&g=
t;data =3D (T *)newdata;</font></div><div><font face=3D"monospace, monospac=
e">=C2=A0 =C2=A0 }</font></div><div><font face=3D"monospace, monospace">}</=
font><br></div><div><br></div><div>the library implementor could try to imp=
rove performance by adding a specialization:</div><div><br></div><div><div>=
<font face=3D"monospace, monospace">template<class T></font></div><di=
v><font face=3D"monospace, monospace">void Vector<T>::resize(size_t n=
, std::enable_if_t<std::is_trivially_relocatable_v<T>, int> =3D=
0) {</font></div><div><font face=3D"monospace, monospace">=C2=A0 =C2=A0 wh=
ile (this->length > n) {</font></div><div><font face=3D"monospace, mo=
nospace">=C2=A0 =C2=A0 =C2=A0 =C2=A0 this->data[--this->length].~T();=
</font></div><div><font face=3D"monospace, monospace">=C2=A0 =C2=A0 }</font=
></div><div><font face=3D"monospace, monospace">=C2=A0 =C2=A0 if (n > th=
is->capacity) {</font></div><div><font face=3D"monospace, monospace">=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 char *newdata =3D new char[n * sizeof(T)]; =C2=A0/=
/ modulo alignment</font></div><div><font face=3D"monospace, monospace">=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 <font color=3D"#ff0000">memcpy(newdata, this->d=
ata, this->length * sizeof(T)); =C2=A0// relocate instead of move-constr=
ucting + destructing</font></font></div><div><font face=3D"monospace, monos=
pace">=C2=A0 =C2=A0 =C2=A0 =C2=A0 for (size_t i =3D this->length; i <=
n; ++i) {<br></font></div><div><font face=3D"monospace, monospace">=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 new ((void*)&newdata[i * sizeof(T)])=
T{};</font></div><div><font face=3D"monospace, monospace">=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 }<br></font></div><div><font face=3D"monospace, monospace">=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 delete [] (char *)this->data;</font></div><d=
iv><font face=3D"monospace, monospace">=C2=A0 =C2=A0 =C2=A0 =C2=A0 this->=
;data =3D (T *)newdata;</font></div><div><font face=3D"monospace, monospace=
">=C2=A0 =C2=A0 }</font></div><div><font face=3D"monospace, monospace">}</f=
ont><br></div></div><div><br></div><div>Although, having written that out, =
I'm not convinced that a smart compiler such as GCC or Clang couldn'=
;t still optimize my first code sample into the moral equivalent of memcpy,=
<b>under the as-if rule,</b> via a combination of inlining and constant-pr=
opagating. (For example, inlining the part of <font face=3D"monospace, mono=
space">T</font>'s move-constructor that sets <font face=3D"monospace, m=
onospace">rhs->ptr =3D nullptr</font>, and then constant-propagating tha=
t nullptr down into the part of <font face=3D"monospace, monospace">~T</fon=
t> that does <font face=3D"monospace, monospace">delete ptr</font> to prove=
that the destructor is a no-op.)</div><div>Clang 3.5 does a certain amount=
of constant-propagation on</div><div><br></div><div><p style=3D"margin:0px=
;font-size:11px;font-family:Menlo">using T =3D std::vector<int>;</p><=
p style=3D"margin:0px;font-size:11px;font-family:Menlo">void relocate(T&=
; dst, T src) {</p>
<p style=3D"margin:0px;font-size:11px;font-family:Menlo">=C2=A0 =C2=A0 new =
(&dst) T { std::move(src) };</p>
<p style=3D"margin:0px;font-size:11px;font-family:Menlo">}</p></div><div><b=
r></div><div>although not as much as I had hoped (it elides the destructor,=
but still pointlessly zeroes=C2=A0<font face=3D"monospace, monospace">src<=
/font> before returning). I don't know if Clang 3.7 does better.</div><=
div><br></div><div>The problem with my second code sample, <a href=3D"https=
://groups.google.com/a/isocpp.org/d/msg/std-proposals/Y6gjtmVyzBo/J0MdKDePD=
boJ">as David Rodr=C3=ADguez Ibeas pointed out</a>, is that memcpy'ing =
a bunch of bytes into a char buffer doesn't magically create a new <fon=
t face=3D"monospace, monospace">T</font> object as far as the runtime seman=
tics are concerned. The implementation would be within its rights to detect=
subsequent uses of <font face=3D"monospace, monospace">this->data[0]</f=
ont> as undefined behavior (e.g. by using type-based alias analysis to prov=
e that that memory address currently holds a <font face=3D"monospace, monos=
pace">char</font>, so it cannot possibly hold a <font face=3D"monospace, mo=
nospace">T</font>).</div><div><br></div><div>I believe I've seen some p=
roposals in-flight regarding standard library hooks to "bless" a =
memory region as a given type. I don't know enough about these issues t=
o say whether the proposals are good ideas or bad ideas, or whether they=
9;d save this "is_trivially_relocatable" idea. IIUC, the intended=
usage would be something like</div><div><br></div><div><div><font face=3D"=
monospace, monospace">template<class T></font></div><div><font face=
=3D"monospace, monospace">void Vector<T>::resize(size_t n, std::enabl=
e_if_t<std::is_trivially_relocatable_v<T>, int> =3D 0) {</font>=
</div><div><font face=3D"monospace, monospace">=C2=A0 =C2=A0 while (this-&g=
t;length > n) {</font></div><div><font face=3D"monospace, monospace">=C2=
=A0 =C2=A0 =C2=A0 =C2=A0 this->data[--this->length].~T();</font></div=
><div><font face=3D"monospace, monospace">=C2=A0 =C2=A0 }</font></div><div>=
<font face=3D"monospace, monospace">=C2=A0 =C2=A0 if (n > this->capac=
ity) {</font></div><div><font face=3D"monospace, monospace">=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 char *newdata =3D new char[n * sizeof(T)]; =C2=A0// modulo al=
ignment</font></div><div><font face=3D"monospace, monospace">=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 <font color=3D"#9900ff">for (size_t i =3D 0; i < this->=
length; ++i) std::unbless<T>(this->data[i]);</font></font></div><d=
iv><font face=3D"monospace, monospace">=C2=A0 =C2=A0 =C2=A0 =C2=A0 memcpy(n=
ewdata, this->data, this->length * sizeof(T)); =C2=A0// relocate inst=
ead of move-constructing + destructing</font></div><div><font face=3D"monos=
pace, monospace">=C2=A0 =C2=A0 =C2=A0 =C2=A0 <font color=3D"#9900ff">for (s=
ize_t i =3D 0; i < this->length; ++i) std::bless<T>(newdata[i *=
sizeof(T)]);</font></font></div><div><span style=3D"font-family:monospace,=
monospace">=C2=A0 =C2=A0 =C2=A0 =C2=A0 for (size_t i =3D this->length; i=
< n; ++i) {</span><br></div><div><font face=3D"monospace, monospace">=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 new ((void*)&newdata[i * size=
of(T)]) T{};</font></div><div><font face=3D"monospace, monospace">=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 }<br></font></div><div><font face=3D"monospace, monosp=
ace">=C2=A0 =C2=A0 =C2=A0 =C2=A0 delete [] (char *)this->data;</font></d=
iv><div><font face=3D"monospace, monospace">=C2=A0 =C2=A0 =C2=A0 =C2=A0 thi=
s->data =3D (T *)newdata;</font></div><div><font face=3D"monospace, mono=
space">=C2=A0 =C2=A0 }</font></div><div><font face=3D"monospace, monospace"=
>}</font></div></div><div><br></div><div>=E2=80=93Arthur</div><div><br></di=
v><div><br></div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail=
_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:=
1ex"><div dir=3D"ltr"><div>On Saturday, July 25, 2015 at 11:36:42 AM UTC-6,=
Thiago Macieira wrote:<br></div><blockquote class=3D"gmail_quote" style=3D=
"margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,20=
4);border-left-width:1px;border-left-style:solid">On Saturday 25 July 2015 =
10:24:49 David Rodr=C3=ADguez Ibeas wrote:
<br>> I have not looked at the implementation of std::string in gcc 5, b=
ut it
<br>> seems as a natural choice. When you want to support small object
<br>> optimization you have to choose your poison: either you penalize e=
very
<br>> access with an 'if' to determine which way to go (small bu=
ffer, heap) or
<br>> you have a self-referencing data structure.
<br>
<br>Yeah, but you're paying an overhead penalty for using the self-refe=
rencing=20
<br>solution. You're keeping a pointer to a location you already know a=
bout and=20
<br>you're keeping far too many bytes for the size. That's at least=
15 more bytes=20
<br>you could use for the data on a 64-bit machine.
<br>
<br>On a typical string object of {begin, size, alloc}, that means your SSO=
=20
<br>optimises for 8-byte strings (incl. NUL) with an overhead of 200%. The=
=20
<br>equivalent 1-bit solution would allow for 23 bytes and an overhead of 4=
..3%.=20
<br>
<br>> One point that was not mentioned, and I feel is much harder to res=
olve, is
<br>> whether this kind of approach can be done for objects live in the =
stack
<br>> (destructively moving something in the stack somewhere else), I ha=
ve seen
<br>> suggestions in the past, but there are quite a few problems due to=
the fact
<br>> that the compiler needs to be able to determine whether the destru=
ctor is
<br>> to be run or not.=C2=A0 I am mentioning this only to see if someon=
e smarter than
<br>> me can come up with some ideas.
<br>
<br>It cannot be used.
<br>
<br>The trait can only be used if you can guarantee the destructor will not=
get=20
<br>called for the original object. You can't guarantee that for on-sta=
ck objects.
<br>
<br>Well... you could with assembly by doing an early exit or by relocating=
the=20
<br>stack. At that point, you're ABI-dependent and writing assembly any=
way.
<br><span class=3D"HOEnZb"><font color=3D"#888888">
<br>--=20
<br>Thiago Macieira - thiago (AT) <a href=3D"http://macieira.info" rel=3D"n=
ofollow" target=3D"_blank">macieira.info</a> - thiago (AT) <a href=3D"http:=
//kde.org" rel=3D"nofollow" target=3D"_blank">kde.org</a>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>=C2=A0 =C2=A0 =C2=A0 PGP/GPG: 0x6EF45358; fingerprint:
<br>=C2=A0 =C2=A0 =C2=A0 E067 918B B660 DBD1 105C =C2=A0966C 33F5 F005 6EF4=
5358
<br>
<br></font></span></blockquote></div><span class=3D"HOEnZb"><font color=3D"=
#888888">
<p></p>
-- <br>
<br>
--- <br>
You received this message because you are subscribed to a topic in the Goog=
le Groups "ISO C++ Standard - Future Proposals" group.<br>
To unsubscribe from this topic, visit <a href=3D"https://groups.google.com/=
a/isocpp.org/d/topic/std-proposals/Y6gjtmVyzBo/unsubscribe" target=3D"_blan=
k">https://groups.google.com/a/isocpp.org/d/topic/std-proposals/Y6gjtmVyzBo=
/unsubscribe</a>.<br>
To unsubscribe from this group and all its topics, send an email to <a href=
=3D"mailto:std-proposals+unsubscribe@isocpp.org" target=3D"_blank">std-prop=
osals+unsubscribe@isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br>
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/" target=3D"_blank">http://groups.google.com/a/isocpp.org/gro=
up/std-proposals/</a>.<br>
</font></span></blockquote></div><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--f46d043c7c54f339ec051bd4d01a--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Mon, 27 Jul 2015 00:30:50 -0700
Raw View
On Sunday 26 July 2015 22:42:16 Arthur O'Dwyer wrote:
> char *newdata = new char[n * sizeof(T)]; // modulo alignment
> memcpy(newdata, this->data, this->length * sizeof(T)); // relocate
> instead of move-constructing + destructing
> for (size_t i = this->length; i < n; ++i) {
> new ((void*)&newdata[i * sizeof(T)]) T{};
> }
> delete [] (char *)this->data;
> this->data = (T *)newdata;
Even better: use realloc().
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
.
Author: =?UTF-8?Q?David_Rodr=C3=ADguez_Ibeas?= <dibeas@ieee.org>
Date: Mon, 27 Jul 2015 10:57:44 +0100
Raw View
--047d7b34391a98ad90051bd86296
Content-Type: text/plain; charset=UTF-8
On Mon, Jul 27, 2015 at 6:42 AM, Arthur O'Dwyer <arthur.j.odwyer@gmail.com>
wrote:
> I believe I've seen some proposals in-flight regarding standard library
> hooks to "bless" a memory region as a given type.
>
Probably this?
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4393.pdf
An alternative would be to grant those magic powers to memcpy/memmove
directly, but I am not sure how complicated that would be. To some extent
for POD types this is already the case, you have a buffer of characters,
you memcpy into it an object holding a double and now you have a double
living over that memory location. The implication (bear with me, I have no
clue on how compilers are really implemented) would be that type-analysis
would "transfer" the type of the source in a memcpy (if known) to the
destination. Whether this is feasible at all is a different question for
someone that knows compilers :)
David
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
--047d7b34391a98ad90051bd86296
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote">On M=
on, Jul 27, 2015 at 6:42 AM, Arthur O'Dwyer <span dir=3D"ltr"><<a hr=
ef=3D"mailto:arthur.j.odwyer@gmail.com" target=3D"_blank">arthur.j.odwyer@g=
mail.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=
=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div>I belie=
ve I've seen some proposals in-flight regarding standard library hooks =
to "bless" a memory region as a given type.</div></div></div></di=
v></blockquote><div><br>Probably this? <br><br><a href=3D"http://www.open-s=
td.org/jtc1/sc22/wg21/docs/papers/2015/n4393.pdf">http://www.open-std.org/j=
tc1/sc22/wg21/docs/papers/2015/n4393.pdf</a>=C2=A0<br><br>An alternative wo=
uld be to grant those magic powers to memcpy/memmove directly, but I am not=
sure how complicated that would be. To some extent for POD types this is a=
lready the case, you have a buffer of characters, you memcpy into it an obj=
ect holding a double and now you have a double living over that memory loca=
tion.=C2=A0 The implication (bear with me, I have no clue on how compilers =
are really implemented) would be that type-analysis would "transfer&qu=
ot; the type of the source in a memcpy (if known) to the destination. Wheth=
er this is feasible at all is a different question for someone that knows c=
ompilers :)<br><br>=C2=A0 =C2=A0 David</div></div></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
--047d7b34391a98ad90051bd86296--
.
Author: =?UTF-8?Q?David_Rodr=C3=ADguez_Ibeas?= <dribeas@gmail.com>
Date: Mon, 27 Jul 2015 05:58:29 -0700 (PDT)
Raw View
------=_Part_881_1505626207.1438001909823
Content-Type: multipart/alternative;
boundary="----=_Part_882_397759282.1438001909824"
------=_Part_882_397759282.1438001909824
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
In such a platform a compliant memcpy implementation must already track the=
=20
pointer-ness of the memory, as both in C and C++ you can use memcpy to copy=
=20
pointers around:
// C code
struct X {
int *p;
};
struct X a =3D { (int*)malloc(sizeof(int)) }, b;
assert(a.p);
memcpy(&b, &a, sizeof a);
assert(b.p); // this *must* pass (if the above=
=20
passed)
free(a.p);
So that would not be a concern. That is part of the advantage of giving=20
the creation of live to 'memcpy': it is already a special function in the=
=20
language.
David
On Saturday, July 25, 2015 at 3:43:08 PM UTC+1, denis bider wrote:
>
> A while ago, I saw this interesting comment about exotic treatment of=20
> pointers on a particular IBM platform. It seems that a system like this *=
may=20
> or may not* have issues if objects are relocated by memcpy, depending on=
=20
> the memcpy implementation:
>
>
> http://stackoverflow.com/questions/12645647/what-happens-in-os-when-we-de=
reference-a-null-pointer-in-c/12646182#12646182
>
> On this system, a pointer may have to be moved: (1) in a 128-bit load and=
=20
> store operation as a whole; and (2) to a 128-bit aligned memory location;=
=20
> in order for the system to properly update the underlying valid pointers=
=20
> table. Otherwise, future attempts to access the moved pointer may result =
in=20
> null pointer access, instead.
>
> It seems that a platform-specific implementation of memcpy could=20
> accommodate such moves, by ensuring use of pointer-compatible loads and=
=20
> stores.
>
> I'm not sure if there are platforms that genuinely *cannot* relocate=20
> objects. If there are, it seems it would be more useful to expose this vi=
a=20
> some compiler-provided property (std::platform_supports_relocate?) than=
=20
> to deny this ability to a (probably large) majority of platforms where it=
's=20
> supported.
>
>
> On Saturday, July 25, 2015 at 4:14:46 AM UTC-6, David Rodr=C3=ADguez Ibea=
s=20
> wrote:
>
>> By the way...
>>
>> On Sat, Jul 25, 2015 at 10:24 AM, David Rodr=C3=ADguez Ibeas <dib...@iee=
e.org>=20
>> wrote:
>>
>>> Arthur, if you are interested in writing a proposal for a=20
>>> std::relocatable trait I could help. Otherwise, if I find the time I ma=
y=20
>>> attempt to write one myself.
>>>
>>> The complicated part is not the wording of the trait, but having to dea=
l=20
>> with lifetime issues. Objects are not *moved*, but the contents of the=
=20
>> objects are moved from one object to another. The identity of objects=20
>> (AFAIK) is pinned by the memory location, and the relocate operation cou=
ld=20
>> be considered as either shifting the "identity" (same object now lives i=
n a=20
>> different location) or as the creation of a new object and disappearance=
of=20
>> the old object (without running the destructor). The first alternative =
is=20
>> probably impossible to adopt, the second would require the standard=20
>> blessing memmove/memcpy as "creators" of object lifetime.
>>
>> There was a proposal by Pablo Halpern some time back about a=20
>> destructive-move function (don't recall the details, and not being in th=
e=20
>> standard meetings I don't know how the proposal fared=E2=80=A6 but I ima=
gine it was=20
>> taken down). That proposal and the proposal of a relocatable trait go ha=
nd=20
>> in hand. My guess is that Pablo's proposal was really about allowing th=
is=20
>> trait in the language.
>>
>> As of today, all the libraries that provide this trait are strictly=20
>> speaking built on undefined behavior, it is just that the compiler's=20
>> provide the expected behavior in these cases --but that does not make th=
em=20
>> correct from the point of view of the language.
>>
>> David
>>
>
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
------=_Part_882_397759282.1438001909824
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">In such a platform a compliant memcpy implementation must =
already track the pointer-ness of the memory, as both in C and C++ you can =
use memcpy to copy pointers around:<br><br>// C code<br>struct X {<br>=C2=
=A0 =C2=A0 int *p;<br><div>};<br>struct X a =3D { (int*)malloc(sizeof(int))=
}, b;<br>assert(a.p);<br>memcpy(&b, &a, sizeof a);<br>assert(b.p);=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0// this *must* pass (if the above passed)<br>free(a=
..p);<br><br>So that would not be a concern. =C2=A0That is part of the advan=
tage of giving the creation of live to 'memcpy': it is already a sp=
ecial function in the language.<br><br>=C2=A0 =C2=A0 David<br><br>On Saturd=
ay, July 25, 2015 at 3:43:08 PM UTC+1, denis bider wrote:<blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;"><div dir=3D"ltr"><div>A while ago, I saw this i=
nteresting comment about exotic treatment of pointers on a particular IBM p=
latform.=C2=A0It seems that a system like this=C2=A0<em>may or may not</em>=
have issues if objects are relocated by <font face=3D"courier new,monospac=
e">memcpy</font>, depending on the <font face=3D"courier new,monospace">mem=
cpy</font> implementation:</div><div><br></div><div><a href=3D"http://stack=
overflow.com/questions/12645647/what-happens-in-os-when-we-dereference-a-nu=
ll-pointer-in-c/12646182#12646182" target=3D"_blank" rel=3D"nofollow" onmou=
sedown=3D"this.href=3D'http://www.google.com/url?q\75http%3A%2F%2Fstack=
overflow.com%2Fquestions%2F12645647%2Fwhat-happens-in-os-when-we-dereferenc=
e-a-null-pointer-in-c%2F12646182%2312646182\46sa\75D\46sntz\0751\46usg\75AF=
QjCNGRPMloY99LvouNfw8QSGgN15INbw';return true;" onclick=3D"this.href=3D=
'http://www.google.com/url?q\75http%3A%2F%2Fstackoverflow.com%2Fquestio=
ns%2F12645647%2Fwhat-happens-in-os-when-we-dereference-a-null-pointer-in-c%=
2F12646182%2312646182\46sa\75D\46sntz\0751\46usg\75AFQjCNGRPMloY99LvouNfw8Q=
SGgN15INbw';return true;">http://stackoverflow.com/questions/12645647/w=
hat-happens-in-os-when-we-dereference-a-null-pointer-in-c/12646182#12646182=
</a></div><div><br></div><div>On this system, a pointer may have to be move=
d: (1) in a 128-bit load and store operation as a whole; and (2) to a 128-b=
it aligned memory location; in order for the system to properly update the =
underlying valid pointers table. Otherwise, future attempts to access the m=
oved pointer may result in null pointer access, instead.</div><div><br></di=
v><div>It seems that a platform-specific implementation of <font face=3D"co=
urier new,monospace">memcpy</font> could accommodate such moves, by ensurin=
g use of pointer-compatible loads and stores.</div><div><br></div><div>I=
9;m not sure if there are platforms that genuinely <em>cannot</em> relocate=
objects. If there are, it seems it would be more useful to expose this via=
some compiler-provided property (<font face=3D"courier new,monospace">std:=
:platform_supports_relocate?</font>) than to deny this ability to a (probab=
ly large) majority of platforms where it's supported.</div><div><br><br=
>On Saturday, July 25, 2015 at 4:14:46 AM UTC-6, David Rodr=C3=ADguez Ibeas=
wrote:</div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px =
0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width=
:1px;border-left-style:solid"><div dir=3D"ltr">By the way...<br><div><br><d=
iv class=3D"gmail_quote">On Sat, Jul 25, 2015 at 10:24 AM, David Rodr=C3=AD=
guez Ibeas <span dir=3D"ltr"><<a rel=3D"nofollow">dib...@ieee.org</a>>=
;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0px 0p=
x 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left=
-width:1px;border-left-style:solid"><div dir=3D"ltr"><div>Arthur, if you ar=
e interested in writing a proposal for a std::relocatable trait I could hel=
p. Otherwise, if I find the time I may attempt to write one myself.</div><d=
iv><br></div></div></blockquote><div>The complicated part is not the wordin=
g of the trait, but having to deal with lifetime issues. Objects are not *m=
oved*, but the contents of the objects are moved from one object to another=
.. The identity of objects (AFAIK) is pinned by the memory location, and the=
relocate operation could be considered as either shifting the "identi=
ty" (same object now lives in a different location) or as the creation=
of a new object and disappearance of the old object (without running the d=
estructor).=C2=A0 The first alternative is probably impossible to adopt, th=
e second would require the standard blessing memmove/memcpy as "creato=
rs" of object lifetime.</div><div><br></div><div>There was a proposal =
by Pablo Halpern some time back about a destructive-move function (don'=
t recall the details, and not being in the standard meetings I don't kn=
ow how the proposal fared=E2=80=A6 but I imagine it was taken down). That p=
roposal and the proposal of a relocatable trait go hand in hand.=C2=A0 My g=
uess is that Pablo's proposal was really about allowing this trait in t=
he language.</div><div><br></div><div>As of today, all the libraries that p=
rovide this trait are strictly speaking built on undefined behavior, it is =
just that the compiler's provide the expected behavior in these cases -=
-but that does not make them correct from the point of view of the language=
..</div><div><br></div><div>=C2=A0 =C2=A0 David</div></div></div></div>
</blockquote></div></blockquote></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_882_397759282.1438001909824--
------=_Part_881_1505626207.1438001909823--
.
Author: =?UTF-8?Q?David_Rodr=C3=ADguez_Ibeas?= <dribeas@gmail.com>
Date: Mon, 27 Jul 2015 06:19:47 -0700 (PDT)
Raw View
------=_Part_2962_1923322561.1438003187347
Content-Type: multipart/alternative;
boundary="----=_Part_2963_1665816716.1438003187347"
------=_Part_2963_1665816716.1438003187347
Content-Type: text/plain; charset=UTF-8
On Monday, July 27, 2015 at 8:30:59 AM UTC+1, Thiago Macieira wrote:
>
> Even better: use realloc().
>
>
While for growing the internal buffer 'realloc' *could* be an option (if
the allocator supported such an operation, which it does not currently), I
am sure that you are familiar with other operations for which 'realloc'
would not be useful. For example, removing the first element in a
vector<list<T>> can be done as:
vector<T>::erase(const_iterator __it) { // enabled if the
trait is present
T *__ptr = addressof(*__it);
allocator_traits<Allocator>::destroy(__alloc, __ptr); // cannot throw:
Container requirement
--__end;
memmove(ptr, ptr + 1, __end - __ptr);
}
The compression of the objects after the one being erased can be done with
a single 'memmove'. Currently I a common implementation would run a
sequence of move-assignments followed by the destruction of the last
element.
Similarly insertions in the middle of the vector can be implemented by
memmove to make space followed by construction into the space in the
middle, but the code for this is a bit too involved to show in a message:
If an exception is thrown while constructing the elements in the middle of
the buffer the implementation would have to clean already inserted elements
and run the opposite memmove --for the strong exception guarantee-- or at
least destroy any objects that are not contiguous with the first object,
updating the end pointer in the process --for the basic exception guarantee.
David
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
------=_Part_2963_1665816716.1438003187347
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br>On Monday, July 27, 2015 at 8:30:59 AM UTC+1, Thiago M=
acieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">Even better: use=
realloc().
<br><br></blockquote><div><br>While for growing the internal buffer 're=
alloc' *could* be an option (if the allocator supported such an operati=
on, which it does not currently), I am sure that you are familiar with othe=
r operations for which 'realloc' would not be useful. For example, =
removing the first element in a vector<list<T>> can be done as:=
<br><br></div><div class=3D"prettyprint" style=3D"border: 1px solid rgb(187=
, 187, 187); word-wrap: break-word; background-color: rgb(250, 250, 250);">=
<code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">vector</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify"><</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify">T</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">>::</span><span style=3D"color: #000;" class=3D"=
styled-by-prettify">erase</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">const</span><font color=3D"#666600"><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify">_</span></font><span style=3D"color: #000;" class=
=3D"styled-by-prettify">iterator __it</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><spa=
n style=3D"color: #800;" class=3D"styled-by-prettify">// enabled if the tra=
it is present</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"><br>=C2=A0 =C2=A0 T </span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">*</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">__ptr </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> addres=
sof</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(*</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify">__it</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 allocator_=
traits</span><span style=3D"color: #660;" class=3D"styled-by-prettify"><=
</span><span style=3D"color: #606;" class=3D"styled-by-prettify">Allocator<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">>::</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify">destroy</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify">__alloc</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> __ptr</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">);</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #800;" class=3D"sty=
led-by-prettify">// cannot throw: Container requirement</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">--</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">__end</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 memmove</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">ptr</span><span style=3D"color: #660=
;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> ptr </span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">+</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> </span><span style=3D"color: #066;" class=3D"styled-by-prettify"=
>1</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> __end </span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">-</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> __ptr</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">);</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">}</span></div></code></div><div><br><br>The co=
mpression of the objects after the one being erased can be done with a sing=
le 'memmove'. Currently I a common implementation would run a seque=
nce of move-assignments followed by the destruction of the last element. =
=C2=A0<br><br>Similarly insertions in the middle of the vector can be imple=
mented by memmove to make space followed by construction into the space in =
the middle, but the code for this is a bit too involved to show in a messag=
e: If an exception is thrown while constructing the elements in the middle =
of the buffer the implementation would have to clean already inserted eleme=
nts and run the opposite memmove --for the strong exception guarantee-- or =
at least destroy any objects that are not contiguous with the first object,=
updating the end pointer in the process --for the basic exception guarante=
e.<br><br>=C2=A0 =C2=A0 David<br><br></div></div>
<p></p>
-- <br />
<br />
--- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
Visit this group at <a href=3D"http://groups.google.com/a/isocpp.org/group/=
std-proposals/">http://groups.google.com/a/isocpp.org/group/std-proposals/<=
/a>.<br />
------=_Part_2963_1665816716.1438003187347--
------=_Part_2962_1923322561.1438003187347--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Mon, 27 Jul 2015 09:32:43 -0700
Raw View
On Monday 27 July 2015 06:19:47 David Rodr=C3=ADguez Ibeas wrote:
> While for growing the internal buffer 'realloc' *could* be an option (if =
the
> allocator supported such an operation, which it does not currently), I am
> sure that you are familiar with other operations for which 'realloc' woul=
d
> not be useful.
Of course. My point was just that you used the very case where realloc() wo=
uld=20
be most useful in.
The allocators don't support the operation because the containers cannot ma=
ke=20
use of it yet, except for trivial types for which the optimising compiler w=
ill=20
generate the memcpy already. I fully expect the allocator API to be extende=
d=20
to support realloc if we add this trait that the containers can act on.
--=20
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
--=20
---=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposa=
ls/.
.
Author: forforums@melkov.ru
Date: Fri, 26 Feb 2016 14:48:08 -0800 (PST)
Raw View
------=_Part_1131_871423013.1456526888097
Content-Type: multipart/alternative;
boundary="----=_Part_1132_1452078403.1456526888098"
------=_Part_1132_1452078403.1456526888098
Content-Type: text/plain; charset=UTF-8
Hi, I've found this old discussion and would like ask whether it was
continued elsewhere or just died.
Considering the proposal, the amount of new keyword extensions scares me a
bit. Also, the idea that existing catch blocks may not handle exception
lists is also worrisome.
Therefore I would like you to consider the following idea:
1. Catch blocks for exception lists are to be declared as
catch(std::exception_list<exception_type>).
2. Existing exception handlers simply operate on the front elements of the
list.
To be more specific, the following catch-block:
catch(exception_type e) {
do_something;
}
would be equivalent to:
catch(std::exception_list<exception_type> ex_list) {
exception_type e = ex_list.pop_front();
do_something;
if (!ex_list.empty())
throw ex_list;
}
Additionally, *throw* in *catch block* should add to the *front* of the
list, unlike adding to the back elsewhere:
catch(exception_type e) {
do_something;
throw;
}
would be equivalent to:
catch(std::exception_list<exception_type> ex_list) {
exception_type e = ex_list.pop_front();
do_something;
ex_list.push_front(e);
throw ex_list;
}
On Sunday, July 19, 2015 at 7:33:46 PM UTC+3, denis bider wrote:
>
> Based on feedback I've received, here and elsewhere, the Aggregated
> Exceptions proposal has evolved, and would benefit from a page where
> its most recent state is published.
>
> I have created this page in this post:
>
>
> http://denisbider.blogspot.com/2015/07/aggregated-exceptions-proposal-summary.html
>
> This does not contain new information compared to what has been so far
> discussed here, but it summarizes the state of the proposal.
>
>
> On Sunday, July 19, 2015 at 6:03:44 AM UTC-6, denis bider wrote:
>
>> I agree with comments that waiting for memory is a bad policy.
>>
>> I support the suggestion that std::terminate should be the go-to option
>> when memory for exception aggregation cannot be secured.
>>
>>
>> For applications that need to guarantee that exception unwinding will
>> succeed in all circumstances, a sufficient amount of memory can be
>> pre-reserved, e.g. via exposing something like:
>>
>> void std::preallocate_exception_memory(size_t max_count, size_t
>> max_bytes);
>>
>> If this is a guarantee you must have, then you:
>>
>> - Analyze your program for the maximum number of exceptions you think it
>> may need to handle concurrently.
>>
>> - Call the above function to preallocate memory at start.
>>
>>
>> There is also my previous suggestion for:
>>
>> bool std::can_throw(size_t);
>>
>> In the multi-exception paradigm, this would provide similar functionality
>> that std::uncaught_exception() provides currently. It provides a
>> destructor a way to detect a circumstance where throwing an exception would
>> result in std::terminate(); and in that case, allows the destructor to
>> do something else if it wants to.
>>
>> When std::preallocate_exception_memory() has been called with parameters
>> appropriate for the program, std::can_throw() would always return true in
>> practice. It would also always return true outside of destructors.
>>
>>
>> I think these two suggestions would adequately address use of
>> multi-exceptions in limited-memory environments.
>>
>> A program that doesn't wish to use any of this could also continue to use
>> existing mechanics with no change in behavior. A program can still use
>> noexcept destructors. If it uses destructors that are noexcept(false),
>> it can still call std::uncaught_exception() and not throw if an
>> exception is in progress. To avoid aggregated exceptions from containers,
>> the program can still avoid using containers to store objects whose
>> destructors are noexcept(false), - which is currently the only safe
>> practice.
>>
>> In other words - if the program adheres to all the same limitations that
>> we have in place today, it will experience no shortcomings. However, a
>> function like std::preallocate_exception_memory() would make it safe to
>> use aggregated exceptions in limited memory environments, also.
>>
>> I do not see this as much different than pre-allocating a large enough
>> stack.
>>
>>
>> On Sunday, July 19, 2015 at 5:03:42 AM UTC-6, wher...@gmail.com wrote:
>>
>>> On Saturday, July 18, 2015 at 9:15:10 PM UTC+3, denis bider wrote:
>>>>
>>>> In 20 years, I have never seen *bad_alloc* on Windows unless the
>>>> program requested an unreasonable amount of memory. In all of these cases,
>>>> normal-sized allocations could still continue.
>>>>
>>>> Windows will go to extreme lengths to avoid failing a reasonable
>>>> memory request. I argue that this is what an operating system should do.
>>>>
>>>
>>> For example, Windows Phone devices with 512 MB of memory are running
>>> Windows 8/8.1/10, but only allow 140/180 MB of memory for a single process
>>> and do not have a paging file. So for a resource-heavy application it is
>>> possible to see bad_alloc quite 'early' due to running out of memory.
>>>
>>
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/8f946937-4065-4f4b-82c5-561d02ab3342%40isocpp.org.
------=_Part_1132_1452078403.1456526888098
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Hi, I've found this old discussion and would like ask =
whether it was continued elsewhere or just died.<br><br>Considering the pro=
posal, the amount of new keyword extensions scares me a bit. Also, the idea=
that existing catch blocks may not handle exception lists is also worrisom=
e.<br><br>Therefore I would like you to consider the following idea:<br><br=
>1. Catch blocks for exception lists are to be declared as catch(std::excep=
tion_list<exception_type>).<br>2. Existing exception handlers simply =
operate on the front elements of the list.<br><br>To be more specific, the =
following catch-block:<br><br><div class=3D"prettyprint" style=3D"backgroun=
d-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style=
: solid; border-width: 1px; word-wrap: break-word;"><code class=3D"prettypr=
int"><div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">catch</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">exception_type e</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 do_som=
ething</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><s=
pan style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div></code></di=
v><br>would be equivalent to:<br><br><div class=3D"prettyprint" style=3D"ba=
ckground-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); borde=
r-style: solid; border-width: 1px; word-wrap: break-word;"><code class=3D"p=
rettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008;" clas=
s=3D"styled-by-prettify">catch</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify">std</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">exce=
ption_list</span><span style=3D"color: #080;" class=3D"styled-by-prettify">=
<exception_type></span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"> ex_list</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">)</span><span style=3D"color: #000;" class=3D"styled-by-prettify"=
> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 except=
ion_type e </span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> ex_li=
st</span><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify">pop_front</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">();</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 do_something</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><sp=
an style=3D"color: #008;" class=3D"styled-by-prettify">if</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">(!</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify">ex_list</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">.</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">empty</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">())</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"styled=
-by-prettify">throw</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> ex_list</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><b=
r></span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span>=
</div></code></div><br>Additionally, <i>throw</i> in <i>catch block</i> sho=
uld add to the <i>front</i> of the list, unlike adding to the back elsewher=
e:<br><br><div class=3D"prettyprint" style=3D"background-color: rgb(250, 25=
0, 250); border-color: rgb(187, 187, 187); border-style: solid; border-widt=
h: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"s=
ubprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">ca=
tch</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify">exception_type e=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>=C2=A0 do_something</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">throw</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">}</span></div></code></div><br>would be equivalent =
to:<br><br><div class=3D"prettyprint" style=3D"background-color: rgb(250, 2=
50, 250); border-color: rgb(187, 187, 187); border-style: solid; border-wid=
th: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"=
subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">c=
atch</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify">std</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">exception_list</span><span s=
tyle=3D"color: #080;" class=3D"styled-by-prettify"><exception_type></=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> ex_list</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br>=C2=A0 exception_type e </span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> ex_list</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">pop_front</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">();</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"><br>=C2=A0 do_something</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify"><br>=C2=A0 ex_list</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">push_front</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">e</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">throw</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> ex_list</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span></div>=
</code></div><br><br>On Sunday, July 19, 2015 at 7:33:46 PM UTC+3, denis bi=
der wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left:=
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><di=
v>Based on feedback I've received, here and elsewhere, the Aggregated E=
xceptions proposal has evolved, and would benefit from a page where its=C2=
=A0most recent=C2=A0state is published.</div><div><br></div><div>I have cre=
ated this page in this post:</div><div><br></div><div><a href=3D"http://den=
isbider.blogspot.com/2015/07/aggregated-exceptions-proposal-summary.html" t=
arget=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://ww=
w.google.com/url?q\75http%3A%2F%2Fdenisbider.blogspot.com%2F2015%2F07%2Fagg=
regated-exceptions-proposal-summary.html\46sa\75D\46sntz\0751\46usg\75AFQjC=
NHoV_qxRzQyc3J8kc7gVKbZDBrk6w';return true;" onclick=3D"this.href=3D=
9;http://www.google.com/url?q\75http%3A%2F%2Fdenisbider.blogspot.com%2F2015=
%2F07%2Faggregated-exceptions-proposal-summary.html\46sa\75D\46sntz\0751\46=
usg\75AFQjCNHoV_qxRzQyc3J8kc7gVKbZDBrk6w';return true;">http://denisbid=
er.blogspot.<wbr>com/2015/07/aggregated-<wbr>exceptions-proposal-summary.<w=
br>html</a></div><div><br></div><div>This does not contain=C2=A0new informa=
tion compared to what has been so far discussed here, but it summarizes the=
state of the proposal.<br>
<br><br>On Sunday, July 19, 2015 at 6:03:44 AM UTC-6, denis bider wrote:</d=
iv><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padd=
ing-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;borde=
r-left-style:solid"><div dir=3D"ltr"><div>I agree=C2=A0with comments that w=
aiting for memory is a bad policy.</div><div><br></div><div>I=C2=A0support=
=C2=A0the suggestion=C2=A0that=C2=A0=C2=A0<font face=3D"courier new,monospa=
ce">std::<wbr>terminate<font face=3D"arial,sans-serif">=C2=A0should be the =
go-to=C2=A0option when memory for exception aggregation cannot be secured.<=
/font></font></div><div><br></div><div><br></div><div>For applications that=
need to guarantee that exception unwinding will succeed in all circumstanc=
es, a sufficient amount of memory can be pre-reserved, e.g. via exposing so=
mething like:</div><div><br></div><div><font face=3D"courier new,monospace"=
>void std::preallocate_exception_<wbr>memory(size_t max_count, size_t max_b=
ytes);</font></div><div><br></div><div>If this is a guarantee you must have=
, then you:</div><div><br></div><div>- Analyze your program for the maximum=
number of exceptions you think it may need to handle concurrently.</div><d=
iv><br></div><div>-=C2=A0Call the above function to preallocate memory at s=
tart.</div><div><br></div><div><br></div><div>There is also=C2=A0my previou=
s suggestion for:</div><div><font face=3D"Courier New"><br></font></div><di=
v><font face=3D"Courier New">bool std::can_throw(size_t);</font></div><div>=
<font face=3D"Courier New"><br></font></div><div><font face=3D"Arial">In th=
e multi-exception paradigm, this=C2=A0would provide similar functionality t=
hat <font face=3D"courier new,monospace">std::uncaught_exception()</font> p=
rovides currently. It provides a destructor a way to detect a circumstance =
where throwing an exception would result in <font face=3D"courier new,monos=
pace">std::terminate()</font>; and in that case, allows the destructor to d=
o something else if it wants to.</font></div><div><br></div><div>When=C2=A0=
<font face=3D"courier new,monospace">std::preallocate_<wbr>exception_memory=
() <font face=3D"arial,sans-serif">has been called with parameters appropri=
ate for the program,=C2=A0<font face=3D"courier new,monospace">std::can_thr=
ow()</font> would always return <font face=3D"courier new,monospace">true <=
/font>in practice. It would also always return <font face=3D"courier new,mo=
nospace">true</font> outside of destructors.</font></font></div><div><br></=
div><div><br></div><div>I think these two suggestions would adequately addr=
ess use of multi-exceptions in limited-memory environments.</div><div><br><=
/div><div>A=C2=A0program that doesn't wish to use any of this could als=
o continue to use existing mechanics with no change in behavior. A program =
can still use <font face=3D"courier new,monospace">noexcept<font face=3D"ar=
ial,sans-serif"> destructors. If it uses destructors that are <font face=3D=
"courier new,monospace">noexcept(false)<font face=3D"arial,sans-serif">, it=
can still call <font face=3D"courier new,monospace">std::uncaught_exceptio=
n()<font face=3D"arial,sans-serif"> and not throw if an exception is in pro=
gress. To avoid aggregated exceptions from containers, the program can stil=
l avoid using containers to store objects whose destructors are <font face=
=3D"courier new,monospace">noexcept(false)<font face=3D"arial,sans-serif">,=
- which is currently the only safe practice.</font></font></font></font></=
font></font></font></font></div><div><br></div><div>In other words - if the=
program adheres to all the same limitations that we have in place today, i=
t will experience no shortcomings. However, a function like <font face=3D"c=
ourier new,monospace">std::preallocate_exception_<wbr>memory()</font> would=
make it safe to use aggregated exceptions in limited memory environments, =
also.</div><div><br></div><div>I do not see this as much different than pre=
-allocating a large enough stack.</div><div><br></div><div><br>On Sunday, J=
uly 19, 2015 at 5:03:42 AM UTC-6, <a>wher...@gmail.com</a> wrote:</div><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;padding-lef=
t:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-=
style:solid"><div dir=3D"ltr">On Saturday, July 18, 2015 at 9:15:10 PM UTC+=
3, denis bider wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0px =
0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-le=
ft-width:1px;border-left-style:solid"><div dir=3D"ltr"><div>In 20 years, I =
have never seen <i>bad_alloc</i> on Windows unless the=20
program requested an unreasonable amount of memory. In all of these=20
cases, normal-sized allocations could still continue.<br>
<br>=C2=A0Windows will go to extreme lengths to avoid failing a reasonable =
memory=20
request. I argue that this is what an operating system should do.=C2=A0</di=
v></div></blockquote><div>=C2=A0</div><div>For example, Windows Phone devic=
es with 512 MB of memory are running Windows 8/8.1/10, but only allow 140/1=
80 MB of memory for a single process and do not have a paging file. So for =
a resource-heavy application it is possible to see bad_alloc quite 'ear=
ly' due to running out of memory.</div></div></blockquote></div></block=
quote></div></blockquote></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/8f946937-4065-4f4b-82c5-561d02ab3342%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/8f946937-4065-4f4b-82c5-561d02ab3342=
%40isocpp.org</a>.<br />
------=_Part_1132_1452078403.1456526888098--
------=_Part_1131_871423013.1456526888097--
.
Author: isocppgroup@denisbider.com
Date: Fri, 26 Feb 2016 17:20:20 -0800 (PST)
Raw View
------=_Part_1105_360140694.1456536021059
Content-Type: multipart/alternative;
boundary="----=_Part_1106_1545191715.1456536021060"
------=_Part_1106_1545191715.1456536021060
Content-Type: text/plain; charset=UTF-8
I am inclined to prefer behavior you've described, but the objection was
that this would modify the behavior of existing programs. A program
that currently throws an exception in the path of another will terminate.
If multi-exceptions were introduced, and could be caught by regular
handlers, such programs would now run, with the non-first exceptions being
ignored. I would be inclined to consider this acceptable, in the sense that
it's trading one type of bug for another type of bug. However, there is the
objection that current behavior (program termination) could be
theoretically being relied upon by some code.
Overall, discussion of this proposal may look like it died partly because I
feel I've iterated on it as well as I could, and it's up to others to pick
it up, if anyone wants to. In the end, a compiler implementer needs to
consider something a good idea, else it's dead.
On Friday, February 26, 2016 at 4:48:08 PM UTC-6, forf...@melkov.ru wrote:
> Hi, I've found this old discussion and would like ask whether it was
> continued elsewhere or just died.
>
> Considering the proposal, the amount of new keyword extensions scares me a
> bit. Also, the idea that existing catch blocks may not handle exception
> lists is also worrisome.
>
> Therefore I would like you to consider the following idea:
>
> 1. Catch blocks for exception lists are to be declared as
> catch(std::exception_list<exception_type>).
> 2. Existing exception handlers simply operate on the front elements of the
> list.
>
> To be more specific, the following catch-block:
>
> catch(exception_type e) {
> do_something;
> }
>
> would be equivalent to:
>
> catch(std::exception_list<exception_type> ex_list) {
> exception_type e = ex_list.pop_front();
> do_something;
> if (!ex_list.empty())
> throw ex_list;
> }
>
> Additionally, *throw* in *catch block* should add to the *front* of the
> list, unlike adding to the back elsewhere:
>
> catch(exception_type e) {
> do_something;
> throw;
> }
>
> would be equivalent to:
>
> catch(std::exception_list<exception_type> ex_list) {
> exception_type e = ex_list.pop_front();
> do_something;
> ex_list.push_front(e);
> throw ex_list;
> }
>
>
> On Sunday, July 19, 2015 at 7:33:46 PM UTC+3, denis bider wrote:
>>
>> Based on feedback I've received, here and elsewhere, the Aggregated
>> Exceptions proposal has evolved, and would benefit from a page where
>> its most recent state is published.
>>
>> I have created this page in this post:
>>
>>
>> http://denisbider.blogspot.com/2015/07/aggregated-exceptions-proposal-summary.html
>>
>> This does not contain new information compared to what has been so far
>> discussed here, but it summarizes the state of the proposal.
>>
>>
>> On Sunday, July 19, 2015 at 6:03:44 AM UTC-6, denis bider wrote:
>>
>>> I agree with comments that waiting for memory is a bad policy.
>>>
>>> I support the suggestion that std::terminate should be the
>>> go-to option when memory for exception aggregation cannot be secured.
>>>
>>>
>>> For applications that need to guarantee that exception unwinding will
>>> succeed in all circumstances, a sufficient amount of memory can be
>>> pre-reserved, e.g. via exposing something like:
>>>
>>> void std::preallocate_exception_memory(size_t max_count, size_t
>>> max_bytes);
>>>
>>> If this is a guarantee you must have, then you:
>>>
>>> - Analyze your program for the maximum number of exceptions you think it
>>> may need to handle concurrently.
>>>
>>> - Call the above function to preallocate memory at start.
>>>
>>>
>>> There is also my previous suggestion for:
>>>
>>> bool std::can_throw(size_t);
>>>
>>> In the multi-exception paradigm, this would provide similar
>>> functionality that std::uncaught_exception() provides currently. It
>>> provides a destructor a way to detect a circumstance where throwing an
>>> exception would result in std::terminate(); and in that case, allows
>>> the destructor to do something else if it wants to.
>>>
>>> When std::preallocate_exception_memory() has been called with
>>> parameters appropriate for the program, std::can_throw() would always
>>> return true in practice. It would also always return true outside of
>>> destructors.
>>>
>>>
>>> I think these two suggestions would adequately address use of
>>> multi-exceptions in limited-memory environments.
>>>
>>> A program that doesn't wish to use any of this could also continue to
>>> use existing mechanics with no change in behavior. A program can still use
>>> noexcept destructors. If it uses destructors that are noexcept(false),
>>> it can still call std::uncaught_exception() and not throw if an
>>> exception is in progress. To avoid aggregated exceptions from containers,
>>> the program can still avoid using containers to store objects whose
>>> destructors are noexcept(false), - which is currently the only safe
>>> practice.
>>>
>>> In other words - if the program adheres to all the same limitations that
>>> we have in place today, it will experience no shortcomings. However, a
>>> function like std::preallocate_exception_memory() would make it safe to
>>> use aggregated exceptions in limited memory environments, also.
>>>
>>> I do not see this as much different than pre-allocating a large enough
>>> stack.
>>>
>>>
>>> On Sunday, July 19, 2015 at 5:03:42 AM UTC-6, wher...@gmail.com wrote:
>>>
>>>> On Saturday, July 18, 2015 at 9:15:10 PM UTC+3, denis bider wrote:
>>>>>
>>>>> In 20 years, I have never seen *bad_alloc* on Windows unless the
>>>>> program requested an unreasonable amount of memory. In all of these cases,
>>>>> normal-sized allocations could still continue.
>>>>>
>>>>> Windows will go to extreme lengths to avoid failing a reasonable
>>>>> memory request. I argue that this is what an operating system should do.
>>>>>
>>>>
>>>> For example, Windows Phone devices with 512 MB of memory are running
>>>> Windows 8/8.1/10, but only allow 140/180 MB of memory for a single process
>>>> and do not have a paging file. So for a resource-heavy application it is
>>>> possible to see bad_alloc quite 'early' due to running out of memory.
>>>>
>>>
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/36beea82-b076-4fcc-bec3-6409cf4a90e5%40isocpp.org.
------=_Part_1106_1545191715.1456536021060
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>I=C2=A0am inclined to prefer behavior you've desc=
ribed, but the objection was that this would modify the=C2=A0behavior of ex=
isting programs. A program that=C2=A0currently throws=C2=A0an=C2=A0exceptio=
n in the path of another will terminate. If multi-exceptions were introduce=
d, and could be caught by regular handlers,=C2=A0such programs=C2=A0would n=
ow run, with the non-first exceptions being ignored. I would be inclined to=
=C2=A0consider this acceptable, in the sense that it's trading=C2=A0one=
type of bug for another type of bug.=C2=A0However,=C2=A0there is the objec=
tion=C2=A0that current behavior (program termination) could be theoreticall=
y being relied upon by some code.</div><div><br></div><div>Overall, discuss=
ion of this proposal may look like it died=C2=A0partly because=C2=A0I feel =
I've iterated on=C2=A0it as well as I could, and it's up to others =
to pick it up, if anyone wants to. In the end, a compiler implementer needs=
to consider something a good idea, else it's dead.</div><div><br><br>O=
n Friday, February 26, 2016 at 4:48:08 PM UTC-6, forf...@melkov.ru wrote:</=
div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; p=
adding-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-width:=
1px; border-left-style: solid;"><div dir=3D"ltr">Hi, I've found this o=
ld discussion and would like ask whether it was continued elsewhere or just=
died.<br><br>Considering the proposal, the amount of new keyword extension=
s scares me a bit. Also, the idea that existing catch blocks may not handle=
exception lists is also worrisome.<br><br>Therefore I would like you to co=
nsider the following idea:<br><br>1. Catch blocks for exception lists are t=
o be declared as catch(std::exception_list<<wbr>exception_type>).<br>=
2. Existing exception handlers simply operate on the front elements of the =
list.<br><br>To be more specific, the following catch-block:<br><br><div st=
yle=3D"border: 1px solid rgb(187, 187, 187); border-image: none; -ms-word-w=
rap: break-word; background-color: rgb(250, 250, 250);"><code><div><span st=
yle=3D"color: rgb(0, 0, 136);">catch</span><span style=3D"color: rgb(102, 1=
02, 0);">(</span><span style=3D"color: rgb(0, 0, 0);">exception_type e</spa=
n><span style=3D"color: rgb(102, 102, 0);">)</span><span style=3D"color: rg=
b(0, 0, 0);"> </span><span style=3D"color: rgb(102, 102, 0);">{</span><span=
style=3D"color: rgb(0, 0, 0);"><br>=C2=A0 do_something</span><span style=
=3D"color: rgb(102, 102, 0);">;</span><span style=3D"color: rgb(0, 0, 0);">=
<br></span><span style=3D"color: rgb(102, 102, 0);">}</span><span style=3D"=
color: rgb(0, 0, 0);"><br></span></div></code></div><br>would be equivalent=
to:<br><br><div style=3D"border: 1px solid rgb(187, 187, 187); border-imag=
e: none; -ms-word-wrap: break-word; background-color: rgb(250, 250, 250);">=
<code><div><span style=3D"color: rgb(0, 0, 136);">catch</span><span style=
=3D"color: rgb(102, 102, 0);">(</span><span style=3D"color: rgb(0, 0, 0);">=
std</span><span style=3D"color: rgb(102, 102, 0);">::</span><span style=3D"=
color: rgb(0, 0, 0);">exception_list</span><span style=3D"color: rgb(0, 136=
, 0);"><<wbr>exception_type></span><span style=3D"color: rgb(0, 0, 0)=
;"> ex_list</span><span style=3D"color: rgb(102, 102, 0);">)</span><span st=
yle=3D"color: rgb(0, 0, 0);"> </span><span style=3D"color: rgb(102, 102, 0)=
;">{</span><span style=3D"color: rgb(0, 0, 0);"><br>=C2=A0 exception_type e=
</span><span style=3D"color: rgb(102, 102, 0);">=3D</span><span style=3D"c=
olor: rgb(0, 0, 0);"> ex_list</span><span style=3D"color: rgb(102, 102, 0);=
">.</span><span style=3D"color: rgb(0, 0, 0);">pop_front</span><span style=
=3D"color: rgb(102, 102, 0);">();</span><span style=3D"color: rgb(0, 0, 0);=
"><br>=C2=A0 do_something</span><span style=3D"color: rgb(102, 102, 0);">;<=
/span><span style=3D"color: rgb(0, 0, 0);"><br>=C2=A0 </span><span style=3D=
"color: rgb(0, 0, 136);">if</span><span style=3D"color: rgb(0, 0, 0);"> </s=
pan><span style=3D"color: rgb(102, 102, 0);">(!</span><span style=3D"color:=
rgb(0, 0, 0);">ex_list</span><span style=3D"color: rgb(102, 102, 0);">.</s=
pan><span style=3D"color: rgb(0, 0, 0);">empty</span><span style=3D"color: =
rgb(102, 102, 0);">())</span><span style=3D"color: rgb(0, 0, 0);"><br>=C2=
=A0 =C2=A0 </span><span style=3D"color: rgb(0, 0, 136);">throw</span><span =
style=3D"color: rgb(0, 0, 0);"> ex_list</span><span style=3D"color: rgb(102=
, 102, 0);">;</span><span style=3D"color: rgb(0, 0, 0);"><br></span><span s=
tyle=3D"color: rgb(102, 102, 0);">}</span></div></code></div><br>Additional=
ly, <i>throw</i> in <i>catch block</i> should add to the <i>front</i> of th=
e list, unlike adding to the back elsewhere:<br><br><div style=3D"border: 1=
px solid rgb(187, 187, 187); border-image: none; -ms-word-wrap: break-word;=
background-color: rgb(250, 250, 250);"><code><div><span style=3D"color: rg=
b(0, 0, 136);">catch</span><span style=3D"color: rgb(102, 102, 0);">(</span=
><span style=3D"color: rgb(0, 0, 0);">exception_type e</span><span style=3D=
"color: rgb(102, 102, 0);">)</span><span style=3D"color: rgb(0, 0, 0);"> </=
span><span style=3D"color: rgb(102, 102, 0);">{</span><span style=3D"color:=
rgb(0, 0, 0);"><br>=C2=A0 do_something</span><span style=3D"color: rgb(102=
, 102, 0);">;</span><span style=3D"color: rgb(0, 0, 0);"><br>=C2=A0 </span>=
<span style=3D"color: rgb(0, 0, 136);">throw</span><span style=3D"color: rg=
b(102, 102, 0);">;</span><span style=3D"color: rgb(0, 0, 0);"><br></span><s=
pan style=3D"color: rgb(102, 102, 0);">}</span></div></code></div><br>would=
be equivalent to:<br><br><div style=3D"border: 1px solid rgb(187, 187, 187=
); border-image: none; -ms-word-wrap: break-word; background-color: rgb(250=
, 250, 250);"><code><div><span style=3D"color: rgb(0, 0, 136);">catch</span=
><span style=3D"color: rgb(102, 102, 0);">(</span><span style=3D"color: rgb=
(0, 0, 0);">std</span><span style=3D"color: rgb(102, 102, 0);">::</span><sp=
an style=3D"color: rgb(0, 0, 0);">exception_list</span><span style=3D"color=
: rgb(0, 136, 0);"><<wbr>exception_type></span><span style=3D"color: =
rgb(0, 0, 0);"> ex_list</span><span style=3D"color: rgb(102, 102, 0);">)</s=
pan><span style=3D"color: rgb(0, 0, 0);"> </span><span style=3D"color: rgb(=
102, 102, 0);">{</span><span style=3D"color: rgb(0, 0, 0);"><br>=C2=A0 exce=
ption_type e </span><span style=3D"color: rgb(102, 102, 0);">=3D</span><spa=
n style=3D"color: rgb(0, 0, 0);"> ex_list</span><span style=3D"color: rgb(1=
02, 102, 0);">.</span><span style=3D"color: rgb(0, 0, 0);">pop_front</span>=
<span style=3D"color: rgb(102, 102, 0);">();</span><span style=3D"color: rg=
b(0, 0, 0);"><br>=C2=A0 do_something</span><span style=3D"color: rgb(102, 1=
02, 0);">;</span><span style=3D"color: rgb(0, 0, 0);"><br>=C2=A0 ex_list</s=
pan><span style=3D"color: rgb(102, 102, 0);">.</span><span style=3D"color: =
rgb(0, 0, 0);">push_front</span><span style=3D"color: rgb(102, 102, 0);">(<=
/span><span style=3D"color: rgb(0, 0, 0);">e</span><span style=3D"color: rg=
b(102, 102, 0);">);</span><span style=3D"color: rgb(0, 0, 0);"><br>=C2=A0 <=
/span><span style=3D"color: rgb(0, 0, 136);">throw</span><span style=3D"col=
or: rgb(0, 0, 0);"> ex_list</span><span style=3D"color: rgb(102, 102, 0);">=
;</span><span style=3D"color: rgb(0, 0, 0);"><br></span><span style=3D"colo=
r: rgb(102, 102, 0);">}</span></div></code></div><br><br>On Sunday, July 19=
, 2015 at 7:33:46 PM UTC+3, denis bider wrote:<blockquote class=3D"gmail_qu=
ote" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-col=
or: rgb(204, 204, 204); border-left-width: 1px; border-left-style: solid;">=
<div dir=3D"ltr"><div>Based on feedback I've received, here and elsewhe=
re, the Aggregated Exceptions proposal has evolved, and would benefit from =
a page where its=C2=A0most recent=C2=A0state is published.</div><div><br></=
div><div>I have created this page in this post:</div><div><br></div><div><a=
onmousedown=3D"this.href=3D'http://www.google.com/url?q\75http%3A%2F%2=
Fdenisbider.blogspot.com%2F2015%2F07%2Faggregated-exceptions-proposal-summa=
ry.html\46sa\75D\46sntz\0751\46usg\75AFQjCNHoV_qxRzQyc3J8kc7gVKbZDBrk6w'=
;;return true;" onclick=3D"this.href=3D'http://www.google.com/url?q\75h=
ttp%3A%2F%2Fdenisbider.blogspot.com%2F2015%2F07%2Faggregated-exceptions-pro=
posal-summary.html\46sa\75D\46sntz\0751\46usg\75AFQjCNHoV_qxRzQyc3J8kc7gVKb=
ZDBrk6w';return true;" href=3D"http://denisbider.blogspot.com/2015/07/a=
ggregated-exceptions-proposal-summary.html" target=3D"_blank" rel=3D"nofoll=
ow">http://denisbider.blogspot.<wbr>com/2015/07/aggregated-<wbr>exceptions-=
proposal-summary.<wbr>html</a></div><div><br></div><div>This does not conta=
in=C2=A0new information compared to what has been so far discussed here, bu=
t it summarizes the state of the proposal.<br>
<br><br>On Sunday, July 19, 2015 at 6:03:44 AM UTC-6, denis bider wrote:</d=
iv><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; pa=
dding-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-width: =
1px; border-left-style: solid;"><div dir=3D"ltr"><div>I agree=C2=A0with com=
ments that waiting for memory is a bad policy.</div><div><br></div><div>I=
=C2=A0support=C2=A0the suggestion=C2=A0that=C2=A0=C2=A0<font face=3D"courie=
r new,monospace">std::<wbr>terminate<font face=3D"arial,sans-serif">=C2=A0s=
hould be the go-to=C2=A0option when memory for exception aggregation cannot=
be secured.</font></font></div><div><br></div><div><br></div><div>For appl=
ications that need to guarantee that exception unwinding will succeed in al=
l circumstances, a sufficient amount of memory can be pre-reserved, e.g. vi=
a exposing something like:</div><div><br></div><div><font face=3D"courier n=
ew,monospace">void std::preallocate_exception_<wbr>memory(size_t max_count,=
size_t max_bytes);</font></div><div><br></div><div>If this is a guarantee =
you must have, then you:</div><div><br></div><div>- Analyze your program fo=
r the maximum number of exceptions you think it may need to handle concurre=
ntly.</div><div><br></div><div>-=C2=A0Call the above function to preallocat=
e memory at start.</div><div><br></div><div><br></div><div>There is also=C2=
=A0my previous suggestion for:</div><div><font face=3D"Courier New"><br></f=
ont></div><div><font face=3D"Courier New">bool std::can_throw(size_t);</fon=
t></div><div><font face=3D"Courier New"><br></font></div><div><font face=3D=
"Arial">In the multi-exception paradigm, this=C2=A0would provide similar fu=
nctionality that <font face=3D"courier new,monospace">std::uncaught_excepti=
on()</font> provides currently. It provides a destructor a way to detect a =
circumstance where throwing an exception would result in <font face=3D"cour=
ier new,monospace">std::terminate()</font>; and in that case, allows the de=
structor to do something else if it wants to.</font></div><div><br></div><d=
iv>When=C2=A0<font face=3D"courier new,monospace">std::preallocate_<wbr>exc=
eption_memory() <font face=3D"arial,sans-serif">has been called with parame=
ters appropriate for the program,=C2=A0<font face=3D"courier new,monospace"=
>std::can_throw()</font> would always return <font face=3D"courier new,mono=
space">true </font>in practice. It would also always return <font face=3D"c=
ourier new,monospace">true</font> outside of destructors.</font></font></di=
v><div><br></div><div><br></div><div>I think these two suggestions would ad=
equately address use of multi-exceptions in limited-memory environments.</d=
iv><div><br></div><div>A=C2=A0program that doesn't wish to use any of t=
his could also continue to use existing mechanics with no change in behavio=
r. A program can still use <font face=3D"courier new,monospace">noexcept<fo=
nt face=3D"arial,sans-serif"> destructors. If it uses destructors that are =
<font face=3D"courier new,monospace">noexcept(false)<font face=3D"arial,san=
s-serif">, it can still call <font face=3D"courier new,monospace">std::unca=
ught_exception()<font face=3D"arial,sans-serif"> and not throw if an except=
ion is in progress. To avoid aggregated exceptions from containers, the pro=
gram can still avoid using containers to store objects whose destructors ar=
e <font face=3D"courier new,monospace">noexcept(false)<font face=3D"arial,s=
ans-serif">, - which is currently the only safe practice.</font></font></fo=
nt></font></font></font></font></font></div><div><br></div><div>In other wo=
rds - if the program adheres to all the same limitations that we have in pl=
ace today, it will experience no shortcomings. However, a function like <fo=
nt face=3D"courier new,monospace">std::preallocate_exception_<wbr>memory()<=
/font> would make it safe to use aggregated exceptions in limited memory en=
vironments, also.</div><div><br></div><div>I do not see this as much differ=
ent than pre-allocating a large enough stack.</div><div><br></div><div><br>=
On Sunday, July 19, 2015 at 5:03:42 AM UTC-6, <a>wher...@gmail.com</a> wrot=
e:</div><blockquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8e=
x; padding-left: 1ex; border-left-color: rgb(204, 204, 204); border-left-wi=
dth: 1px; border-left-style: solid;"><div dir=3D"ltr">On Saturday, July 18,=
2015 at 9:15:10 PM UTC+3, denis bider wrote:<blockquote class=3D"gmail_quo=
te" style=3D"margin: 0px 0px 0px 0.8ex; padding-left: 1ex; border-left-colo=
r: rgb(204, 204, 204); border-left-width: 1px; border-left-style: solid;"><=
div dir=3D"ltr"><div>In 20 years, I have never seen <i>bad_alloc</i> on Win=
dows unless the=20
program requested an unreasonable amount of memory. In all of these=20
cases, normal-sized allocations could still continue.<br>
<br>=C2=A0Windows will go to extreme lengths to avoid failing a reasonable =
memory=20
request. I argue that this is what an operating system should do.=C2=A0</di=
v></div></blockquote><div>=C2=A0</div><div>For example, Windows Phone devic=
es with 512 MB of memory are running Windows 8/8.1/10, but only allow 140/1=
80 MB of memory for a single process and do not have a paging file. So for =
a resource-heavy application it is possible to see bad_alloc quite 'ear=
ly' due to running out of memory.</div></div></blockquote></div></block=
quote></div></blockquote></div></blockquote></div>
<p></p>
-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals" group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/36beea82-b076-4fcc-bec3-6409cf4a90e5%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/36beea82-b076-4fcc-bec3-6409cf4a90e5=
%40isocpp.org</a>.<br />
------=_Part_1106_1545191715.1456536021060--
------=_Part_1105_360140694.1456536021059--
.