Topic: a proposal to handle exception thrown during
Author: crusader.mike@gmail.com
Date: Sun, 27 Aug 2017 18:35:21 -0700 (PDT)
Raw View
------=_Part_6123_995368769.1503884121373
Content-Type: multipart/alternative;
boundary="----=_Part_6124_304178775.1503884121374"
------=_Part_6124_304178775.1503884121374
Content-Type: text/plain; charset="UTF-8"
Hi,
Everyone knows that you aren't supposed to throw from destructor unless
std::terminate() is what you want. What do you think about changing this?
Here are my thoughts:
- both C-style error handling and C++ exceptions do effectively the same
thing -- construct error object and pass it up the call stack, differences
are:
- C: error type is known to caller and caller is responsible for allocating
memory for error object
- C: caller is responsible for proper propagation of error
- EH: caller only knows whether some error can bubble up (ignoring
exception specs here, since they are deprecated)
- EH: there is a mechanism that automates error propagation (and matching
to related catch clause)
- so, if you are "cleaning up" after receiving C-style error -- nothing
prevents you from handling second error produced by "cleanup" call (since
propagation is handled by developer anyway). You may choose to replace
older error with new one, chain them together, etc
- with EH language-provided mechanism has no idea what to do with second
error object, so decision was made to call terminate execution since user
allowed error to escape. The idea is that user needs to somehow handle
second error before it "meets" first one. Unfortunately this seriously
limits what you can do -- for example you can't replace old exception with
new one (and continue propagation).
How about providing more sensible default behavior (and maybe some knobs
for user to tune this process a bit)?
Proposed "more sensible" behavior would be this:
- new exception replaces old one
- new exception gets wrapped into (equivalent-of/modified-version-of)
std::nested_exception
- ... which instead of one std::exception_ptr holds many (our exception can
replace multiple others during propagation)
wrt to actual execution flow, it should look like this:
this code:
{
T1 t1;
T2 t2;
T3 t3;
}
will be executed like this:
{
T1::T1(&t1); // construct T1 at address t1
on_leave_scope(T1::~T1(&t1));
{
T2::T2(&t2);
on_leave_scope(T2::~T2(&t2));
{
T3::T3(&t3);
on_leave_scope(T3::~T3(&t3));
}
}
}
i.e. exception in ~T2() does not prevent ~T1() from happening and exception
thrown from ~T1() will replace exception thrown from ~T2().
Similarly in case of struct/class all member variables will have their
destructor invoked even if main dtor (or any of member's dtor) threw. Same
for operator delete -- even if dtor throws, memory will be deallocated. The
latest exceptions replaces all others (but they don't disappear without a
trace -- they all will be organized into a tree and will be accessible).
It is not hard to come up with alternative way of combining two exceptions
when one "catches up" with another, but approach described above seems like
most sensible default. "Knobs" mentioned earlier still needs to be fleshed
out.
Expected impact:
- incorrect programs (those that throw from destructors) will stop crashing
- correct programs won't be affected
I don't expect any implementation problems, but you are welcome to prove me
wrong. I also expect this to be a welcome change in the language,
especially for beginners as well as those who occasionally find a real need
for throwing destructor.
Do you think this idea has any chance to see the light?
Regards,
Michael.
--
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/4e81a22f-7634-465f-a7d3-6b9339eb7a52%40isocpp.org.
------=_Part_6124_304178775.1503884121374
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Hi,</div><div><br></div><div>Everyone knows that you =
aren't supposed to throw from destructor unless std::terminate() is wha=
t you want. What do you think about changing this?</div><div><br></div><div=
>Here are my thoughts:</div><div>- both C-style error handling and C++ exce=
ptions do effectively the same thing -- construct error object and pass it =
up the call stack, differences are:</div><div><blockquote style=3D"margin: =
0 0 0 40px; border: none; padding: 0px;"><div>- C: error type is known to c=
aller and caller is responsible for allocating memory for error object</div=
></blockquote></div><blockquote style=3D"margin: 0 0 0 40px; border: none; =
padding: 0px;"><div><div>- C: caller is responsible for proper propagation =
of error=C2=A0</div></div></blockquote><blockquote style=3D"margin: 0 0 0 4=
0px; border: none; padding: 0px;"><div><div>- EH: caller only knows whether=
some error can bubble up (ignoring exception specs here, since they are de=
precated)</div></div></blockquote><blockquote style=3D"margin: 0 0 0 40px; =
border: none; padding: 0px;"><div>- EH: there is a mechanism that automates=
error propagation (and matching to related catch clause)</div></blockquote=
><div>=C2=A0- so, if you are "cleaning up" after receiving C-styl=
e error -- nothing prevents you from handling second error produced by &quo=
t;cleanup" call (since propagation is handled by developer anyway). Yo=
u may choose to replace older error with new one, chain them together, etc<=
/div><div>- with EH language-provided mechanism has no idea what to do with=
second error object, so decision was made to call terminate execution sinc=
e user allowed error to escape. The idea is that user needs to somehow hand=
le second error before it "meets" first one. Unfortunately this s=
eriously limits what you can do -- for example you can't replace old ex=
ception with new one (and continue propagation).<br></div><div><br></div><d=
iv>How about providing more sensible default behavior (and maybe some knobs=
for user to tune this process a bit)?</div><div><br></div><div>Proposed &q=
uot;more sensible" behavior would be this:</div><div>- new exception r=
eplaces old one</div><div>- new exception gets wrapped into (equivalent-of/=
modified-version-of) std::nested_exception</div><div>- ... which instead of=
one std::exception_ptr holds many (our exception can replace multiple othe=
rs during propagation)</div><div><br></div><div>wrt to actual execution flo=
w, it should look like this:</div><div><br></div><div>this code:</div><div>=
{<br></div><div>=C2=A0 =C2=A0 T1 t1;</div><div>=C2=A0 =C2=A0 T2 t2;</div><d=
iv>=C2=A0 =C2=A0 T3 t3;</div><div>}</div><div><br></div><div>will be execut=
ed like this:</div><div>{</div><div>=C2=A0 =C2=A0 T1::T1(&t1); =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 // construct T1 at address t1<br></div><div>=C2=
=A0 =C2=A0 on_leave_scope(T1::~T1(&t1));</div><div>=C2=A0 =C2=A0 {</div=
><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 T2::T2(&t2);</div><div>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 on_leave_scope(T2::~T2(&t2));</div><div>=C2=A0 =C2=A0 =C2=
=A0 =C2=A0 {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 T3::T3(&am=
p;t3);</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 on_leave_scope(T=
3::~T3(&t3));</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 }</div><div>=C2=A0 =
=C2=A0 }</div><div>}</div><div><br></div><div>i.e. exception in ~T2() does =
not prevent ~T1() from happening and exception thrown from ~T1() will repla=
ce exception thrown from ~T2().</div><div><br></div><div>Similarly in case =
of struct/class all member variables will have their destructor invoked eve=
n if main dtor (or any of member's dtor) threw. Same for operator delet=
e -- even if dtor throws, memory will be deallocated. The latest exceptions=
replaces all others (but they don't disappear without a trace -- they =
all will be organized into a tree and will be accessible).</div><div><br></=
div><div>It is not hard to come up with alternative way of combining two ex=
ceptions when one "catches up" with another, but approach describ=
ed above seems like most sensible default. "Knobs" mentioned earl=
ier still needs to be fleshed out.</div><div><br></div><div>Expected impact=
:</div><div>- incorrect programs (those that throw from destructors) will s=
top crashing</div><div>- correct programs won't be affected</div><div><=
br></div><div>I don't expect any implementation problems, but you are w=
elcome to prove me wrong. I also expect this to be a welcome change in the =
language, especially for beginners as well as those who occasionally find a=
real need for throwing destructor.</div><div><br></div><div>Do you think t=
his idea has any chance to see the light?</div><div><br></div><div>Regards,=
</div><div>Michael.</div><div><br></div></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/4e81a22f-7634-465f-a7d3-6b9339eb7a52%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/4e81a22f-7634-465f-a7d3-6b9339eb7a52=
%40isocpp.org</a>.<br />
------=_Part_6124_304178775.1503884121374--
------=_Part_6123_995368769.1503884121373--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Sun, 27 Aug 2017 19:19:57 -0700 (PDT)
Raw View
------=_Part_5828_1914518735.1503886797120
Content-Type: multipart/alternative;
boundary="----=_Part_5829_1921011971.1503886797121"
------=_Part_5829_1921011971.1503886797121
Content-Type: text/plain; charset="UTF-8"
On Sunday, August 27, 2017 at 9:35:21 PM UTC-4, crusad...@gmail.com wrote:
>
> Hi,
>
> Everyone knows that you aren't supposed to throw from destructor unless
> std::terminate() is what you want. What do you think about changing this?
>
It's unclear what you mean by this.
The reason (standard-wise) why a destructor that emits an exception calls
`std::terminate()` is because destructors are *implicitly* declared
`noexcept`. You are free to declare them `noexcept(false)`, and they can
therefore freely emit exceptions. So there is nothing to change if you want
to throw in a destructor.
Now, perhaps you're talking about an exception collision. That is, having
an exception emitted by a destructor that is being called during stack
unwinding.
Preventing that is why the standard was written in C++11 to make all
destructors implicitly `noexcept`.
But there's an even better reason: throwing from a destructor effectively
means that the object's destruction failed. So... what state is the object
in? Throwing from a destructor means that all of the subobjects have not
yet been destroyed (unless it is one of their destructors that threw, in
which case it is all subojects after that point). What happens to them? Are
they just zombie objects? What happens to any code that was relying on
those objects being destroyed?
Stack unwinding *cannot *resolve these issues.
No, a throwing destructor is a terrible, horrible, no-good, very-bad idea.
Implicitly forbidding it is a good thing, and C++ has absolutely no need to
support exception clashing (which can only happen through a throwing
destructor).
Here are my thoughts:
> - both C-style error handling and C++ exceptions do effectively the same
> thing -- construct error object and pass it up the call stack, differences
> are:
>
> - C: error type is known to caller and caller is responsible for
> allocating memory for error object
>
> - C: caller is responsible for proper propagation of error
>
> - EH: caller only knows whether some error can bubble up (ignoring
> exception specs here, since they are deprecated)
>
> - EH: there is a mechanism that automates error propagation (and matching
> to related catch clause)
>
>
- EH: Arbitrary code can execute between the generation of the error code
and its reception. That code itself can fail.
That's the difference. Failing to fail is not a possibility in C. It is a
possibility in exception handing. Failing to fail is not a rational
situation; it represents incoherent programming logic and is therefore
unrecoverable.
- so, if you are "cleaning up" after receiving C-style error --nothing
> prevents you from handling second error produced by "cleanup" call (since
> propagation is handled by developer anyway). You may choose to replace
> older error with new one, chain them together, etc
>
- with EH language-provided mechanism has no idea what to do with second
> error object, so decision was made to call terminate execution since user
> allowed error to escape. The idea is that user needs to somehow handle
> second error before it "meets" first one. Unfortunately this seriously
> limits what you can do -- for example you can't replace old exception with
> new one (and continue propagation).
>
.... why would you want to?
Think about this for a second. Your call stack looks like this:
A->B->C->D->E
Now, E emits an exception. One that is caught by C. That catch provokes
stack unwinding down to C.
D's unwinding throws an exception. One that is caught by B. That catch
provokes stack unwinding down to... where?
You've got two choices: it can either go to C as it already was, or it can
go to B.
If it goes to B, that means that the catch block at C will never be
executed. But it was *supposed* to be executed; C and E were both written
with that as a requirement.
You can go to C. In which case... what happens to the exception thrown by
D? Because after C's catch block executes, the program continues on to the
next statement. C's catch block is written with that as an expectation. So
you can't just have the exception from D force further stack unwinding
after C's catch.
An exception is going to be missed. Even if you somehow transfer the
information thrown by E to B, that doesn't mean that B has the ability to
do what C's catch statement could (and *needed to*). After all, C's catch
statement could access variables in C's scope. Which were destroyed by
stack unwinding.
No, this is a nonsensical situation.
How about providing more sensible default behavior (and maybe some knobs
> for user to tune this process a bit)?
>
Proposed "more sensible" behavior would be this:
> - new exception replaces old one
>
How is that sensible? I explained above how this fails.
> - new exception gets wrapped into (equivalent-of/modified-version-of)
> std::nested_exception
>
How is that sensible? Is the user expecting to catch a
`std::nested_exception`? Would the user even know what to do in that case?
As in the above case, the location of B doesn't have access to what C's
catch clause does.
- ... which instead of one std::exception_ptr holds many (our exception can
> replace multiple others during propagation)
>
How is that even remotely sensible?
wrt to actual execution flow, it should look like this:
>
> this code:
> {
> T1 t1;
> T2 t2;
> T3 t3;
> }
>
> will be executed like this:
> {
> T1::T1(&t1); // construct T1 at address t1
> on_leave_scope(T1::~T1(&t1));
> {
> T2::T2(&t2);
> on_leave_scope(T2::~T2(&t2));
> {
> T3::T3(&t3);
> on_leave_scope(T3::~T3(&t3));
> }
> }
> }
>
> i.e. exception in ~T2() does not prevent ~T1() from happening and
> exception thrown from ~T1() will replace exception thrown from ~T2().
>
> Similarly in case of struct/class all member variables will have their
> destructor invoked even if main dtor (or any of member's dtor) threw. Same
> for operator delete -- even if dtor throws, memory will be deallocated. The
> latest exceptions replaces all others (but they don't disappear without a
> trace -- they all will be organized into a tree and will be accessible).
>
> It is not hard to come up with alternative way of combining two exceptions
> when one "catches up" with another, but approach described above seems like
> most sensible default. "Knobs" mentioned earlier still needs to be fleshed
> out.
>
> Expected impact:
> - incorrect programs (those that throw from destructors) will stop crashing
>
Right. Because the best thing we could have incorrect programs do is *keep
running*, and thus potentially damage all kinds of memory and data until
they finally trigger a genuine fault.
No; if a program is incorrect, a controlled halt is far better than
pretending that everything is fine when it really isn't.
- correct programs won't be affected
>
> I don't expect any implementation problems, but you are welcome to prove
> me wrong.
>
Here's a better idea: why do you go look at implementations and *tell us*
if there would be any problems.
I also expect this to be a welcome change in the language, especially for
> beginners as well as those who occasionally find a real need for throwing
> destructor.
>
People who have a "'real need' for a throwing destructor" tend to be one of
the following:
- Wrong about that "real need"
- Very careful about preventing clashes. Like checking
`std::uncaught_exceptions` to see if their destructor is being called due
to unwinding or not, and thus being able to know if it's safe to emit an
exception.
As for beginners, encouraging them to write broken code is not helpful to
anyone.
Do you think this idea has any chance to see the light?
>
God, I hope not.
--
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/aeb96d4c-99ea-4c3e-8fc7-a7012c943143%40isocpp.org.
------=_Part_5829_1921011971.1503886797121
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Sunday, August 27, 2017 at 9:35:21 PM UTC-4, crusad...@=
gmail.com 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"lt=
r"><div>Hi,</div><div><br></div><div>Everyone knows that you aren't sup=
posed to throw from destructor unless std::terminate() is what you want. Wh=
at do you think about changing this?</div></div></blockquote><div><br>It=
9;s unclear what you mean by this.<br><br>The reason (standard-wise) why a =
destructor that emits an exception calls `std::terminate()` is because dest=
ructors are <i>implicitly</i> declared `noexcept`. You are free to declare =
them `noexcept(false)`, and they can therefore freely emit exceptions. So t=
here is nothing to change if you want to throw in a destructor.<br><br>Now,=
perhaps you're talking about an exception collision. That is, having a=
n exception emitted by a destructor that is being called during stack unwin=
ding.<br><br>Preventing that is why the standard was written in C++11 to ma=
ke all destructors implicitly `noexcept`.<br><br>But there's an even be=
tter reason: throwing from a destructor effectively means that the object&#=
39;s destruction failed. So... what state is the object in? Throwing from a=
destructor means that all of the subobjects have not yet been destroyed (u=
nless it is one of their destructors that threw, in which case it is all su=
bojects after that point). What happens to them? Are they just zombie objec=
ts? What happens to any code that was relying on those objects being destro=
yed?<br><br>Stack unwinding <i>cannot </i>resolve these issues.<br><br>No, =
a throwing destructor is a terrible, horrible, no-good, very-bad idea. Impl=
icitly forbidding it is a good thing, and C++ has absolutely no need to sup=
port exception clashing (which can only happen through a throwing destructo=
r).<br><br></div><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></div><div>Here are my thoughts:</div><div>- both C-style error ha=
ndling and C++ exceptions do effectively the same thing -- construct error =
object and pass it up the call stack, differences are:</div><div><blockquot=
e style=3D"margin:0 0 0 40px;border:none;padding:0px"><div>- C: error type =
is known to caller and caller is responsible for allocating memory for erro=
r object</div></blockquote></div><blockquote style=3D"margin:0 0 0 40px;bor=
der:none;padding:0px"><div><div>- C: caller is responsible for proper propa=
gation of error=C2=A0</div></div></blockquote><blockquote style=3D"margin:0=
0 0 40px;border:none;padding:0px"><div><div>- EH: caller only knows whethe=
r some error can bubble up (ignoring exception specs here, since they are d=
eprecated)</div></div></blockquote><blockquote style=3D"margin:0 0 0 40px;b=
order:none;padding:0px"><div>- EH: there is a mechanism that automates erro=
r propagation (and matching to related catch clause)</div></blockquote></di=
v></blockquote><div><br>- EH: Arbitrary code can execute between the genera=
tion of the error code and its reception. That code itself can fail.<br><br=
>That's the difference. Failing to fail is not a possibility in C. It i=
s a possibility in exception handing. Failing to fail is not a rational sit=
uation; it represents incoherent programming logic and is therefore unrecov=
erable.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div>=C2=A0- so, if you are "cleaning up" after receivin=
g C-style error --nothing prevents you from handling second error produced =
by "cleanup" call (since propagation is handled by developer anyw=
ay). You may choose to replace older error with new one, chain them togethe=
r, etc</div></div></blockquote><blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
><div dir=3D"ltr"><div>- with EH language-provided mechanism has no idea wh=
at to do with second error object, so decision was made to call terminate e=
xecution since user allowed error to escape. The idea is that user needs to=
somehow handle second error before it "meets" first one. Unfortu=
nately this seriously limits what you can do -- for example you can't r=
eplace old exception with new one (and continue propagation).<br></div></di=
v></blockquote><div><br>... why would you want to?<br><br>Think about this =
for a second. Your call stack looks like this:<br><br><div style=3D"backgro=
und-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-sty=
le: solid; border-width: 1px; overflow-wrap: break-word;" class=3D"prettypr=
int"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=
=3D"color: #000;" class=3D"styled-by-prettify">A</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">-></span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify">B</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">-></span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">C</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">-></span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify">D</span><span style=3D"color: #660;" class=3D"styled-by-prettify">->=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify">E</span><=
/div></code></div><br>Now, E emits an exception. One that is caught by C. T=
hat catch provokes stack unwinding down to C.<br><br>D's unwinding thro=
ws an exception. One that is caught by B. That catch provokes stack unwindi=
ng down to... where?<br><br>You've got two choices: it can either go to=
C as it already was, or it can go to B.<br><br>If it goes to B, that means=
that the catch block at C will never be executed. But it was <i>supposed</=
i> to be executed; C and E were both written with that as a requirement.<br=
><br>You can go to C. In which case... what happens to the exception thrown=
by D? Because after C's catch block executes, the program continues on=
to the next statement. C's catch block is written with that as an expe=
ctation. So you can't just have the exception from D force further stac=
k unwinding after C's catch.<br><br>An exception is going to be missed.=
Even if you somehow transfer the information thrown by E to B, that doesn&=
#39;t mean that B has the ability to do what C's catch statement could =
(and <i>needed to</i>). After all, C's catch statement could access var=
iables in C's scope. Which were destroyed by stack unwinding.<br><br>No=
, this is a nonsensical situation.<br><br></div><blockquote class=3D"gmail_=
quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pa=
dding-left: 1ex;"><div dir=3D"ltr"><div></div><div></div><div>How about pro=
viding more sensible default behavior (and maybe some knobs for user to tun=
e this process a bit)?</div></div></blockquote><div></div><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></div><div>Proposed "=
;more sensible" behavior would be this:</div><div>- new exception repl=
aces old one</div></div></blockquote><div><br>How is that sensible? I expla=
ined above how this fails.<br>=C2=A0</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"><div>- new exception gets wrapped into (equiva=
lent-of/modified-<wbr>version-of) std::nested_exception</div></div></blockq=
uote><div><br>How is that sensible? Is the user expecting to catch a `std::=
nested_exception`? Would the user even know what to do in that case? As in =
the above case, the location of B doesn't have access to what C's c=
atch clause does.<br><br></div><blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
><div dir=3D"ltr"><div>- ... which instead of one std::exception_ptr holds =
many (our exception can replace multiple others during propagation)</div></=
div></blockquote><div><br>How is that even remotely sensible?<br><br></div>=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><d=
iv>wrt to actual execution flow, it should look like this:</div><div><br></=
div><div>this code:</div><div>{<br></div><div>=C2=A0 =C2=A0 T1 t1;</div><di=
v>=C2=A0 =C2=A0 T2 t2;</div><div>=C2=A0 =C2=A0 T3 t3;</div><div>}</div><div=
><br></div><div>will be executed like this:</div><div>{</div><div>=C2=A0 =
=C2=A0 T1::T1(&t1); =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // construct T1 =
at address t1<br></div><div>=C2=A0 =C2=A0 on_leave_scope(T1::~T1(&t1));=
</div><div>=C2=A0 =C2=A0 {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 T2::T2(&am=
p;t2);</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 on_leave_scope(T2::~T2(&t2=
));</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 {</div><div>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 T3::T3(&t3);</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0=
=C2=A0 =C2=A0 on_leave_scope(T3::~T3(&t3));</div><div>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 }</div><div>=C2=A0 =C2=A0 }</div><div>}</div><div><br></div><=
div>i.e. exception in ~T2() does not prevent ~T1() from happening and excep=
tion thrown from ~T1() will replace exception thrown from ~T2().</div><div>=
<br></div><div>Similarly in case of struct/class all member variables will =
have their destructor invoked even if main dtor (or any of member's dto=
r) threw. Same for operator delete -- even if dtor throws, memory will be d=
eallocated. The latest exceptions replaces all others (but they don't d=
isappear without a trace -- they all will be organized into a tree and will=
be accessible).</div><div><br></div><div>It is not hard to come up with al=
ternative way of combining two exceptions when one "catches up" w=
ith another, but approach described above seems like most sensible default.=
"Knobs" mentioned earlier still needs to be fleshed out.</div><d=
iv><br></div><div>Expected impact:</div><div>- incorrect programs (those th=
at throw from destructors) will stop crashing</div></div></blockquote><div>=
<br>Right. Because the best thing we could have incorrect programs do is <i=
>keep running</i>, and thus potentially damage all kinds of memory and data=
until they finally trigger a genuine fault.<br><br>No; if a program is inc=
orrect, a controlled halt is far better than pretending that everything is =
fine when it really isn't.<br><br></div><blockquote class=3D"gmail_quot=
e" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddin=
g-left: 1ex;"><div dir=3D"ltr"><div>- correct programs won't be affecte=
d</div><div><br></div><div>I don't expect any implementation problems, =
but you are welcome to prove me wrong.</div></div></blockquote><div><br>Her=
e's a better idea: why do you go look at implementations and <i>tell us=
</i> if there would be any problems.<br><br></div><blockquote class=3D"gmai=
l_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;=
padding-left: 1ex;"><div dir=3D"ltr"><div>I also expect this to be a welcom=
e change in the language, especially for beginners as well as those who occ=
asionally find a real need for throwing destructor.</div></div></blockquote=
><div><br>People who have a "'real need' for a throwing destru=
ctor" tend to be one of the following:<br><br>- Wrong about that "=
;real need"<br>- Very careful about preventing clashes. Like checking =
`std::uncaught_exceptions` to see if their destructor is being called due t=
o unwinding or not, and thus being able to know if it's safe to emit an=
exception.<br><br>As for beginners, encouraging them to write broken code =
is not helpful to anyone.<br><br></div><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-lef=
t: 1ex;"><div dir=3D"ltr"><div>Do you think this idea has any chance to see=
the light?</div></div></blockquote><div><br>God, I hope not. <br></div></d=
iv>
<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/aeb96d4c-99ea-4c3e-8fc7-a7012c943143%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/aeb96d4c-99ea-4c3e-8fc7-a7012c943143=
%40isocpp.org</a>.<br />
------=_Part_5829_1921011971.1503886797121--
------=_Part_5828_1914518735.1503886797120--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Sun, 27 Aug 2017 21:54:39 -0700
Raw View
On Sunday, 27 August 2017 18:35:21 PDT crusader.mike@gmail.com wrote:
> Everyone knows that you aren't supposed to throw from destructor unless
> std::terminate() is what you want. What do you think about changing this?
It's the same problem in C.
See this code:
http://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/io/
qfilesystemengine_unix.cpp?h=dev#n1116
I'm handling a failure from sendfile() by "unwinding" my work. What should my
code do if ftruncate() fails?
There's nothing it can do. My code needs to swallow that second failure and
pretend it did not happen.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/214845754.DnGgfvoGfH%40tjmaciei-mobl1.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Sun, 27 Aug 2017 22:00:55 -0700
Raw View
On Sunday, 27 August 2017 19:19:57 PDT Nicol Bolas wrote:
> But there's an even better reason: throwing from a destructor effectively
> means that the object's destruction failed. So... what state is the object
> in? Throwing from a destructor means that all of the subobjects have not
> yet been destroyed (unless it is one of their destructors that threw, in
> which case it is all subojects after that point). What happens to them? Are
> they just zombie objects? What happens to any code that was relying on
> those objects being destroyed?
>
> Stack unwinding *cannot *resolve these issues.
>
> No, a throwing destructor is a terrible, horrible, no-good, very-bad idea.
> Implicitly forbidding it is a good thing, and C++ has absolutely no need to
> support exception clashing (which can only happen through a throwing
> destructor).
Let me give a better C example of equivalent problem: fclose.
fclose can fail, If it failed, what is the state of the FILE* object? Is it
destroyed or not? Can you fclose again?
No, usually, you cannot.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/3005246.zvK4UqkCqo%40tjmaciei-mobl1.
.
Author: crusader.mike@gmail.com
Date: Mon, 28 Aug 2017 09:06:30 -0700 (PDT)
Raw View
------=_Part_3339_608032875.1503936390531
Content-Type: multipart/alternative;
boundary="----=_Part_3340_1171866404.1503936390532"
------=_Part_3340_1171866404.1503936390532
Content-Type: text/plain; charset="UTF-8"
Before reading stuff below I suggest to set aside any dogmatic blinders you
may have, namely:
- realize that there is nothing particular special about destructors --
they are just functions that runtime calls automatically in specific
circumstances and yes, they may want to report an error
- you can't really tell what makes sense or not -- only end user makes this
decision
- what is proposed -- is just a tool, whether to use it or not, is up to
end user
On Sunday, August 27, 2017 at 9:19:57 PM UTC-5, Nicol Bolas wrote:
>
> On Sunday, August 27, 2017 at 9:35:21 PM UTC-4, crusad...@gmail.com wrote:
>>
>> Hi,
>>
>> Everyone knows that you aren't supposed to throw from destructor unless
>> std::terminate() is what you want. What do you think about changing this?
>>
>
> It's unclear what you mean by this.
>
> The reason (standard-wise) why a destructor that emits an exception calls
> `std::terminate()` is because destructors are *implicitly* declared
> `noexcept`. You are free to declare them `noexcept(false)`, and they can
> therefore freely emit exceptions. So there is nothing to change if you want
> to throw in a destructor.
>
> Now, perhaps you're talking about an exception collision. That is, having
> an exception emitted by a destructor that is being called during stack
> unwinding.
>
Yes.
Preventing that is why the standard was written in C++11 to make all
> destructors implicitly `noexcept`.
>
And it probably makes sense to make it a default. Imho current 'enforcing'
noexcept does more harm than good, but it is offtopic. If you want to
discuss this -- start another thread or talk to me in private.
> But there's an even better reason: throwing from a destructor effectively
> means that the object's destruction failed. So... what state is the object
> in?
>
it doesn't exist.
Throwing from a destructor means that all of the subobjects have not yet
> been destroyed (unless it is one of their destructors that threw, in which
> case it is all subojects after that point). What happens to them? Are they
> just zombie objects? What happens to any code that was relying on those
> objects being destroyed?
>
I explained it in original post -- each subobject's dtor will be called
too. And their state will change to 'no longer exist' too.
Stack unwinding *cannot *resolve these issues.
>
I see no issues.
No, a throwing destructor is a terrible, horrible, no-good, very-bad idea.
> Implicitly forbidding it is a good thing, and C++ has absolutely no need to
> support exception clashing (which can only happen through a throwing
> destructor).
>
> Here are my thoughts:
>> - both C-style error handling and C++ exceptions do effectively the same
>> thing -- construct error object and pass it up the call stack, differences
>> are:
>>
>> - C: error type is known to caller and caller is responsible for
>> allocating memory for error object
>>
>> - C: caller is responsible for proper propagation of error
>>
>> - EH: caller only knows whether some error can bubble up (ignoring
>> exception specs here, since they are deprecated)
>>
>> - EH: there is a mechanism that automates error propagation (and matching
>> to related catch clause)
>>
>>
> - EH: Arbitrary code can execute between the generation of the error code
> and its reception. That code itself can fail.
>
no, same thing can happen with C-style error handling. It looks rather
obvious to me
> That's the difference. Failing to fail is not a possibility in C. It is a
> possibility in exception handing. Failing to fail is not a rational
> situation; it represents incoherent programming logic and is therefore
> unrecoverable.
>
There are only two possibilities of 'failing to fail' in EH -- first one I
addressed in another proposal (failure to allocate memory) and another one
is addressed with this proposal (providing ability to handle multiple
errors).
> - so, if you are "cleaning up" after receiving C-style error --nothing
>> prevents you from handling second error produced by "cleanup" call (since
>> propagation is handled by developer anyway). You may choose to replace
>> older error with new one, chain them together, etc
>>
> - with EH language-provided mechanism has no idea what to do with second
>> error object, so decision was made to call terminate execution since user
>> allowed error to escape. The idea is that user needs to somehow handle
>> second error before it "meets" first one. Unfortunately this seriously
>> limits what you can do -- for example you can't replace old exception with
>> new one (and continue propagation).
>>
>
> ... why would you want to?
>
> Think about this for a second. Your call stack looks like this:
>
> A->B->C->D->E
>
> Now, E emits an exception. One that is caught by C. That catch provokes
> stack unwinding down to C.
>
> D's unwinding throws an exception. One that is caught by B. That catch
> provokes stack unwinding down to... where?
>
exception emitted by E will be replaced by exception emitted by D during
unwinding (when exception will "meet") and unwinding will continue. C may
or may not catch it (depending on catch clause).
You've got two choices: it can either go to C as it already was, or it can
> go to B.
>
> If it goes to B, that means that the catch block at C will never be
> executed. But it was *supposed* to be executed; C and E were both written
> with that as a requirement.
>
> You can go to C. In which case... what happens to the exception thrown by
> D?
>
see above
> Because after C's catch block executes, the program continues on to the
> next statement. C's catch block is written with that as an expectation. So
> you can't just have the exception from D force further stack unwinding
> after C's catch.
>
No, see above
An exception is going to be missed.
>
No, exception thrown by E is not going to disappear -- it will be
accessible via nested_exception-like magic (see below).
> Even if you somehow transfer the information thrown by E to B, that
> doesn't mean that B has the ability to do what C's catch statement could
> (and *needed to*). After all, C's catch statement could access variables
> in C's scope. Which were destroyed by stack unwinding.
>
> No, this is a nonsensical situation.
>
If end user does not create non-sensical situations -- he won't have to
deal with them. If C's catch clause is written in such way that it doesn't
catch exception in certain cases -- maybe he shouldn't write it this way?
> How about providing more sensible default behavior (and maybe some knobs
>> for user to tune this process a bit)?
>>
> Proposed "more sensible" behavior would be this:
>> - new exception replaces old one
>>
>
> How is that sensible? I explained above how this fails.
>
No, it doesn't fail. Or better to say it fails successfully :-)
- new exception gets wrapped into (equivalent-of/modified-version-of)
> std::nested_exception
>
> How is that sensible? Is the user expecting to catch a
> `std::nested_exception`? Would the user even know what to do in that case?
> As in the above case, the location of B doesn't have access to what C's
> catch clause does.
>
In more or less the same way you are supposed to deal with nested_exception
now. First time MyException meets with another exception, it gets replaced
with smth like this:
class : public std::nested_exception, public MyException
{
};
where instead of single exception_ptr, nested_exception will have a
collection(e.g. vector/deque). Each time this exception (during unwinding)
replaces another exception -- replaced exception gets added to this list.
Access to this collection can be organised in a similar (that is very
awkward) way you can access std::nested_exception innards (rethrow
_if_nested/etc).
Again, it is just one way of doing it -- another way would be instead of
replacing earlier exception -- to transform it in a similar manner and add
contender to it's list. Or provide a user-controlled mechanism that will
decide what to do with some sensible default. This may not be very easy to
come up with a mechanism like that.
> - ... which instead of one std::exception_ptr holds many (our exception
>> can replace multiple others during propagation)
>>
>
> How is that even remotely sensible?
>
Here is a C-style code:
error_t foo()
{
...
error_t res1 = do_smth1();
error_t res2 = do_smth2();
error_t res3 = do_smth3();
// somehow combine results
error_t res = ...;
return res;
}
try writing similar logic using EH -- it will be very awkward, lots of
code. Keep in mind that no matter what each of functions above need to be
called no matter what. Let's say that each one attempts to switch off a
piece of very expensive machinery. You can't make it no-fail for physical
reasons. And if something goes wrong you need to report error(s) upstairs
for analysis and associated actions.
with this proposal you can put these do_smthN() calls into destructors and
automatically get "always gets invoked" guarantee along with some
(hopefully sensible) mechanism that is going to combine these errors for
propagation up-stack. If user doesn't like default mechanism -- he'll use
aforementioned knobs to tune it to his liking.
Right now you have to make these dtors silent and accumulate these errors
elsewhere -- basically turning EH into some weird mix of both styles.
> wrt to actual execution flow, it should look like this:
>>
>> this code:
>> {
>> T1 t1;
>> T2 t2;
>> T3 t3;
>> }
>>
>> will be executed like this:
>> {
>> T1::T1(&t1); // construct T1 at address t1
>> on_leave_scope(T1::~T1(&t1));
>> {
>> T2::T2(&t2);
>> on_leave_scope(T2::~T2(&t2));
>> {
>> T3::T3(&t3);
>> on_leave_scope(T3::~T3(&t3));
>> }
>> }
>> }
>>
>> i.e. exception in ~T2() does not prevent ~T1() from happening and
>> exception thrown from ~T1() will replace exception thrown from ~T2().
>>
>> Similarly in case of struct/class all member variables will have their
>> destructor invoked even if main dtor (or any of member's dtor) threw. Same
>> for operator delete -- even if dtor throws, memory will be deallocated. The
>> latest exceptions replaces all others (but they don't disappear without a
>> trace -- they all will be organized into a tree and will be accessible).
>>
>> It is not hard to come up with alternative way of combining two
>> exceptions when one "catches up" with another, but approach described above
>> seems like most sensible default. "Knobs" mentioned earlier still needs to
>> be fleshed out.
>>
>> Expected impact:
>> - incorrect programs (those that throw from destructors) will stop
>> crashing
>>
>
> Right. Because the best thing we could have incorrect programs do is *keep
> running*, and thus potentially damage all kinds of memory and data until
> they finally trigger a genuine fault.
>
> No; if a program is incorrect, a controlled halt is far better than
> pretending that everything is fine when it really isn't.
>
Yes, that was an unfortunate statement. Point was that change is not
intrusive -- correct code will continue working without change to it's
behavior. But as you already pointed out -- incorrect code will still crash
due to implicit noexcept on dtors.
> - correct programs won't be affected
>>
>> I don't expect any implementation problems, but you are welcome to prove
>> me wrong.
>>
>
> Here's a better idea: why do you go look at implementations and *tell us*
> if there would be any problems.
>
In those implementations I know relatively well there should be no
problems. There is a limit to how much one person can know. If it wasn't
the case -- I wouldn't be posting here. I'd simply make my own language...
with blackjack and hookers.
> I also expect this to be a welcome change in the language, especially for
>> beginners as well as those who occasionally find a real need for throwing
>> destructor.
>>
>
> People who have a "'real need' for a throwing destructor" tend to be one
> of the following:
>
> - Wrong about that "real need"
> - Very careful about preventing clashes. Like checking
> `std::uncaught_exceptions` to see if their destructor is being called due
> to unwinding or not, and thus being able to know if it's safe to emit an
> exception.
>
> As for beginners, encouraging them to write broken code is not helpful to
> anyone.
>
> Do you think this idea has any chance to see the light?
>>
>
> God, I hope not.
>
I got it -- you don't like it. I've seen cases where it makes sense. If you
slow down a bit and open your mind -- you may see my point. And once you do
-- we could discuss what would be the good "sensible default".
--
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/3546c5d5-2584-412e-b8da-fbf51ff1f924%40isocpp.org.
------=_Part_3340_1171866404.1503936390532
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div>Before reading stuff below I suggest to set aside any=
dogmatic blinders you may have, namely:</div><div>- realize that there is =
nothing particular special about destructors -- they are just functions tha=
t runtime calls automatically in specific circumstances and yes, they may w=
ant to report an error</div><div>- you can't really tell what makes sen=
se or not -- only end user makes this decision</div><div>- what is proposed=
-- is just a tool, whether to use it or not, is up to end user</div><div><=
br></div><div><br></div>On Sunday, August 27, 2017 at 9:19:57 PM UTC-5, Nic=
ol Bolas 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=
">On Sunday, August 27, 2017 at 9:35:21 PM UTC-4, <a>crusad...@gmail.com</a=
> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>Hi,</=
div><div><br></div><div>Everyone knows that you aren't supposed to thro=
w from destructor unless std::terminate() is what you want. What do you thi=
nk about changing this?</div></div></blockquote><div><br>It's unclear w=
hat you mean by this.<br><br>The reason (standard-wise) why a destructor th=
at emits an exception calls `std::terminate()` is because destructors are <=
i>implicitly</i> declared `noexcept`. You are free to declare them `noexcep=
t(false)`, and they can therefore freely emit exceptions. So there is nothi=
ng to change if you want to throw in a destructor.<br><br>Now, perhaps you&=
#39;re talking about an exception collision. That is, having an exception e=
mitted by a destructor that is being called during stack unwinding.<br></di=
v></div></blockquote><div><br></div><div>Yes.</div><div>=C2=A0</div><div><b=
r></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"><div>=
Preventing that is why the standard was written in C++11 to make all destru=
ctors implicitly `noexcept`.<br></div></div></blockquote><div><br></div><di=
v>And it probably makes sense to make it a default. Imho current 'enfor=
cing' noexcept does more harm than good, but it is offtopic. If you wan=
t to discuss this -- start another thread or talk to me in private.</div><d=
iv><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">=
<div dir=3D"ltr"><div>But there's an even better reason: throwing from =
a destructor effectively means that the object's destruction failed. So=
.... what state is the object in?</div></div></blockquote><div><br></div><di=
v>it doesn't exist.</div><div>=C2=A0</div><div><br></div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px =
#ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div> Throwing from a destr=
uctor means that all of the subobjects have not yet been destroyed (unless =
it is one of their destructors that threw, in which case it is all suboject=
s after that point). What happens to them? Are they just zombie objects? Wh=
at happens to any code that was relying on those objects being destroyed?<b=
r></div></div></blockquote><div><br></div><div>I explained it in original p=
ost -- each subobject's dtor will be called too. And their state will c=
hange to 'no longer exist' too.</div><div>=C2=A0</div><div><br></di=
v><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;b=
order-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>Stack =
unwinding <i>cannot </i>resolve these issues.<br></div></div></blockquote><=
div><br></div><div>I see no issues.</div><div>=C2=A0</div><div><br></div><b=
lockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;borde=
r-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>No, a thro=
wing destructor is a terrible, horrible, no-good, very-bad idea. Implicitly=
forbidding it is a good thing, and C++ has absolutely no need to support e=
xception clashing (which can only happen through a throwing destructor).<br=
><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"><div></=
div><div>Here are my thoughts:</div><div>- both C-style error handling and =
C++ exceptions do effectively the same thing -- construct error object and =
pass it up the call stack, differences are:</div><div><blockquote style=3D"=
margin:0 0 0 40px;border:none;padding:0px"><div>- C: error type is known to=
caller and caller is responsible for allocating memory for error object</d=
iv></blockquote></div><blockquote style=3D"margin:0 0 0 40px;border:none;pa=
dding:0px"><div><div>- C: caller is responsible for proper propagation of e=
rror=C2=A0</div></div></blockquote><blockquote style=3D"margin:0 0 0 40px;b=
order:none;padding:0px"><div><div>- EH: caller only knows whether some erro=
r can bubble up (ignoring exception specs here, since they are deprecated)<=
/div></div></blockquote><blockquote style=3D"margin:0 0 0 40px;border:none;=
padding:0px"><div>- EH: there is a mechanism that automates error propagati=
on (and matching to related catch clause)</div></blockquote></div></blockqu=
ote><div><br>- EH: Arbitrary code can execute between the generation of the=
error code and its reception. That code itself can fail.<br></div></div></=
blockquote><div><br></div><div>no, same thing can happen with C-style error=
handling. It looks rather obvious to me</div><div><br></div><div>=C2=A0</d=
iv><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>That&=
#39;s the difference. Failing to fail is not a possibility in C. It is a po=
ssibility in exception handing. Failing to fail is not a rational situation=
; it represents incoherent programming logic and is therefore unrecoverable=
..<br></div></div></blockquote><div><br></div><div>There are only two possib=
ilities of 'failing to fail' in EH -- first one I addressed in anot=
her proposal (failure to allocate memory) and another one is addressed with=
this proposal (providing ability to handle multiple errors).</div><div><br=
></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: =
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div d=
ir=3D"ltr"><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>=
=C2=A0- so, if you are "cleaning up" after receiving C-style erro=
r --nothing prevents you from handling second error produced by "clean=
up" call (since propagation is handled by developer anyway). You may c=
hoose to replace older error with new one, chain them together, etc</div></=
div></blockquote><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>- with EH language-provided mechanism has no idea what to do with secon=
d error object, so decision was made to call terminate execution since user=
allowed error to escape. The idea is that user needs to somehow handle sec=
ond error before it "meets" first one. Unfortunately this serious=
ly limits what you can do -- for example you can't replace old exceptio=
n with new one (and continue propagation).<br></div></div></blockquote><div=
><br>... why would you want to?<br><br>Think about this for a second. Your =
call stack looks like this:<br><br><div style=3D"background-color:rgb(250,2=
50,250);border-color:rgb(187,187,187);border-style:solid;border-width:1px">=
<code><div><span style=3D"color:#000">A</span><span style=3D"color:#660">-&=
gt;</span><span style=3D"color:#000">B</span><span style=3D"color:#660">-&g=
t;</span><span style=3D"color:#000">C</span><span style=3D"color:#660">->=
;</span><span style=3D"color:#000">D</span><span style=3D"color:#660">->=
</span><span style=3D"color:#000">E</span></div></code></div><br>Now, E emi=
ts an exception. One that is caught by C. That catch provokes stack unwindi=
ng down to C.<br><br>D's unwinding throws an exception. One that is cau=
ght by B. That catch provokes stack unwinding down to... where?<br></div></=
div></blockquote><div><br></div><div>exception emitted by E will be replace=
d by exception emitted by D during unwinding (when exception will "mee=
t") and unwinding will continue. C may or may not catch it (depending =
on catch clause).</div><div>=C2=A0</div><div><br></div><blockquote class=3D=
"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc s=
olid;padding-left: 1ex;"><div dir=3D"ltr"><div>You've got two choices: =
it can either go to C as it already was, or it can go to B.<br><br>If it go=
es to B, that means that the catch block at C will never be executed. But i=
t was <i>supposed</i> to be executed; C and E were both written with that a=
s a requirement.<br><br>You can go to C. In which case... what happens to t=
he exception thrown by D?</div></div></blockquote><div><br></div><div>see a=
bove</div><div><br></div><div>=C2=A0</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"><div> Because after C's catch block execut=
es, the program continues on to the next statement. C's catch block is =
written with that as an expectation. So you can't just have the excepti=
on from D force further stack unwinding after C's catch.<br></div></div=
></blockquote><div><br></div><div>No, see above</div><div>=C2=A0</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"><di=
v>An exception is going to be missed.</div></div></blockquote><div><br></di=
v><div>No, exception thrown by E is not going to disappear -- it will be ac=
cessible via nested_exception-like magic (see below).</div><div><br></div><=
div>=C2=A0</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"lt=
r"><div> Even if you somehow transfer the information thrown by E to B, tha=
t doesn't mean that B has the ability to do what C's catch statemen=
t could (and <i>needed to</i>). After all, C's catch statement could ac=
cess variables in C's scope. Which were destroyed by stack unwinding.<b=
r><br>No, this is a nonsensical situation.<br></div></div></blockquote><div=
><br></div><div>If end user does not create non-sensical situations -- he w=
on't have to deal with them. If C's catch clause is written in such=
way that it doesn't catch exception in certain cases -- maybe he shoul=
dn't write it this way?</div><div><br></div><div>=C2=A0</div><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"><blockquote class=3D"gm=
ail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;p=
adding-left:1ex"><div dir=3D"ltr"><div>How about providing more sensible de=
fault behavior (and maybe some knobs for user to tune this process a bit)?<=
/div></div></blockquote><div></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"><div></div><div>Proposed "more sensible" behavi=
or would be this:</div><div>- new exception replaces old one</div></div></b=
lockquote><div><br>How is that sensible? I explained above how this fails.<=
br></div></div></blockquote><div><br></div><div>No, it doesn't fail. Or=
better to say it fails successfully :-)</div><div>=C2=A0</div><div><br></d=
iv><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>=C2=
=A0- new exception gets wrapped into (equivalent-of/modified-<wbr>version-o=
f) std::nested_exception</div><div><br>How is that sensible? Is the user ex=
pecting to catch a `std::nested_exception`? Would the user even know what t=
o do in that case? As in the above case, the location of B doesn't have=
access to what C's catch clause does.<br></div></div></blockquote><div=
><br></div><div>In more or less the same way you are supposed to deal with =
nested_exception now. First time MyException meets with another exception, =
it gets replaced with smth like this:</div><div><br></div><div>class : publ=
ic std::nested_exception, public=C2=A0MyException</div><div>{</div><div>};<=
br></div><div><br></div><div>where instead of single exception_ptr, nested_=
exception will have a collection(e.g. vector/deque). Each time this excepti=
on (during unwinding) replaces another exception -- replaced exception gets=
added to this list.</div><div><br></div><div>Access to this collection can=
be organised in a similar (that is very awkward) way you can access std::n=
ested_exception innards (rethrow _if_nested/etc).</div><div><br></div><div>=
Again, it is just one way of doing it -- another way would be instead of re=
placing earlier exception -- to transform it in a similar manner and add co=
ntender to it's list. Or provide a user-controlled mechanism that will =
decide what to do with some sensible default. This may not be very easy to =
come up with a mechanism like that.</div><div><br></div><div>=C2=A0</div><b=
lockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;borde=
r-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc=
solid;padding-left:1ex"><div dir=3D"ltr"><div>- ... which instead of one s=
td::exception_ptr holds many (our exception can replace multiple others dur=
ing propagation)</div></div></blockquote><div><br>How is that even remotely=
sensible?<br></div></div></blockquote><div><br></div><div>Here is a C-styl=
e code:</div><div><br></div><div>error_t foo()</div><div>{</div><div>=C2=A0=
=C2=A0 ...</div><div>=C2=A0 =C2=A0 error_t res1 =3D do_smth1();</div><div>=
=C2=A0 =C2=A0 error_t res2 =3D do_smth2();</div><div>=C2=A0 =C2=A0 error_t =
res3 =3D do_smth3();</div><div><br></div><div>=C2=A0 =C2=A0 // somehow comb=
ine results</div><div>=C2=A0 =C2=A0 error_t res =3D ...;</div><div>=C2=A0 =
=C2=A0 return res;</div><div>}</div><div><br></div><div>try writing similar=
logic using EH -- it will be very awkward, lots of code. Keep in mind that=
no matter what each of functions above need to be called no matter what. L=
et's say that each one attempts to switch off a piece of very expensive=
machinery. You can't make it no-fail for physical reasons. And if some=
thing goes wrong you need to report error(s) upstairs for analysis and asso=
ciated actions.</div><div><br></div><div>with this proposal you can put the=
se do_smthN() calls into destructors and automatically get "always get=
s invoked" guarantee along with some (hopefully sensible) mechanism th=
at is going to combine these errors for propagation up-stack. If user doesn=
't like default mechanism -- he'll use aforementioned knobs to tune=
it to his liking.</div><div><br></div><div>Right now you have to make thes=
e dtors silent and accumulate these errors elsewhere -- basically turning E=
H into some weird mix of both styles.</div><div><br></div><div>=C2=A0<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"><blockquo=
te class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>wrt to actual executio=
n flow, it should look like this:</div><div><br></div><div>this code:</div>=
<div>{<br></div><div>=C2=A0 =C2=A0 T1 t1;</div><div>=C2=A0 =C2=A0 T2 t2;</d=
iv><div>=C2=A0 =C2=A0 T3 t3;</div><div>}</div><div><br></div><div>will be e=
xecuted like this:</div><div>{</div><div>=C2=A0 =C2=A0 T1::T1(&t1); =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // construct T1 at address t1<br></div><div=
>=C2=A0 =C2=A0 on_leave_scope(T1::~T1(&t1));</div><div>=C2=A0 =C2=A0 {<=
/div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 T2::T2(&t2);</div><div>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 on_leave_scope(T2::~T2(&t2));</div><div>=C2=A0 =C2=A0=
=C2=A0 =C2=A0 {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 T3::T3=
(&t3);</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 on_leave_sco=
pe(T3::~T3(&t3));</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 }</div><div>=C2=
=A0 =C2=A0 }</div><div>}</div><div><br></div><div>i.e. exception in ~T2() d=
oes not prevent ~T1() from happening and exception thrown from ~T1() will r=
eplace exception thrown from ~T2().</div><div><br></div><div>Similarly in c=
ase of struct/class all member variables will have their destructor invoked=
even if main dtor (or any of member's dtor) threw. Same for operator d=
elete -- even if dtor throws, memory will be deallocated. The latest except=
ions replaces all others (but they don't disappear without a trace -- t=
hey all will be organized into a tree and will be accessible).</div><div><b=
r></div><div>It is not hard to come up with alternative way of combining tw=
o exceptions when one "catches up" with another, but approach des=
cribed above seems like most sensible default. "Knobs" mentioned =
earlier still needs to be fleshed out.</div><div><br></div><div>Expected im=
pact:</div><div>- incorrect programs (those that throw from destructors) wi=
ll stop crashing</div></div></blockquote><div><br>Right. Because the best t=
hing we could have incorrect programs do is <i>keep running</i>, and thus p=
otentially damage all kinds of memory and data until they finally trigger a=
genuine fault.<br><br>No; if a program is incorrect, a controlled halt is =
far better than pretending that everything is fine when it really isn't=
..<br></div></div></blockquote><div><br></div><div>Yes, that was an unfortun=
ate statement. Point was that change is not intrusive -- correct code will =
continue working without change to it's behavior. But as you already po=
inted out -- incorrect code will still crash due to implicit noexcept on dt=
ors.</div><div><br></div><div>=C2=A0</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"mar=
gin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div d=
ir=3D"ltr"><div>- correct programs won't be affected</div><div><br></di=
v><div>I don't expect any implementation problems, but you are welcome =
to prove me wrong.</div></div></blockquote><div><br>Here's a better ide=
a: why do you go look at implementations and <i>tell us</i> if there would =
be any problems.<br></div></div></blockquote><div><br></div><div>In those i=
mplementations I know relatively well there should be no problems. There is=
a limit to how much one person can know. If it wasn't the case -- I wo=
uldn't be posting here. I'd simply make my own language... with bla=
ckjack and hookers.</div><div><br></div><div>=C2=A0</div><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"><blockquote class=3D"gmail_quo=
te" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-=
left:1ex"><div dir=3D"ltr"><div>I also expect this to be a welcome change i=
n the language, especially for beginners as well as those who occasionally =
find a real need for throwing destructor.</div></div></blockquote><div><br>=
People who have a "'real need' for a throwing destructor"=
tend to be one of the following:<br><br>- Wrong about that "real need=
"<br>- Very careful about preventing clashes. Like checking `std::unca=
ught_exceptions` to see if their destructor is being called due to unwindin=
g or not, and thus being able to know if it's safe to emit an exception=
..<br><br>As for beginners, encouraging them to write broken code is not hel=
pful to anyone.<br><br></div><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div d=
ir=3D"ltr"><div>Do you think this idea has any chance to see the light?</di=
v></div></blockquote><div><br>God, I hope not. <br></div></div></blockquote=
><div><br></div><div>I got it -- you don't like it. I've seen cases=
where it makes sense. If you slow down a bit and open your mind -- you may=
see my point. And once you do -- we could discuss what would be the good &=
quot;sensible default".</div></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/3546c5d5-2584-412e-b8da-fbf51ff1f924%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/3546c5d5-2584-412e-b8da-fbf51ff1f924=
%40isocpp.org</a>.<br />
------=_Part_3340_1171866404.1503936390532--
------=_Part_3339_608032875.1503936390531--
.
Author: crusader.mike@gmail.com
Date: Mon, 28 Aug 2017 09:26:56 -0700 (PDT)
Raw View
------=_Part_2478_1856732128.1503937616209
Content-Type: multipart/alternative;
boundary="----=_Part_2479_1630195932.1503937616210"
------=_Part_2479_1630195932.1503937616210
Content-Type: text/plain; charset="UTF-8"
On Sunday, August 27, 2017 at 11:54:46 PM UTC-5, Thiago Macieira wrote:
>
> On Sunday, 27 August 2017 18:35:21 PDT crusad...@gmail.com <javascript:>
> wrote:
> > Everyone knows that you aren't supposed to throw from destructor unless
> > std::terminate() is what you want. What do you think about changing
> this?
>
> It's the same problem in C.
>
> See this code:
> http://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/io/
> qfilesystemengine_unix.cpp?h=dev#n1116
> <http://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/io/qfilesystemengine_unix.cpp?h=dev#n1116>
>
> I'm handling a failure from sendfile() by "unwinding" my work. What should
> my
> code do if ftruncate() fails?
>
> There's nothing it can do. My code needs to swallow that second failure
> and
> pretend it did not happen.
>
No, you **chose** to swallow second failure. Nothing prevented you from
returning smth more complex than "bool". But you chose not too -- and it is
OK. You are the end user and you know what is best in any given situation.
Language is simply a tool and only you can decide whether given tool is ok
to use and how to use. I am just trying to make one particular tool a bit
more useful.
Here is an example where I'd choose a different path:
- a function that drives some machinery that has multiple components
- it switches them (components) ON, does work and has to **always** switch
them off before leaving the scope (no matter what)
- I'd call all these functions on exit, combine results into something that
allows me to enumerate devices (that failed to switch off) later and return
this to caller
I can obviously use C-style approach -- but then my code will be littered
with "if"s (and nested "if"s) just like yours. Or I can rely on stack
unwinding to guarantee that these functions get called -- in which case
code becomes nice and neat, but (as of now)I can't report any failures
without inventing some sort of 'under the hood' logic that circumvents
"no-fail dtor" rule.
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
>
>
--
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/3d141307-ba2a-44ff-8903-42f62fd3512d%40isocpp.org.
------=_Part_2479_1630195932.1503937616210
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Sunday, August 27, 2017 at 11:54:46 PM UTC-5, 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 Sunday, 27 Aug=
ust 2017 18:35:21 PDT <a href=3D"javascript:" target=3D"_blank" gdf-obfusca=
ted-mailto=3D"oTq-mQh2DAAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D=
9;javascript:';return true;" onclick=3D"this.href=3D'javascript:=
9;;return true;">crusad...@gmail.com</a> wrote:
<br>> Everyone knows that you aren't supposed to throw from destruct=
or unless
<br>> std::terminate() is what you want. What do you think about changin=
g this?
<br>
<br>It's the same problem in C.
<br>
<br>See this code:
<br><a href=3D"http://code.qt.io/cgit/qt/qtbase.git/tree/src/corelib/io/qfi=
lesystemengine_unix.cpp?h=3Ddev#n1116" target=3D"_blank" rel=3D"nofollow" o=
nmousedown=3D"this.href=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2F=
code.qt.io%2Fcgit%2Fqt%2Fqtbase.git%2Ftree%2Fsrc%2Fcorelib%2Fio%2Fqfilesyst=
emengine_unix.cpp%3Fh%3Ddev%23n1116\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjC=
NEhQDOK-n7XcrBEvNpsYofojA2_vQ';return true;" onclick=3D"this.href=3D=
9;http://www.google.com/url?q\x3dhttp%3A%2F%2Fcode.qt.io%2Fcgit%2Fqt%2Fqtba=
se.git%2Ftree%2Fsrc%2Fcorelib%2Fio%2Fqfilesystemengine_unix.cpp%3Fh%3Ddev%2=
3n1116\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEhQDOK-n7XcrBEvNpsYofojA2_vQ=
';return true;">http://code.qt.io/cgit/qt/<wbr>qtbase.git/tree/src/core=
lib/<wbr>io/
<br>qfilesystemengine_unix.cpp?h=3D<wbr>dev#n1116</a>
<br>
<br>I'm handling a failure from sendfile() by "unwinding" my =
work. What should my=20
<br>code do if ftruncate() fails?
<br>
<br>There's nothing it can do. My code needs to swallow that second fai=
lure and=20
<br>pretend it did not happen.
<br></blockquote><div><br></div><div>No, you **chose** to swallow second fa=
ilure. Nothing prevented you from returning smth more complex than "bo=
ol". But you chose not too -- and it is OK. You are the end user and y=
ou know what is best in any given situation. Language is simply a tool and =
only you can decide whether given tool is ok to use and how to use. I am ju=
st trying to make one particular tool a bit more useful.</div><div><br></di=
v><div>Here is an example where I'd choose a different path:</div><div>=
- a function that drives some machinery that has multiple components</div><=
div>- it switches them (components) ON, does work and has to **always** swi=
tch them off before leaving the scope (no matter what)</div><div>- I'd =
call all these functions on exit, combine results into something that allow=
s me to enumerate devices (that failed to switch off) later and return this=
to caller</div><div><br></div><div>I can obviously use C-style approach --=
but then my code will be littered with "if"s (and nested "i=
f"s) just like yours. Or I can rely on stack unwinding to guarantee th=
at these functions get called -- in which case code becomes nice and neat, =
but (as of now)I can't report any failures without inventing some sort =
of 'under the hood' logic that circumvents "no-fail dtor"=
rule.</div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quot=
e" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddin=
g-left: 1ex;">--=20
<br>Thiago Macieira - thiago (AT) <a href=3D"http://macieira.info" target=
=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.goo=
gle.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x3dD\x26sntz\x3d1\x26usg\=
x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.hr=
ef=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x=
3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return t=
rue;">macieira.info</a> - thiago (AT) <a href=3D"http://kde.org" target=3D"=
_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.google.=
com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNH=
GRJdo5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'=
http://www.google.com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1=
\x26usg\x3dAFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;">kde.org</a=
>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>
<br></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/3d141307-ba2a-44ff-8903-42f62fd3512d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/3d141307-ba2a-44ff-8903-42f62fd3512d=
%40isocpp.org</a>.<br />
------=_Part_2479_1630195932.1503937616210--
------=_Part_2478_1856732128.1503937616209--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Mon, 28 Aug 2017 09:42:39 -0700
Raw View
On Monday, 28 August 2017 09:26:56 PDT crusader.mike@gmail.com wrote:
> > There's nothing it can do. My code needs to swallow that second failure
> > and
> > pretend it did not happen.
>
> No, you **chose** to swallow second failure. Nothing prevented you from
> returning smth more complex than "bool". But you chose not too -- and it is
> OK. You are the end user and you know what is best in any given situation.
> Language is simply a tool and only you can decide whether given tool is ok
> to use and how to use. I am just trying to make one particular tool a bit
> more useful.
Then do the same in your code.
In your catch statement, catch the lower failure and do something. If that
something throws again, catch it and throw something more complex.
try {
something();
} catch (const something_exception &e) {
try {
cleanup();
} catch (cleanup_exception &e2) {
throw complex_exception(e.what(), e2.what());
}
// no error cleaning up, rethrow
throw;
}
> I can obviously use C-style approach -- but then my code will be littered
> with "if"s (and nested "if"s) just like yours. Or I can rely on stack
> unwinding to guarantee that these functions get called -- in which case
> code becomes nice and neat, but (as of now)I can't report any failures
> without inventing some sort of 'under the hood' logic that circumvents
> "no-fail dtor" rule.
I think you should litter your code. Relying on the stack unwinding to do
something it's not meant to and guess what you meant is not a good idea.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/1926652.JKneHkDH98%40tjmaciei-mobl1.
.
Author: crusader.mike@gmail.com
Date: Mon, 28 Aug 2017 09:50:55 -0700 (PDT)
Raw View
------=_Part_1554_1282417972.1503939055211
Content-Type: multipart/alternative;
boundary="----=_Part_1555_1155326424.1503939055211"
------=_Part_1555_1155326424.1503939055211
Content-Type: text/plain; charset="UTF-8"
On Monday, August 28, 2017 at 11:42:54 AM UTC-5, Thiago Macieira wrote:
>
> On Monday, 28 August 2017 09:26:56 PDT crusad...@gmail.com <javascript:>
> wrote:
> > > There's nothing it can do. My code needs to swallow that second
> failure
> > > and
> > > pretend it did not happen.
> >
> > No, you **chose** to swallow second failure. Nothing prevented you from
> > returning smth more complex than "bool". But you chose not too -- and it
> is
> > OK. You are the end user and you know what is best in any given
> situation.
> > Language is simply a tool and only you can decide whether given tool is
> ok
> > to use and how to use. I am just trying to make one particular tool a
> bit
> > more useful.
>
> Then do the same in your code.
>
> In your catch statement, catch the lower failure and do something. If that
> something throws again, catch it and throw something more complex.
>
> try {
> something();
> } catch (const something_exception &e) {
> try {
> cleanup();
> } catch (cleanup_exception &e2) {
> throw complex_exception(e.what(), e2.what());
> }
> // no error cleaning up, rethrow
> throw;
> }
>
Can you write this code for three functions that need to be called -- i.e.
cleanup1(), cleanup2(), cleanup3() ?
Make sure each cleanupN() is called only if related somethingN() succeeded.
;-)
> > I can obviously use C-style approach -- but then my code will be
> littered
> > with "if"s (and nested "if"s) just like yours. Or I can rely on stack
> > unwinding to guarantee that these functions get called -- in which case
> > code becomes nice and neat, but (as of now)I can't report any failures
> > without inventing some sort of 'under the hood' logic that circumvents
> > "no-fail dtor" rule.
>
> I think you should litter your code. Relying on the stack unwinding to do
> something it's not meant to and guess what you meant is not a good idea.
>
Pretty sure RAII was meant exactly for that -- to guarantee that certain
functions (dtors) get called no matter what. "No-fault dtors" rule is
simply because there is no easy (or right) way to propagate multiple
exceptions (if these dtors throw). None of the provided "but it doesn't
make sense" arguments (you and Nicol provided) seem convincing.
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
>
>
--
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/817124cd-e930-409f-841c-633c0a9a9028%40isocpp.org.
------=_Part_1555_1155326424.1503939055211
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Monday, August 28, 2017 at 11:42:54 AM UTC-5, 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 Monday=
, 28 August 2017 09:26:56 PDT <a href=3D"javascript:" target=3D"_blank" gdf=
-obfuscated-mailto=3D"wsUDDK2cDAAJ" rel=3D"nofollow" onmousedown=3D"this.hr=
ef=3D'javascript:';return true;" onclick=3D"this.href=3D'javasc=
ript:';return true;">crusad...@gmail.com</a> wrote:
<br>> > There's nothing it can do. My code needs to swallow that =
second failure
<br>> > and
<br>> > pretend it did not happen.
<br>>=20
<br>> No, you **chose** to swallow second failure. Nothing prevented you=
from
<br>> returning smth more complex than "bool". But you chose n=
ot too -- and it is
<br>> OK. You are the end user and you know what is best in any given si=
tuation.
<br>> Language is simply a tool and only you can decide whether given to=
ol is ok
<br>> to use and how to use. I am just trying to make one particular too=
l a bit
<br>> more useful.
<br>
<br>Then do the same in your code.
<br>
<br>In your catch statement, catch the lower failure and do something. If t=
hat=20
<br>something throws again, catch it and throw something more complex.
<br>
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0try {
<br>=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=A0something();
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0} catch (const somethin=
g_exception &e) {
<br>=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=A0try {
<br>=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=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
<wbr>cleanup();
<br>=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} catch (cleanup_exception &e2) {
<br>=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=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
throw complex_exception(e.what(), e2.what());
<br>=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}
<br>=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// no error cleaning up, rethrow
<br>=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=A0throw;
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0}
<br></blockquote><div><br></div><div>Can you write this code for three func=
tions that need to be called -- i.e. cleanup1(), cleanup2(), cleanup3() ?</=
div><div>Make sure each cleanupN() is called only if related somethingN() s=
ucceeded.</div><div>;-)<br></div><div><br></div><div>=C2=A0</div><blockquot=
e class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: =
1px #ccc solid;padding-left: 1ex;">> I can obviously use C-style approac=
h -- but then my code will be littered
<br>> with "if"s (and nested "if"s) just like yours.=
Or I can rely on stack
<br>> unwinding to guarantee that these functions get called -- in which=
case
<br>> code becomes nice and neat, but (as of now)I can't report any =
failures
<br>> without inventing some sort of 'under the hood' logic that=
circumvents
<br>> "no-fail dtor" rule.
<br>
<br>I think you should litter your code. Relying on the stack unwinding to =
do=20
<br>something it's not meant to and guess what you meant is not a good =
idea.
<br></blockquote><div><br></div><div>Pretty sure RAII was meant exactly for=
that -- to guarantee that certain functions (dtors) get called no matter w=
hat. "No-fault dtors" rule is simply because there is no easy (or=
right) way to propagate multiple exceptions (if these dtors throw). None o=
f the provided "but it doesn't make sense" arguments (you and=
Nicol provided) seem convincing.</div><div><br></div><div>=C2=A0</div><blo=
ckquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-=
left: 1px #ccc solid;padding-left: 1ex;">--=20
<br>Thiago Macieira - thiago (AT) <a href=3D"http://macieira.info" target=
=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.goo=
gle.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x3dD\x26sntz\x3d1\x26usg\=
x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.hr=
ef=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x=
3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return t=
rue;">macieira.info</a> - thiago (AT) <a href=3D"http://kde.org" target=3D"=
_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.google.=
com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNH=
GRJdo5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'=
http://www.google.com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1=
\x26usg\x3dAFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;">kde.org</a=
>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>
<br></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/817124cd-e930-409f-841c-633c0a9a9028%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/817124cd-e930-409f-841c-633c0a9a9028=
%40isocpp.org</a>.<br />
------=_Part_1555_1155326424.1503939055211--
------=_Part_1554_1282417972.1503939055211--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 28 Aug 2017 10:56:32 -0700 (PDT)
Raw View
------=_Part_7046_337812640.1503942992146
Content-Type: multipart/alternative;
boundary="----=_Part_7047_1523654969.1503942992148"
------=_Part_7047_1523654969.1503942992148
Content-Type: text/plain; charset="UTF-8"
On Monday, August 28, 2017 at 12:06:30 PM UTC-4, crusad...@gmail.com wrote:
>
> Before reading stuff below I suggest to set aside any dogmatic blinders
> you may have, namely:
> - realize that there is nothing particular special about destructors --
> they are just functions that runtime calls automatically in specific
> circumstances and yes, they may want to report an error
>
Untrue. Destructors provoke the ending of the lifetime of an object. That
makes them special. Much like how constructors signal the beginning of the
lifetime of an object.
- you can't really tell what makes sense or not -- only end user makes this
> decision
>
The C++ object model is all about defining what "makes sense". That's why
you can't just pretend that an object exists in some memory.
So the standard has every right to decide that circumstance X doesn't make
sense, so we're not going to support it.
- what is proposed -- is just a tool, whether to use it or not, is up to
> end user
>
The model that the proposal creates still has to make sense. Which it does
not. Giving people tools that are incoherent and encourage bad coding is
not helpful.
On Sunday, August 27, 2017 at 9:19:57 PM UTC-5, Nicol Bolas wrote:
>>
>> On Sunday, August 27, 2017 at 9:35:21 PM UTC-4, crusad...@gmail.com
>> wrote:
>>
> No, a throwing destructor is a terrible, horrible, no-good, very-bad idea.
>> Implicitly forbidding it is a good thing, and C++ has absolutely no need to
>> support exception clashing (which can only happen through a throwing
>> destructor).
>>
>> Here are my thoughts:
>>> - both C-style error handling and C++ exceptions do effectively the same
>>> thing -- construct error object and pass it up the call stack, differences
>>> are:
>>>
>>> - C: error type is known to caller and caller is responsible for
>>> allocating memory for error object
>>>
>>> - C: caller is responsible for proper propagation of error
>>>
>>> - EH: caller only knows whether some error can bubble up (ignoring
>>> exception specs here, since they are deprecated)
>>>
>>> - EH: there is a mechanism that automates error propagation (and
>>> matching to related catch clause)
>>>
>>>
>> - EH: Arbitrary code can execute between the generation of the error code
>> and its reception. That code itself can fail.
>>
>
> no, same thing can happen with C-style error handling. It looks rather
> obvious to me
>
Your analogy says that `return` and the use of the return value are similar
to `throw` and `catch` for that exception. Given that analogy, no, the same
thing cannot happen in C-style error handling. The function that receives
the error is the one that called the function. Between the end of the
initialization of the return value from the function creating the error
code, to the beginning of the initialization of the value that the
receiving function is creating, no user code can be executed.
Oh, there can be code between the generator of the error and where the
error is *resolved*: that is, where you stop dealing with the error
condition and progress normally. You can return the error code up the
stack, do conditional logic based on it, and all kinds of stuff.
But there is a lot more that can happen between a `throw` and a `catch`
that cannot happen between a `return` and the use of that returned value.
That's the difference. Failing to fail is not a possibility in C. It is a
>> possibility in exception handing. Failing to fail is not a rational
>> situation; it represents incoherent programming logic and is therefore
>> unrecoverable.
>>
>
> There are only two possibilities of 'failing to fail' in EH -- first one I
> addressed in another proposal (failure to allocate memory) and another one
> is addressed with this proposal (providing ability to handle multiple
> errors).
>
>
>
>> - so, if you are "cleaning up" after receiving C-style error --nothing
>>> prevents you from handling second error produced by "cleanup" call (since
>>> propagation is handled by developer anyway). You may choose to replace
>>> older error with new one, chain them together, etc
>>>
>> - with EH language-provided mechanism has no idea what to do with second
>>> error object, so decision was made to call terminate execution since user
>>> allowed error to escape. The idea is that user needs to somehow handle
>>> second error before it "meets" first one. Unfortunately this seriously
>>> limits what you can do -- for example you can't replace old exception with
>>> new one (and continue propagation).
>>>
>>
>> ... why would you want to?
>>
>> Think about this for a second. Your call stack looks like this:
>>
>> A->B->C->D->E
>>
>> Now, E emits an exception. One that is caught by C. That catch provokes
>> stack unwinding down to C.
>>
>> D's unwinding throws an exception. One that is caught by B. That catch
>> provokes stack unwinding down to... where?
>>
>
> exception emitted by E will be replaced by exception emitted by D during
> unwinding (when exception will "meet") and unwinding will continue. C may
> or may not catch it (depending on catch clause).
>
OK, so let's say that C knows that D can throw something.
That means C has to look like this:
catch(E_exception &e)
{
//Do stuff for E_exception
}
catch(D_exception &e)
{
//Do stuff for D_exception
throw;
}
catch(E_exception_combined_with_D_exception &e)
{
//Do stuff for E_exception
//Do stuff for D_exception
throw;
}
That's a lot of repetition.
It doesn't really matter what `E_exception_combined_with_D_exception` is.
Whether it's a nested exception that you do some casting tricks on to
detect what it is nested with or whatever. What matters is that you have to
repeat `Do stuff for E_exception` at least once, just to make sure that you
really catch all `E_exception`s that pass by.
The whole point of writing `catch(E_exception &e)` is that it *catches
`E_exception`s!* If an `E_exception` can pass by such a catch statement,
then the whole `catch` system is nonsensical. You may as well be catching
`exception_ptr` directly and working out what the actual type is through
casting tricks (that don't actually exist).
You've got two choices: it can either go to C as it already was, or it can
>> go to B.
>>
>> If it goes to B, that means that the catch block at C will never be
>> executed. But it was *supposed* to be executed; C and E were both
>> written with that as a requirement.
>>
>> You can go to C. In which case... what happens to the exception thrown by
>> D?
>>
>
> see above
>
>
>
>> Because after C's catch block executes, the program continues on to the
>> next statement. C's catch block is written with that as an expectation. So
>> you can't just have the exception from D force further stack unwinding
>> after C's catch.
>>
>
> No, see above
>
>
> An exception is going to be missed.
>>
>
> No, exception thrown by E is not going to disappear -- it will be
> accessible via nested_exception-like magic (see below).
>
When I say "missed", I mean that the catch block for the exception that was
thrown will not be executed. It doesn't matter if some other catch block
will be able to find out about the error. What matters is that the
communication between E and C will not happen.
Even if you somehow transfer the information thrown by E to B, that doesn't
>> mean that B has the ability to do what C's catch statement could (and *needed
>> to*). After all, C's catch statement could access variables in C's
>> scope. Which were destroyed by stack unwinding.
>>
>> No, this is a nonsensical situation.
>>
>
> If end user does not create non-sensical situations -- he won't have to
> deal with them.
>
Yes, you do. Because you cannot control the exception behavior of other
people's code.
Right now, the standard actively forbids exception clashing. If it happens,
the application dies. And therefore, nobody has to write `catch` statements
that expect such things.
If you allow exception clashing, then some middle-ware library can write
code that causes it. Which means that every `catch` statement has to deal
with this possibility. See the above circumstances for the fallout.
If C's catch clause is written in such way that it doesn't catch exception
> in certain cases -- maybe he shouldn't write it this way?
>
I get the distinct impression that you like to write a lot of `catch(...)`
in your code. Or at the very least, that you want us to do so.
How about providing more sensible default behavior (and maybe some knobs
>>> for user to tune this process a bit)?
>>>
>> Proposed "more sensible" behavior would be this:
>>> - new exception replaces old one
>>>
>>
>> How is that sensible? I explained above how this fails.
>>
>
> No, it doesn't fail. Or better to say it fails successfully :-)
>
>
> - new exception gets wrapped into (equivalent-of/modified-version-of)
>> std::nested_exception
>>
>> How is that sensible? Is the user expecting to catch a
>> `std::nested_exception`? Would the user even know what to do in that case?
>> As in the above case, the location of B doesn't have access to what C's
>> catch clause does.
>>
>
> In more or less the same way you are supposed to deal with
> nested_exception now.
>
Except... we don't really deal with `nested_exception` now. Or rather,
you're not required to do so. That's a choice that the user makes. You want
to turn that into a choice the standard forces upon you. That's not good.
First time MyException meets with another exception, it gets replaced with
> smth like this:
>
> class : public std::nested_exception, public MyException
> {
> };
>
So what happens if you throw an `int`?
where instead of single exception_ptr, nested_exception will have a
> collection(e.g. vector/deque). Each time this exception (during unwinding)
> replaces another exception -- replaced exception gets added to this list.
>
> Access to this collection can be organised in a similar (that is very
> awkward) way you can access std::nested_exception innards (rethrow
> _if_nested/etc).
>
Which of course only magnifies the problem.
Consider my `A->B->C->D->E` example above. Let's say that we are writing
`B`, which is expecting to catch something that could be emitted by `D`.
That means `B` is written like this:
catch(D_exception &e)
{
...
}
OK, so... how does this code know that there's a `nested_exception` stuck
to `e`? `D_exception` isn't necessarily a virtual type. So you can't use
`dynamic_cast` to get it.
And even if you manage to answer that question, you're still left with one
very important fact: you can't investigate what that exception was. You can
only rethrow it or get an `exception_ptr` to it. How do you find out that
it's really `E_exception`? Do you have to do a throw/catch in the middle of
your existing `catch` clause?
Again, it is just one way of doing it -- another way would be instead of
> replacing earlier exception -- to transform it in a similar manner and add
> contender to it's list. Or provide a user-controlled mechanism that will
> decide what to do with some sensible default. This may not be very easy to
> come up with a mechanism like that.
>
The only sensible default is `std::terminate`.
- ... which instead of one std::exception_ptr holds many (our exception can
>>> replace multiple others during propagation)
>>>
>>
>> How is that even remotely sensible?
>>
>
> Here is a C-style code:
>
Error codes are not the same kind of error mechanism as exceptions. Error
codes *must* be handled directly by the caller; exceptions are handled
non-locally. Exceptions permit the execution of arbitrary code between the
sending and receiving of the error; error codes do not.
So this analogy does not work.
> error_t foo()
> {
> ...
> error_t res1 = do_smth1();
> error_t res2 = do_smth2();
> error_t res3 = do_smth3();
>
> // somehow combine results
> error_t res = ...;
> return res;
> }
>
> try writing similar logic using EH -- it will be very awkward, lots of
> code.
>
Please provide a practical example of that. Something from the real world,
where "somehow combine results" is something other than "swallow the
exception".
> Keep in mind that no matter what each of functions above need to be called
> no matter what.
>
>
Let's say that each one attempts to switch off a piece of very expensive
> machinery. You can't make it no-fail for physical reasons. And if something
> goes wrong you need to report error(s) upstairs for analysis and associated
> actions.
>
> with this proposal you can put these do_smthN() calls into destructors and
> automatically get "always gets invoked" guarantee along with some
> (hopefully sensible) mechanism that is going to combine these errors for
> propagation up-stack. If user doesn't like default mechanism -- he'll use
> aforementioned knobs to tune it to his liking.
>
> Right now you have to make these dtors silent and accumulate these errors
> elsewhere -- basically turning EH into some weird mix of both styles.
>
.... OK, I'll play along. You want people to write this:
try
{
something_doer_3 t3{};
something_doer_2 t2{};
something_doer_1 t1{};
}
catch(something)
{
//Combine the errors
}
Where the destructors of those three types are what does the work.
Even ignoring the exception clash issue, that is *objectively terrible code*.
You have to express the order of operations *backwards* in order to make
that work. So even if you got what you wanted, nobody would ever write
this. And if they do, nobody else would want to read/maintain it.
The fact that your proposal would in any way *encourage* this style of
coding is a strike against it.
Also, what does `Combine the errors` look like?
Do you think this idea has any chance to see the light?
>>>
>>
>> God, I hope not.
>>
>
> I got it -- you don't like it. I've seen cases where it makes sense. If
> you slow down a bit and open your mind -- you may see my point. And once
> you do -- we could discuss what would be the good "sensible default".
>
Why do people always assume that, when you disagree with them, that you
don't understand what they're saying. I understand what you're talking
about. That doesn't make it a good idea, for all of the reasons I've listed.
And you've provided no "cases where it makes sense". You have provided only
general "if I wanted to do X" hypotheticals, not actual cases of genuine
error handling.
The foundation of your proposal is an analogy (exceptions should be like
error codes) that is ultimately not correct. There are plenty of cases
where error codes are the right way to work, even disregarding performance
issues.
--
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/cbc96b7a-1d1f-412f-8e75-321d03251795%40isocpp.org.
------=_Part_7047_1523654969.1503942992148
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Monday, August 28, 2017 at 12:06:30 PM UTC-4, crusad...=
@gmail.com wrote:<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>Before reading stuff below I suggest to set aside any dogmatic bli=
nders you may have, namely:</div><div>- realize that there is nothing parti=
cular special about destructors -- they are just functions that runtime cal=
ls automatically in specific circumstances and yes, they may want to report=
an error</div></div></blockquote><div><br>Untrue. Destructors provoke the =
ending of the lifetime of an object. That makes them special. Much like how=
constructors signal the beginning of the lifetime of an object.<br><br></d=
iv><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>- you=
can't really tell what makes sense or not -- only end user makes this =
decision</div></div></blockquote><div><br>The C++ object model is all about=
defining what "makes sense". That's why you can't just p=
retend that an object exists in some memory.<br><br>So the standard has eve=
ry right to decide that circumstance X doesn't make sense, so we're=
not going to support it.<br><br></div><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-lef=
t: 1ex;"><div dir=3D"ltr"><div>- what is proposed -- is just a tool, whethe=
r to use it or not, is up to end user</div></div></blockquote><div><br>The =
model that the proposal creates still has to make sense. Which it does not.=
Giving people tools that are incoherent and encourage bad coding is not he=
lpful.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div></div>On Sunday, August 27, 2017 at 9:19:57 PM UTC-5, Nicol B=
olas 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">On Sund=
ay, August 27, 2017 at 9:35:21 PM UTC-4, <a>crusad...@gmail.com</a> wrote:<=
/div></blockquote><div></div><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div d=
ir=3D"ltr"><div>No, a throwing destructor is a terrible, horrible, no-good,=
very-bad idea. Implicitly forbidding it is a good thing, and C++ has absol=
utely no need to support exception clashing (which can only happen through =
a throwing destructor).<br><br></div><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex=
"><div dir=3D"ltr"><div></div><div>Here are my thoughts:</div><div>- both C=
-style error handling and C++ exceptions do effectively the same thing -- c=
onstruct error object and pass it up the call stack, differences are:</div>=
<div><blockquote style=3D"margin:0 0 0 40px;border:none;padding:0px"><div>-=
C: error type is known to caller and caller is responsible for allocating =
memory for error object</div></blockquote></div><blockquote style=3D"margin=
:0 0 0 40px;border:none;padding:0px"><div><div>- C: caller is responsible f=
or proper propagation of error=C2=A0</div></div></blockquote><blockquote st=
yle=3D"margin:0 0 0 40px;border:none;padding:0px"><div><div>- EH: caller on=
ly knows whether some error can bubble up (ignoring exception specs here, s=
ince they are deprecated)</div></div></blockquote><blockquote style=3D"marg=
in:0 0 0 40px;border:none;padding:0px"><div>- EH: there is a mechanism that=
automates error propagation (and matching to related catch clause)</div></=
blockquote></div></blockquote><div><br>- EH: Arbitrary code can execute bet=
ween the generation of the error code and its reception. That code itself c=
an fail.<br></div></div></blockquote><div><br></div><div>no, same thing can=
happen with C-style error handling. It looks rather obvious to me</div></d=
iv></blockquote><div><br>Your analogy says that `return` and the use of the=
return value are similar to `throw` and `catch` for that exception. Given =
that analogy, no, the same thing cannot happen in C-style error handling. T=
he function that receives the error is the one that called the function. Be=
tween the end of the initialization of the return value from the function c=
reating the error code, to the beginning of the initialization of the value=
that the receiving function is creating, no user code can be executed.<br>=
<br>Oh, there can be code between the generator of the error and where the =
error is <i>resolved</i>: that is, where you stop dealing with the error co=
ndition and progress normally. You can return the error code up the stack, =
do conditional logic based on it, and all kinds of stuff.<br><br>But there =
is a lot more that can happen between a `throw` and a `catch` that cannot h=
appen between a `return` and the use of that returned value.<br><br></div><=
blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bord=
er-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><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>That's the d=
ifference. Failing to fail is not a possibility in C. It is a possibility i=
n exception handing. Failing to fail is not a rational situation; it repres=
ents incoherent programming logic and is therefore unrecoverable.<br></div>=
</div></blockquote><div><br></div><div>There are only two possibilities of =
'failing to fail' in EH -- first one I addressed in another proposa=
l (failure to allocate memory) and another one is addressed with this propo=
sal (providing ability to handle multiple errors).</div><div><br></div><div=
>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-lef=
t:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><bloc=
kquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-lef=
t:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>=C2=A0- so, if you=
are "cleaning up" after receiving C-style error --nothing preven=
ts you from handling second error produced by "cleanup" call (sin=
ce propagation is handled by developer anyway). You may choose to replace o=
lder error with new one, chain them together, etc</div></div></blockquote><=
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>- with EH lang=
uage-provided mechanism has no idea what to do with second error object, so=
decision was made to call terminate execution since user allowed error to =
escape. The idea is that user needs to somehow handle second error before i=
t "meets" first one. Unfortunately this seriously limits what you=
can do -- for example you can't replace old exception with new one (an=
d continue propagation).<br></div></div></blockquote><div><br>... why would=
you want to?<br><br>Think about this for a second. Your call stack looks l=
ike this:<br><br><div style=3D"background-color:rgb(250,250,250);border-col=
or:rgb(187,187,187);border-style:solid;border-width:1px"><code><div><span s=
tyle=3D"color:#000">A</span><span style=3D"color:#660">-></span><span st=
yle=3D"color:#000">B</span><span style=3D"color:#660">-></span><span sty=
le=3D"color:#000">C</span><span style=3D"color:#660">-></span><span styl=
e=3D"color:#000">D</span><span style=3D"color:#660">-></span><span style=
=3D"color:#000">E</span></div></code></div><br>Now, E emits an exception. O=
ne that is caught by C. That catch provokes stack unwinding down to C.<br><=
br>D's unwinding throws an exception. One that is caught by B. That cat=
ch provokes stack unwinding down to... where?<br></div></div></blockquote><=
div><br></div><div>exception emitted by E will be replaced by exception emi=
tted by D during unwinding (when exception will "meet") and unwin=
ding will continue. C may or may not catch it (depending on catch clause).<=
br></div></div></blockquote><div><br>OK, so let's say that C knows that=
D can throw something.<br><br>That means C has to look like this:<br><br><=
div style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 1=
87, 187); border-style: solid; border-width: 1px; overflow-wrap: break-word=
;" class=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"subprett=
yprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">catch</sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify">E_exception </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">&</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify">e</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify"><br>=C2=A0 </span><span style=3D"color: #800;" class=3D"sty=
led-by-prettify">//Do stuff for E_exception</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">catch</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">D_=
exception </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
&</span><span style=3D"color: #000;" class=3D"styled-by-prettify">e</sp=
an><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><span style=3D"color=
: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"colo=
r: #800;" class=3D"styled-by-prettify">//Do stuff for D_exception</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">throw</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></span><span style=3D"color: =
#660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" cl=
ass=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=3D=
"styled-by-prettify">catch</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify">E_exception_combined_with_D_exception </span><span style=3D"color: #=
660;" 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=
"styled-by-prettify">)</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br=
></span><code class=3D"prettyprint"><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">=C2=A0 </span><span style=3D"color: #800;" class=3D"styl=
ed-by-prettify">//Do stuff for E_exception</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"></span></code><code class=3D"prettyprint"><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">=C2=A0 </span><span styl=
e=3D"color: #800;" class=3D"styled-by-prettify">//Do stuff for D_exception<=
/span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"></span></code><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify">=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><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span></div></code></div><br>That's a lot =
of repetition.<br><br>It doesn't really matter what `E_exception_combin=
ed_with_D_exception` is. Whether it's a nested exception that you do so=
me casting tricks on to detect what it is nested with or whatever. What mat=
ters is that you have to repeat `Do stuff for E_exception` at least once, j=
ust to make sure that you really catch all `E_exception`s that pass by.<br>=
<br>The whole point of writing `catch(E_exception &e)` is that it <i>ca=
tches `E_exception`s!</i> If an `E_exception` can pass by such a catch stat=
ement, then the whole `catch` system is nonsensical. You may as well be cat=
ching `exception_ptr` directly and working out what the actual type is thro=
ugh casting tricks (that don't actually exist).<br><br></div><blockquot=
e class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1p=
x solid rgb(204, 204, 204); padding-left: 1ex;"><div></div></blockquote><bl=
ockquote 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></div><div>=
</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"><div>You'=
;ve got two choices: it can either go to C as it already was, or it can go =
to B.<br><br>If it goes to B, that means that the catch block at C will nev=
er be executed. But it was <i>supposed</i> to be executed; C and E were bot=
h written with that as a requirement.<br><br>You can go to C. In which case=
.... what happens to the exception thrown by D?</div></div></blockquote><div=
><br></div><div>see above</div><div><br></div><div>=C2=A0</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"><div> Because after C's ca=
tch block executes, the program continues on to the next statement. C's=
catch block is written with that as an expectation. So you can't just =
have the exception from D force further stack unwinding after C's catch=
..<br></div></div></blockquote><div><br></div><div>No, see above</div><div>=
=C2=A0</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margi=
n:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><div>An exception is going to be missed.</div></div></blockquote><=
div><br></div><div>No, exception thrown by E is not going to disappear -- i=
t will be accessible via nested_exception-like magic (see below).</div></di=
v></blockquote><div><br>When I say "missed", I mean that the catc=
h block for the exception that was thrown will not be executed. It doesn=
9;t matter if some other catch block will be able to find out about the err=
or. What matters is that the communication between E and C will not happen.=
<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"=
><div></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"><div> =
Even if you somehow transfer the information thrown by E to B, that doesn&#=
39;t mean that B has the ability to do what C's catch statement could (=
and <i>needed to</i>). After all, C's catch statement could access vari=
ables in C's scope. Which were destroyed by stack unwinding.<br><br>No,=
this is a nonsensical situation.<br></div></div></blockquote><div><br></di=
v><div>If end user does not create non-sensical situations -- he won't =
have to deal with them.</div></div></blockquote><div><br>Yes, you do. Becau=
se you cannot control the exception behavior of other people's code.<br=
><br>Right now, the standard actively forbids exception clashing. If it hap=
pens, the application dies. And therefore, nobody has to write `catch` stat=
ements that expect such things.<br><br>If you allow exception clashing, the=
n some middle-ware library can write code that causes it. Which means that =
every `catch` statement has to deal with this possibility. See the above ci=
rcumstances for the fallout.<br><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"><div>If C's catch clause is written in suc=
h way that it doesn't catch exception in certain cases -- maybe he shou=
ldn't write it this way?</div></div></blockquote><div><br>I get the dis=
tinct impression that you like to write a lot of `catch(...)` in your code.=
Or at the very least, that you want us to do so.<br><br></div><blockquote =
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1p=
x #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #cc=
c solid;padding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote=
" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-le=
ft:1ex"><div dir=3D"ltr"><div>How about providing more sensible default beh=
avior (and maybe some knobs for user to tune this process a bit)?</div></di=
v></blockquote><div></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"><div></div><div>Proposed "more sensible" behavior would =
be this:</div><div>- new exception replaces old one</div></div></blockquote=
><div><br>How is that sensible? I explained above how this fails.<br></div>=
</div></blockquote><div><br></div><div>No, it doesn't fail. Or better t=
o say it fails successfully :-)</div><div>=C2=A0</div><div><br></div><block=
quote 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>=C2=A0- new excepti=
on gets wrapped into (equivalent-of/modified-<wbr>version-of) std::nested_e=
xception</div><div><br>How is that sensible? Is the user expecting to catch=
a `std::nested_exception`? Would the user even know what to do in that cas=
e? As in the above case, the location of B doesn't have access to what =
C's catch clause does.<br></div></div></blockquote><div><br></div><div>=
In more or less the same way you are supposed to deal with nested_exception=
now.</div></div></blockquote><div><br>Except... we don't really deal w=
ith `nested_exception` now. Or rather, you're not required to do so. Th=
at's a choice that the user makes. You want to turn that into a choice =
the standard forces upon you. That's not good.<br><br></div><blockquote=
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1=
px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>First time MyExcept=
ion meets with another exception, it gets replaced with smth like this:</di=
v><div><br></div><div>class : public std::nested_exception, public=C2=A0MyE=
xception</div><div>{</div><div>};<br></div></div></blockquote><div><br>So w=
hat happens if you throw an `int`?<br><br></div><blockquote class=3D"gmail_=
quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pa=
dding-left: 1ex;"><div dir=3D"ltr"><div></div><div></div><div>where instead=
of single exception_ptr, nested_exception will have a collection(e.g. vect=
or/deque). Each time this exception (during unwinding) replaces another exc=
eption -- replaced exception gets added to this list.</div><div><br></div><=
div>Access to this collection can be organised in a similar (that is very a=
wkward) way you can access std::nested_exception innards (rethrow _if_neste=
d/etc).</div></div></blockquote><div><br>Which of course only magnifies the=
problem.<br><br>Consider my `A->B->C->D->E` example above. Let=
's say that we are writing `B`, which is expecting to catch something t=
hat could be emitted by `D`. That means `B` is written like this:<br><br><d=
iv style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 18=
7, 187); border-style: solid; border-width: 1px; overflow-wrap: break-word;=
" class=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"subpretty=
print"><span style=3D"color: #008;" class=3D"styled-by-prettify">catch</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">D_exception </span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">&</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify">e</span><span style=3D"colo=
r: #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><span style=3D"color: #000;" class=3D"style=
d-by-prettify"><br>=C2=A0 </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">...</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">}</span></div></code></div><br>OK, so... how does this code know that th=
ere's a `nested_exception` stuck to `e`? `D_exception` isn't necess=
arily a virtual type. So you can't use `dynamic_cast` to get it.<br><br=
>And even if you manage to answer that question, you're still left with=
one very important fact: you can't investigate what that exception was=
.. You can only rethrow it or get an `exception_ptr` to it. How do you find =
out that it's really `E_exception`? Do you have to do a throw/catch in =
the middle of your existing `catch` clause?<br><br></div><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></div><div>Again, it is j=
ust one way of doing it -- another way would be instead of replacing earlie=
r exception -- to transform it in a similar manner and add contender to it&=
#39;s list. Or provide a user-controlled mechanism that will decide what to=
do with some sensible default. This may not be very easy to come up with a=
mechanism like that.</div></div></blockquote><div><br>The only sensible de=
fault is `std::terminate`.<br><br></div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-le=
ft: 1ex;"><div dir=3D"ltr"><div></div><blockquote class=3D"gmail_quote" sty=
le=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1e=
x"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0;mar=
gin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr=
"><div>- ... which instead of one std::exception_ptr holds many (our except=
ion can replace multiple others during propagation)</div></div></blockquote=
><div><br>How is that even remotely sensible?<br></div></div></blockquote><=
div><br></div><div>Here is a C-style code:</div></div></blockquote><div><br=
>Error codes are not the same kind of error mechanism as exceptions. Error =
codes <i>must</i> be handled directly by the caller; exceptions are handled=
non-locally. Exceptions permit the execution of arbitrary code between the=
sending and receiving of the error; error codes do not.<br><br>So this ana=
logy does not work.<br>=C2=A0<br></div><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-lef=
t: 1ex;"><div dir=3D"ltr"><div></div><div>error_t foo()</div><div>{</div><d=
iv>=C2=A0 =C2=A0 ...</div><div>=C2=A0 =C2=A0 error_t res1 =3D do_smth1();</=
div><div>=C2=A0 =C2=A0 error_t res2 =3D do_smth2();</div><div>=C2=A0 =C2=A0=
error_t res3 =3D do_smth3();</div><div><br></div><div>=C2=A0 =C2=A0 // som=
ehow combine results</div><div>=C2=A0 =C2=A0 error_t res =3D ...;</div><div=
>=C2=A0 =C2=A0 return res;</div><div>}</div><div><br></div><div>try writing=
similar logic using EH -- it will be very awkward, lots of code.</div></di=
v></blockquote><div><br>Please provide a practical example of that. Somethi=
ng from the real world, where "somehow combine results" is someth=
ing other than "swallow the exception".<br>=C2=A0</div><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>Keep in mind that =
no matter what each of functions above need to be called no matter what.</d=
iv></div></blockquote><blockquote class=3D"gmail_quote" style=3D"margin: 0p=
x 0px 0px 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1=
ex;"><div>=C2=A0</div></blockquote><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>Let's say that each one attempts to switch =
off a piece of very expensive machinery. You can't make it no-fail for =
physical reasons. And if something goes wrong you need to report error(s) u=
pstairs for analysis and associated actions.</div><div><br></div><div>with =
this proposal you can put these do_smthN() calls into destructors and autom=
atically get "always gets invoked" guarantee along with some (hop=
efully sensible) mechanism that is going to combine these errors for propag=
ation up-stack. If user doesn't like default mechanism -- he'll use=
aforementioned knobs to tune it to his liking.</div><div><br></div><div>Ri=
ght now you have to make these dtors silent and accumulate these errors els=
ewhere -- basically turning EH into some weird mix of both styles.</div></d=
iv></blockquote><div><br>... OK, I'll play along. You want people to wr=
ite this:<br><br><div style=3D"background-color: rgb(250, 250, 250); border=
-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; overflo=
w-wrap: break-word;" class=3D"prettyprint"><code class=3D"prettyprint"><div=
class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-p=
rettify">try</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</s=
pan><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 so=
mething_doer_3 t3</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">{};</span><span style=3D"color: #000;" class=3D"styled-by-prettify">=
<br>=C2=A0 something_doer_2 t2</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 something_doer_1 t1</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">{};</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br></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: #008;" class=3D"styled-by-prett=
ify">catch</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">something=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 //Combine the errors<br=
></span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><=
span style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div><=
/code></div><br>Where the destructors of those three types are what does th=
e work.<br><br>Even
ignoring the exception clash issue, that is <i>objectively terrible code</=
i>. You have to express the order of operations <i>backwards</i> in order t=
o make that work. So even if=20
you got what you wanted, nobody would ever write this. And if they do,=20
nobody else would want to read/maintain it.<br><br>The fact that your propo=
sal would in any way <i>encourage</i> this style of coding is a strike agai=
nst it.<br><br>Also, what does `Combine the errors` look like?<br><br></div=
><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><=
div></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"><div></d=
iv><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bo=
rder-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>Do you thi=
nk this idea has any chance to see the light?</div></div></blockquote><div>=
<br>God, I hope not. <br></div></div></blockquote><div><br></div><div>I got=
it -- you don't like it. I've seen cases where it makes sense. If =
you slow down a bit and open your mind -- you may see my point. And once yo=
u do -- we could discuss what would be the good "sensible default"=
;.</div></div></blockquote><div><br>Why do people always assume that, when =
you disagree with them, that you don't understand what they're sayi=
ng. I understand what you're talking about. That doesn't make it a =
good idea, for all of the reasons I've listed.<br><br>And you've pr=
ovided no "cases where it makes sense". You have provided only ge=
neral "if I wanted to do X" hypotheticals, not actual cases of ge=
nuine error handling.<br><br>The foundation of your proposal is an analogy =
(exceptions should be like error codes) that is ultimately not correct. The=
re are plenty of cases where error codes are the right way to work, even di=
sregarding performance issues.<br></div></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/cbc96b7a-1d1f-412f-8e75-321d03251795%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/cbc96b7a-1d1f-412f-8e75-321d03251795=
%40isocpp.org</a>.<br />
------=_Part_7047_1523654969.1503942992148--
------=_Part_7046_337812640.1503942992146--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 28 Aug 2017 11:13:38 -0700 (PDT)
Raw View
------=_Part_1123_1978285447.1503944018138
Content-Type: multipart/alternative;
boundary="----=_Part_1124_183180476.1503944018138"
------=_Part_1124_183180476.1503944018138
Content-Type: text/plain; charset="UTF-8"
On Monday, August 28, 2017 at 12:50:55 PM UTC-4, crusad...@gmail.com wrote:
>
> On Monday, August 28, 2017 at 11:42:54 AM UTC-5, Thiago Macieira wrote:
>>
>> On Monday, 28 August 2017 09:26:56 PDT crusad...@gmail.com wrote:
>
> > I can obviously use C-style approach -- but then my code will be
>> littered
>> > with "if"s (and nested "if"s) just like yours. Or I can rely on stack
>> > unwinding to guarantee that these functions get called -- in which case
>> > code becomes nice and neat, but (as of now)I can't report any failures
>> > without inventing some sort of 'under the hood' logic that circumvents
>> > "no-fail dtor" rule.
>>
>> I think you should litter your code. Relying on the stack unwinding to do
>> something it's not meant to and guess what you meant is not a good idea.
>>
>
> Pretty sure RAII was meant exactly for that -- to guarantee that certain
> functions (dtors) get called no matter what.
>
RAII exists *because* destructors are guaranteed to be called, not the
other way around. Destructors exist for the same reason as object
constructors. We can use the constructor/destructor paradigm plus scoping
to create RAII-style objects that use their lifetime to manage resources.
Lifetime was the design; constructors and destructors were a consequence of
that design. RAII was an outgrowth of those consequences. Not vice-versa.
"No-fault dtors" rule is simply because there is no easy (or right) way to
> propagate multiple exceptions (if these dtors throw).
>
That's the strongest argument, yes, but that doesn't mean throwing
destructors suddenly make sense.
None of the provided "but it doesn't make sense" arguments (you and Nicol
> provided) seem convincing.
>
That's only true if you look at it from the perspective of "there is
nothing particular special about destructors -- they are just functions
that runtime calls automatically in specific circumstances." If you look at
the language as an arbitrary collection of stuff that can be used, then a
failing destructor doesn't have any more meaning than a failing constructor.
But if you look at the language as a real construct that has logic behind
it, where the individual pieces exist to serve a purpose, the idea of
failing destructors is incoherent.
--
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/9f6f597b-3d71-4666-a0a0-a98211b167a2%40isocpp.org.
------=_Part_1124_183180476.1503944018138
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Monday, August 28, 2017 at 12:50:55 PM UTC-4, crusad...=
@gmail.com wrote:<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">On Monday, August 28, 2017 at 11:42:54 AM UTC-5, Thiago Macieira wrote:=
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;borde=
r-left:1px #ccc solid;padding-left:1ex">On Monday, 28 August 2017 09:26:56 =
PDT <a rel=3D"nofollow">crusad...@gmail.com</a> wrote:
</blockquote><div></div><blockquote class=3D"gmail_quote" style=3D"margin:0=
;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex">> I can =
obviously use C-style approach -- but then my code will be littered
<br>> with "if"s (and nested "if"s) just like yours.=
Or I can rely on stack
<br>> unwinding to guarantee that these functions get called -- in which=
case
<br>> code becomes nice and neat, but (as of now)I can't report any =
failures
<br>> without inventing some sort of 'under the hood' logic that=
circumvents
<br>> "no-fail dtor" rule.
<br>
<br>I think you should litter your code. Relying on the stack unwinding to =
do=20
<br>something it's not meant to and guess what you meant is not a good =
idea.
<br></blockquote><div><br></div><div>Pretty sure RAII was meant exactly for=
that -- to guarantee that certain functions (dtors) get called no matter w=
hat.</div></div></blockquote><div><br>RAII exists <i>because</i> destructor=
s are guaranteed to be called, not the other way around. Destructors exist =
for the same reason as object constructors. We can use the constructor/dest=
ructor paradigm plus scoping to create RAII-style objects that use their li=
fetime to manage resources.<br><br>Lifetime was the design; constructors an=
d destructors were a consequence of that design. RAII was an outgrowth of t=
hose consequences. Not vice-versa.<br><br></div><blockquote class=3D"gmail_=
quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pa=
dding-left: 1ex;"><div dir=3D"ltr"><div>"No-fault dtors" rule is =
simply because there is no easy (or right) way to propagate multiple except=
ions (if these dtors throw).</div></div></blockquote><div><br>That's th=
e strongest argument, yes, but that doesn't mean throwing destructors s=
uddenly make sense.<br><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"><div>None of the provided "but it doesn't make=
sense" arguments (you and Nicol provided) seem convincing.</div></div=
></blockquote><div><br>That's only true if you look at it from the pers=
pective of "there is nothing particular special about destructors -- t=
hey are just functions that runtime calls automatically in specific circums=
tances." If you look at the language as an arbitrary collection of stu=
ff that can be used, then a failing destructor doesn't have any more me=
aning than a failing constructor.<br><br>But if you look at the language as=
a real construct that has logic behind it, where the individual pieces exi=
st to serve a purpose, the idea of failing destructors is incoherent.<br></=
div></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/9f6f597b-3d71-4666-a0a0-a98211b167a2%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/9f6f597b-3d71-4666-a0a0-a98211b167a2=
%40isocpp.org</a>.<br />
------=_Part_1124_183180476.1503944018138--
------=_Part_1123_1978285447.1503944018138--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Mon, 28 Aug 2017 11:14:10 -0700
Raw View
On Monday, 28 August 2017 09:50:55 PDT crusader.mike@gmail.com wrote:
> > > I can obviously use C-style approach -- but then my code will be
> >
> > littered
> >
> > > with "if"s (and nested "if"s) just like yours. Or I can rely on stack
> > > unwinding to guarantee that these functions get called -- in which case
> > > code becomes nice and neat, but (as of now)I can't report any failures
> > > without inventing some sort of 'under the hood' logic that circumvents
> > > "no-fail dtor" rule.
> >
> > I think you should litter your code. Relying on the stack unwinding to do
> > something it's not meant to and guess what you meant is not a good idea.
>
> Pretty sure RAII was meant exactly for that -- to guarantee that certain
> functions (dtors) get called no matter what. "No-fault dtors" rule is
> simply because there is no easy (or right) way to propagate multiple
> exceptions (if these dtors throw). None of the provided "but it doesn't
> make sense" arguments (you and Nicol provided) seem convincing.
There's a difference between the unwinding and destruction and the act of
cleanup.
If the clean up can fail, then it's not something that should be done in the
destructor. Try it before, catch any errors, and fail accordingly. If you fail
to clean up in response to an earlier failure, handle it appropriately
according to your code.
Now, I don't care much for exceptions, so I really don't care how ugly that
code makes. You chose to use exceptions... live with them.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/2969816.PIxBPYMZKu%40tjmaciei-mobl1.
.
Author: crusader.mike@gmail.com
Date: Mon, 28 Aug 2017 12:09:43 -0700 (PDT)
Raw View
------=_Part_6302_53032660.1503947383311
Content-Type: multipart/alternative;
boundary="----=_Part_6303_1640490729.1503947383313"
------=_Part_6303_1640490729.1503947383313
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Monday, August 28, 2017 at 12:56:32 PM UTC-5, Nicol Bolas wrote:
>
> On Monday, August 28, 2017 at 12:06:30 PM UTC-4, crusad...@gmail.com=20
> wrote:
>>
>> Before reading stuff below I suggest to set aside any dogmatic blinders=
=20
>> you may have, namely:
>> - realize that there is nothing particular special about destructors --=
=20
>> they are just functions that runtime calls automatically in specific=20
>> circumstances and yes, they may want to report an error
>>
>
> Untrue. Destructors provoke the ending of the lifetime of an object. That=
=20
> makes them special. Much like how constructors signal the beginning of th=
e=20
> lifetime of an object.
>
It is a function. And it can throw exception as it is right now. It is=20
noexcept right by default, but nothing prevents me to declare it=20
noexcept(false) and it will work. The only case when it won't is when it=20
throws during unwinding. I believe it can be changed and it should be=20
changed to accomodate for a practical situation. And it won't affect=20
existing code at all.
=20
> - you can't really tell what makes sense or not -- only end user makes=20
>> this decision
>>
>
> The C++ object model is all about defining what "makes sense". That's why=
=20
> you can't just pretend that an object exists in some memory.
>
I never said that. Nothing prevents me from destroying object with error=20
right now and it will work just fine:
void foo()
{
struct X { ~X() { throw 1; } x;
}
object still gets destroyed just fine. What logical meaning I associated=20
with 'failed destructor' is my (end user) business. And it may make sense=
=20
to me.
=20
> So the standard has every right to decide that circumstance X doesn't mak=
e=20
> sense, so we're not going to support it.
>
> - what is proposed -- is just a tool, whether to use it or not, is up to=
=20
>> end user
>>
>
> The model that the proposal creates still has to make sense. Which it doe=
s=20
> not. Giving people tools that are incoherent and encourage bad coding is=
=20
> not helpful.
>
You claim "make no sense" very vigorously, but I've yet to see any good=20
argument for that.
=20
> On Sunday, August 27, 2017 at 9:19:57 PM UTC-5, Nicol Bolas wrote:
>>>
>>> On Sunday, August 27, 2017 at 9:35:21 PM UTC-4, crusad...@gmail.com=20
>>> wrote:
>>>
>> No, a throwing destructor is a terrible, horrible, no-good, very-bad=20
>>> idea. Implicitly forbidding it is a good thing, and C++ has absolutely =
no=20
>>> need to support exception clashing (which can only happen through a=20
>>> throwing destructor).
>>>
>>> Here are my thoughts:
>>>> - both C-style error handling and C++ exceptions do effectively the=20
>>>> same thing -- construct error object and pass it up the call stack,=20
>>>> differences are:
>>>>
>>>> - C: error type is known to caller and caller is responsible for=20
>>>> allocating memory for error object
>>>>
>>>> - C: caller is responsible for proper propagation of error=20
>>>>
>>>> - EH: caller only knows whether some error can bubble up (ignoring=20
>>>> exception specs here, since they are deprecated)
>>>>
>>>> - EH: there is a mechanism that automates error propagation (and=20
>>>> matching to related catch clause)
>>>>
>>>>
>>> - EH: Arbitrary code can execute between the generation of the error=20
>>> code and its reception. That code itself can fail.
>>>
>>
>> no, same thing can happen with C-style error handling. It looks rather=
=20
>> obvious to me
>>
>
> Your analogy says that `return` and the use of the return value are=20
> similar to `throw` and `catch` for that exception. Given that analogy, no=
,=20
> the same thing cannot happen in C-style error handling. The function that=
=20
> receives the error is the one that called the function. Between the end o=
f=20
> the initialization of the return value from the function creating the err=
or=20
> code, to the beginning of the initialization of the value that the=20
> receiving function is creating, no user code can be executed.
>
> Oh, there can be code between the generator of the error and where the=20
> error is *resolved*: that is, where you stop dealing with the error=20
> condition and progress normally. You can return the error code up the=20
> stack, do conditional logic based on it, and all kinds of stuff.
>
> But there is a lot more that can happen between a `throw` and a `catch`=
=20
> that cannot happen between a `return` and the use of that returned value.
>
Again, no. Two situations -- propagation of error to the point where it=20
gets handled through unwinding mechanism is fundamentally the same as=20
propagation of it via "if (auto err =3D foo()) return err". In both cases=
=20
anything could happen in-between.
=20
> - so, if you are "cleaning up" after receiving C-style error --nothing=
=20
>>>> prevents you from handling second error produced by "cleanup" call (si=
nce=20
>>>> propagation is handled by developer anyway). You may choose to replace=
=20
>>>> older error with new one, chain them together, etc
>>>>
>>> - with EH language-provided mechanism has no idea what to do with secon=
d=20
>>>> error object, so decision was made to call terminate execution since u=
ser=20
>>>> allowed error to escape. The idea is that user needs to somehow handle=
=20
>>>> second error before it "meets" first one. Unfortunately this seriously=
=20
>>>> limits what you can do -- for example you can't replace old exception =
with=20
>>>> new one (and continue propagation).
>>>>
>>>
>>> ... why would you want to?
>>>
>>> Think about this for a second. Your call stack looks like this:
>>>
>>> A->B->C->D->E
>>>
>>> Now, E emits an exception. One that is caught by C. That catch provokes=
=20
>>> stack unwinding down to C.
>>>
>>> D's unwinding throws an exception. One that is caught by B. That catch=
=20
>>> provokes stack unwinding down to... where?
>>>
>>
>> exception emitted by E will be replaced by exception emitted by D during=
=20
>> unwinding (when exception will "meet") and unwinding will continue. C ma=
y=20
>> or may not catch it (depending on catch clause).
>>
>
> OK, so let's say that C knows that D can throw something.
>
> That means C has to look like this:
>
Wrong. It does not **have** to. You (as end user) certainly can create=20
situation like that, but unless you like to shoot yourself in the foot --=
=20
you'll come up with better approach
=20
> catch(E_exception &e)
> {
> //Do stuff for E_exception
> }
> catch(D_exception &e)
> {
> //Do stuff for D_exception
> throw;
> }
> catch(E_exception_combined_with_D_exception &e)
> {
> //Do stuff for E_exception
> //Do stuff for D_exception
> throw;
> }
>
> That's a lot of repetition.
>
You literally built a gun, took it in your hands, aimed at your feet and=20
pressed the trigger. What prevents you from catching one base exception? In=
=20
most cases you wouldn't care if it replaced bunch of others -- operation=20
failed, here is a result from one of failed sub-operations. You may have=20
some additional information if you 'unroll' nested struct. Most of code is=
=20
unlikely to use throwing dtors and therefore they won't have to deal with=
=20
this.
Wrt "one_exception_combined_with_others" check -- I'd like to wrap=20
**every** exception into a structure like this, but this would be breaking=
=20
change and against the spirit of C++ "you don't pay until you use it". So=
=20
proposal is to apply wrapper on first instance of "replacing".
And again -- actual 'combination' logic is not set in stone. What I=20
proposed is just a first attempt.
=20
> It doesn't really matter what `E_exception_combined_with_D_exception` is.=
=20
> Whether it's a nested exception that you do some casting tricks on to=20
> detect what it is nested with or whatever. What matters is that you have =
to=20
> repeat `Do stuff for E_exception` at least once, just to make sure that y=
ou=20
> really catch all `E_exception`s that pass by.
>
If I choose so, yes. It is the same for both C-style and EH. If you don't=
=20
like it -- implement it differently.
=20
> The whole point of writing `catch(E_exception &e)` is that it *catches=20
> `E_exception`s!* If an `E_exception` can pass by such a catch statement,=
=20
> then the whole `catch` system is nonsensical. You may as well be catching=
=20
> `exception_ptr` directly and working out what the actual type is through=
=20
> casting tricks (that don't actually exist).
>
> You've got two choices: it can either go to C as it already was, or it ca=
n=20
>>> go to B.
>>>
>>> If it goes to B, that means that the catch block at C will never be=20
>>> executed. But it was *supposed* to be executed; C and E were both=20
>>> written with that as a requirement.
>>>
>>> You can go to C. In which case... what happens to the exception thrown=
=20
>>> by D?
>>>
>>
>> see above
>>
>> =20
>>
>>> Because after C's catch block executes, the program continues on to the=
=20
>>> next statement. C's catch block is written with that as an expectation.=
So=20
>>> you can't just have the exception from D force further stack unwinding=
=20
>>> after C's catch.
>>>
>>
>> No, see above
>> =20
>>
>> An exception is going to be missed.
>>>
>>
>> No, exception thrown by E is not going to disappear -- it will be=20
>> accessible via nested_exception-like magic (see below).
>>
>
> When I say "missed", I mean that the catch block for the exception that=
=20
> was thrown will not be executed. It doesn't matter if some other catch=20
> block will be able to find out about the error. What matters is that the=
=20
> communication between E and C will not happen.
>
Again, it depends on details 'combining' mechanism. Currently only one=20
exception can be generated. With this proposal -- both of them can happen=
=20
and that mechanism will have to decide which exception is 'leading'. Or=20
maybe both (doubt it is possible do it in general case, though).
=20
Even if you somehow transfer the information thrown by E to B, that doesn't=
=20
>>> mean that B has the ability to do what C's catch statement could (and *=
needed=20
>>> to*). After all, C's catch statement could access variables in C's=20
>>> scope. Which were destroyed by stack unwinding.
>>>
>>> No, this is a nonsensical situation.
>>>
>>
>> If end user does not create non-sensical situations -- he won't have to=
=20
>> deal with them.
>>
>
> Yes, you do. Because you cannot control the exception behavior of other=
=20
> people's code.
>
Neither can you control return values of other people's code -- it doesn't=
=20
prevent us from writing C programs.
=20
> Right now, the standard actively forbids exception clashing. If it=20
> happens, the application dies. And therefore, nobody has to write `catch`=
=20
> statements that expect such things.
>
> If you allow exception clashing, then some middle-ware library can write=
=20
> code that causes it. Which means that every `catch` statement has to deal=
=20
> with this possibility. See the above circumstances for the fallout.
>
No, you'll catch leading exception, that is it. You'll have access to=20
additional information, if you desire. Right now these middleware libs=20
don't have any other options -- they have to swallow other failures (just=
=20
like Thiago's code does). I don't think it is a good thing.
=20
> If C's catch clause is written in such way that it doesn't catch exceptio=
n=20
>> in certain cases -- maybe he shouldn't write it this way?
>>
>
> I get the distinct impression that you like to write a lot of `catch(...)=
`=20
> in your code. Or at the very least, that you want us to do so.
>
No, but you certainly can do it -- with this change or without. :-)
=20
> How about providing more sensible default behavior (and maybe some knobs=
=20
>>>> for user to tune this process a bit)?
>>>>
>>> Proposed "more sensible" behavior would be this:
>>>> - new exception replaces old one
>>>>
>>>
>>> How is that sensible? I explained above how this fails.
>>>
>>
>> No, it doesn't fail. Or better to say it fails successfully :-)
>> =20
>>
>> - new exception gets wrapped into (equivalent-of/modified-version-of)=
=20
>>> std::nested_exception
>>>
>>> How is that sensible? Is the user expecting to catch a=20
>>> `std::nested_exception`? Would the user even know what to do in that ca=
se?=20
>>> As in the above case, the location of B doesn't have access to what C's=
=20
>>> catch clause does.
>>>
>>
>> In more or less the same way you are supposed to deal with=20
>> nested_exception now.
>>
>
> Except... we don't really deal with `nested_exception` now. Or rather,=20
> you're not required to do so. That's a choice that the user makes. You wa=
nt=20
> to turn that into a choice the standard forces upon you. That's not good.
>
Same here: if you don't use throwing dtors -- you don't need to deal with=
=20
this. If 3rd party lib uses it -- you still not required to deal with it.
=20
> First time MyException meets with another exception, it gets replaced wit=
h=20
>> smth like this:
>>
>> class : public std::nested_exception, public MyException
>> {
>> };
>>
>
> So what happens if you throw an `int`?
>
Good question -- I guess the same as in case of std::throw_with_nested(-1).=
=20
But it is open for debate.
=20
> where instead of single exception_ptr, nested_exception will have a=20
>> collection(e.g. vector/deque). Each time this exception (during unwindin=
g)=20
>> replaces another exception -- replaced exception gets added to this list=
..
>>
>> Access to this collection can be organised in a similar (that is very=20
>> awkward) way you can access std::nested_exception innards (rethrow=20
>> _if_nested/etc).
>>
>
> Which of course only magnifies the problem.
>
> Consider my `A->B->C->D->E` example above. Let's say that we are writing=
=20
> `B`, which is expecting to catch something that could be emitted by `D`.=
=20
> That means `B` is written like this:
>
> catch(D_exception &e)
> {
> ...
> }
>
> OK, so... how does this code know that there's a `nested_exception` stuck=
=20
> to `e`? `D_exception` isn't necessarily a virtual type. So you can't use=
=20
> `dynamic_cast` to get it.
>
> And even if you manage to answer that question, you're still left with on=
e=20
> very important fact: you can't investigate what that exception was. You c=
an=20
> only rethrow it or get an `exception_ptr` to it. How do you find out that=
=20
> it's really `E_exception`? Do you have to do a throw/catch in the middle =
of=20
> your existing `catch` clause?
>
The same problems currently exist wrt=20
std::nested_exception/throw_with_nested/etc -- and yet it is in standard.
=20
> Again, it is just one way of doing it -- another way would be instead of=
=20
>> replacing earlier exception -- to transform it in a similar manner and a=
dd=20
>> contender to it's list. Or provide a user-controlled mechanism that will=
=20
>> decide what to do with some sensible default. This may not be very easy =
to=20
>> come up with a mechanism like that.
>>
>
> The only sensible default is `std::terminate`.
>
Quote:
dog=C2=B7mat=C2=B7ic
inclined to lay down principles as incontrovertibly true.
;-)
=20
> - ... which instead of one std::exception_ptr holds many (our exception=
=20
>>>> can replace multiple others during propagation)
>>>>
>>>
>>> How is that even remotely sensible?
>>>
>>
>> Here is a C-style code:
>>
>
> Error codes are not the same kind of error mechanism as exceptions. Error=
=20
> codes *must* be handled directly by the caller;
>
No. I guess you can call "propagating it further" as "handling" it, but it=
=20
doesn't change much.
=20
> exceptions are handled non-locally. Exceptions permit the execution of=20
> arbitrary code between the sending and receiving of the error; error code=
s=20
> do not.
>
> So this analogy does not work.
> =20
>
>> error_t foo()
>> {
>> ...
>> error_t res1 =3D do_smth1();
>> error_t res2 =3D do_smth2();
>> error_t res3 =3D do_smth3();
>>
>> // somehow combine results
>> error_t res =3D ...;
>> return res;
>> }
>>
>> try writing similar logic using EH -- it will be very awkward, lots of=
=20
>> code.
>>
>
> Please provide a practical example of that. Something from the real world=
,=20
> where "somehow combine results" is something other than "swallow the=20
> exception".
>
error_t do_work()
{
start_device1();
// return if failed to start, return array of values (one code per=20
device)
start_device2();
// if failed: stop_device1, if device1 fails to stop -- set it's error=
=20
code too
start_device3();
// if failed: stop_device1, if device1 fails to stop -- set it's error=
=20
code too
// stop_device2, if device2 fails to stop -- set it's=20
error code too
// do work using these devices (don't forget to stop them if smth fails=
=20
during it)
...
// time to stop devices
code res1 =3D stop_device3();
code res2 =3D stop_device2();
code res3 =3D stop_device1();
// somehow combine results
return {res1, res2, res3};
}
In case if you wonder -- this is not made up situation. I've seen it.
=20
> =20
>
>> Keep in mind that no matter what each of functions above need to be=20
>> called no matter what.
>>
> =20
>>
> Let's say that each one attempts to switch off a piece of very expensive=
=20
>> machinery. You can't make it no-fail for physical reasons. And if someth=
ing=20
>> goes wrong you need to report error(s) upstairs for analysis and associa=
ted=20
>> actions.
>>
>> with this proposal you can put these do_smthN() calls into destructors=
=20
>> and automatically get "always gets invoked" guarantee along with some=20
>> (hopefully sensible) mechanism that is going to combine these errors for=
=20
>> propagation up-stack. If user doesn't like default mechanism -- he'll us=
e=20
>> aforementioned knobs to tune it to his liking.
>>
>> Right now you have to make these dtors silent and accumulate these error=
s=20
>> elsewhere -- basically turning EH into some weird mix of both styles.
>>
>
> ... OK, I'll play along. You want people to write this:
>
> try
> {
> something_doer_3 t3{};
> something_doer_2 t2{};
> something_doer_1 t1{};
> }
> catch(something)
> {
> //Combine the errors
> }
>
> Where the destructors of those three types are what does the work.
>
rewriting example from above using EH:
try
{
auto_start_stop device1{}; // starts device in ctor, stops in dtor=
=20
-- both ops can fail with exception
auto_start_stop device2{};
auto_start_stop device3{};
// do work using these devices (which can throw too)
}
catch(error_base const&)
{
// entire operation failed, if we want, we could check if this is a=20
combined exception and pull it apart)
}
=20
> Even ignoring the exception clash issue, that is *objectively terrible=20
> code*.=20
>
How so? Show me. Code looks *objectively* very clean. ;)
=20
> You have to express the order of operations *backwards* in order to make=
=20
> that work. So even if you got what you wanted, nobody would ever write=20
> this. And if they do, nobody else would want to read/maintain it.
>
The fact that your proposal would in any way *encourage* this style of=20
> coding is a strike against it.
>
It won't. I don't know where you got this idea from.
=20
> Also, what does `Combine the errors` look like?
>
I proposed one way. It is not ideal, but in my opinion -- better than=20
std::terminate(). Especially considering that it will never be used if all=
=20
your dtors are noexcept.
=20
> Do you think this idea has any chance to see the light?
>>>>
>>>
>>> God, I hope not.=20
>>>
>>
>> I got it -- you don't like it. I've seen cases where it makes sense. If=
=20
>> you slow down a bit and open your mind -- you may see my point. And once=
=20
>> you do -- we could discuss what would be the good "sensible default".
>>
>
> Why do people always assume that, when you disagree with them, that you=
=20
> don't understand what they're saying. I understand what you're talking=20
> about. That doesn't make it a good idea, for all of the reasons I've list=
ed.
>
> And you've provided no "cases where it makes sense". You have provided=20
> only general "if I wanted to do X" hypotheticals, not actual cases of=20
> genuine error handling.
>
See above.
=20
The foundation of your proposal is an analogy (exceptions should be like=20
> error codes) that is ultimately not correct.
>
You've yet to show it.
=20
> There are plenty of cases where error codes are the right way to work,=20
> even disregarding performance issues.
>
I have nothing against error codes. But I prefer boilerplate (propagation)=
=20
to be generated for me. So, between two I choose that tool that makes my=20
life easier.
You are correct about performance, though. It is unfortunate.
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/98d507ed-c5cb-4eab-969a-7cdc4109eb7d%40isocpp.or=
g.
------=_Part_6303_1640490729.1503947383313
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Monday, August 28, 2017 at 12:56:32 PM UTC-5, N=
icol Bolas wrote:<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">On Monday, August 28, 2017 at 12:06:30 PM UTC-4, <a>crusad...@gmail.com=
</a> 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>Be=
fore reading stuff below I suggest to set aside any dogmatic blinders you m=
ay have, namely:</div><div>- realize that there is nothing particular speci=
al about destructors -- they are just functions that runtime calls automati=
cally in specific circumstances and yes, they may want to report an error</=
div></div></blockquote><div><br>Untrue. Destructors provoke the ending of t=
he lifetime of an object. That makes them special. Much like how constructo=
rs signal the beginning of the lifetime of an object.<br></div></div></bloc=
kquote><div><br></div><div>It is a function. And it can throw exception as =
it is right now. It is noexcept right by default, but nothing prevents me t=
o declare it noexcept(false) and it will work. The only case when it won=
9;t is when it throws during unwinding. I believe it can be changed and it =
should be changed to accomodate for a practical situation. And it won't=
affect existing code at all.</div><div><br></div><div>=C2=A0</div><blockqu=
ote 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:0;margin-left:0.8ex;border-left:1px #ccc solid=
;padding-left:1ex"><div dir=3D"ltr"><div>- you can't really tell what m=
akes sense or not -- only end user makes this decision</div></div></blockqu=
ote><div><br>The C++ object model is all about defining what "makes se=
nse". That's why you can't just pretend that an object exists =
in some memory.<br></div></div></blockquote><div><br></div><div>I never sai=
d that. Nothing prevents me from destroying object with error right now and=
it will work just fine:</div><div>void foo()</div><div>{</div><div>=C2=A0 =
=C2=A0 struct X { ~X() { throw 1; } x;</div><div>}</div><div><br></div><div=
>object still gets destroyed just fine. What logical meaning I associated w=
ith 'failed destructor' is my (end user) business. And it may make =
sense to me.</div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmai=
l_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;=
padding-left: 1ex;"><div dir=3D"ltr"><div>So the standard has every right t=
o decide that circumstance X doesn't make sense, so we're not going=
to support it.<br><br></div><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div d=
ir=3D"ltr"><div>- what is proposed -- is just a tool, whether to use it or =
not, is up to end user</div></div></blockquote><div><br>The model that the =
proposal creates still has to make sense. Which it does not. Giving people =
tools that are incoherent and encourage bad coding is not helpful.<br></div=
></div></blockquote><div><br></div><div>You claim "make no sense"=
very vigorously, but I've yet to see any good argument for that.</div>=
<div><br></div><div>=C2=A0</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:0;marg=
in-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"=
>On Sunday, August 27, 2017 at 9:19:57 PM UTC-5, Nicol Bolas wrote:<blockqu=
ote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1=
px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On Sunday, August 27, 2017=
at 9:35:21 PM UTC-4, <a>crusad...@gmail.com</a> wrote:</div></blockquote><=
div></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"><div>No,=
a throwing destructor is a terrible, horrible, no-good, very-bad idea. Imp=
licitly forbidding it is a good thing, and C++ has absolutely no need to su=
pport exception clashing (which can only happen through a throwing destruct=
or).<br><br></div><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"ltr">=
<div></div><div>Here are my thoughts:</div><div>- both C-style error handli=
ng and C++ exceptions do effectively the same thing -- construct error obje=
ct and pass it up the call stack, differences are:</div><div><blockquote st=
yle=3D"margin:0 0 0 40px;border:none;padding:0px"><div>- C: error type is k=
nown to caller and caller is responsible for allocating memory for error ob=
ject</div></blockquote></div><blockquote style=3D"margin:0 0 0 40px;border:=
none;padding:0px"><div><div>- C: caller is responsible for proper propagati=
on of error=C2=A0</div></div></blockquote><blockquote style=3D"margin:0 0 0=
40px;border:none;padding:0px"><div><div>- EH: caller only knows whether so=
me error can bubble up (ignoring exception specs here, since they are depre=
cated)</div></div></blockquote><blockquote style=3D"margin:0 0 0 40px;borde=
r:none;padding:0px"><div>- EH: there is a mechanism that automates error pr=
opagation (and matching to related catch clause)</div></blockquote></div></=
blockquote><div><br>- EH: Arbitrary code can execute between the generation=
of the error code and its reception. That code itself can fail.<br></div><=
/div></blockquote><div><br></div><div>no, same thing can happen with C-styl=
e error handling. It looks rather obvious to me</div></div></blockquote><di=
v><br>Your analogy says that `return` and the use of the return value are s=
imilar to `throw` and `catch` for that exception. Given that analogy, no, t=
he same thing cannot happen in C-style error handling. The function that re=
ceives the error is the one that called the function. Between the end of th=
e initialization of the return value from the function creating the error c=
ode, to the beginning of the initialization of the value that the receiving=
function is creating, no user code can be executed.<br><br>Oh, there can b=
e code between the generator of the error and where the error is <i>resolve=
d</i>: that is, where you stop dealing with the error condition and progres=
s normally. You can return the error code up the stack, do conditional logi=
c based on it, and all kinds of stuff.<br><br>But there is a lot more that =
can happen between a `throw` and a `catch` that cannot happen between a `re=
turn` and the use of that returned value.<br></div></div></blockquote><div>=
<br></div><div>Again, no. Two situations -- propagation of error to the poi=
nt where it gets handled through unwinding mechanism is fundamentally the s=
ame as propagation of it via "if (auto err =3D foo()) return err"=
.. In both cases anything could happen in-between.</div><div><br></div><div>=
<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margi=
n: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><di=
v dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-le=
ft:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-le=
ft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"g=
mail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;=
padding-left:1ex"><div dir=3D"ltr"><div>=C2=A0- so, if you are "cleani=
ng up" after receiving C-style error --nothing prevents you from handl=
ing second error produced by "cleanup" call (since propagation is=
handled by developer anyway). You may choose to replace older error with n=
ew one, chain them together, etc</div></div></blockquote><blockquote class=
=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><div>- with EH language-provided me=
chanism has no idea what to do with second error object, so decision was ma=
de to call terminate execution since user allowed error to escape. The idea=
is that user needs to somehow handle second error before it "meets&qu=
ot; first one. Unfortunately this seriously limits what you can do -- for e=
xample you can't replace old exception with new one (and continue propa=
gation).<br></div></div></blockquote><div><br>... why would you want to?<br=
><br>Think about this for a second. Your call stack looks like this:<br><br=
><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,1=
87);border-style:solid;border-width:1px"><code><div><span style=3D"color:#0=
00">A</span><span style=3D"color:#660">-></span><span style=3D"color:#00=
0">B</span><span style=3D"color:#660">-></span><span style=3D"color:#000=
">C</span><span style=3D"color:#660">-></span><span style=3D"color:#000"=
>D</span><span style=3D"color:#660">-></span><span style=3D"color:#000">=
E</span></div></code></div><br>Now, E emits an exception. One that is caugh=
t by C. That catch provokes stack unwinding down to C.<br><br>D's unwin=
ding throws an exception. One that is caught by B. That catch provokes stac=
k unwinding down to... where?<br></div></div></blockquote><div><br></div><d=
iv>exception emitted by E will be replaced by exception emitted by D during=
unwinding (when exception will "meet") and unwinding will contin=
ue. C may or may not catch it (depending on catch clause).<br></div></div><=
/blockquote><div><br>OK, so let's say that C knows that D can throw som=
ething.<br><br>That means C has to look like this:<br></div></div></blockqu=
ote><div><br></div><div>Wrong. It does not **have** to. You (as end user) c=
ertainly can create situation like that, but unless you like to shoot yours=
elf in the foot -- you'll come up with better approach</div><div><br></=
div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div><div style=3D"background-color:rgb(250,250,250);border-color:=
rgb(187,187,187);border-style:solid;border-width:1px"><code><div><span styl=
e=3D"color:#008">catch</span><span style=3D"color:#660">(</span><span style=
=3D"color:#000">E_exception </span><span style=3D"color:#660">&</span><=
span style=3D"color:#000">e</span><span style=3D"color:#660">)</span><span =
style=3D"color:#000"><br></span><span style=3D"color:#660">{</span><span st=
yle=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#800">//Do stuff =
for E_exception</span><span style=3D"color:#000"><br></span><span style=3D"=
color:#660">}</span><span style=3D"color:#000"><br></span><span style=3D"co=
lor:#008">catch</span><span style=3D"color:#660">(</span><span style=3D"col=
or:#000">D_exception </span><span style=3D"color:#660">&</span><span st=
yle=3D"color:#000">e</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#800">//Do stuff for=
D_exception</span><span style=3D"color:#000"><br>=C2=A0 </span><span style=
=3D"color:#008">throw</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#660">}</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#008">catch</span><span sty=
le=3D"color:#660">(</span><span style=3D"color:#000">E_exception_combined_<=
wbr>with_D_exception </span><span style=3D"color:#660">&</span><span st=
yle=3D"color:#000">e</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"><br></span><code><span style=3D"color:#000">=C2=A0 </span><=
span style=3D"color:#800">//Do stuff for E_exception</span><span style=3D"c=
olor:#000"><br></span><span style=3D"color:#000"></span></code><code><span =
style=3D"color:#000">=C2=A0 </span><span style=3D"color:#800">//Do stuff fo=
r D_exception</span><span style=3D"color:#000"><br></span><span style=3D"co=
lor:#000"></span></code><span style=3D"color:#000">=C2=A0 </span><span styl=
e=3D"color:#008">throw</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#660">}</span><span style=
=3D"color:#000"><br></span></div></code></div><br>That's a lot of repet=
ition.<br></div></div></blockquote><div><br></div><div>You literally built =
a gun, took it in your hands, aimed at your feet and pressed the trigger. W=
hat prevents you from catching one base exception? In most cases you wouldn=
't care if it replaced bunch of others -- operation failed, here is a r=
esult from one of failed sub-operations. You may have some additional infor=
mation if you 'unroll' nested struct. Most of code is unlikely to u=
se throwing dtors and therefore they won't have to deal with this.</div=
><div><br></div><div>Wrt "one_exception_combined_with_others" che=
ck -- I'd like to wrap **every** exception into a structure like this, =
but this would be breaking change and against the spirit of C++ "you d=
on't pay until you use it". So proposal is to apply wrapper on fir=
st instance of "replacing".</div><div><br></div><div>And again --=
actual 'combination' logic is not set in stone. What I proposed is=
just a first attempt.</div><div><br></div><div>=C2=A0</div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #=
ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>It doesn't really m=
atter what `E_exception_combined_with_D_<wbr>exception` is. Whether it'=
s a nested exception that you do some casting tricks on to detect what it i=
s nested with or whatever. What matters is that you have to repeat `Do stuf=
f for E_exception` at least once, just to make sure that you really catch a=
ll `E_exception`s that pass by.<br></div></div></blockquote><div><br></div>=
<div>If I choose so, yes. It is the same for both C-style and EH. If you do=
n't like it -- implement it differently.</div><div><br></div><div>=C2=
=A0</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"><div=
>The whole point of writing `catch(E_exception &e)` is that it <i>catch=
es `E_exception`s!</i> If an `E_exception` can pass by such a catch stateme=
nt, then the whole `catch` system is nonsensical. You may as well be catchi=
ng `exception_ptr` directly and working out what the actual type is through=
casting tricks (that don't actually exist).<br><br></div><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px soli=
d rgb(204,204,204);padding-left:1ex"><div></div></blockquote><blockquote cl=
ass=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></div><div></div><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>You've got two choi=
ces: it can either go to C as it already was, or it can go to B.<br><br>If =
it goes to B, that means that the catch block at C will never be executed. =
But it was <i>supposed</i> to be executed; C and E were both written with t=
hat as a requirement.<br><br>You can go to C. In which case... what happens=
to the exception thrown by D?</div></div></blockquote><div><br></div><div>=
see above</div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_q=
uote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddin=
g-left:1ex"><div dir=3D"ltr"><div> Because after C's catch block execut=
es, the program continues on to the next statement. C's catch block is =
written with that as an expectation. So you can't just have the excepti=
on from D force further stack unwinding after C's catch.<br></div></div=
></blockquote><div><br></div><div>No, see above</div><div>=C2=A0</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"><div>An =
exception is going to be missed.</div></div></blockquote><div><br></div><di=
v>No, exception thrown by E is not going to disappear -- it will be accessi=
ble via nested_exception-like magic (see below).</div></div></blockquote><d=
iv><br>When I say "missed", I mean that the catch block for the e=
xception that was thrown will not be executed. It doesn't matter if som=
e other catch block will be able to find out about the error. What matters =
is that the communication between E and C will not happen.<br></div></div><=
/blockquote><div><br></div><div>Again, it depends on details 'combining=
' mechanism. Currently only one exception can be generated. With this p=
roposal -- both of them can happen and that mechanism will have to decide w=
hich exception is 'leading'. Or maybe both (doubt it is possible do=
it in general case, though).</div><div>=C2=A0</div><div><br></div><blockqu=
ote 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: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:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"=
><div dir=3D"ltr"><div>Even if you somehow transfer the information thrown =
by E to B, that doesn't mean that B has the ability to do what C's =
catch statement could (and <i>needed to</i>). After all, C's catch stat=
ement could access variables in C's scope. Which were destroyed by stac=
k unwinding.<br><br>No, this is a nonsensical situation.<br></div></div></b=
lockquote><div><br></div><div>If end user does not create non-sensical situ=
ations -- he won't have to deal with them.</div></div></blockquote><div=
><br>Yes, you do. Because you cannot control the exception behavior of othe=
r people's code.<br></div></div></blockquote><div><br></div><div>Neithe=
r can you control return values of other people's code -- it doesn'=
t prevent us from writing C programs.</div><div><br></div><div>=C2=A0</div>=
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>Right no=
w, the standard actively forbids exception clashing. If it happens, the app=
lication dies. And therefore, nobody has to write `catch` statements that e=
xpect such things.<br><br>If you allow exception clashing, then some middle=
-ware library can write code that causes it. Which means that every `catch`=
statement has to deal with this possibility. See the above circumstances f=
or the fallout.<br></div></div></blockquote><div><br></div><div>No, you'=
;ll catch leading exception, that is it. You'll have access to addition=
al information, if you desire. Right now these middleware libs don't ha=
ve any other options -- they have to swallow other failures (just like Thia=
go's code does). I don't think it is a good thing.</div><div><br></=
div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><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>If C=
's catch clause is written in such way that it doesn't catch except=
ion in certain cases -- maybe he shouldn't write it this way?</div></di=
v></blockquote><div><br>I get the distinct impression that you like to writ=
e a lot of `catch(...)` in your code. Or at the very least, that you want u=
s to do so.<br></div></div></blockquote><div><br></div><div>No, but you cer=
tainly can do it -- with this change or without. :-)</div><div><br></div><d=
iv>=C2=A0</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:0;margin-left:0.8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><blockquote clas=
s=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:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left=
:1ex"><div dir=3D"ltr"><div>How about providing more sensible default behav=
ior (and maybe some knobs for user to tune this process a bit)?</div></div>=
</blockquote><div></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"><div></div><div>Proposed "more sensible" behavior would be =
this:</div><div>- new exception replaces old one</div></div></blockquote><d=
iv><br>How is that sensible? I explained above how this fails.<br></div></d=
iv></blockquote><div><br></div><div>No, it doesn't fail. Or better to s=
ay it fails successfully :-)</div><div>=C2=A0</div><div><br></div><blockquo=
te class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>=C2=A0- new exception =
gets wrapped into (equivalent-of/modified-<wbr>version-of) std::nested_exce=
ption</div><div><br>How is that sensible? Is the user expecting to catch a =
`std::nested_exception`? Would the user even know what to do in that case? =
As in the above case, the location of B doesn't have access to what C&#=
39;s catch clause does.<br></div></div></blockquote><div><br></div><div>In =
more or less the same way you are supposed to deal with nested_exception no=
w.</div></div></blockquote><div><br>Except... we don't really deal with=
`nested_exception` now. Or rather, you're not required to do so. That&=
#39;s a choice that the user makes. You want to turn that into a choice the=
standard forces upon you. That's not good.<br></div></div></blockquote=
><div><br></div><div>Same here: if you don't use throwing dtors -- you =
don't need to deal with this. If 3rd party lib uses it -- you still not=
required to deal with it.</div><div><br></div><div>=C2=A0</div><blockquote=
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1=
px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><blockquote class=3D"gma=
il_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pa=
dding-left:1ex"><div dir=3D"ltr"><div>First time MyException meets with ano=
ther exception, it gets replaced with smth like this:</div><div><br></div><=
div>class : public std::nested_exception, public=C2=A0MyException</div><div=
>{</div><div>};<br></div></div></blockquote><div><br>So what happens if you=
throw an `int`?<br></div></div></blockquote><div><br></div><div>Good quest=
ion -- I guess the same as in case of=C2=A0std::throw_with_nested(-1). But =
it is open for debate.</div><div><br></div><div>=C2=A0</div><blockquote cla=
ss=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_q=
uote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddin=
g-left:1ex"><div dir=3D"ltr"><div>where instead of single exception_ptr, ne=
sted_exception will have a collection(e.g. vector/deque). Each time this ex=
ception (during unwinding) replaces another exception -- replaced exception=
gets added to this list.</div><div><br></div><div>Access to this collectio=
n can be organised in a similar (that is very awkward) way you can access s=
td::nested_exception innards (rethrow _if_nested/etc).</div></div></blockqu=
ote><div><br>Which of course only magnifies the problem.<br><br>Consider my=
`A->B->C->D->E` example above. Let's say that we are writi=
ng `B`, which is expecting to catch something that could be emitted by `D`.=
That means `B` is written like this:<br><br><div style=3D"background-color=
:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-w=
idth:1px"><code><div><span style=3D"color:#008">catch</span><span style=3D"=
color:#660">(</span><span style=3D"color:#000">D_exception </span><span sty=
le=3D"color:#660">&</span><span style=3D"color:#000">e</span><span styl=
e=3D"color:#660">)</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 </span><span =
style=3D"color:#660">...</span><span style=3D"color:#000"><br></span><span =
style=3D"color:#660">}</span></div></code></div><br>OK, so... how does this=
code know that there's a `nested_exception` stuck to `e`? `D_exception=
` isn't necessarily a virtual type. So you can't use `dynamic_cast`=
to get it.<br><br>And even if you manage to answer that question, you'=
re still left with one very important fact: you can't investigate what =
that exception was. You can only rethrow it or get an `exception_ptr` to it=
.. How do you find out that it's really `E_exception`? Do you have to do=
a throw/catch in the middle of your existing `catch` clause?<br></div></di=
v></blockquote><div><br></div><div>The same problems currently exist wrt st=
d::nested_exception/throw_with_nested/etc -- and yet it is in standard.</di=
v><div><br></div><div>=C2=A0</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:0;=
margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"=
ltr"><div>Again, it is just one way of doing it -- another way would be ins=
tead of replacing earlier exception -- to transform it in a similar manner =
and add contender to it's list. Or provide a user-controlled mechanism =
that will decide what to do with some sensible default. This may not be ver=
y easy to come up with a mechanism like that.</div></div></blockquote><div>=
<br>The only sensible default is `std::terminate`.<br></div></div></blockqu=
ote><br>Quote:<br><blockquote style=3D"margin: 0 0 0 40px; border: none; pa=
dding: 0px;">dog=C2=B7mat=C2=B7ic<br>inclined to lay down principles as inc=
ontrovertibly true.</blockquote><div>;-)</div><div><br></div><div>=C2=A0</d=
iv><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"><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"><blockquote class=3D"gmail_q=
uote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddin=
g-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"mar=
gin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div d=
ir=3D"ltr"><div>- ... which instead of one std::exception_ptr holds many (o=
ur exception can replace multiple others during propagation)</div></div></b=
lockquote><div><br>How is that even remotely sensible?<br></div></div></blo=
ckquote><div><br></div><div>Here is a C-style code:</div></div></blockquote=
><div><br>Error codes are not the same kind of error mechanism as exception=
s. Error codes <i>must</i> be handled directly by the caller;</div></div></=
blockquote><div><br></div><div>No. I guess you can call "propagating i=
t further" as "handling" it, but it doesn't change much.=
</div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" sty=
le=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left=
: 1ex;"><div dir=3D"ltr"><div> exceptions are handled non-locally. Exceptio=
ns permit the execution of arbitrary code between the sending and receiving=
of the error; error codes do not.<br><br>So this analogy does not work.<br=
>=C2=A0<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"><=
div></div><div>error_t foo()</div><div>{</div><div>=C2=A0 =C2=A0 ...</div><=
div>=C2=A0 =C2=A0 error_t res1 =3D do_smth1();</div><div>=C2=A0 =C2=A0 erro=
r_t res2 =3D do_smth2();</div><div>=C2=A0 =C2=A0 error_t res3 =3D do_smth3(=
);</div><div><br></div><div>=C2=A0 =C2=A0 // somehow combine results</div><=
div>=C2=A0 =C2=A0 error_t res =3D ...;</div><div>=C2=A0 =C2=A0 return res;<=
/div><div>}</div><div><br></div><div>try writing similar logic using EH -- =
it will be very awkward, lots of code.</div></div></blockquote><div><br>Ple=
ase provide a practical example of that. Something from the real world, whe=
re "somehow combine results" is something other than "swallo=
w the exception".<br></div></div></blockquote><div><br></div><div><div=
>error_t do_work()</div><div>{</div><div>=C2=A0 =C2=A0 start_device1();</di=
v><div>=C2=A0 =C2=A0 // return if failed to start, return array of values (=
one code per device)</div><div>=C2=A0 =C2=A0 start_device2();</div><div>=C2=
=A0 =C2=A0 // if failed: stop_device1, if device1 fails to stop -- set it&#=
39;s error code too</div><div>=C2=A0 =C2=A0 start_device3();</div><div>=C2=
=A0 =C2=A0 // if failed: stop_device1, if device1 fails to stop -- set it&#=
39;s error code too</div><div>=C2=A0 =C2=A0 // =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 stop_device2, if device2 fails to stop -- set it's=
error code too</div><div><br></div><div>=C2=A0 =C2=A0// do work using thes=
e devices (don't forget to stop them if smth fails during it)</div><div=
>=C2=A0 =C2=A0 ...</div><div><br></div><div>=C2=A0 =C2=A0 // time to stop d=
evices</div><div>=C2=A0 =C2=A0 code res1 =3D stop_device3();</div><div>=C2=
=A0 =C2=A0 code res2 =3D stop_device2();</div><div>=C2=A0 =C2=A0 code res3 =
=3D stop_device1();</div><div><br></div><div>=C2=A0 =C2=A0 // somehow combi=
ne results</div><div>=C2=A0 =C2=A0 return {res1, res2, res3};</div><div>}<b=
r></div></div><div><br></div><div>In case if you wonder -- this is not made=
up situation. I've seen it.</div><div><br></div><div>=C2=A0</div><bloc=
kquote 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>=C2=A0</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"><div>Keep in mind t=
hat no matter what each of functions above need to be called no matter what=
..</div></div></blockquote><blockquote class=3D"gmail_quote" style=3D"margin=
:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"=
><div>=C2=A0</div></blockquote><blockquote class=3D"gmail_quote" style=3D"m=
argin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div=
dir=3D"ltr"><div>Let's say that each one attempts to switch off a piec=
e of very expensive machinery. You can't make it no-fail for physical r=
easons. And if something goes wrong you need to report error(s) upstairs fo=
r analysis and associated actions.</div><div><br></div><div>with this propo=
sal you can put these do_smthN() calls into destructors and automatically g=
et "always gets invoked" guarantee along with some (hopefully sen=
sible) mechanism that is going to combine these errors for propagation up-s=
tack. If user doesn't like default mechanism -- he'll use aforement=
ioned knobs to tune it to his liking.</div><div><br></div><div>Right now yo=
u have to make these dtors silent and accumulate these errors elsewhere -- =
basically turning EH into some weird mix of both styles.</div></div></block=
quote><div><br>... OK, I'll play along. You want people to write this:<=
br><br><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187=
,187,187);border-style:solid;border-width:1px"><code><div><span style=3D"co=
lor:#008">try</span><span style=3D"color:#000"><br></span><span style=3D"co=
lor:#660">{</span><span style=3D"color:#000"><br>=C2=A0 something_doer_3 t3=
</span><span style=3D"color:#660">{};</span><span style=3D"color:#000"><br>=
=C2=A0 something_doer_2 t2</span><span style=3D"color:#660">{};</span><span=
style=3D"color:#000"><br>=C2=A0 something_doer_1 t1</span><span style=3D"c=
olor:#660">{};</span><span style=3D"color:#000"><br></span><span style=3D"c=
olor:#660">}</span><span style=3D"color:#000"><br></span><span style=3D"col=
or:#008">catch</span><span style=3D"color:#660">(</span><span style=3D"colo=
r:#000">something</span><span style=3D"color:#660">)</span><span style=3D"c=
olor:#000"><br></span><span style=3D"color:#660">{</span><span style=3D"col=
or:#000"><br>=C2=A0 //Combine the errors<br></span><span style=3D"color:#66=
0">}</span><span style=3D"color:#000"><br></span></div></code></div><br>Whe=
re the destructors of those three types are what does the work.<br></div></=
div></blockquote><div><br></div><div>rewriting example from above using EH:=
</div><div>try</div><div>{</div><div>=C2=A0 =C2=A0 auto_start_stop device1{=
}; =C2=A0 =C2=A0// starts device in ctor, stops in dtor -- both ops can fai=
l with exception</div><div>=C2=A0 =C2=A0 auto_start_stop device2{};</div><d=
iv>=C2=A0 =C2=A0 auto_start_stop device3{};</div><div><br></div><div>=C2=A0=
=C2=A0 // do work using these devices (which can throw too)</div><div>}</d=
iv><div>catch(error_base const&)</div><div>{</div><div>=C2=A0 =C2=A0 //=
entire operation failed, if we want, we could check if this is a combined =
exception and pull it apart)</div><div>}</div><div><br></div><div>=C2=A0</d=
iv><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>Even
ignoring the exception clash issue, that is <i>objectively terrible code</=
i>. </div></div></blockquote><div><br></div><div>How so? Show me. Code look=
s <i>objectively</i> very clean. ;)</div><div><br></div><div>=C2=A0</div><b=
lockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;borde=
r-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>You have t=
o express the order of operations <i>backwards</i> in order to make that wo=
rk. So even if=20
you got what you wanted, nobody would ever write this. And if they do,=20
nobody else would want to read/maintain it.<br></div></div></blockquote><bl=
ockquote 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>The fact th=
at your proposal would in any way <i>encourage</i> this style of coding is =
a strike against it.<br></div></div></blockquote><div><br></div><div>It won=
't. I don't know where you got this idea from.</div><div><br></div>=
<div>=C2=A0</div><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>Also, what does `Combine the errors` look like?<br></div></div></b=
lockquote><div><br></div><div>I proposed one way. It is not ideal, but in m=
y opinion -- better than std::terminate(). Especially considering that it w=
ill never be used if all your dtors are noexcept.</div><div><br></div><div>=
=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><=
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:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:=
1ex"><div dir=3D"ltr"><div>Do you think this idea has any chance to see the=
light?</div></div></blockquote><div><br>God, I hope not. <br></div></div><=
/blockquote><div><br></div><div>I got it -- you don't like it. I've=
seen cases where it makes sense. If you slow down a bit and open your mind=
-- you may see my point. And once you do -- we could discuss what would be=
the good "sensible default".</div></div></blockquote><div><br>Wh=
y do people always assume that, when you disagree with them, that you don&#=
39;t understand what they're saying. I understand what you're talki=
ng about. That doesn't make it a good idea, for all of the reasons I=
9;ve listed.<br><br>And you've provided no "cases where it makes s=
ense". You have provided only general "if I wanted to do X" =
hypotheticals, not actual cases of genuine error handling.<br></div></div><=
/blockquote><div><br></div><div>See above.</div><div>=C2=A0</div><div><br><=
/div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>The=
foundation of your proposal is an analogy (exceptions should be like error=
codes) that is ultimately not correct.</div></div></blockquote><div><br></=
div><div>You've yet to show it.</div><div><br></div><div>=C2=A0</div><b=
lockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;borde=
r-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div> There are=
plenty of cases where error codes are the right way to work, even disregar=
ding performance issues.<br></div></div></blockquote><div><br></div><div>I =
have nothing against error codes. But I prefer boilerplate (propagation) to=
be generated for me. So, between two I choose that tool that makes my life=
easier.</div><div><br></div><div>You are correct about performance, though=
.. It is unfortunate.</div></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/98d507ed-c5cb-4eab-969a-7cdc4109eb7d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/98d507ed-c5cb-4eab-969a-7cdc4109eb7d=
%40isocpp.org</a>.<br />
------=_Part_6303_1640490729.1503947383313--
------=_Part_6302_53032660.1503947383311--
.
Author: crusader.mike@gmail.com
Date: Mon, 28 Aug 2017 12:25:35 -0700 (PDT)
Raw View
------=_Part_7149_2902628.1503948335051
Content-Type: multipart/alternative;
boundary="----=_Part_7150_1640825184.1503948335052"
------=_Part_7150_1640825184.1503948335052
Content-Type: text/plain; charset="UTF-8"
On Monday, August 28, 2017 at 1:14:17 PM UTC-5, Thiago Macieira wrote:
>
> On Monday, 28 August 2017 09:50:55 PDT crusad...@gmail.com <javascript:>
> wrote:
> > > > I can obviously use C-style approach -- but then my code will be
> > >
> > > littered
> > >
> > > > with "if"s (and nested "if"s) just like yours. Or I can rely on
> stack
> > > > unwinding to guarantee that these functions get called -- in which
> case
> > > > code becomes nice and neat, but (as of now)I can't report any
> failures
> > > > without inventing some sort of 'under the hood' logic that
> circumvents
> > > > "no-fail dtor" rule.
> > >
> > > I think you should litter your code. Relying on the stack unwinding to
> do
> > > something it's not meant to and guess what you meant is not a good
> idea.
> >
> > Pretty sure RAII was meant exactly for that -- to guarantee that certain
> > functions (dtors) get called no matter what. "No-fault dtors" rule is
> > simply because there is no easy (or right) way to propagate multiple
> > exceptions (if these dtors throw). None of the provided "but it doesn't
> > make sense" arguments (you and Nicol provided) seem convincing.
>
> There's a difference between the unwinding and destruction and the act of
> cleanup.
>
> If the clean up can fail, then it's not something that should be done in
> the
> destructor.
Why? This logic is the result of "dtor shouldn't fail" dogma. Which I am
kind of challenging right now. If my challenge succeeds -- this statement
has to legs to stand on.
> Try it before, catch any errors, and fail accordingly. If you fail
> to clean up in response to an earlier failure, handle it appropriately
> according to your code.
>
I proposed you to write code that has to perform three different cleanup
tasks. I had to do it multiple times in my life -- every time had to resort
to some equivalent of C-style error handling and it didn't make me happy.
Here is another consideration:
class File
{
file* f;
...
};
void foo()
{
File f = ...;
// write stuff
// gotta close it because it may fail and we can't report failure from
dtor
f.close();
// now File invariant has to support 'not open' state via additional
boolean member (or magical NULL value)
// and ~File() (and probably bunch of other member functions) have to
contain unnecessary branch that checks for that state
}
> Now, I don't care much for exceptions, so I really don't care how ugly
> that
> code makes. You chose to use exceptions... live with them.
>
"Your way of doing things is ugly but you shouldn't be fixing it, better
use ours" -- doesn't look like a very good argument to me. I floated this
with expectations that someone will show why that fix won't work. Not why
it is ideologically incorrect.
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
>
>
--
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/07064057-bfe9-47d8-b99e-ea2476a74455%40isocpp.org.
------=_Part_7150_1640825184.1503948335052
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Monday, August 28, 2017 at 1:14:17 PM UTC-5, Th=
iago Macieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Monday,=
28 August 2017 09:50:55 PDT <a href=3D"javascript:" target=3D"_blank" gdf-=
obfuscated-mailto=3D"eWbA1qmhDAAJ" rel=3D"nofollow" onmousedown=3D"this.hre=
f=3D'javascript:';return true;" onclick=3D"this.href=3D'javascr=
ipt:';return true;">crusad...@gmail.com</a> wrote:
<br>> > > I can obviously use C-style approach -- but then my code=
will be
<br>> >=20
<br>> > littered
<br>> >=20
<br>> > > with "if"s (and nested "if"s) just l=
ike yours. Or I can rely on stack
<br>> > > unwinding to guarantee that these functions get called -=
- in which case
<br>> > > code becomes nice and neat, but (as of now)I can't r=
eport any failures
<br>> > > without inventing some sort of 'under the hood' =
logic that circumvents
<br>> > > "no-fail dtor" rule.
<br>> >=20
<br>> > I think you should litter your code. Relying on the stack unw=
inding to do
<br>> > something it's not meant to and guess what you meant is n=
ot a good idea.
<br>>=20
<br>> Pretty sure RAII was meant exactly for that -- to guarantee that c=
ertain
<br>> functions (dtors) get called no matter what. "No-fault dtors&=
quot; rule is
<br>> simply because there is no easy (or right) way to propagate multip=
le
<br>> exceptions (if these dtors throw). None of the provided "but =
it doesn't
<br>> make sense" arguments (you and Nicol provided) seem convincin=
g.
<br>
<br>There's a difference between the unwinding and destruction and the =
act of=20
<br>cleanup.
<br>
<br>If the clean up can fail, then it's not something that should be do=
ne in the=20
<br>destructor.</blockquote><div><br></div><div>Why? This logic is the resu=
lt of "dtor shouldn't fail" dogma. Which I am kind of challen=
ging right now. If my challenge succeeds -- this statement has to legs to s=
tand on.</div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_qu=
ote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padd=
ing-left: 1ex;"> Try it before, catch any errors, and fail accordingly. If =
you fail=20
<br>to clean up in response to an earlier failure, handle it appropriately=
=20
<br>according to your code.
<br></blockquote><div><br></div><div>I proposed you to write code that has =
to perform three different cleanup tasks. I had to do it multiple times in =
my life -- every time had to resort to some equivalent of C-style error han=
dling and it didn't make me happy.</div><div><br></div><div>Here is ano=
ther consideration:</div><div><br></div><div>class File</div><div>{</div><d=
iv>=C2=A0 =C2=A0 file* f;</div><div>=C2=A0 =C2=A0 ...</div><div>};</div><di=
v><br></div><div>void foo()</div><div>{</div><div>=C2=A0 =C2=A0 File f =3D =
....;</div><div>=C2=A0 =C2=A0 // write stuff</div><div><br></div><div>=C2=A0=
=C2=A0 // gotta close it because it may fail and we can't report failu=
re from dtor</div><div>=C2=A0 =C2=A0 f.close();</div><div><br></div><div>=
=C2=A0 =C2=A0 // now File invariant has to support 'not open' state=
via additional boolean member (or magical NULL value)</div><div>=C2=A0 =C2=
=A0 // and ~File() (and probably bunch of other member functions) have to c=
ontain unnecessary branch that checks for that state</div><div>}</div><div>=
<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margi=
n: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">Now=
, I don't care much for exceptions, so I really don't care how ugly=
that=20
<br>code makes. You chose to use exceptions... live with them.
<br></blockquote><div><br></div><div>"Your way of doing things is ugly=
but you shouldn't be fixing it, better use ours" -- doesn't l=
ook like a very good argument to me. I floated this with expectations that =
someone will show why that fix won't work. Not why it is ideologically =
incorrect.</div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_=
quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pa=
dding-left: 1ex;">--=20
<br>Thiago Macieira - thiago (AT) <a href=3D"http://macieira.info" target=
=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.goo=
gle.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x3dD\x26sntz\x3d1\x26usg\=
x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.hr=
ef=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x=
3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return t=
rue;">macieira.info</a> - thiago (AT) <a href=3D"http://kde.org" target=3D"=
_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.google.=
com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNH=
GRJdo5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'=
http://www.google.com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1=
\x26usg\x3dAFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;">kde.org</a=
>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>
<br></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/07064057-bfe9-47d8-b99e-ea2476a74455%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/07064057-bfe9-47d8-b99e-ea2476a74455=
%40isocpp.org</a>.<br />
------=_Part_7150_1640825184.1503948335052--
------=_Part_7149_2902628.1503948335051--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Mon, 28 Aug 2017 12:29:54 -0700
Raw View
On Monday, 28 August 2017 12:09:43 PDT crusader.mike@gmail.com wrote:
> I never said that. Nothing prevents me from destroying object with error
> right now and it will work just fine:
> void foo()
> {
> struct X { ~X() { throw 1; } x;
> }
>
> object still gets destroyed just fine.
Says who?
struct Base
{
virtual ~Base();
};
struct X : public Base
{
~X() { throw 1; }
};
void foo()
{
X x;
}
It will throw during destruction. Did it get destroyed just fine?
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/4325148.e7ImLdxd7h%40tjmaciei-mobl1.
.
Author: crusader.mike@gmail.com
Date: Mon, 28 Aug 2017 12:35:22 -0700 (PDT)
Raw View
------=_Part_7090_1747885847.1503948922474
Content-Type: multipart/alternative;
boundary="----=_Part_7091_2075742191.1503948922474"
------=_Part_7091_2075742191.1503948922474
Content-Type: text/plain; charset="UTF-8"
On Monday, August 28, 2017 at 2:29:59 PM UTC-5, Thiago Macieira wrote:
>
> On Monday, 28 August 2017 12:09:43 PDT crusad...@gmail.com <javascript:>
> wrote:
> > I never said that. Nothing prevents me from destroying object with error
> > right now and it will work just fine:
> > void foo()
> > {
> > struct X { ~X() { throw 1; } x;
> > }
> >
> > object still gets destroyed just fine.
>
> Says who?
>
> struct Base
> {
> virtual ~Base();
> };
> struct X : public Base
> {
> ~X() { throw 1; }
> };
>
> void foo()
> {
> X x;
> }
>
> It will throw during destruction. Did it get destroyed just fine?
>
Yep <http://coliru.stacked-crooked.com/a/92e9e5ca672051a0>
>
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
>
>
--
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/d3ed73c5-aa23-491e-9fbb-83fd30ecce98%40isocpp.org.
------=_Part_7091_2075742191.1503948922474
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Monday, August 28, 2017 at 2:29:59 PM UTC-5, Th=
iago Macieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Monday,=
28 August 2017 12:09:43 PDT <a href=3D"javascript:" target=3D"_blank" gdf-=
obfuscated-mailto=3D"Jbx-UsulDAAJ" rel=3D"nofollow" onmousedown=3D"this.hre=
f=3D'javascript:';return true;" onclick=3D"this.href=3D'javascr=
ipt:';return true;">crusad...@gmail.com</a> wrote:
<br>> I never said that. Nothing prevents me from destroying object with=
error
<br>> right now and it will work just fine:
<br>> void foo()
<br>> {
<br>> =C2=A0 =C2=A0 struct X { ~X() { throw 1; } x;
<br>> }
<br>>=20
<br>> object still gets destroyed just fine.
<br>
<br>Says who?
<br>
<br>struct Base
<br>{
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0virtual ~Base();
<br>};
<br>struct X : public Base
<br>{
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0~X() { throw 1; }
<br>};
<br>
<br>void foo()
<br>{
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0X x;
<br>}
<br>
<br>It will throw during destruction. Did it get destroyed just fine?
<br></blockquote><div><br></div><div><a href=3D"http://coliru.stacked-crook=
ed.com/a/92e9e5ca672051a0">Yep</a></div><div><br></div><div><br></div><div>=
=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">
<br>--=20
<br>Thiago Macieira - thiago (AT) <a href=3D"http://macieira.info" target=
=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.goo=
gle.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x3dD\x26sntz\x3d1\x26usg\=
x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.hr=
ef=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x=
3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return t=
rue;">macieira.info</a> - thiago (AT) <a href=3D"http://kde.org" target=3D"=
_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.google.=
com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNH=
GRJdo5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'=
http://www.google.com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1=
\x26usg\x3dAFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;">kde.org</a=
>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>
<br></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/d3ed73c5-aa23-491e-9fbb-83fd30ecce98%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/d3ed73c5-aa23-491e-9fbb-83fd30ecce98=
%40isocpp.org</a>.<br />
------=_Part_7091_2075742191.1503948922474--
------=_Part_7090_1747885847.1503948922474--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Mon, 28 Aug 2017 12:40:24 -0700
Raw View
On Monday, 28 August 2017 12:35:22 PDT crusader.mike@gmail.com wrote:
> > It will throw during destruction. Did it get destroyed just fine?
>
> Yep <http://coliru.stacked-crooked.com/a/92e9e5ca672051a0>
That doesn't prove it's "fine". It only proves the base destructor got run.
The point of "fine" is that the destruction cleaned up the resources as
expected. The X destructor could have left the Base sub-object in an invalid
state before the throw.
You can claim that this is a mistake in the author of the X class. But that's
exactly the point: the code that the X destructor runs before the Base
destructor can run must not throw.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/6043413.vChnhBd2tc%40tjmaciei-mobl1.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Mon, 28 Aug 2017 12:49:34 -0700
Raw View
On Monday, 28 August 2017 12:25:35 PDT crusader.mike@gmail.com wrote:
> > If the clean up can fail, then it's not something that should be done in
> > the
> > destructor.
>
> Why? This logic is the result of "dtor shouldn't fail" dogma. Which I am
> kind of challenging right now. If my challenge succeeds -- this statement
> has to legs to stand on.
Ok, how about this:
Did you or did you not destroy the object completely? If you did, then why did
you throw?
If you did not, what are you going to do to the bits and pieces that did not
get properly destroyed?
> > Try it before, catch any errors, and fail accordingly. If you fail
> > to clean up in response to an earlier failure, handle it appropriately
> > according to your code.
>
> I proposed you to write code that has to perform three different cleanup
> tasks. I had to do it multiple times in my life -- every time had to resort
> to some equivalent of C-style error handling and it didn't make me happy.
Life isn't fair or easy. Properly handling error conditions is definitely in
the "not easy" camp.
> Here is another consideration:
>
> class File
> {
> file* f;
> ...
> };
>
> void foo()
> {
> File f = ...;
> // write stuff
>
> // gotta close it because it may fail and we can't report failure from
> dtor
> f.close();
>
> // now File invariant has to support 'not open' state via additional
> boolean member (or magical NULL value)
> // and ~File() (and probably bunch of other member functions) have to
> contain unnecessary branch that checks for that state
> }
Yeah, so?
Let me make your example more concrete:
class File
{
FILE *f;
public:
File(const char *name) : f(fopen(name, "r")) {}
~File();
};
File::~File()
{
if (fclose(f) != 0)
throw errno;
}
Let's say that fclose() failed to flush the buffers, so there's still data in
the buffers. And let's say that this C implementation allows you to retry
fclose.
*How* do you flush those buffers? How do you free the memory associated with
them and with the FILE* itself, after File::~File has run?
> > Now, I don't care much for exceptions, so I really don't care how ugly
> > that
> > code makes. You chose to use exceptions... live with them.
>
> "Your way of doing things is ugly but you shouldn't be fixing it, better
> use ours" -- doesn't look like a very good argument to me. I floated this
> with expectations that someone will show why that fix won't work. Not why
> it is ideologically incorrect.
I don't use exceptions in my own code. I don't think they are the correct way
to report errors, for many reasons including the ones you've brought to
discussion -- the fail to fail problem.
But they are most definitely the wrong tool for both clean-up and normal error
conditions. This is not an inherent problem with exceptions, but with how they
are used. It's an API problem -- the same problem that fclose() has: the
destruction can fail and your only recourse is to leak.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/1758357.2LJ5BOKfMC%40tjmaciei-mobl1.
.
Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Mon, 28 Aug 2017 16:04:36 -0400
Raw View
On 2017-08-28 12:06, crusader.mike@gmail.com wrote:
> Here is a C-style code:
>
> error_t foo()
> {
> ...
> error_t res1 = do_smth1();
> error_t res2 = do_smth2();
> error_t res3 = do_smth3();
>
> // somehow combine results
> error_t res = ...;
> return res;
> }
>
> try writing similar logic using EH
std::vector<std::exception_ptr> g_exceptions;
error_t foo()
{
...
trap(do_smth1);
trap(do_smth2);
trap(do_smth3);
if (!g_exceptions.empty())
{
// somehow combine results
error_t res = ...;
return res;
}
return E_OK;
}
....where `trap` executes a functor, catches any exceptions it throws,
and appends them to `g_exceptions`. (Alternatively, it could wrap
exceptions in an `expected`.)
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/0a5c42b2-667a-1a8e-5258-4a18c907c84b%40gmail.com.
.
Author: crusader.mike@gmail.com
Date: Mon, 28 Aug 2017 14:53:22 -0700 (PDT)
Raw View
------=_Part_7318_341828264.1503957203006
Content-Type: multipart/alternative;
boundary="----=_Part_7319_1203792346.1503957203006"
------=_Part_7319_1203792346.1503957203006
Content-Type: text/plain; charset="UTF-8"
On Monday, August 28, 2017 at 2:40:30 PM UTC-5, Thiago Macieira wrote:
>
> On Monday, 28 August 2017 12:35:22 PDT crusad...@gmail.com <javascript:>
> wrote:
> > > It will throw during destruction. Did it get destroyed just fine?
> >
> > Yep <http://coliru.stacked-crooked.com/a/92e9e5ca672051a0>
>
> That doesn't prove it's "fine". It only proves the base destructor got
> run.
>
Well, it got destroyed and it's memory "freed", didn't it? So, throwing
from dtor has defined behavior in C++. Why it chose exceptions to report
problem -- is another matter entirely in user's domain. Likely because
fclose() isn't guaranteed to succeed and moving it out into separate method
doesn't change anything, but adds complexity.
The point of "fine" is that the destruction cleaned up the resources as
> expected. The X destructor could have left the Base sub-object in an
> invalid
> state before the throw.
>
> You can claim that this is a mistake in the author of the X class.
That is precisely what I am going to claim. If you chose to use exception
to report problem from dtor -- you better write it in such way that it
makes sense wrt your subobjects. You don't expect smth to go wrong if your
ctor throws after subobjects have been constructed? This is similar case.
> But that's
> exactly the point: the code that the X destructor runs before the Base
> destructor can run must not throw.
>
As long as Base's invariant isn't compromised -- why not? And why would you
compromised your subobject's invariant? you don't do it for member
variables -- shouldn't do it for base class.
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
>
>
--
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/1e19c881-52d4-4b1d-908d-30ffd7aa0460%40isocpp.org.
------=_Part_7319_1203792346.1503957203006
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Monday, August 28, 2017 at 2:40:30 PM UTC-5, Th=
iago Macieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Monday,=
28 August 2017 12:35:22 PDT <a href=3D"javascript:" target=3D"_blank" gdf-=
obfuscated-mailto=3D"zAzqFl6mDAAJ" rel=3D"nofollow" onmousedown=3D"this.hre=
f=3D'javascript:';return true;" onclick=3D"this.href=3D'javascr=
ipt:';return true;">crusad...@gmail.com</a> wrote:
<br>> > It will throw during destruction. Did it get destroyed just f=
ine?
<br>>=20
<br>> Yep <<a href=3D"http://coliru.stacked-crooked.com/a/92e9e5ca672=
051a0" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'h=
ttp://www.google.com/url?q\x3dhttp%3A%2F%2Fcoliru.stacked-crooked.com%2Fa%2=
F92e9e5ca672051a0\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFYpWW-EpQNXDHXCfc=
e-RDhaH3vfQ';return true;" onclick=3D"this.href=3D'http://www.googl=
e.com/url?q\x3dhttp%3A%2F%2Fcoliru.stacked-crooked.com%2Fa%2F92e9e5ca672051=
a0\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFYpWW-EpQNXDHXCfce-RDhaH3vfQ'=
;;return true;">http://coliru.stacked-<wbr>crooked.com/a/92e9e5ca672051a0</=
a><wbr>>
<br>
<br>That doesn't prove it's "fine". It only proves the ba=
se destructor got run.
<br></blockquote><div><br></div><div>Well, it got destroyed and it's me=
mory "freed", didn't it? So, throwing from dtor has defined b=
ehavior in C++. Why it chose exceptions to report problem -- is another mat=
ter entirely in user's domain. Likely because fclose() isn't guaran=
teed to succeed and moving it out into separate method doesn't change a=
nything, but adds complexity.</div><div><br></div><div><br></div><blockquot=
e class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: =
1px #ccc solid;padding-left: 1ex;">The point of "fine" is that th=
e destruction cleaned up the resources as=20
<br>expected. The X destructor could have left the Base sub-object in an in=
valid=20
<br>state before the throw.
<br>
<br>You can claim that this is a mistake in the author of the X class. </bl=
ockquote><div><br></div><div>That is precisely what I am going to claim. If=
you chose to use exception to report problem from dtor -- you better write=
it in such way that it makes sense wrt your subobjects. You don't expe=
ct smth to go wrong if your ctor throws after subobjects have been construc=
ted? This is similar case.</div><div><br></div><div>=C2=A0</div><blockquote=
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1=
px #ccc solid;padding-left: 1ex;">But that's=20
<br>exactly the point: the code that the X destructor runs before the Base=
=20
<br>destructor can run must not throw.
<br></blockquote><div><br></div><div>As long as Base's invariant isn=
9;t compromised -- why not? And why would you compromised your subobject=
9;s invariant? you don't do it for member variables -- shouldn't do=
it for base class.</div><div><br></div><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;">--=20
<br>Thiago Macieira - thiago (AT) <a href=3D"http://macieira.info" target=
=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.goo=
gle.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x3dD\x26sntz\x3d1\x26usg\=
x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.hr=
ef=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x=
3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return t=
rue;">macieira.info</a> - thiago (AT) <a href=3D"http://kde.org" target=3D"=
_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.google.=
com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNH=
GRJdo5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'=
http://www.google.com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1=
\x26usg\x3dAFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;">kde.org</a=
>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>
<br></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/1e19c881-52d4-4b1d-908d-30ffd7aa0460%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/1e19c881-52d4-4b1d-908d-30ffd7aa0460=
%40isocpp.org</a>.<br />
------=_Part_7319_1203792346.1503957203006--
------=_Part_7318_341828264.1503957203006--
.
Author: crusader.mike@gmail.com
Date: Mon, 28 Aug 2017 15:08:05 -0700 (PDT)
Raw View
------=_Part_7266_1833299170.1503958085077
Content-Type: multipart/alternative;
boundary="----=_Part_7267_8247942.1503958085077"
------=_Part_7267_8247942.1503958085077
Content-Type: text/plain; charset="UTF-8"
On Monday, August 28, 2017 at 2:49:40 PM UTC-5, Thiago Macieira wrote:
>
> On Monday, 28 August 2017 12:25:35 PDT crusad...@gmail.com <javascript:>
> wrote:
> > > If the clean up can fail, then it's not something that should be done
> in
> > > the
> > > destructor.
> >
> > Why? This logic is the result of "dtor shouldn't fail" dogma. Which I am
> > kind of challenging right now. If my challenge succeeds -- this
> statement
> > has to legs to stand on.
>
> Ok, how about this:
>
> Did you or did you not destroy the object completely? If you did, then why
> did
> you throw?
>
It's destructor has completed (doesn't matter how execution left it) --
that means object is destroyed. I did throw to report an error (machine
refused to switch off or disk controller returned error code).
We are now getting into the realm of how user should define his object's
invariant/states -- each user will have it's own view, I don't see any
particular reason to limit him.
If you did not, what are you going to do to the bits and pieces that did
> not
> get properly destroyed?
>
> > > Try it before, catch any errors, and fail accordingly. If you fail
> > > to clean up in response to an earlier failure, handle it appropriately
> > > according to your code.
> >
> > I proposed you to write code that has to perform three different cleanup
> > tasks. I had to do it multiple times in my life -- every time had to
> resort
> > to some equivalent of C-style error handling and it didn't make me
> happy.
>
> Life isn't fair or easy. Properly handling error conditions is definitely
> in
> the "not easy" camp.
>
True. :-) But the way I look at it -- EH provides with "easier" (though
probably not as efficient) way to propagate and handle errors. Why not
devise default 'collision resolution mechanism'? It certainly won't be
universal (just like EH is), but it will be a sensible usable behavior.
> > Here is another consideration:
> >
> > class File
> > {
> > file* f;
> > ...
> > };
> >
> > void foo()
> > {
> > File f = ...;
> > // write stuff
> >
> > // gotta close it because it may fail and we can't report failure
> from
> > dtor
> > f.close();
> >
> > // now File invariant has to support 'not open' state via additional
> > boolean member (or magical NULL value)
> > // and ~File() (and probably bunch of other member functions) have
> to
> > contain unnecessary branch that checks for that state
> > }
>
> Yeah, so?
>
> Let me make your example more concrete:
> class File
> {
> FILE *f;
> public:
> File(const char *name) : f(fopen(name, "r")) {}
> ~File();
> };
> File::~File()
> {
> if (fclose(f) != 0)
> throw errno;
> }
>
> Let's say that fclose() failed to flush the buffers, so there's still data
> in
> the buffers. And let's say that this C implementation allows you to retry
> fclose.
>
We both know fclose() does not allow retries. So, you either swallow error
or try to report it and design your higher level logic to take care of the
incompletely written file.
*How* do you flush those buffers? How do you free the memory associated
> with
> them and with the FILE* itself, after File::~File has run?
>
If runtime allowed me to retry -- I will certainly design it differently.
Either loop and sleep in dtor (obviously not ideal) or maintain a pool of
files to flush, hand it over to another thread and design my logic in such
way that file isn't considered written until it is flushed. Possibilities
are endless and all of them are kinda outside of the scope of this idea.
> > > Now, I don't care much for exceptions, so I really don't care how ugly
> > > that
> > > code makes. You chose to use exceptions... live with them.
> >
> > "Your way of doing things is ugly but you shouldn't be fixing it, better
> > use ours" -- doesn't look like a very good argument to me. I floated
> this
> > with expectations that someone will show why that fix won't work. Not
> why
> > it is ideologically incorrect.
>
> I don't use exceptions in my own code. I don't think they are the correct
> way
> to report errors, for many reasons including the ones you've brought to
> discussion -- the fail to fail problem.
>
I am very pragmatical -- I don't care about EH or C-style. Whatever is most
convenient in given circumstances -- even if it is "using pigeons to
deliver error messages". :-)
In most cases EH is very convenient. In other cases it isn't. It is just a
tool, I am trying to sharpen it a bit because I believe it might be used in
(probably small) subset of situations.
> But they are most definitely the wrong tool for both clean-up and normal
> error
> conditions. This is not an inherent problem with exceptions, but with how
> they
> are used. It's an API problem -- the same problem that fclose() has: the
> destruction can fail and your only recourse is to leak.
>
You have deeply embedded belief that destructor should never fail. In fact
exception doesn't even mean anything failed -- it is just a way to redirect
execution to another place. It is rather inefficient for that, of course,
but if I had a cent for every time I saw code that can be done more
efficiently -- I would have bought me a planet already.
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
>
>
--
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/875e6d97-ce54-4302-96e3-9c63c324bdcb%40isocpp.org.
------=_Part_7267_8247942.1503958085077
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Monday, August 28, 2017 at 2:49:40 PM UTC-5, Th=
iago Macieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Monday,=
28 August 2017 12:25:35 PDT <a href=3D"javascript:" target=3D"_blank" gdf-=
obfuscated-mailto=3D"1bldLd6mDAAJ" rel=3D"nofollow" onmousedown=3D"this.hre=
f=3D'javascript:';return true;" onclick=3D"this.href=3D'javascr=
ipt:';return true;">crusad...@gmail.com</a> wrote:
<br>> > If the clean up can fail, then it's not something that sh=
ould be done in
<br>> > the
<br>> > destructor.
<br>>=20
<br>> Why? This logic is the result of "dtor shouldn't fail&quo=
t; dogma. Which I am
<br>> kind of challenging right now. If my challenge succeeds -- this st=
atement
<br>> has to legs to stand on.
<br>
<br>Ok, how about this:
<br>
<br>Did you or did you not destroy the object completely? If you did, then =
why did=20
<br>you throw?
<br></blockquote><div><br></div><div>It's destructor has completed (doe=
sn't matter how execution left it) -- that means object is destroyed. I=
did throw to report an error (machine refused to switch off or disk contro=
ller returned error code).</div><div><br></div><div>We are now getting into=
the realm of how user should define his object's invariant/states -- e=
ach user will have it's own view, I don't see any particular reason=
to limit him.</div><div>=C2=A0</div><div><br></div><blockquote class=3D"gm=
ail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc soli=
d;padding-left: 1ex;">If you did not, what are you going to do to the bits =
and pieces that did not=20
<br>get properly destroyed?
<br>
<br>> > Try it before, catch any errors, and fail accordingly. If you=
fail
<br>> > to clean up in response to an earlier failure, handle it appr=
opriately
<br>> > according to your code.
<br>>=20
<br>> I proposed you to write code that has to perform three different c=
leanup
<br>> tasks. I had to do it multiple times in my life -- every time had =
to resort
<br>> to some equivalent of C-style error handling and it didn't mak=
e me happy.
<br>
<br>Life isn't fair or easy. Properly handling error conditions is defi=
nitely in=20
<br>the "not easy" camp.
<br></blockquote><div><br></div><div>True. :-) But the way I look at it -- =
EH provides with "easier" (though probably not as efficient) way =
to propagate and handle errors. Why not devise default 'collision resol=
ution mechanism'? It certainly won't be universal (just like EH is)=
, but it will be a sensible usable behavior.</div><div><br></div><div>=C2=
=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">> Here is another =
consideration:
<br>>=20
<br>> class File
<br>> {
<br>> =C2=A0 =C2=A0 file* f;
<br>> =C2=A0 =C2=A0 ...
<br>> };
<br>>=20
<br>> void foo()
<br>> {
<br>> =C2=A0 =C2=A0 File f =3D ...;
<br>> =C2=A0 =C2=A0 // write stuff
<br>>=20
<br>> =C2=A0 =C2=A0 // gotta close it because it may fail and we can'=
;t report failure from
<br>> dtor
<br>> =C2=A0 =C2=A0 f.close();
<br>>=20
<br>> =C2=A0 =C2=A0 // now File invariant has to support 'not open&#=
39; state via additional
<br>> boolean member (or magical NULL value)
<br>> =C2=A0 =C2=A0 // and ~File() (and probably bunch of other member f=
unctions) have to
<br>> contain unnecessary branch that checks for that state
<br>> }
<br>
<br>Yeah, so?
<br>
<br>Let me make your example more concrete:
<br>class File
<br>{
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0FILE *f;
<br>public:
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0File(const char *name) =
: f(fopen(name, "r")) {}
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0~File();
<br>};
<br>File::~File()
<br>{
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0if (fclose(f) !=3D 0)
<br>=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=A0throw errno;
<br>}
<br>
<br>Let's say that fclose() failed to flush the buffers, so there's=
still data in=20
<br>the buffers. And let's say that this C implementation allows you to=
retry=20
<br>fclose.
<br></blockquote><div><br></div><div>We both know fclose() does not allow r=
etries. So, you either swallow error or try to report it and design your hi=
gher level logic to take care of the incompletely written file.</div><div>=
=C2=A0</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"margi=
n: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">*Ho=
w* do you flush those buffers? How do you free the memory associated with=
=20
<br>them and with the FILE* itself, after File::~File has run?
<br></blockquote><div><br></div><div>If runtime allowed me to retry -- I wi=
ll certainly design it differently. Either loop and sleep in dtor (obviousl=
y not ideal) or maintain a pool of files to flush, hand it over to another =
thread and design my logic in such way that file isn't considered writt=
en until it is flushed. Possibilities are endless and all of them are kinda=
outside of the scope of this idea.</div><div><br></div><div>=C2=A0</div><b=
lockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;borde=
r-left: 1px #ccc solid;padding-left: 1ex;">> > Now, I don't care =
much for exceptions, so I really don't care how ugly
<br>> > that
<br>> > code makes. You chose to use exceptions... live with them.
<br>>=20
<br>> "Your way of doing things is ugly but you shouldn't be fi=
xing it, better
<br>> use ours" -- doesn't look like a very good argument to me=
.. I floated this
<br>> with expectations that someone will show why that fix won't wo=
rk. Not why
<br>> it is ideologically incorrect.
<br>
<br>I don't use exceptions in my own code. I don't think they are t=
he correct way=20
<br>to report errors, for many reasons including the ones you've brough=
t to=20
<br>discussion -- the fail to fail problem.
<br></blockquote><div><br></div><div>I am very pragmatical -- I don't c=
are about EH or C-style. Whatever is most convenient in given circumstances=
-- even if it is "using pigeons to deliver error messages". :-)<=
/div><div><br></div><div>In most cases EH is very convenient. In other case=
s it isn't. It is just a tool, I am trying to sharpen it a bit because =
I believe it might be used in (probably small) subset of situations.</div><=
div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
>But they are most definitely the wrong tool for both clean-up and normal e=
rror=20
<br>conditions. This is not an inherent problem with exceptions, but with h=
ow they=20
<br>are used. It's an API problem -- the same problem that fclose() has=
: the=20
<br>destruction can fail and your only recourse is to leak.
<br></blockquote><div><br></div><div>You have deeply embedded belief that d=
estructor should never fail. In fact exception doesn't even mean anythi=
ng failed -- it is just a way to redirect execution to another place. It is=
rather inefficient for that, of course, but if I had a cent for every time=
I saw code that can be done more efficiently -- I would have bought me a p=
lanet already.</div><div><br></div><div>=C2=A0</div><blockquote class=3D"gm=
ail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc soli=
d;padding-left: 1ex;">--=20
<br>Thiago Macieira - thiago (AT) <a href=3D"http://macieira.info" target=
=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.goo=
gle.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x3dD\x26sntz\x3d1\x26usg\=
x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.hr=
ef=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x=
3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return t=
rue;">macieira.info</a> - thiago (AT) <a href=3D"http://kde.org" target=3D"=
_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.google.=
com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNH=
GRJdo5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'=
http://www.google.com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1=
\x26usg\x3dAFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;">kde.org</a=
>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>
<br></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/875e6d97-ce54-4302-96e3-9c63c324bdcb%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/875e6d97-ce54-4302-96e3-9c63c324bdcb=
%40isocpp.org</a>.<br />
------=_Part_7267_8247942.1503958085077--
------=_Part_7266_1833299170.1503958085077--
.
Author: Bryce Glover <randomdsdevel@gmail.com>
Date: Mon, 28 Aug 2017 18:10:10 -0400
Raw View
--Apple-Mail=_EE38BDCF-998A-4ACF-AF3D-1601F88DB58A
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset="UTF-8"
Just to pop my head up from lurking for a second, this seems, upon pre=
liminary skimming, like it might be a use case for P0322 on `exception_list=
`s <http://wg21.link/p0322> if it were multithreaded, but it=E2=80=99s not,=
so it probably isn=E2=80=99t, though you might be able to set up similar w=
ith coroutines=E2=80=A6? =20
Nowhere near being entirely sure at all,=20
Bryce Glover
RandomDSdevel@gmail.com
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/7B5367AC-735D-4559-A4AE-33C11FBCFD06%40gmail.com=
..
--Apple-Mail=_EE38BDCF-998A-4ACF-AF3D-1601F88DB58A
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""> &nbs=
p;Just to pop my head up from lurking for a second, this seems, upon prelim=
inary skimming, like it might be a use case for <a href=3D"http://wg21=
..link/p0322" class=3D"">P0322 on `exception_list`s</a> if it were mult=
ithreaded, but it=E2=80=99s not, so it probably isn=E2=80=99t, though you m=
ight be able to set up similar with coroutines=E2=80=A6? <br class=3D=
""><br class=3D""><div class=3D"">
<div style=3D"color: rgb(0, 0, 0); letter-spacing: normal; orphans: auto; t=
ext-align: start; text-indent: 0px; text-transform: none; white-space: norm=
al; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-w=
rap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-=
space;" class=3D""><div style=3D"color: rgb(0, 0, 0); letter-spacing: norma=
l; orphans: auto; text-align: start; text-indent: 0px; text-transform: none=
; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke=
-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-=
break: after-white-space;" class=3D""><div style=3D"color: rgb(0, 0, 0); le=
tter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; t=
ext-transform: none; white-space: normal; widows: auto; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><div class=3D"">No=
where near being entirely sure at <i class=3D"">all</i>, </div><div cl=
ass=3D""> Bryce Glover</div><div class=3D"">  =
; <a href=3D"mailto:RandomDSdevel@gmail.com" class=3D"">RandomDSdevel=
@gmail.com</a></div></div></div></div></div></body></html>
<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/7B5367AC-735D-4559-A4AE-33C11FBCFD06%=
40gmail.com?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/7B5367AC-735D-4559-A4AE-33C11FBCFD06%=
40gmail.com</a>.<br />
--Apple-Mail=_EE38BDCF-998A-4ACF-AF3D-1601F88DB58A--
.
Author: crusader.mike@gmail.com
Date: Mon, 28 Aug 2017 15:13:21 -0700 (PDT)
Raw View
------=_Part_7177_517953169.1503958402033
Content-Type: multipart/alternative;
boundary="----=_Part_7178_972323317.1503958402034"
------=_Part_7178_972323317.1503958402034
Content-Type: text/plain; charset="UTF-8"
On Monday, August 28, 2017 at 3:04:46 PM UTC-5, Matthew Woehlke wrote:
>
> On 2017-08-28 12:06, crusad...@gmail.com <javascript:> wrote:
> > Here is a C-style code:
> >
> > error_t foo()
> > {
> > ...
> > error_t res1 = do_smth1();
> > error_t res2 = do_smth2();
> > error_t res3 = do_smth3();
> >
> > // somehow combine results
> > error_t res = ...;
> > return res;
> > }
> >
> > try writing similar logic using EH
>
>
> std::vector<std::exception_ptr> g_exceptions;
>
> error_t foo()
> {
> ...
> trap(do_smth1);
> trap(do_smth2);
> trap(do_smth3);
>
> if (!g_exceptions.empty())
> {
> // somehow combine results
> error_t res = ...;
> return res;
> }
> return E_OK;
> }
>
> ...where `trap` executes a functor, catches any exceptions it throws,
> and appends them to `g_exceptions`. (Alternatively, it could wrap
> exceptions in an `expected`.)
>
Didn't you just created a "weird mix of both styles"? :-)
> --
> 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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/06a1b769-8b1e-495c-948c-1925b0653677%40isocpp.org.
------=_Part_7178_972323317.1503958402034
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Monday, August 28, 2017 at 3:04:46 PM UTC-5, Ma=
tthew Woehlke wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 2017-08=
-28 12:06, <a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=
=3D"0JWYNrGnDAAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascri=
pt:';return true;" onclick=3D"this.href=3D'javascript:';return =
true;">crusad...@gmail.com</a> wrote:
<br>> Here is a C-style code:
<br>>=20
<br>> error_t foo()
<br>> {
<br>> =C2=A0 =C2=A0 ...
<br>> =C2=A0 =C2=A0 error_t res1 =3D do_smth1();
<br>> =C2=A0 =C2=A0 error_t res2 =3D do_smth2();
<br>> =C2=A0 =C2=A0 error_t res3 =3D do_smth3();
<br>>=20
<br>> =C2=A0 =C2=A0 // somehow combine results
<br>> =C2=A0 =C2=A0 error_t res =3D ...;
<br>> =C2=A0 =C2=A0 return res;
<br>> }
<br>>=20
<br>> try writing similar logic using EH
<br>
<br>
<br>=C2=A0 std::vector<std::exception_<wbr>ptr> g_exceptions;
<br>
<br>=C2=A0 error_t foo()
<br>=C2=A0 {
<br>=C2=A0 =C2=A0 ...
<br>=C2=A0 =C2=A0 trap(do_smth1);
<br>=C2=A0 =C2=A0 trap(do_smth2);
<br>=C2=A0 =C2=A0 trap(do_smth3);
<br>
<br>=C2=A0 =C2=A0 if (!g_exceptions.empty())
<br>=C2=A0 =C2=A0 {
<br>=C2=A0 =C2=A0 =C2=A0 // somehow combine results
<br>=C2=A0 =C2=A0 =C2=A0 error_t res =3D ...;
<br>=C2=A0 =C2=A0 =C2=A0 return res;
<br>=C2=A0 =C2=A0 }
<br>=C2=A0 =C2=A0 return E_OK;
<br>=C2=A0 }
<br>
<br>...where `trap` executes a functor, catches any exceptions it throws,
<br>and appends them to `g_exceptions`. (Alternatively, it could wrap
<br>exceptions in an `expected`.)
<br></blockquote><div><br></div><div>Didn't you just created a "we=
ird mix of both styles"? :-) </div><div><br></div><div><br></div><bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-l=
eft: 1px #ccc solid;padding-left: 1ex;">
<br>--=20
<br>Matthew
<br></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/06a1b769-8b1e-495c-948c-1925b0653677%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/06a1b769-8b1e-495c-948c-1925b0653677=
%40isocpp.org</a>.<br />
------=_Part_7178_972323317.1503958402034--
------=_Part_7177_517953169.1503958402033--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Mon, 28 Aug 2017 15:52:13 -0700
Raw View
On Monday, 28 August 2017 14:53:22 PDT crusader.mike@gmail.com wrote:
> That is precisely what I am going to claim. If you chose to use exception
> to report problem from dtor -- you better write it in such way that it
> makes sense wrt your subobjects. You don't expect smth to go wrong if your
> ctor throws after subobjects have been constructed? This is similar case.
Similar and yet very different.
If a constructor throws, all of the already-constructed sub-objects get
unwound and destroyed. At the end of this, the object is completely destroyed.
If a destructor throws, the not-yet-destroyed sub-objects still need to be
destroyed. To avoid resource leaks, it needs to continue destroying as if the
exception hadn't happened. Throwing from a destructor sounds like "in addition
to destroying, I found this error, but don't worry, I have completed my work".
And hence my question: if the destructor successfully destroyed, why did it
need to throw?
> > But that's
> > exactly the point: the code that the X destructor runs before the Base
> > destructor can run must not throw.
>
> As long as Base's invariant isn't compromised -- why not? And why would you
> compromised your subobject's invariant? you don't do it for member
> variables -- shouldn't do it for base class.
Sorry, you don't get to question what code is questionable. You're arguing for
making code that everyone else thinks is questionable legit.
Anyway, a simple example for FILE*: let's say it's a protected member of the
class. Also, to avoid fclose() failing, let's say an invariant condition is
that every member function flushes the buffer. But since it's protected, let's
say your derived class's destructor does fwrite something (like the
terminating CRLF or a QUIT command, etc.). That violates the invariant
condition. Now the Base class destructor may fail to clean up its resources.
In my opinion, this is questionable code. But I think it's questionable
because the destructor is doing something that can fail in the first place --
that should not be part of the destructor, but of a cleaning up operation
beforehand. It's no different than in C: to avoid fclose() failing, you should
fflush() the stream before you close, to ensure everything got written. If there
were errors, you can still recover because the FILE* is still valid.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/3345591.MgFJpW9PKI%40tjmaciei-mobl1.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Mon, 28 Aug 2017 15:57:50 -0700
Raw View
On Monday, 28 August 2017 15:08:05 PDT crusader.mike@gmail.com wrote:
> > But they are most definitely the wrong tool for both clean-up and normal
> > error
> > conditions. This is not an inherent problem with exceptions, but with how
> > they
> > are used. It's an API problem -- the same problem that fclose() has: the
> > destruction can fail and your only recourse is to leak.
>
> You have deeply embedded belief that destructor should never fail. In fact
> exception doesn't even mean anything failed -- it is just a way to redirect
> execution to another place. It is rather inefficient for that, of course,
> but if I had a cent for every time I saw code that can be done more
> efficiently -- I would have bought me a planet already.
Yes. Exceptions should be used for exceptional behaviour, that something
unexpected happened. They should not be used for normal behaviour, like
failing to open a file because it doesn't exist.
But more importantly in your case, pay attention to your own words "destructor
should never fail" and "exception doesn't mean anything failed". If nothing
failed, then the destructor didn't fail. So why the hell did it throw?
If you've recovered from the error, then why does it need reporting? Maybe
you're looking for logging, not exceptions.
If you didn't recover from the error, then you should hope that all that's
wrong now is that you have a resource leak.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/55705718.C2rzbhjTXS%40tjmaciei-mobl1.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 28 Aug 2017 16:16:42 -0700 (PDT)
Raw View
------=_Part_7356_1414331437.1503962202351
Content-Type: multipart/alternative;
boundary="----=_Part_7357_796122659.1503962202352"
------=_Part_7357_796122659.1503962202352
Content-Type: text/plain; charset="UTF-8"
On Monday, August 28, 2017 at 3:09:43 PM UTC-4, crusad...@gmail.com wrote:
>
> On Monday, August 28, 2017 at 12:56:32 PM UTC-5, Nicol Bolas wrote:
>>
>> On Monday, August 28, 2017 at 12:06:30 PM UTC-4, crusad...@gmail.com
>> wrote:
>>>
>>> Before reading stuff below I suggest to set aside any dogmatic blinders
>>> you may have, namely:
>>> - realize that there is nothing particular special about destructors --
>>> they are just functions that runtime calls automatically in specific
>>> circumstances and yes, they may want to report an error
>>>
>>
>> Untrue. Destructors provoke the ending of the lifetime of an object. That
>> makes them special. Much like how constructors signal the beginning of the
>> lifetime of an object.
>>
>
> It is a function. And it can throw exception as it is right now. It is
> noexcept right by default, but nothing prevents me to declare it
> noexcept(false) and it will work. The only case when it won't is when it
> throws during unwinding. I believe it can be changed and it should be
> changed to accomodate for a practical situation. And it won't affect
> existing code at all.
>
If exception collisions affect the type of exception being caught, then it
affects any existing code where that user does not control what objects get
destroyed between themselves and the source of the exception they're
catching.
- you can't really tell what makes sense or not -- only end user makes this
>>> decision
>>>
>>
>> The C++ object model is all about defining what "makes sense". That's why
>> you can't just pretend that an object exists in some memory.
>>
>
> I never said that.
>
Nor did I accuse you of saying it. My point is that your perspective is
that of someone who's doesn't care about what a piece of functionality
*means*; what matters to you is what it can do. It's a perspective of
trying to view C++, not as a collection of meaningful parts and
functionality, but an arbitrary assemblage of things onto which you can
graft your own meaning.
Destructors mean something to the C++ object model. They're not just a
function call. Just like constructors mean something to the C++ object
model. What "makes sense" *matters*.
Nothing prevents me from destroying object with error right now and it will
> work just fine:
> void foo()
> {
> struct X { ~X() { throw 1; } x;
> }
>
> object still gets destroyed just fine.
>
That calls `std::terminate`, since you tried to emit an exception through a
`noexcept` function. While yes, the object `x` has had its lifetime ended,
that happened when the destructor *started*. So the throw is essentially
irrelevant.
What matters is what the state of the system means in this event.
What logical meaning I associated with 'failed destructor' is my (end user)
> business.
>
No, it's not. It's everybody else's business too.
For example, if I put an object with a throwing destructor in my object
which doesn't have a throwing destructor... what does that mean?
And it may make sense to me.
>
And your code needs to work with the rest of the world.
So the standard has every right to decide that circumstance X doesn't make
>> sense, so we're not going to support it.
>>
>> - what is proposed -- is just a tool, whether to use it or not, is up to
>>> end user
>>>
>>
>> The model that the proposal creates still has to make sense. Which it
>> does not. Giving people tools that are incoherent and encourage bad coding
>> is not helpful.
>>
>
> You claim "make no sense" very vigorously, but I've yet to see any good
> argument for that.
>
That's because you're looking from a world view where destructors "are just
functions that runtime calls automatically in specific circumstances". It
stops making sense once you move to a perspective where there is an actual
meaning to object destruction besides calling a bunch of functions.
I can't help your world view. I understand it, but I do not subscribe to it.
On Sunday, August 27, 2017 at 9:19:57 PM UTC-5, Nicol Bolas wrote:
>>>>
>>>> On Sunday, August 27, 2017 at 9:35:21 PM UTC-4, crusad...@gmail.com
>>>> wrote:
>>>>
>>> No, a throwing destructor is a terrible, horrible, no-good, very-bad
>>>> idea. Implicitly forbidding it is a good thing, and C++ has absolutely no
>>>> need to support exception clashing (which can only happen through a
>>>> throwing destructor).
>>>>
>>>> Here are my thoughts:
>>>>> - both C-style error handling and C++ exceptions do effectively the
>>>>> same thing -- construct error object and pass it up the call stack,
>>>>> differences are:
>>>>>
>>>>> - C: error type is known to caller and caller is responsible for
>>>>> allocating memory for error object
>>>>>
>>>>> - C: caller is responsible for proper propagation of error
>>>>>
>>>>> - EH: caller only knows whether some error can bubble up (ignoring
>>>>> exception specs here, since they are deprecated)
>>>>>
>>>>> - EH: there is a mechanism that automates error propagation (and
>>>>> matching to related catch clause)
>>>>>
>>>>>
>>>> - EH: Arbitrary code can execute between the generation of the error
>>>> code and its reception. That code itself can fail.
>>>>
>>>
>>> no, same thing can happen with C-style error handling. It looks rather
>>> obvious to me
>>>
>>
>> Your analogy says that `return` and the use of the return value are
>> similar to `throw` and `catch` for that exception. Given that analogy, no,
>> the same thing cannot happen in C-style error handling. The function that
>> receives the error is the one that called the function. Between the end of
>> the initialization of the return value from the function creating the error
>> code, to the beginning of the initialization of the value that the
>> receiving function is creating, no user code can be executed.
>>
>> Oh, there can be code between the generator of the error and where the
>> error is *resolved*: that is, where you stop dealing with the error
>> condition and progress normally. You can return the error code up the
>> stack, do conditional logic based on it, and all kinds of stuff.
>>
>> But there is a lot more that can happen between a `throw` and a `catch`
>> that cannot happen between a `return` and the use of that returned value.
>>
>
> Again, no. Two situations -- propagation of error to the point where it
> gets handled through unwinding mechanism is fundamentally the same as
> propagation of it via "if (auto err = foo()) return err". In both cases
> anything could happen in-between.
>
I just realized something. There is one similarity between error code
propagation and exception-caused stack unwinding. In both cases...
destructors *cannot* affect an error code being returned by value ;)
No really; go ahead and try to make a destructor change the value of a
returned error code. Even if you do this:
error_code func()
{
error_code ec = ...;
change_error_code changer(&ec);
return ec;
}
`change_error_code` could store a pointer/reference to `ec` and modify it
in its destructor. But it won't affect the returned value. Because by C++'s
rules, the return value will be copied/moved out of the expression *before*
destructors are called. That's why `return ec;` treats `ec` as an rvalue.
Why should exceptions be any different? If destructors can't affect error
codes, why should exceptions?
That being said, I have another perspective on this. Every error mechanism
has a cost; nothing is free. The question is what cost the cost you're
willing to pay is.
With error codes, in order to get the error from the source to the
resolver, every call along the way must *actively* participate in
transferring the error. That's the price you pay for using error codes.
With exceptions, in order to get the error from the source to the resolver,
every call along the way must not *inhibit* the flow of the error. That's
the price you pay for using exceptions.
The error code price means that you have to stick the error code in a
return value or output parameter. The exception price means that you can't
emit exceptions during stack unwinding.
If you need to be able to combine errors arbitrarily like you want, to have
sequences of failing processes where you accumulate errors and do something
with them, then you need to use error codes. That kind of specialized
handling is what they're good at.
- so, if you are "cleaning up" after receiving C-style error --nothing
>>>>> prevents you from handling second error produced by "cleanup" call (since
>>>>> propagation is handled by developer anyway). You may choose to replace
>>>>> older error with new one, chain them together, etc
>>>>>
>>>> - with EH language-provided mechanism has no idea what to do with
>>>>> second error object, so decision was made to call terminate execution since
>>>>> user allowed error to escape. The idea is that user needs to somehow handle
>>>>> second error before it "meets" first one. Unfortunately this seriously
>>>>> limits what you can do -- for example you can't replace old exception with
>>>>> new one (and continue propagation).
>>>>>
>>>>
>>>> ... why would you want to?
>>>>
>>>> Think about this for a second. Your call stack looks like this:
>>>>
>>>> A->B->C->D->E
>>>>
>>>> Now, E emits an exception. One that is caught by C. That catch provokes
>>>> stack unwinding down to C.
>>>>
>>>> D's unwinding throws an exception. One that is caught by B. That catch
>>>> provokes stack unwinding down to... where?
>>>>
>>>
>>> exception emitted by E will be replaced by exception emitted by D during
>>> unwinding (when exception will "meet") and unwinding will continue. C may
>>> or may not catch it (depending on catch clause).
>>>
>>
>> OK, so let's say that C knows that D can throw something.
>>
>> That means C has to look like this:
>>
>
> Wrong. It does not **have** to. You (as end user) certainly can create
> situation like that, but unless you like to shoot yourself in the foot --
> you'll come up with better approach
>
Then what is `C` supposed to look like if it's going to catch *all*
`E_exception`s that try to pass it?
catch(E_exception &e)
>> {
>> //Do stuff for E_exception
>> }
>> catch(D_exception &e)
>> {
>> //Do stuff for D_exception
>> throw;
>> }
>> catch(E_exception_combined_with_D_exception &e)
>> {
>> //Do stuff for E_exception
>> //Do stuff for D_exception
>> throw;
>> }
>>
>> That's a lot of repetition.
>>
>
> You literally built a gun, took it in your hands, aimed at your feet and
> pressed the trigger. What prevents you from catching one base exception?
>
Your question is like asking "why return X, when you could return a
`std::any` that maybe contains an X or a Y?"
If I wrote C and E, but not D (E may be a callback/continuation/etc passed
to D), why would I tie my `E_exception` to whatever D throws? The whole
point of exception catching is that I choose what to catch, and the
compiler will find the right handler for the exception.
In most cases you wouldn't care if it replaced bunch of others -- operation
> failed, here is a result from one of failed sub-operations.
>
That is an... interesting perspective on how you think people catch
exceptions and treat their contents.
You may have some additional information if you 'unroll' nested struct.
> Most of code is unlikely to use throwing dtors and therefore they won't
> have to deal with this.
>
But since you don't control all code, you can't know that it won't happen.
And therefore, every `catch` statement must be written expecting this
possibility.
Whereas right now, I don't have to care. Throwing destructors during
unwinding will yield `std::terminate`. And that's not something I have to
write code for.
> Wrt "one_exception_combined_with_others" check -- I'd like to wrap
> **every** exception into a structure like this,
>
That would be the fastest way to make everybody stop using exception
handling.
> but this would be breaking change and against the spirit of C++ "you don't
> pay until you use it". So proposal is to apply wrapper on first instance of
> "replacing".
>
And again -- actual 'combination' logic is not set in stone. What I
> proposed is just a first attempt.
>
OK, can we have an attempt that makes sense and is at least theoretically
usable? Because thus far, even if I *wanted* to have a solution to
exception collisions, the ideas you've proposed make working with
exceptions *incredibly tedious*. Having to catch a single type and manually
fish out of it the type you're maybe interested in, and then propagating
the rest if any? No, that's horrible code that should be handled by the
system.
Not having to write that code is precisely why `catch` statements are
*typed*.
try writing similar logic using EH -- it will be very awkward, lots of code.
>>>
>>
>> Please provide a practical example of that. Something from the real
>> world, where "somehow combine results" is something other than "swallow the
>> exception".
>>
>
> error_t do_work()
> {
> start_device1();
> // return if failed to start, return array of values (one code per
> device)
> start_device2();
> // if failed: stop_device1, if device1 fails to stop -- set it's error
> code too
> start_device3();
> // if failed: stop_device1, if device1 fails to stop -- set it's error
> code too
> // stop_device2, if device2 fails to stop -- set it's
> error code too
>
> // do work using these devices (don't forget to stop them if smth fails
> during it)
> ...
>
> // time to stop devices
> code res1 = stop_device3();
> code res2 = stop_device2();
> code res3 = stop_device1();
>
> // somehow combine results
> return {res1, res2, res3};
> }
>
> In case if you wonder -- this is not made up situation. I've seen it.
>
>
>
>>
>>
>>> Keep in mind that no matter what each of functions above need to be
>>> called no matter what.
>>>
>>
>>>
>> Let's say that each one attempts to switch off a piece of very expensive
>>> machinery. You can't make it no-fail for physical reasons. And if something
>>> goes wrong you need to report error(s) upstairs for analysis and associated
>>> actions.
>>>
>>> with this proposal you can put these do_smthN() calls into destructors
>>> and automatically get "always gets invoked" guarantee along with some
>>> (hopefully sensible) mechanism that is going to combine these errors for
>>> propagation up-stack. If user doesn't like default mechanism -- he'll use
>>> aforementioned knobs to tune it to his liking.
>>>
>>> Right now you have to make these dtors silent and accumulate these
>>> errors elsewhere -- basically turning EH into some weird mix of both styles.
>>>
>>
>> ... OK, I'll play along. You want people to write this:
>>
>> try
>> {
>> something_doer_3 t3{};
>> something_doer_2 t2{};
>> something_doer_1 t1{};
>> }
>> catch(something)
>> {
>> //Combine the errors
>> }
>>
>> Where the destructors of those three types are what does the work.
>>
>
> rewriting example from above using EH:
> try
> {
> auto_start_stop device1{}; // starts device in ctor, stops in dtor
> -- both ops can fail with exception
> auto_start_stop device2{};
> auto_start_stop device3{};
>
> // do work using these devices (which can throw too)
> }
> catch(error_base const&)
> {
> // entire operation failed, if we want, we could check if this is a
> combined exception and pull it apart)
> }
>
Now, show me the code for this "check if this is a combined exception and
pull it apart". Then compare it to the error code equivalent. Show me how
this is in any way better.
Indeed, this is a perfect example of exactly why your idea doesn't work.
OK, let's say that something in "do work using these devices (which can
throw too)" throws. The caller of this function catches it, so the stack
starts unwinding. Those destructors start failing, so a second exception is
emitted that gets caught right here.
So... what about the first exception? That exception represents a condition
that has not yet been resolved (since the code to resolve it has not been
executed). How does it get to its destination, so that the error can be
resolved? Is the catch statement here supposed to extract it and propagate
it on, or will the system do so automatically? If it requires manual
coding, is the user able to code it so that it works with *any* exception,
or does the user have to special-case it for certain exception types? Is it
possible for this catch statement to effectively swallow *all* exceptions,
in the event that it throws during unwinding?
Even taking your idea at face value, there are just too many unknowns about
it to really give it any consideration.
By contrast, with the error code version (or rather the `File::close`
version, where the destructor and an explicit member can both close, but
the destructor swallows the error), it just eats the errors as the stack
unwinds. Nobody gets informed about those problems, but nobody *needs* to
be either. Does the person receiving the exception from "do work using
these devices" really need to know if device stopping failed?
The case you describe is actually perfect for an out-of-band error
mechanism (something like `std:errno` or `glGetError`) to report the errors
from the destructor of the device class. That allows the caller to be able
to ask whether device stoppage succeeded *without* having to have this
aggregation of return values. And it works very well with exceptions, since
the error can still be reported without interfering in the exception
itself. After all, you're talking about what is a different *channel* of
error from the original exception.
No one error handling mechanism fits all cases. Even `errno` has its place.
--
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/6a9c0d42-d76e-4b56-b5e7-51df8191dacd%40isocpp.org.
------=_Part_7357_796122659.1503962202352
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Monday, August 28, 2017 at 3:09:43 PM UTC-4, crusad...@=
gmail.com 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"lt=
r">On Monday, August 28, 2017 at 12:56:32 PM UTC-5, Nicol Bolas wrote:<bloc=
kquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-lef=
t:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On Monday, August 28, 2=
017 at 12:06:30 PM UTC-4, <a>crusad...@gmail.com</a> wrote:<blockquote clas=
s=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div dir=3D"ltr"><div>Before reading stuff below I =
suggest to set aside any dogmatic blinders you may have, namely:</div><div>=
- realize that there is nothing particular special about destructors -- the=
y are just functions that runtime calls automatically in specific circumsta=
nces and yes, they may want to report an error</div></div></blockquote><div=
><br>Untrue. Destructors provoke the ending of the lifetime of an object. T=
hat makes them special. Much like how constructors signal the beginning of =
the lifetime of an object.<br></div></div></blockquote><div><br></div><div>=
It is a function. And it can throw exception as it is right now. It is noex=
cept right by default, but nothing prevents me to declare it noexcept(false=
) and it will work. The only case when it won't is when it throws durin=
g unwinding. I believe it can be changed and it should be changed to accomo=
date for a practical situation. And it won't affect existing code at al=
l.</div></div></blockquote><div><br>If exception collisions affect the type=
of exception being caught, then it affects any existing code where that us=
er does not control what objects get destroyed between themselves and the s=
ource of the exception they're catching.<br><br></div><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></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" s=
tyle=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:=
1ex"><div dir=3D"ltr"><div>- you can't really tell what makes sense or =
not -- only end user makes this decision</div></div></blockquote><div><br>T=
he C++ object model is all about defining what "makes sense". Tha=
t's why you can't just pretend that an object exists in some memory=
..<br></div></div></blockquote><div><br></div><div>I never said that.</div><=
/div></blockquote><div><br>Nor did I accuse you of saying it. My point is t=
hat your perspective is that of someone who's doesn't care about wh=
at a piece of functionality=C2=A0<i>means</i>; what matters to you is what =
it can do. It's a perspective of trying to view C++, not as a collectio=
n of meaningful parts and functionality, but an arbitrary assemblage of thi=
ngs onto which you can graft your own meaning.<br><br>Destructors mean some=
thing to the C++ object model. They're not just a function call. Just l=
ike constructors mean something to the C++ object model. What "makes s=
ense" <i>matters</i>.<br><br></div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-le=
ft: 1ex;"><div dir=3D"ltr"><div>Nothing prevents me from destroying object =
with error right now and it will work just fine:</div><div>void foo()</div>=
<div>{</div><div>=C2=A0 =C2=A0 struct X { ~X() { throw 1; } x;</div><div>}<=
/div><div><br></div><div>object still gets destroyed just fine.</div></div>=
</blockquote><div><br>That calls `std::terminate`, since you tried to emit =
an exception through a `noexcept` function. While yes, the object `x` has h=
ad its lifetime ended, that happened when the destructor <i>started</i>. So=
the throw is essentially irrelevant.<br><br>What matters is what the state=
of the system means in this event.<br><br></div><blockquote class=3D"gmail=
_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;p=
adding-left: 1ex;"><div dir=3D"ltr"><div>What logical meaning I associated =
with 'failed destructor' is my (end user) business.</div></div></bl=
ockquote><div><br>No, it's not. It's everybody else's business =
too.<br><br>For example, if I put an object with a throwing destructor in m=
y object which doesn't have a throwing destructor... what does that mea=
n?<br><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"lt=
r"><div>And it may make sense to me.</div></div></blockquote><div><br>And y=
our code needs to work with the rest of the world.<br><br></div><blockquote=
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1=
px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div dir=3D"ltr"><div>So the standard has every =
right to decide that circumstance X doesn't make sense, so we're no=
t going to support it.<br><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"><div>- what is proposed -- is just a tool, whether to use=
it or not, is up to end user</div></div></blockquote><div><br>The model th=
at the proposal creates still has to make sense. Which it does not. Giving =
people tools that are incoherent and encourage bad coding is not helpful.<b=
r></div></div></blockquote><div><br></div><div>You claim "make no sens=
e" very vigorously, but I've yet to see any good argument for that=
..</div></div></blockquote><div><br>That's because you're looking fr=
om a world view where destructors "are just functions that runtime cal=
ls automatically in specific circumstances". It stops making sense onc=
e you move to a perspective where there is an actual meaning to object dest=
ruction besides calling a bunch of functions.<br><br>I can't help your =
world view. I understand it, but I do not subscribe to it.<br><br></div><bl=
ockquote 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></div><bloc=
kquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-lef=
t:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gm=
ail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;p=
adding-left:1ex"><div dir=3D"ltr">On Sunday, August 27, 2017 at 9:19:57 PM =
UTC-5, Nicol Bolas 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">On Sunday, August 27, 2017 at 9:35:21 PM UTC-4, <a>crusad...@gmail=
..com</a> wrote:</div></blockquote><div></div><blockquote class=3D"gmail_quo=
te" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-=
left:1ex"><div dir=3D"ltr"><div>No, a throwing destructor is a terrible, ho=
rrible, no-good, very-bad idea. Implicitly forbidding it is a good thing, a=
nd C++ has absolutely no need to support exception clashing (which can only=
happen through a throwing destructor).<br><br></div><blockquote class=3D"g=
mail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;=
padding-left:1ex"><div dir=3D"ltr"><div></div><div>Here are my thoughts:</d=
iv><div>- both C-style error handling and C++ exceptions do effectively the=
same thing -- construct error object and pass it up the call stack, differ=
ences are:</div><div><blockquote style=3D"margin:0 0 0 40px;border:none;pad=
ding:0px"><div>- C: error type is known to caller and caller is responsible=
for allocating memory for error object</div></blockquote></div><blockquote=
style=3D"margin:0 0 0 40px;border:none;padding:0px"><div><div>- C: caller =
is responsible for proper propagation of error=C2=A0</div></div></blockquot=
e><blockquote style=3D"margin:0 0 0 40px;border:none;padding:0px"><div><div=
>- EH: caller only knows whether some error can bubble up (ignoring excepti=
on specs here, since they are deprecated)</div></div></blockquote><blockquo=
te style=3D"margin:0 0 0 40px;border:none;padding:0px"><div>- EH: there is =
a mechanism that automates error propagation (and matching to related catch=
clause)</div></blockquote></div></blockquote><div><br>- EH: Arbitrary code=
can execute between the generation of the error code and its reception. Th=
at code itself can fail.<br></div></div></blockquote><div><br></div><div>no=
, same thing can happen with C-style error handling. It looks rather obviou=
s to me</div></div></blockquote><div><br>Your analogy says that `return` an=
d the use of the return value are similar to `throw` and `catch` for that e=
xception. Given that analogy, no, the same thing cannot happen in C-style e=
rror handling. The function that receives the error is the one that called =
the function. Between the end of the initialization of the return value fro=
m the function creating the error code, to the beginning of the initializat=
ion of the value that the receiving function is creating, no user code can =
be executed.<br><br>Oh, there can be code between the generator of the erro=
r and where the error is <i>resolved</i>: that is, where you stop dealing w=
ith the error condition and progress normally. You can return the error cod=
e up the stack, do conditional logic based on it, and all kinds of stuff.<b=
r><br>But there is a lot more that can happen between a `throw` and a `catc=
h` that cannot happen between a `return` and the use of that returned value=
..<br></div></div></blockquote><div><br></div><div>Again, no. Two situations=
-- propagation of error to the point where it gets handled through unwindi=
ng mechanism is fundamentally the same as propagation of it via "if (a=
uto err =3D foo()) return err". In both cases anything could happen in=
-between.</div></div></blockquote><div><br>I just realized something. There=
is one similarity between error code propagation and exception-caused stac=
k unwinding. In both cases... destructors <i>cannot</i> affect an error cod=
e being returned by value ;)<br><br>No really; go ahead and try to make a d=
estructor change the value of a returned error code. Even if you do this:<b=
r><br><div style=3D"background-color: rgb(250, 250, 250); border-color: rgb=
(187, 187, 187); border-style: solid; border-width: 1px; overflow-wrap: bre=
ak-word;" class=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"s=
ubprettyprint"><span style=3D"color: #000;" class=3D"styled-by-prettify">er=
ror_code func</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">()</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br><=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 error_cod=
e ec </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D</=
span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">...;</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 change_error_cod=
e changer</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(=
&</span><span style=3D"color: #000;" class=3D"styled-by-prettify">ec</s=
pan><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">return</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify"> ec</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><span style=3D"color: #000;" class=3D"=
styled-by-prettify"><br></span></div></code></div><br>`change_error_code` c=
ould store a pointer/reference to `ec` and modify it in its destructor. But=
it won't affect the returned value. Because by C++'s rules, the re=
turn value will be copied/moved out of the expression <i>before</i> destruc=
tors are called. That's why `return ec;` treats `ec` as an rvalue.<br><=
br>Why should exceptions be any different? If destructors can't affect =
error codes, why should exceptions?<br></div><div><br>That being said, I ha=
ve another perspective on this. Every error mechanism has a cost; nothing i=
s free. The question is what cost the cost you're willing to pay is.<br=
><br>With error codes, in order to get the error from the source to the res=
olver, every call along the way must <i>actively</i> participate in transfe=
rring the error. That's the price you pay for using error codes.<br><br=
>With exceptions, in order to get the error from the source to the resolver=
, every call along the way must not <i>inhibit</i> the flow of the error. T=
hat's the price you pay for using exceptions.<br><br>The error code pri=
ce means that you have to stick the error code in a return value or output =
parameter. The exception price means that you can't emit exceptions dur=
ing stack unwinding.<br><br>If you need to be able to combine errors arbitr=
arily like you want, to have sequences of failing processes where you accum=
ulate errors and do something with them, then you need to use error codes. =
That kind of specialized handling is what they're good at.<br><br></div=
><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></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:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" s=
tyle=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:0;m=
argin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"l=
tr"><div>=C2=A0- so, if you are "cleaning up" after receiving C-s=
tyle error --nothing prevents you from handling second error produced by &q=
uot;cleanup" call (since propagation is handled by developer anyway). =
You may choose to replace older error with new one, chain them together, et=
c</div></div></blockquote><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>- with EH language-provided mechanism has no idea what to do =
with second error object, so decision was made to call terminate execution =
since user allowed error to escape. The idea is that user needs to somehow =
handle second error before it "meets" first one. Unfortunately th=
is seriously limits what you can do -- for example you can't replace ol=
d exception with new one (and continue propagation).<br></div></div></block=
quote><div><br>... why would you want to?<br><br>Think about this for a sec=
ond. Your call stack looks like this:<br><br><div style=3D"background-color=
:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;border-w=
idth:1px"><code><div><span style=3D"color:#000">A</span><span style=3D"colo=
r:#660">-></span><span style=3D"color:#000">B</span><span style=3D"color=
:#660">-></span><span style=3D"color:#000">C</span><span style=3D"color:=
#660">-></span><span style=3D"color:#000">D</span><span style=3D"color:#=
660">-></span><span style=3D"color:#000">E</span></div></code></div><br>=
Now, E emits an exception. One that is caught by C. That catch provokes sta=
ck unwinding down to C.<br><br>D's unwinding throws an exception. One t=
hat is caught by B. That catch provokes stack unwinding down to... where?<b=
r></div></div></blockquote><div><br></div><div>exception emitted by E will =
be replaced by exception emitted by D during unwinding (when exception will=
"meet") and unwinding will continue. C may or may not catch it (=
depending on catch clause).<br></div></div></blockquote><div><br>OK, so let=
's say that C knows that D can throw something.<br><br>That means C has=
to look like this:<br></div></div></blockquote><div><br></div><div>Wrong. =
It does not **have** to. You (as end user) certainly can create situation l=
ike that, but unless you like to shoot yourself in the foot -- you'll c=
ome up with better approach</div></div></blockquote><div><br>Then what is `=
C` supposed to look like if it's going to catch <i>all</i> `E_exception=
`s that try to pass it?<br><br></div><blockquote class=3D"gmail_quote" styl=
e=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left:=
1ex;"><div dir=3D"ltr"><div></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"><div><div style=3D"background-color:rgb(250,250,250);bord=
er-color:rgb(187,187,187);border-style:solid;border-width:1px"><code><div><=
span style=3D"color:#008">catch</span><span style=3D"color:#660">(</span><s=
pan style=3D"color:#000">E_exception </span><span style=3D"color:#660">&=
;</span><span style=3D"color:#000">e</span><span style=3D"color:#660">)</sp=
an><span style=3D"color:#000"><br></span><span style=3D"color:#660">{</span=
><span style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#800">//=
Do stuff for E_exception</span><span style=3D"color:#000"><br></span><span =
style=3D"color:#660">}</span><span style=3D"color:#000"><br></span><span st=
yle=3D"color:#008">catch</span><span style=3D"color:#660">(</span><span sty=
le=3D"color:#000">D_exception </span><span style=3D"color:#660">&</span=
><span style=3D"color:#000">e</span><span style=3D"color:#660">)</span><spa=
n style=3D"color:#000"><br></span><span style=3D"color:#660">{</span><span =
style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#800">//Do stuf=
f for D_exception</span><span style=3D"color:#000"><br>=C2=A0 </span><span =
style=3D"color:#008">throw</span><span style=3D"color:#660">;</span><span s=
tyle=3D"color:#000"><br></span><span style=3D"color:#660">}</span><span sty=
le=3D"color:#000"><br></span><span style=3D"color:#008">catch</span><span s=
tyle=3D"color:#660">(</span><span style=3D"color:#000">E_exception_combined=
_<wbr>with_D_exception </span><span style=3D"color:#660">&</span><span =
style=3D"color:#000">e</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"><br></span><code><span style=3D"color:#000">=C2=A0 </span><=
span style=3D"color:#800">//Do stuff for E_exception</span><span style=3D"c=
olor:#000"><br></span><span style=3D"color:#000"></span></code><code><span =
style=3D"color:#000">=C2=A0 </span><span style=3D"color:#800">//Do stuff fo=
r D_exception</span><span style=3D"color:#000"><br></span><span style=3D"co=
lor:#000"></span></code><span style=3D"color:#000">=C2=A0 </span><span styl=
e=3D"color:#008">throw</span><span style=3D"color:#660">;</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#660">}</span><span style=
=3D"color:#000"><br></span></div></code></div><br>That's a lot of repet=
ition.<br></div></div></blockquote><div><br></div><div>You literally built =
a gun, took it in your hands, aimed at your feet and pressed the trigger. W=
hat prevents you from catching one base exception?</div></div></blockquote>=
<div><br>Your question is like asking "why return X, when you could re=
turn a `std::any` that maybe contains an X or a Y?"<br><br>If I wrote =
C and E, but not D (E may be a callback/continuation/etc passed to D), why =
would I tie my `E_exception` to whatever D throws? The whole point of excep=
tion catching is that I choose what to catch, and the compiler will find th=
e right handler for the exception.<br><br></div><blockquote class=3D"gmail_=
quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;pa=
dding-left: 1ex;"><div dir=3D"ltr"><div>In most cases you wouldn't care=
if it replaced bunch of others -- operation failed, here is a result from =
one of failed sub-operations.</div></div></blockquote><div><br>That is an..=
.. interesting perspective on how you think people catch exceptions and trea=
t their contents.<br><br></div><blockquote class=3D"gmail_quote" style=3D"m=
argin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"=
><div dir=3D"ltr"><div>You may have some additional information if you '=
;unroll' nested struct. Most of code is unlikely to use throwing dtors =
and therefore they won't have to deal with this.</div></div></blockquot=
e><div><br>But since you don't control all code, you can't know tha=
t it won't happen. And therefore, every `catch` statement must be writt=
en expecting this possibility.<br><br>Whereas right now, I don't have t=
o care. Throwing destructors during unwinding will yield `std::terminate`. =
And that's not something I have to write code for.<br>=C2=A0</div><bloc=
kquote 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>Wrt "one=
_exception_combined_with_<wbr>others" check -- I'd like to wrap **=
every** exception into a structure like this,</div></div></blockquote><div>=
<br>That would be the fastest way to make everybody stop using exception ha=
ndling.<br>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0=
;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div di=
r=3D"ltr"><div>but this would be breaking change and against the spirit of =
C++ "you don't pay until you use it". So proposal is to apply=
wrapper on first instance of "replacing".</div></div></blockquot=
e><div></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">=
<div></div><div>And again -- actual 'combination' logic is not set =
in stone. What I proposed is just a first attempt. <br></div></div></blockq=
uote><br>OK, can we have an attempt that makes sense and is at least theore=
tically usable? Because thus far, even if I <i>wanted</i> to have a solutio=
n to exception collisions, the ideas you've proposed make working with =
exceptions <i>incredibly tedious</i>. Having to catch a single type and man=
ually fish out of it the type you're maybe interested in, and then prop=
agating the rest if any? No, that's horrible code that should be handle=
d by the system.<br><br>Not having to write that code is precisely why `cat=
ch` statements are <i>typed</i>.<br><br><blockquote class=3D"gmail_quote" s=
tyle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-le=
ft: 1ex;"><div dir=3D"ltr"><div></div><blockquote class=3D"gmail_quote" sty=
le=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1e=
x"><div dir=3D"ltr"><div></div><blockquote class=3D"gmail_quote" style=3D"m=
argin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div=
dir=3D"ltr"><div></div><div>try writing similar logic using EH -- it will =
be very awkward, lots of code.</div></div></blockquote><div><br>Please prov=
ide a practical example of that. Something from the real world, where "=
;somehow combine results" is something other than "swallow the ex=
ception".<br></div></div></blockquote><div><br></div><div><div>error_t=
do_work()</div><div>{</div><div>=C2=A0 =C2=A0 start_device1();</div><div>=
=C2=A0 =C2=A0 // return if failed to start, return array of values (one cod=
e per device)</div><div>=C2=A0 =C2=A0 start_device2();</div><div>=C2=A0 =C2=
=A0 // if failed: stop_device1, if device1 fails to stop -- set it's er=
ror code too</div><div>=C2=A0 =C2=A0 start_device3();</div><div>=C2=A0 =C2=
=A0 // if failed: stop_device1, if device1 fails to stop -- set it's er=
ror code too</div><div>=C2=A0 =C2=A0 // =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 stop_device2, if device2 fails to stop -- set it's error =
code too</div><div><br></div><div>=C2=A0 =C2=A0// do work using these devic=
es (don't forget to stop them if smth fails during it)</div><div>=C2=A0=
=C2=A0 ...</div><div><br></div><div>=C2=A0 =C2=A0 // time to stop devices<=
/div><div>=C2=A0 =C2=A0 code res1 =3D stop_device3();</div><div>=C2=A0 =C2=
=A0 code res2 =3D stop_device2();</div><div>=C2=A0 =C2=A0 code res3 =3D sto=
p_device1();</div><div><br></div><div>=C2=A0 =C2=A0 // somehow combine resu=
lts</div><div>=C2=A0 =C2=A0 return {res1, res2, res3};</div><div>}<br></div=
></div><div><br></div><div>In case if you wonder -- this is not made up sit=
uation. I've seen it.</div><div><br></div><div>=C2=A0</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"><div>=C2=A0</div><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div dir=3D"ltr"><div>Keep in mind that no matte=
r what each of functions above need to be called no matter what.</div></div=
></blockquote><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px=
0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>=C2=A0=
</div></blockquote><blockquote class=3D"gmail_quote" style=3D"margin:0;marg=
in-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"=
><div>Let's say that each one attempts to switch off a piece of very ex=
pensive machinery. You can't make it no-fail for physical reasons. And =
if something goes wrong you need to report error(s) upstairs for analysis a=
nd associated actions.</div><div><br></div><div>with this proposal you can =
put these do_smthN() calls into destructors and automatically get "alw=
ays gets invoked" guarantee along with some (hopefully sensible) mecha=
nism that is going to combine these errors for propagation up-stack. If use=
r doesn't like default mechanism -- he'll use aforementioned knobs =
to tune it to his liking.</div><div><br></div><div>Right now you have to ma=
ke these dtors silent and accumulate these errors elsewhere -- basically tu=
rning EH into some weird mix of both styles.</div></div></blockquote><div><=
br>... OK, I'll play along. You want people to write this:<br><br><div =
style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);bo=
rder-style:solid;border-width:1px"><code><div><span style=3D"color:#008">tr=
y</span><span style=3D"color:#000"><br></span><span style=3D"color:#660">{<=
/span><span style=3D"color:#000"><br>=C2=A0 something_doer_3 t3</span><span=
style=3D"color:#660">{};</span><span style=3D"color:#000"><br>=C2=A0 somet=
hing_doer_2 t2</span><span style=3D"color:#660">{};</span><span style=3D"co=
lor:#000"><br>=C2=A0 something_doer_1 t1</span><span style=3D"color:#660">{=
};</span><span style=3D"color:#000"><br></span><span style=3D"color:#660">}=
</span><span style=3D"color:#000"><br></span><span style=3D"color:#008">cat=
ch</span><span style=3D"color:#660">(</span><span style=3D"color:#000">some=
thing</span><span style=3D"color:#660">)</span><span style=3D"color:#000"><=
br></span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br=
>=C2=A0 //Combine the errors<br></span><span style=3D"color:#660">}</span><=
span style=3D"color:#000"><br></span></div></code></div><br>Where the destr=
uctors of those three types are what does the work.<br></div></div></blockq=
uote><div><br></div><div>rewriting example from above using EH:</div><div>t=
ry</div><div>{</div><div>=C2=A0 =C2=A0 auto_start_stop device1{}; =C2=A0 =
=C2=A0// starts device in ctor, stops in dtor -- both ops can fail with exc=
eption</div><div>=C2=A0 =C2=A0 auto_start_stop device2{};</div><div>=C2=A0 =
=C2=A0 auto_start_stop device3{};</div><div><br></div><div>=C2=A0 =C2=A0 //=
do work using these devices (which can throw too)</div><div>}</div><div>ca=
tch(error_base const&)</div><div>{</div><div>=C2=A0 =C2=A0 // entire op=
eration failed, if we want, we could check if this is a combined exception =
and pull it apart)</div><div>}</div></div></blockquote><div><br>Now, show m=
e the code for this "check if this is a combined exception and pull it=
apart". Then compare it to the error code equivalent. Show me how thi=
s is in any way better.<br><br>Indeed, this is a perfect example of exactly=
why your idea doesn't work.<br><br>OK, let's say that something in=
"do work using these devices (which can throw too)" throws. The =
caller of this function catches it, so the stack starts unwinding. Those de=
structors start failing, so a second exception is emitted that gets caught =
right here.<br><br>So... what about the first exception? That exception rep=
resents a condition that has not yet been resolved (since the code to resol=
ve it has not been executed). How does it get to its destination, so that t=
he error can be resolved? Is the catch statement here supposed to extract i=
t and propagate it on, or will the system do so automatically? If it requir=
es manual coding, is the user able to code it so that it works with <i>any<=
/i> exception, or does the user have to special-case it for certain excepti=
on types? Is it possible for this catch statement to effectively swallow <i=
>all</i> exceptions, in the event that it throws during unwinding?<br><br>E=
ven taking your idea at face value, there are just too many unknowns about =
it to really give it any consideration.<br><br>By contrast, with the error =
code version (or rather the `File::close` version, where the destructor and=
an explicit member can both close, but the destructor swallows the error),=
it just eats the errors as the stack unwinds. Nobody gets informed about t=
hose problems, but nobody <i>needs</i> to be either. Does the person receiv=
ing the exception from "do work using these devices" really need =
to know if device stopping failed?<br><br>The case you describe is actually=
perfect for an out-of-band error mechanism (something like `std:errno` or =
`glGetError`) to report the errors from the destructor of the device class.=
That allows the caller to be able to ask whether device stoppage succeeded=
<i>without</i> having to have this aggregation of return values. And it wo=
rks very well with exceptions, since the error can still be reported withou=
t interfering in the exception itself. After all, you're talking about =
what is a different <i>channel</i> of error from the original exception.<br=
><br>No one error handling mechanism fits all cases. Even `errno` has its p=
lace.<br> </div></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/6a9c0d42-d76e-4b56-b5e7-51df8191dacd%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/6a9c0d42-d76e-4b56-b5e7-51df8191dacd=
%40isocpp.org</a>.<br />
------=_Part_7357_796122659.1503962202352--
------=_Part_7356_1414331437.1503962202351--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Mon, 28 Aug 2017 16:16:59 -0700 (PDT)
Raw View
------=_Part_7234_916716392.1503962219351
Content-Type: multipart/alternative;
boundary="----=_Part_7235_1318285980.1503962219351"
------=_Part_7235_1318285980.1503962219351
Content-Type: text/plain; charset="UTF-8"
On Monday, August 28, 2017 at 3:25:35 PM UTC-4, crusad...@gmail.com wrote:
>
>
>
> On Monday, August 28, 2017 at 1:14:17 PM UTC-5, Thiago Macieira wrote:
>>
>> On Monday, 28 August 2017 09:50:55 PDT crusad...@gmail.com wrote:
>> > > > I can obviously use C-style approach -- but then my code will be
>> > >
>> > > littered
>> > >
>> > > > with "if"s (and nested "if"s) just like yours. Or I can rely on
>> stack
>> > > > unwinding to guarantee that these functions get called -- in which
>> case
>> > > > code becomes nice and neat, but (as of now)I can't report any
>> failures
>> > > > without inventing some sort of 'under the hood' logic that
>> circumvents
>> > > > "no-fail dtor" rule.
>> > >
>> > > I think you should litter your code. Relying on the stack unwinding
>> to do
>> > > something it's not meant to and guess what you meant is not a good
>> idea.
>> >
>> > Pretty sure RAII was meant exactly for that -- to guarantee that
>> certain
>> > functions (dtors) get called no matter what. "No-fault dtors" rule is
>> > simply because there is no easy (or right) way to propagate multiple
>> > exceptions (if these dtors throw). None of the provided "but it doesn't
>> > make sense" arguments (you and Nicol provided) seem convincing.
>>
>> There's a difference between the unwinding and destruction and the act of
>> cleanup.
>>
>> If the clean up can fail, then it's not something that should be done in
>> the
>> destructor.
>
>
> Why? This logic is the result of "dtor shouldn't fail" dogma. Which I am
> kind of challenging right now. If my challenge succeeds -- this statement
> has to legs to stand on.
>
I've yet to see you explain how it *does* make sense to say that an
object's destruction has failed. What does it say about the state of the
object for its destruction to fail? What does it say about the state of the
program?
The closest you've gotten is from a world-view perspective where
destructors are no different from regular function calls. And therefore
they should be able to fail. That doesn't exactly tell me what it *means*
when an object's destructor has failed.
Try it before, catch any errors, and fail accordingly. If you fail
>> to clean up in response to an earlier failure, handle it appropriately
>> according to your code.
>>
>
> I proposed you to write code that has to perform three different cleanup
> tasks. I had to do it multiple times in my life -- every time had to resort
> to some equivalent of C-style error handling and it didn't make me happy.
>
> Here is another consideration:
>
> class File
> {
> file* f;
> ...
> };
>
> void foo()
> {
> File f = ...;
> // write stuff
>
> // gotta close it because it may fail and we can't report failure from
> dtor
> f.close();
>
> // now File invariant has to support 'not open' state via additional
> boolean member (or magical NULL value)
> // and ~File() (and probably bunch of other member functions) have to
> contain unnecessary branch that checks for that
>
But `File` has to do that anyway. Why? Because it should be *moveable*, and
therefore a moved-from `File` object needs to be able to exist.
So you're going to have that functionality for other reasons.
--
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/16fc24ef-9172-4993-a575-bca3fb1ba339%40isocpp.org.
------=_Part_7235_1318285980.1503962219351
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Monday, August 28, 2017 at 3:25:35 PM UTC-4, cr=
usad...@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: =
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div d=
ir=3D"ltr"><br><br>On Monday, August 28, 2017 at 1:14:17 PM UTC-5, Thiago M=
acieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-le=
ft:0.8ex;border-left:1px #ccc solid;padding-left:1ex">On Monday, 28 August =
2017 09:50:55 PDT <a rel=3D"nofollow">crusad...@gmail.com</a> wrote:
<br>> > > I can obviously use C-style approach -- but then my code=
will be
<br>> >=20
<br>> > littered
<br>> >=20
<br>> > > with "if"s (and nested "if"s) just l=
ike yours. Or I can rely on stack
<br>> > > unwinding to guarantee that these functions get called -=
- in which case
<br>> > > code becomes nice and neat, but (as of now)I can't r=
eport any failures
<br>> > > without inventing some sort of 'under the hood' =
logic that circumvents
<br>> > > "no-fail dtor" rule.
<br>> >=20
<br>> > I think you should litter your code. Relying on the stack unw=
inding to do
<br>> > something it's not meant to and guess what you meant is n=
ot a good idea.
<br>>=20
<br>> Pretty sure RAII was meant exactly for that -- to guarantee that c=
ertain
<br>> functions (dtors) get called no matter what. "No-fault dtors&=
quot; rule is
<br>> simply because there is no easy (or right) way to propagate multip=
le
<br>> exceptions (if these dtors throw). None of the provided "but =
it doesn't
<br>> make sense" arguments (you and Nicol provided) seem convincin=
g.
<br>
<br>There's a difference between the unwinding and destruction and the =
act of=20
<br>cleanup.
<br>
<br>If the clean up can fail, then it's not something that should be do=
ne in the=20
<br>destructor.</blockquote><div><br></div><div>Why? This logic is the resu=
lt of "dtor shouldn't fail" dogma. Which I am kind of challen=
ging right now. If my challenge succeeds -- this statement has to legs to s=
tand on.</div></div></blockquote><div><br>I've yet to see you explain h=
ow it <i>does</i> make sense to say that an
object's destruction has failed. What does it say about the state of=
=20
the object for its destruction to fail? What does it say about the state
of the program?<br><br>The closest you've gotten is from a world-view =
perspective where destructors are no different from regular function calls.=
And therefore they should be able to fail. That doesn't exactly tell m=
e what it <i>means</i> when an object's destructor has failed.<br><br><=
/div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><blockqu=
ote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1=
px #ccc solid;padding-left:1ex"> Try it before, catch any errors, and fail =
accordingly. If you fail=20
<br>to clean up in response to an earlier failure, handle it appropriately=
=20
<br>according to your code.
<br></blockquote><div><br></div><div>I proposed you to write code that has =
to perform three different cleanup tasks. I had to do it multiple times in =
my life -- every time had to resort to some equivalent of C-style error han=
dling and it didn't make me happy.</div><div><br></div><div>Here is ano=
ther consideration:</div><div><br></div><div>class File</div><div>{</div><d=
iv>=C2=A0 =C2=A0 file* f;</div><div>=C2=A0 =C2=A0 ...</div><div>};</div><di=
v><br></div><div>void foo()</div><div>{</div><div>=C2=A0 =C2=A0 File f =3D =
....;</div><div>=C2=A0 =C2=A0 // write stuff</div><div><br></div><div>=C2=A0=
=C2=A0 // gotta close it because it may fail and we can't report failu=
re from dtor</div><div>=C2=A0 =C2=A0 f.close();</div><div><br></div><div>=
=C2=A0 =C2=A0 // now File invariant has to support 'not open' state=
via additional boolean member (or magical NULL value)</div><div>=C2=A0 =C2=
=A0 // and ~File() (and probably bunch of other member functions) have to c=
ontain unnecessary branch that checks for that </div></div></blockquote><di=
v><br>But `File` has to do that anyway. Why? Because it should be <i>moveab=
le</i>, and therefore a moved-from `File` object needs to be able to exist.=
<br><br>So you're going to have that functionality for other reasons.<b=
r></div></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/16fc24ef-9172-4993-a575-bca3fb1ba339%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/16fc24ef-9172-4993-a575-bca3fb1ba339=
%40isocpp.org</a>.<br />
------=_Part_7235_1318285980.1503962219351--
------=_Part_7234_916716392.1503962219351--
.
Author: crusader.mike@gmail.com
Date: Tue, 29 Aug 2017 10:27:34 -0700 (PDT)
Raw View
------=_Part_3207_2039423965.1504027654790
Content-Type: multipart/alternative;
boundary="----=_Part_3208_519919484.1504027654790"
------=_Part_3208_519919484.1504027654790
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Monday, August 28, 2017 at 5:10:44 PM UTC-5, Bryce Glover wrote:
>
> Just to pop my head up from lurking for a second, this seems, upon=
=20
> preliminary skimming, like it might be a use case for P0322 on=20
> `exception_list`s <http://wg21.link/p0322> if it were multithreaded, but=
=20
> it=E2=80=99s not, so it probably isn=E2=80=99t, though you might be able =
to set up similar=20
> with coroutines=E2=80=A6? =20
>
Yep, this can be used as aforementioned container
=20
>
> Nowhere near being entirely sure at *all*,=20
> Bryce Glover
> Random...@gmail.com <javascript:>
>
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/1d9ba50f-fdb1-4693-b791-db7f2c19fb2d%40isocpp.or=
g.
------=_Part_3208_519919484.1504027654790
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Monday, August 28, 2017 at 5:10:44 PM UTC-5, Bryce Glov=
er wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word-wr=
ap:break-word">=C2=A0 =C2=A0 =C2=A0Just to pop my head up from lurking for =
a second, this seems, upon preliminary skimming, like it might be a use cas=
e for=C2=A0<a href=3D"http://wg21.link/p0322" target=3D"_blank" rel=3D"nofo=
llow" onmousedown=3D"this.href=3D'http://www.google.com/url?q\x3dhttp%3=
A%2F%2Fwg21.link%2Fp0322\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHO9iKbbiXn=
CGnBZEOFjtO4D6D0qQ';return true;" onclick=3D"this.href=3D'http://ww=
w.google.com/url?q\x3dhttp%3A%2F%2Fwg21.link%2Fp0322\x26sa\x3dD\x26sntz\x3d=
1\x26usg\x3dAFQjCNHO9iKbbiXnCGnBZEOFjtO4D6D0qQ';return true;">P0322 on =
`exception_list`s</a>=C2=A0if it were multithreaded, but it=E2=80=99s not, =
so it probably isn=E2=80=99t, though you might be able to set up similar wi=
th coroutines=E2=80=A6? =C2=A0<br></div></blockquote><div><br></div><div>Ye=
p, this can be used as aforementioned container</div><div><br></div><div>=
=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=3D"word=
-wrap:break-word"><br><div>
<div style=3D"color:rgb(0,0,0);letter-spacing:normal;text-align:start;text-=
indent:0px;text-transform:none;white-space:normal;word-spacing:0px;word-wra=
p:break-word"><div style=3D"color:rgb(0,0,0);letter-spacing:normal;text-ali=
gn:start;text-indent:0px;text-transform:none;white-space:normal;word-spacin=
g:0px;word-wrap:break-word"><div style=3D"color:rgb(0,0,0);letter-spacing:n=
ormal;text-align:start;text-indent:0px;text-transform:none;white-space:norm=
al;word-spacing:0px;word-wrap:break-word"><div>Nowhere near being entirely =
sure at <i>all</i>,=C2=A0</div><div>=C2=A0 =C2=A0 =C2=A0Bryce Glover</div><=
div>=C2=A0 =C2=A0 =C2=A0<a href=3D"javascript:" target=3D"_blank" gdf-obfus=
cated-mailto=3D"EjKL4ZCuDAAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D&=
#39;javascript:';return true;" onclick=3D"this.href=3D'javascript:&=
#39;;return true;">Random...@gmail.com</a></div></div></div></div></div></d=
iv></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/1d9ba50f-fdb1-4693-b791-db7f2c19fb2d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/1d9ba50f-fdb1-4693-b791-db7f2c19fb2d=
%40isocpp.org</a>.<br />
------=_Part_3208_519919484.1504027654790--
------=_Part_3207_2039423965.1504027654790--
.
Author: crusader.mike@gmail.com
Date: Tue, 29 Aug 2017 10:32:20 -0700 (PDT)
Raw View
------=_Part_1945_424764713.1504027940681
Content-Type: multipart/alternative;
boundary="----=_Part_1946_2107931625.1504027940681"
------=_Part_1946_2107931625.1504027940681
Content-Type: text/plain; charset="UTF-8"
On Monday, August 28, 2017 at 5:57:54 PM UTC-5, Thiago Macieira wrote:
>
> On Monday, 28 August 2017 15:08:05 PDT crusad...@gmail.com <javascript:>
> wrote:
> > > But they are most definitely the wrong tool for both clean-up and
> normal
> > > error
> > > conditions. This is not an inherent problem with exceptions, but with
> how
> > > they
> > > are used. It's an API problem -- the same problem that fclose() has:
> the
> > > destruction can fail and your only recourse is to leak.
> >
> > You have deeply embedded belief that destructor should never fail. In
> fact
> > exception doesn't even mean anything failed -- it is just a way to
> redirect
> > execution to another place. It is rather inefficient for that, of
> course,
> > but if I had a cent for every time I saw code that can be done more
> > efficiently -- I would have bought me a planet already.
>
> Yes. Exceptions should be used for exceptional behaviour, that something
> unexpected happened. They should not be used for normal behaviour, like
> failing to open a file because it doesn't exist.
>
> But more importantly in your case, pay attention to your own words
> "destructor
> should never fail" and "exception doesn't mean anything failed". If
> nothing
> failed, then the destructor didn't fail. So why the hell did it throw?
>
'Failure' is defined by user. On language level there is no such this as
'failed function call'. I as a user want to return some sort of status
code, error object from given function call and language doesn't really
care if dtor exited normally or via exception.
If you've recovered from the error, then why does it need reporting? Maybe
> you're looking for logging, not exceptions.
>
> If you didn't recover from the error, then you should hope that all that's
> wrong now is that you have a resource leak.
>
It depends on logic user put into dtor -- I don't see why exception have to
result in resource leak. Forcing dtors to eat exceptions is not a good idea.
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
>
>
--
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/57d27c76-5abc-4f82-84b1-64373948560b%40isocpp.org.
------=_Part_1946_2107931625.1504027940681
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Monday, August 28, 2017 at 5:57:54 PM UTC-5, Th=
iago Macieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Monday,=
28 August 2017 15:08:05 PDT <a href=3D"javascript:" target=3D"_blank" gdf-=
obfuscated-mailto=3D"QhQT4SOxDAAJ" rel=3D"nofollow" onmousedown=3D"this.hre=
f=3D'javascript:';return true;" onclick=3D"this.href=3D'javascr=
ipt:';return true;">crusad...@gmail.com</a> wrote:
<br>> > But they are most definitely the wrong tool for both clean-up=
and normal
<br>> > error
<br>> > conditions. This is not an inherent problem with exceptions, =
but with how
<br>> > they
<br>> > are used. It's an API problem -- the same problem that fc=
lose() has: the
<br>> > destruction can fail and your only recourse is to leak.
<br>>=20
<br>> You have deeply embedded belief that destructor should never fail.=
In fact
<br>> exception doesn't even mean anything failed -- it is just a wa=
y to redirect
<br>> execution to another place. It is rather inefficient for that, of =
course,
<br>> but if I had a cent for every time I saw code that can be done mor=
e
<br>> efficiently -- I would have bought me a planet already.
<br>
<br>Yes. Exceptions should be used for exceptional behaviour, that somethin=
g=20
<br>unexpected happened. They should not be used for normal behaviour, like=
=20
<br>failing to open a file because it doesn't exist.
<br>
<br>But more importantly in your case, pay attention to your own words &quo=
t;destructor=20
<br>should never fail" and "exception doesn't mean anything f=
ailed". If nothing=20
<br>failed, then the destructor didn't fail. So why the hell did it thr=
ow?
<br></blockquote><div><br></div><div>'Failure' is defined by user. =
On language level there is no such this as 'failed function call'. =
I as a user want to return some sort of status code, error object from give=
n function call and language doesn't really care if dtor exited normall=
y or via exception.</div><div>=C2=A0</div><div><br></div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;">If you've recovered from the error, then wh=
y does it need reporting? Maybe=20
<br>you're looking for logging, not exceptions.
<br>
<br>If you didn't recover from the error, then you should hope that all=
that's=20
<br>wrong now is that you have a resource leak.
<br></blockquote><div><br></div><div>It depends on logic user put into dtor=
-- I don't see why exception have to result in resource leak. Forcing =
dtors to eat exceptions is not a good idea.</div><div><br></div><div>=C2=A0=
</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8=
ex;border-left: 1px #ccc solid;padding-left: 1ex;">--=20
<br>Thiago Macieira - thiago (AT) <a href=3D"http://macieira.info" target=
=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.goo=
gle.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x3dD\x26sntz\x3d1\x26usg\=
x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.hr=
ef=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x=
3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return t=
rue;">macieira.info</a> - thiago (AT) <a href=3D"http://kde.org" target=3D"=
_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.google.=
com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNH=
GRJdo5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'=
http://www.google.com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1=
\x26usg\x3dAFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;">kde.org</a=
>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>
<br></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/57d27c76-5abc-4f82-84b1-64373948560b%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/57d27c76-5abc-4f82-84b1-64373948560b=
%40isocpp.org</a>.<br />
------=_Part_1946_2107931625.1504027940681--
------=_Part_1945_424764713.1504027940681--
.
Author: crusader.mike@gmail.com
Date: Tue, 29 Aug 2017 10:39:21 -0700 (PDT)
Raw View
------=_Part_8360_443755053.1504028361106
Content-Type: multipart/alternative;
boundary="----=_Part_8361_1496771562.1504028361106"
------=_Part_8361_1496771562.1504028361106
Content-Type: text/plain; charset="UTF-8"
On Monday, August 28, 2017 at 5:52:23 PM UTC-5, Thiago Macieira wrote:
>
> On Monday, 28 August 2017 14:53:22 PDT crusad...@gmail.com <javascript:>
> wrote:
> > That is precisely what I am going to claim. If you chose to use
> exception
> > to report problem from dtor -- you better write it in such way that it
> > makes sense wrt your subobjects. You don't expect smth to go wrong if
> your
> > ctor throws after subobjects have been constructed? This is similar
> case.
>
> Similar and yet very different.
> If a constructor throws, all of the already-constructed sub-objects get
> unwound and destroyed. At the end of this, the object is completely
> destroyed.
>
> If a destructor throws, the not-yet-destroyed sub-objects still need to be
> destroyed.
so, what is the difference between 'already-constructed' and
'not-yet-destroyed'? ;)
> To avoid resource leaks, it needs to continue destroying as if the
> exception hadn't happened. Throwing from a destructor sounds like "in
> addition
> to destroying, I found this error, but don't worry, I have completed my
> work".
>
Yep, I don't see anything wrong here. Especially considering that all this
is already in the language. Plus, again -- language doesn't define what
error is -- user assign this semantic to certain outcomes. He may even
choose to treat exceptions as normal and normal exit -- as error.
> And hence my question: if the destructor successfully destroyed, why did
> it
> need to throw?
>
To report an error that happened during dtor call. Because instead of "I
will close file in dtor" semantic, user asserted "I will try to close file
in dtor" when designing his class.
> > > But that's
> > > exactly the point: the code that the X destructor runs before the Base
> > > destructor can run must not throw.
> >
> > As long as Base's invariant isn't compromised -- why not? And why would
> you
> > compromised your subobject's invariant? you don't do it for member
> > variables -- shouldn't do it for base class.
>
> Sorry, you don't get to question what code is questionable. You're arguing
> for
> making code that everyone else thinks is questionable legit.
>
> Anyway, a simple example for FILE*: let's say it's a protected member of
> the
> class. Also, to avoid fclose() failing, let's say an invariant condition
> is
> that every member function flushes the buffer.
A design error -- you can't guarantee that buffer will be flushed --
therefore you can't guarantee that your invariant won't be violated.
But since it's protected, let's
> say your derived class's destructor does fwrite something (like the
> terminating CRLF or a QUIT command, etc.). That violates the invariant
> condition. Now the Base class destructor may fail to clean up its
> resources.
>
> In my opinion, this is questionable code. But I think it's questionable
> because the destructor is doing something that can fail in the first place
> --
> that should not be part of the destructor, but of a cleaning up operation
> beforehand. It's no different than in C: to avoid fclose() failing, you
> should
> fflush() the stream before you close, to ensure everything got written. If
> there
> were errors, you can still recover because the FILE* is still valid.
>
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
>
>
--
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/fcadf324-62db-4598-b414-8650ac873be2%40isocpp.org.
------=_Part_8361_1496771562.1504028361106
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Monday, August 28, 2017 at 5:52:23 PM UTC-5, Th=
iago Macieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Monday,=
28 August 2017 14:53:22 PDT <a href=3D"javascript:" target=3D"_blank" gdf-=
obfuscated-mailto=3D"9FPSmdawDAAJ" rel=3D"nofollow" onmousedown=3D"this.hre=
f=3D'javascript:';return true;" onclick=3D"this.href=3D'javascr=
ipt:';return true;">crusad...@gmail.com</a> wrote:
<br>> That is precisely what I am going to claim. If you chose to use ex=
ception
<br>> to report problem from dtor -- you better write it in such way tha=
t it
<br>> makes sense wrt your subobjects. You don't expect smth to go w=
rong if your
<br>> ctor throws after subobjects have been constructed? This is simila=
r case.
<br>
<br>Similar and yet very different. =C2=A0</blockquote><blockquote class=3D=
"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc s=
olid;padding-left: 1ex;">
<br>If a constructor throws, all of the already-constructed sub-objects get=
=20
<br>unwound and destroyed. At the end of this, the object is completely des=
troyed.
<br>
<br>If a destructor throws, the not-yet-destroyed sub-objects still need to=
be=20
<br>destroyed. </blockquote><div><br></div><div>so, what is the difference =
between 'already-constructed' and 'not-yet-destroyed'? ;)</=
div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;">To avoid resource leaks, it needs to continue destroying as if the=20
<br>exception hadn't happened. Throwing from a destructor sounds like &=
quot;in addition=20
<br>to destroying, I found this error, but don't worry, I have complete=
d my work".
<br></blockquote><div><br></div><div>Yep, I don't see anything wrong he=
re. Especially considering that all this is already in the language. Plus, =
again -- language doesn't define what error is -- user assign this sema=
ntic to certain outcomes. He may even choose to treat exceptions as normal =
and normal exit -- as error.</div><div><br></div><div>=C2=A0</div><blockquo=
te class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left:=
1px #ccc solid;padding-left: 1ex;">And hence my question: if the destructo=
r successfully destroyed, why did it=20
<br>need to throw?
<br></blockquote><div>=C2=A0</div><div>To report an error that happened dur=
ing dtor call. =C2=A0Because instead of "I will close file in dtor&quo=
t; semantic, user asserted "I will try to close file in dtor" whe=
n designing his class.</div><div><br></div><div>=C2=A0</div><blockquote cla=
ss=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #=
ccc solid;padding-left: 1ex;">> > But that's
<br>> > exactly the point: the code that the X destructor runs before=
the Base
<br>> > destructor can run must not throw.
<br>>=20
<br>> As long as Base's invariant isn't compromised -- why not? =
And why would you
<br>> compromised your subobject's invariant? you don't do it fo=
r member
<br>> variables -- shouldn't do it for base class.
<br>
<br>Sorry, you don't get to question what code is questionable. You'=
;re arguing for=20
<br>making code that everyone else thinks is questionable legit.
<br>
<br>Anyway, a simple example for FILE*: let's say it's a protected =
member of the=20
<br>class. Also, to avoid fclose() failing, let's say an invariant cond=
ition is=20
<br>that every member function flushes the buffer.</blockquote><div><br></d=
iv><div>A design error -- you can't guarantee that buffer will be flush=
ed -- therefore you can't guarantee that your invariant won't be vi=
olated.</div><div>=C2=A0</div><div><br></div><blockquote class=3D"gmail_quo=
te" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddi=
ng-left: 1ex;"> But since it's protected, let's=20
<br>say your derived class's destructor does fwrite something (like the=
=20
<br>terminating CRLF or a QUIT command, etc.). That violates the invariant=
=20
<br>condition. Now the Base class destructor may fail to clean up its resou=
rces.
<br>
<br>In my opinion, this is questionable code. But I think it's question=
able=20
<br>because the destructor is doing something that can fail in the first pl=
ace --=20
<br>that should not be part of the destructor, but of a cleaning up operati=
on=20
<br>beforehand. It's no different than in C: to avoid fclose() failing,=
you should=20
<br>fflush() the stream before you close, to ensure everything got written.=
If there=20
<br>were errors, you can still recover because the FILE* is still valid.
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a href=3D"http://macieira.info" target=
=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.goo=
gle.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x3dD\x26sntz\x3d1\x26usg\=
x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.hr=
ef=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x=
3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return t=
rue;">macieira.info</a> - thiago (AT) <a href=3D"http://kde.org" target=3D"=
_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.google.=
com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNH=
GRJdo5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'=
http://www.google.com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1=
\x26usg\x3dAFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;">kde.org</a=
>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>
<br></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/fcadf324-62db-4598-b414-8650ac873be2%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/fcadf324-62db-4598-b414-8650ac873be2=
%40isocpp.org</a>.<br />
------=_Part_8361_1496771562.1504028361106--
------=_Part_8360_443755053.1504028361106--
.
Author: crusader.mike@gmail.com
Date: Tue, 29 Aug 2017 10:46:39 -0700 (PDT)
Raw View
------=_Part_8079_128790127.1504028799751
Content-Type: multipart/alternative;
boundary="----=_Part_8080_1670375717.1504028799751"
------=_Part_8080_1670375717.1504028799751
Content-Type: text/plain; charset="UTF-8"
On Monday, August 28, 2017 at 6:16:59 PM UTC-5, Nicol Bolas wrote:
>
> On Monday, August 28, 2017 at 3:25:35 PM UTC-4, crusad...@gmail.com wrote:
>>
>> On Monday, August 28, 2017 at 1:14:17 PM UTC-5, Thiago Macieira wrote:
>>>
>>> On Monday, 28 August 2017 09:50:55 PDT crusad...@gmail.com wrote:
>>> > > > I can obviously use C-style approach -- but then my code will be
>>> > >
>>> > > littered
>>> > >
>>> > > > with "if"s (and nested "if"s) just like yours. Or I can rely on
>>> stack
>>> > > > unwinding to guarantee that these functions get called -- in which
>>> case
>>> > > > code becomes nice and neat, but (as of now)I can't report any
>>> failures
>>> > > > without inventing some sort of 'under the hood' logic that
>>> circumvents
>>> > > > "no-fail dtor" rule.
>>> > >
>>> > > I think you should litter your code. Relying on the stack unwinding
>>> to do
>>> > > something it's not meant to and guess what you meant is not a good
>>> idea.
>>> >
>>> > Pretty sure RAII was meant exactly for that -- to guarantee that
>>> certain
>>> > functions (dtors) get called no matter what. "No-fault dtors" rule is
>>> > simply because there is no easy (or right) way to propagate multiple
>>> > exceptions (if these dtors throw). None of the provided "but it
>>> doesn't
>>> > make sense" arguments (you and Nicol provided) seem convincing.
>>>
>>> There's a difference between the unwinding and destruction and the act
>>> of
>>> cleanup.
>>>
>>> If the clean up can fail, then it's not something that should be done in
>>> the
>>> destructor.
>>
>>
>> Why? This logic is the result of "dtor shouldn't fail" dogma. Which I am
>> kind of challenging right now. If my challenge succeeds -- this statement
>> has to legs to stand on.
>>
>
> I've yet to see you explain how it *does* make sense to say that an
> object's destruction has failed. What does it say about the state of the
> object for its destruction to fail? What does it say about the state of the
> program?
>
There is no such thing as "failed call" on language level -- it defines
only call completed with exception or not. Whether it is used as indication
of error or not -- this semantic is associated with certain outcome by user.
> The closest you've gotten is from a world-view perspective where
> destructors are no different from regular function calls. And therefore
> they should be able to fail. That doesn't exactly tell me what it *means*
> when an object's destructor has failed.
>
It means whatever you (developer) want it to mean. In case of FILE* wrapper
class it could mean "if dtor exits with exception -- underlying fclose()
failed".
> Try it before, catch any errors, and fail accordingly. If you fail
>>> to clean up in response to an earlier failure, handle it appropriately
>>> according to your code.
>>>
>>
>> I proposed you to write code that has to perform three different cleanup
>> tasks. I had to do it multiple times in my life -- every time had to resort
>> to some equivalent of C-style error handling and it didn't make me happy.
>>
>> Here is another consideration:
>>
>> class File
>> {
>> file* f;
>> ...
>> };
>>
>> void foo()
>> {
>> File f = ...;
>> // write stuff
>>
>> // gotta close it because it may fail and we can't report failure
>> from dtor
>> f.close();
>>
>> // now File invariant has to support 'not open' state via additional
>> boolean member (or magical NULL value)
>> // and ~File() (and probably bunch of other member functions) have to
>> contain unnecessary branch that checks for that
>>
>
> But `File` has to do that anyway. Why? Because it should be *moveable*,
> and therefore a moved-from `File` object needs to be able to exist.
>
> So you're going to have that functionality for other reasons.
>
You mean 'modify-copied'? ;) There is no real move in C++. Yes, I may
choose to implement move semantic. On the other hand I may not. Or I may
implement it as an update to external global map that associates FILE*
values with File address (thus avoiding need to having NULL value). In any
case this is unrelated to what was discussed.
--
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/4bb258d2-5ef8-49ff-962c-9f83a15e7882%40isocpp.org.
------=_Part_8080_1670375717.1504028799751
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Monday, August 28, 2017 at 6:16:59 PM UTC-5, Nicol Bola=
s 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">On Mo=
nday, August 28, 2017 at 3:25:35 PM UTC-4, <a>crusad...@gmail.com</a> wrote=
:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bord=
er-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On Monday, August=
28, 2017 at 1:14:17 PM UTC-5, Thiago Macieira wrote:<blockquote class=3D"g=
mail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;=
padding-left:1ex">On Monday, 28 August 2017 09:50:55 PDT <a rel=3D"nofollow=
">crusad...@gmail.com</a> wrote:
<br>> > > I can obviously use C-style approach -- but then my code=
will be
<br>> >=20
<br>> > littered
<br>> >=20
<br>> > > with "if"s (and nested "if"s) just l=
ike yours. Or I can rely on stack
<br>> > > unwinding to guarantee that these functions get called -=
- in which case
<br>> > > code becomes nice and neat, but (as of now)I can't r=
eport any failures
<br>> > > without inventing some sort of 'under the hood' =
logic that circumvents
<br>> > > "no-fail dtor" rule.
<br>> >=20
<br>> > I think you should litter your code. Relying on the stack unw=
inding to do
<br>> > something it's not meant to and guess what you meant is n=
ot a good idea.
<br>>=20
<br>> Pretty sure RAII was meant exactly for that -- to guarantee that c=
ertain
<br>> functions (dtors) get called no matter what. "No-fault dtors&=
quot; rule is
<br>> simply because there is no easy (or right) way to propagate multip=
le
<br>> exceptions (if these dtors throw). None of the provided "but =
it doesn't
<br>> make sense" arguments (you and Nicol provided) seem convincin=
g.
<br>
<br>There's a difference between the unwinding and destruction and the =
act of=20
<br>cleanup.
<br>
<br>If the clean up can fail, then it's not something that should be do=
ne in the=20
<br>destructor.</blockquote><div><br></div><div>Why? This logic is the resu=
lt of "dtor shouldn't fail" dogma. Which I am kind of challen=
ging right now. If my challenge succeeds -- this statement has to legs to s=
tand on.</div></div></blockquote><div><br>I've yet to see you explain h=
ow it <i>does</i> make sense to say that an
object's destruction has failed. What does it say about the state of=
=20
the object for its destruction to fail? What does it say about the state
of the program?<br></div></div></blockquote><div><br></div><div>There is n=
o such thing as "failed call" on language level -- it defines onl=
y call completed with exception or not. Whether it is used as indication of=
error or not -- this semantic is associated with certain outcome by user.<=
/div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" styl=
e=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left:=
1ex;"><div dir=3D"ltr"><div>The closest you've gotten is from a world-=
view perspective where destructors are no different from regular function c=
alls. And therefore they should be able to fail. That doesn't exactly t=
ell me what it <i>means</i> when an object's destructor has failed.<br>=
</div></div></blockquote><div><br></div><div>It means whatever you (develop=
er) want it to mean. In case of FILE* wrapper class it could mean "if =
dtor exits with exception -- underlying fclose() failed".</div><div><b=
r></div><div>=C2=A0</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:0;margin-left=
:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><block=
quote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left=
:1px #ccc solid;padding-left:1ex">Try it before, catch any errors, and fail=
accordingly. If you fail=20
<br>to clean up in response to an earlier failure, handle it appropriately=
=20
<br>according to your code.
<br></blockquote><div><br></div><div>I proposed you to write code that has =
to perform three different cleanup tasks. I had to do it multiple times in =
my life -- every time had to resort to some equivalent of C-style error han=
dling and it didn't make me happy.</div><div><br></div><div>Here is ano=
ther consideration:</div><div><br></div><div>class File</div><div>{</div><d=
iv>=C2=A0 =C2=A0 file* f;</div><div>=C2=A0 =C2=A0 ...</div><div>};</div><di=
v><br></div><div>void foo()</div><div>{</div><div>=C2=A0 =C2=A0 File f =3D =
....;</div><div>=C2=A0 =C2=A0 // write stuff</div><div><br></div><div>=C2=A0=
=C2=A0 // gotta close it because it may fail and we can't report failu=
re from dtor</div><div>=C2=A0 =C2=A0 f.close();</div><div><br></div><div>=
=C2=A0 =C2=A0 // now File invariant has to support 'not open' state=
via additional boolean member (or magical NULL value)</div><div>=C2=A0 =C2=
=A0 // and ~File() (and probably bunch of other member functions) have to c=
ontain unnecessary branch that checks for that </div></div></blockquote><di=
v><br>But `File` has to do that anyway. Why? Because it should be <i>moveab=
le</i>, and therefore a moved-from `File` object needs to be able to exist.=
<br></div></div></blockquote><blockquote class=3D"gmail_quote" style=3D"mar=
gin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><=
div dir=3D"ltr"><div><br>So you're going to have that functionality for=
other reasons.<br></div></div></blockquote><div><br></div><div>You mean &#=
39;modify-copied'? ;) There is no real move in C++. Yes, I may choose t=
o implement move semantic. On the other hand I may not. Or I may implement =
it as an update to external global map that associates FILE* values with Fi=
le address (thus avoiding need to having NULL value). In any case this is u=
nrelated to what was discussed.</div><div><br></div><div>=C2=A0</div></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/4bb258d2-5ef8-49ff-962c-9f83a15e7882%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/4bb258d2-5ef8-49ff-962c-9f83a15e7882=
%40isocpp.org</a>.<br />
------=_Part_8080_1670375717.1504028799751--
------=_Part_8079_128790127.1504028799751--
.
Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Tue, 29 Aug 2017 14:19:53 -0400
Raw View
On 2017-08-29 13:39, crusader.mike@gmail.com wrote:
> On Monday, August 28, 2017 at 5:52:23 PM UTC-5, Thiago Macieira wrote:
>> If a constructor throws, all of the already-constructed sub-objects get
>> unwound and destroyed. At the end of this, the object is completely
>> destroyed.
>>
>> If a destructor throws, the not-yet-destroyed sub-objects still need to be
>> destroyed.
>
> so, what is the difference between 'already-constructed' and
> 'not-yet-destroyed'? ;)
You can undo construction. You can't undo destruction.
Even if you could, then you'd have a fully not-deconstructed object that
was being destroyed due to stack unwinding... and then what? ...undo the
stack unwinding back to where the exception was thrown and do something
else?
That's just nonsense. Failing destructors, especially when exceptions
are in flight, are *bad*.
> He may even
> choose to treat exceptions as normal and normal exit -- as error.
Exceptions are *not* normal. They are *exceptional*. It's right there in
the name.
If you are using exceptions for control flow in *unexceptional*
situations, you are using them *wrong*.
>> And hence my question: if the destructor successfully destroyed, why did
>> it need to throw?
>
> To report an error that happened during dtor call. Because instead of "I
> will close file in dtor" semantic, user asserted "I will try to close file
> in dtor" when designing his class.
*Wrong*.
Exceptions are a mechanism to report *failure*, because something went
so sideways that execution in the current context *cannot continue*.
What you are describing is very specifically *not* this case.
Failure to destroy an object is a *hard failure*. There is no practical
way in which that is recoverable, any more than overwriting random
memory is recoverable. Exceptions are *not* a mechanism for an object to
report "well, I went away, but BTW something went wrong". For that, an
out-of-band error reporting mechanism (e.g. errno) is appropriate.
The reason exceptions are giving you trouble is because they are not the
correct tool for what you are trying to achieve.
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/244d46f9-1e5b-15ff-0fb2-7d7a76cd9486%40gmail.com.
.
Author: crusader.mike@gmail.com
Date: Tue, 29 Aug 2017 11:44:33 -0700 (PDT)
Raw View
------=_Part_8385_841582937.1504032273874
Content-Type: multipart/alternative;
boundary="----=_Part_8386_278601144.1504032273874"
------=_Part_8386_278601144.1504032273874
Content-Type: text/plain; charset="UTF-8"
On Tuesday, August 29, 2017 at 1:19:58 PM UTC-5, Matthew Woehlke wrote:
>
> On 2017-08-29 13:39, crusad...@gmail.com <javascript:> wrote:
> > On Monday, August 28, 2017 at 5:52:23 PM UTC-5, Thiago Macieira wrote:
> >> If a constructor throws, all of the already-constructed sub-objects get
> >> unwound and destroyed. At the end of this, the object is completely
> >> destroyed.
> >>
> >> If a destructor throws, the not-yet-destroyed sub-objects still need to
> be
> >> destroyed.
> >
> > so, what is the difference between 'already-constructed' and
> > 'not-yet-destroyed'? ;)
>
> You can undo construction. You can't undo destruction.
>
It is not about undoing anything. You switched context.
> Even if you could, then you'd have a fully not-deconstructed object that
> was being destroyed due to stack unwinding... and then what? ...undo the
> stack unwinding back to where the exception was thrown and do something
> else?
>
I have no idea how you ended up in this logical trap.
> That's just nonsense. Failing destructors, especially when exceptions
> are in flight, are *bad*.
I never said dtor failed. You apparently believe that exception means
failure (whatever that means). For me -- it is a way to propagate an error
object up the stack. Just like you do it with C-style error handling, just
automated.
> > He may even
> choose to treat exceptions as normal and normal exit -- as error.
>
> Exceptions are *not* normal. They are *exceptional*. It's right there in
> the name.
>
> If you are using exceptions for control flow in *unexceptional*
> situations, you are using them *wrong*.
>
> >> And hence my question: if the destructor successfully destroyed, why
> did
> >> it need to throw?
> >
> > To report an error that happened during dtor call. Because instead of
> "I
> > will close file in dtor" semantic, user asserted "I will try to close
> file
> > in dtor" when designing his class.
>
> *Wrong*.
>
> Exceptions are a mechanism to report *failure*, because something went
> so sideways that execution in the current context *cannot continue*.
>
No, it is a n alternative flow control mechanism originally designed to
propagate and handle errors. Just like C-style error codes, but with
propagation automated and handling based off dynamic_cast. Just like
fclose() can return error -- nothing really prevents dtor to throw
exception.
> What you are describing is very specifically *not* this case.
>
> Failure to destroy an object is a *hard failure*. There is no practical
> way in which that is recoverable, any more than overwriting random
> memory is recoverable.
throwing from dtor does not cause "failure to destroy an object" -- clearly
demonstrated by that code snippet Thiago tried to use. What semantic is
associated with this exception (and how to handle it) -- is up to a user.
> Exceptions are *not* a mechanism for an object to
> report "well, I went away, but BTW something went wrong". For that, an
> out-of-band error reporting mechanism (e.g. errno) is appropriate.
>
Care to back it up with quotes from standard? Or it is just your strong
belief?
The reason exceptions are giving you trouble is because they are not the
> correct tool for what you are trying to achieve.
>
I don't have any troubles with exceptions. I have troubles with people and
their preconceptions.
Anyways -- I am tired of this debate. I didn't hear any argument why it is
impossible or unimplementable. All I got is bunch of "you shouldn't do such
thingies, it is against our beliefs". Nor there was any discussion of
actual logic for "exception combining" part. I am going to concentrate on
that part and maybe come up with something reasonably flexible and useful
(instead of going in circles here).
That is unless that reservoir next to me finally gets breached and flushes
me into the Gulf. :D
> --
> 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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/4534c9b4-42d7-493d-91bb-79f280603f50%40isocpp.org.
------=_Part_8386_278601144.1504032273874
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Tuesday, August 29, 2017 at 1:19:58 PM UTC-5, M=
atthew Woehlke wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 2017-0=
8-29 13:39, <a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=
=3D"aNOBdF4wAQAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascri=
pt:';return true;" onclick=3D"this.href=3D'javascript:';return =
true;">crusad...@gmail.com</a> wrote:
<br>> On Monday, August 28, 2017 at 5:52:23 PM UTC-5, Thiago Macieira wr=
ote:
<br>>> If a constructor throws, all of the already-constructed sub-ob=
jects get=20
<br>>> unwound and destroyed. At the end of this, the object is compl=
etely=20
<br>>> destroyed.=20
<br>>>
<br>>> If a destructor throws, the not-yet-destroyed sub-objects stil=
l need to be=20
<br>>> destroyed.=20
<br>>=20
<br>> so, what is the difference between 'already-constructed' a=
nd=20
<br>> 'not-yet-destroyed'? ;)
<br>
<br>You can undo construction. You can't undo destruction.
<br></blockquote><div><br></div><div>It is not about undoing anything. You =
switched context.</div><div><br></div><div>=C2=A0</div><blockquote class=3D=
"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc s=
olid;padding-left: 1ex;">Even if you could, then you'd have a fully not=
-deconstructed object that
<br>was being destroyed due to stack unwinding... and then what? ...undo th=
e
<br>stack unwinding back to where the exception was thrown and do something
<br>else?
<br></blockquote><div><br></div><div>I have no idea how you ended up in thi=
s logical trap.</div><div><br></div><div>=C2=A0</div><blockquote class=3D"g=
mail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc sol=
id;padding-left: 1ex;">That's just nonsense. Failing destructors, espec=
ially when exceptions
<br>are in flight, are *bad*. </blockquote><div><br></div><div>I never said=
dtor failed. You apparently believe that exception means failure (whatever=
that means). For me -- it is a way to propagate an error object up the sta=
ck. Just like you do it with C-style error handling, just automated.</div><=
div><br></div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_qu=
ote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padd=
ing-left: 1ex;">=C2=A0> He may even=C2=A0</blockquote><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;">> choose to treat exceptions as normal and n=
ormal exit -- as error.
<br>
<br>Exceptions are *not* normal. They are *exceptional*. It's right the=
re in
<br>the name.
<br>
<br>If you are using exceptions for control flow in *unexceptional*
<br>situations, you are using them *wrong*.
<br></blockquote><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;">>> And hence my question: if the destructor successfully destro=
yed, why did=20
<br>>> it need to throw?=20
<br>> =C2=A0
<br>> To report an error that happened during dtor call. =C2=A0Because i=
nstead of "I=20
<br>> will close file in dtor" semantic, user asserted "I will=
try to close file=20
<br>> in dtor" when designing his class.
<br>
<br>*Wrong*.
<br>
<br>Exceptions are a mechanism to report *failure*, because something went
<br>so sideways that execution in the current context *cannot continue*.
<br></blockquote><div><br></div><div>No, it is a n alternative flow control=
mechanism originally designed to propagate and handle errors. Just like C-=
style error codes, but with propagation automated and handling based off dy=
namic_cast. Just like fclose() can return error -- nothing really prevents =
dtor to throw exception.</div><div><br></div><div>=C2=A0</div><blockquote c=
lass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px=
#ccc solid;padding-left: 1ex;">What you are describing is very specificall=
y *not* this case.
<br>
<br>Failure to destroy an object is a *hard failure*. There is no practical
<br>way in which that is recoverable, any more than overwriting random
<br>memory is recoverable. </blockquote><div><br></div><div>throwing from d=
tor does not cause "failure to destroy an object" -- clearly demo=
nstrated by that code snippet Thiago tried to use. What semantic is associa=
ted with this exception (and how to handle it) -- is up to a user.</div><di=
v><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"mar=
gin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">E=
xceptions are *not* a mechanism for an object to
<br>report "well, I went away, but BTW something went wrong". For=
that, an
<br>out-of-band error reporting mechanism (e.g. errno) is appropriate.
<br></blockquote><div><br></div><div>Care to back it up with quotes from st=
andard? Or it is just your strong belief?</div><div>=C2=A0</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;">The reason exceptions are =
giving you trouble is because they are not the
<br>correct tool for what you are trying to achieve.
<br></blockquote><div><br></div><div>I don't have any troubles with exc=
eptions. I have troubles with people and their preconceptions.</div><div><b=
r></div><div><br></div><div>Anyways -- I am tired of this debate. I didn=
9;t hear any argument why it is impossible or unimplementable. All I got is=
bunch of "you shouldn't do such thingies, it is against our belie=
fs". Nor there was any discussion of actual logic for "exception =
combining" part. I am going to concentrate on that part and maybe come=
up with something reasonably flexible and useful (instead of going in circ=
les here).</div><div><br></div><div>That is unless that reservoir next to m=
e finally gets breached and flushes me into the Gulf. :D</div><div><br></di=
v><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;mar=
gin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">--=20
<br>Matthew
<br></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/4534c9b4-42d7-493d-91bb-79f280603f50%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/4534c9b4-42d7-493d-91bb-79f280603f50=
%40isocpp.org</a>.<br />
------=_Part_8386_278601144.1504032273874--
------=_Part_8385_841582937.1504032273874--
.
Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Tue, 29 Aug 2017 15:20:36 -0400
Raw View
On 2017-08-29 14:44, crusader.mike@gmail.com wrote:
> On Tuesday, August 29, 2017 at 1:19:58 PM UTC-5, Matthew Woehlke wrote:
>> On 2017-08-29 13:39, crusad...@gmail.com <javascript:> wrote:
>>> On Monday, August 28, 2017 at 5:52:23 PM UTC-5, Thiago Macieira wrote:
>>>> If a constructor throws, all of the already-constructed sub-objects get
>>>> unwound and destroyed. At the end of this, the object is completely
>>>> destroyed.
>>>>
>>>> If a destructor throws, the not-yet-destroyed sub-objects still need to
>>>> be destroyed.
>>>
>>> so, what is the difference between 'already-constructed' and
>>> 'not-yet-destroyed'? ;)
>>
>> You can undo construction. You can't undo destruction.
>
> It is not about undoing anything. You switched context.
Huh?
You asked why it is okay for a ctor to fail but not a dtor. Both Thiago
and I supplied answers that you apparently did not understand. Or else I
misunderstood your question.
>> Even if you could, then you'd have a fully not-deconstructed object that
>> was being destroyed due to stack unwinding... and then what? ...undo the
>> stack unwinding back to where the exception was thrown and do something
>> else?
>
> I have no idea how you ended up in this logical trap.
See above.
If a ctor fails, I can roll back the work I did up to that point and
continue unwinding from whatever context tried to create the object.
If a dtor fails... I'm SOL. I can't go backwards, because there is no
way in C++ to un-destroy objects, plus I'd still be stuck, per previous
comment. Nor can I go forwards, because later sub-objects may rely on
their predecessors having been destroyed cleanly.
Just throwing up our hands in despair and saying "oh well" is not
acceptable. C++ has never worked that way, and changing it would be too
great a risk of breaking existing code.
>> That's just nonsense. Failing destructors, especially when exceptions
>> are in flight, are *bad*.
>
> I never said dtor failed. You apparently believe that exception means
> failure (whatever that means).
Yes. So does *everyone but you*.
> For me -- it is a way to propagate an error
> object up the stack. Just like you do it with C-style error handling, just
> automated.
But that's *not* what it means. If it were, throwing exceptions wouldn't
cause immediate stack unwinding. The whole point of stack unwinding is
that something went sufficiently wrong that continuing normal execution
is no longer sensible.
It seems to me that what you want is some sort of automatic global error
reporting mechanism that lets you write `if_error (blah)`, where
`if_error` is some magic new facility that checks if an error of the
specified type has been emitted and, if so, pulls it off the pile and
handles it.
You could implement that in a library:
foo()
{
...
if (something_went_wrong)
report_error(blah);
this_will_still_execute();
...
}
bar()
{
...
foo();
if (p = pop_error(blah))
{
handle_error();
}
}
>> Exceptions are a mechanism to report *failure*, because something went
>> so sideways that execution in the current context *cannot continue*.
>
> No, it is a n alternative flow control mechanism originally designed to
> propagate and handle errors. Just like C-style error codes, but with
> propagation automated and handling based off dynamic_cast. Just like
> fclose() can return error -- nothing really prevents dtor to throw
> exception.
Since it appears obvious that you are not interested in the collected
wisdom of others on this forum, I suggest you let this thread die and
come to a meeting to present your paper (where I fully expect the WG to
have the exact same reaction).
> Anyways -- I am tired of this debate. I didn't hear any argument why it is
> impossible or unimplementable.
There's probably a psychology term for this...
> I am going to [continue working on this...] unless that reservoir
> next to me finally gets breached and flushes me into the Gulf. :D
Oy. Let's hope not! :-)
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/d03046ce-e1f9-ba81-dd7a-a8fd9f79265e%40gmail.com.
.
Author: crusader.mike@gmail.com
Date: Tue, 29 Aug 2017 12:53:36 -0700 (PDT)
Raw View
------=_Part_8523_1746441497.1504036416516
Content-Type: multipart/alternative;
boundary="----=_Part_8524_1644726739.1504036416516"
------=_Part_8524_1644726739.1504036416516
Content-Type: text/plain; charset="UTF-8"
On Tuesday, August 29, 2017 at 2:20:43 PM UTC-5, Matthew Woehlke wrote:
>
> On 2017-08-29 14:44, crusad...@gmail.com <javascript:> wrote:
> > On Tuesday, August 29, 2017 at 1:19:58 PM UTC-5, Matthew Woehlke wrote:
> >> On 2017-08-29 13:39, crusad...@gmail.com <javascript:> wrote:
> >>> On Monday, August 28, 2017 at 5:52:23 PM UTC-5, Thiago Macieira wrote:
> >>>> If a constructor throws, all of the already-constructed sub-objects
> get
> >>>> unwound and destroyed. At the end of this, the object is completely
> >>>> destroyed.
> >>>>
> >>>> If a destructor throws, the not-yet-destroyed sub-objects still need
> to
> >>>> be destroyed.
> >>>
> >>> so, what is the difference between 'already-constructed' and
> >>> 'not-yet-destroyed'? ;)
> >>
> >> You can undo construction. You can't undo destruction.
> >
> > It is not about undoing anything. You switched context.
>
> Huh?
>
> You asked why it is okay for a ctor to fail but not a dtor.
No, I did not.
> Both Thiago
> and I supplied answers that you apparently did not understand. Or else I
> misunderstood your question.
>
I perfectly understand what you talking about -- I just trying to get you
to look at this from the other angle.
> >> Even if you could, then you'd have a fully not-deconstructed object
> that
> >> was being destroyed due to stack unwinding... and then what? ...undo
> the
> >> stack unwinding back to where the exception was thrown and do something
> >> else?
> >
> > I have no idea how you ended up in this logical trap.
>
> See above.
>
> If a ctor fails, I can roll back the work I did up to that point and
> continue unwinding from whatever context tried to create the object.
>
You use the same word "fail" in two different contexts:
- when object was not completely constructed because execution left
constructor via exception -- yes, from language perspective object didn't
finish constructing; unwinding kicks in and destroys those subobjects that
have been constructed
- when destructor leaves via exception -- there is nothing critical about
this from language perspective. It is not even "fail" from language
perspective. It still will call dtors of every other subobject (similar to
what it does in first case)
> If a dtor fails... I'm SOL. I can't go backwards, because there is no
> way in C++ to un-destroy objects, plus I'd still be stuck, per previous
> comment. Nor can I go forwards, because later sub-objects may rely on
> their predecessors having been destroyed cleanly.
>
> Just throwing up our hands in despair and saying "oh well" is not
> acceptable.
the only place we "throw up our hands" is when we call std::terminate()
when two exceptions meet (well and when we can't allocate memory for
exception object). This is what I'd like to fix
> C++ has never worked that way, and changing it would be too
> great a risk of breaking existing code.
I thought I already demonstrated that existing code won't be affected. At
all.
> >> That's just nonsense. Failing destructors, especially when exceptions
> >> are in flight, are *bad*.
> >
> > I never said dtor failed. You apparently believe that exception means
> > failure (whatever that means).
>
> Yes. So does *everyone but you*.
>
I am not aware of your status in this forum -- are you qualified to
represent everyone?
> > For me -- it is a way to propagate an error
> > object up the stack. Just like you do it with C-style error handling,
> just
> > automated.
>
> But that's *not* what it means. If it were, throwing exceptions wouldn't
> cause immediate stack unwinding. The whole point of stack unwinding is
> that something went sufficiently wrong that continuing normal execution
> is no longer sensible.
>
> It seems to me that what you want is some sort of automatic global error
> reporting mechanism that lets you write `if_error (blah)`, where
> `if_error` is some magic new facility that checks if an error of the
> specified type has been emitted and, if so, pulls it off the pile and
> handles it.
>
> You could implement that in a library:
>
> foo()
> {
> ...
> if (something_went_wrong)
> report_error(blah);
> this_will_still_execute();
> ...
> }
>
> bar()
> {
> ...
> foo();
> if (p = pop_error(blah))
> {
> handle_error();
> }
> }
>
That is not what this proposal about.
> >> Exceptions are a mechanism to report *failure*, because something went
> >> so sideways that execution in the current context *cannot continue*.
> >
> > No, it is a n alternative flow control mechanism originally designed to
> > propagate and handle errors. Just like C-style error codes, but with
> > propagation automated and handling based off dynamic_cast. Just like
> > fclose() can return error -- nothing really prevents dtor to throw
> > exception.
>
> Since it appears obvious that you are not interested in the collected
> wisdom of others on this forum ...
>
....
There's probably a psychology term for this...
>
You know, I am certainly not looking for *this* type of "collected wisdom".
Glad you didn't call me Nazi or infidel...
--
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/e924fd1a-4641-4ad4-bfb4-376842d3c21b%40isocpp.org.
------=_Part_8524_1644726739.1504036416516
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Tuesday, August 29, 2017 at 2:20:43 PM UTC-5, M=
atthew Woehlke wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 2017-0=
8-29 14:44, <a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=
=3D"LveRL68zAQAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascri=
pt:';return true;" onclick=3D"this.href=3D'javascript:';return =
true;">crusad...@gmail.com</a> wrote:
<br>> On Tuesday, August 29, 2017 at 1:19:58 PM UTC-5, Matthew Woehlke w=
rote:
<br>>> On 2017-08-29 13:39, <a>crusad...@gmail.com</a> <javascript=
:> wrote:=20
<br>>>> On Monday, August 28, 2017 at 5:52:23 PM UTC-5, Thiago Mac=
ieira wrote:=20
<br>>>>> If a constructor throws, all of the already-constructe=
d sub-objects get=20
<br>>>>> unwound and destroyed. At the end of this, the object =
is completely=20
<br>>>>> destroyed.=20
<br>>>>>
<br>>>>> If a destructor throws, the not-yet-destroyed sub-obje=
cts still need to=20
<br>>>>> be destroyed.=20
<br>>>>
<br>>>> so, what is the difference between 'already-constructe=
d' and=20
<br>>>> 'not-yet-destroyed'? ;)=20
<br>>>
<br>>> You can undo construction. You can't undo destruction.=20
<br>>=20
<br>> It is not about undoing anything. You switched context.
<br>
<br>Huh?
<br>
<br>You asked why it is okay for a ctor to fail but not a dtor. </blockquot=
e><div><br></div><div>No, I did not.=C2=A0</div><div><br></div><div>=C2=A0<=
/div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;">Both Thiago
<br>and I supplied answers that you apparently did not understand. Or else =
I
<br>misunderstood your question.
<br></blockquote><div><br></div><div>I perfectly understand what you talkin=
g about -- I just trying to get you to look at this from the other angle.</=
div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=
=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: =
1ex;">>> Even if you could, then you'd have a fully not-deconstru=
cted object that=20
<br>>> was being destroyed due to stack unwinding... and then what? .=
...undo the=20
<br>>> stack unwinding back to where the exception was thrown and do =
something=20
<br>>> else?=20
<br>>=20
<br>> I have no idea how you ended up in this logical trap.
<br>
<br>See above.
<br>
<br>If a ctor fails, I can roll back the work I did up to that point and
<br>continue unwinding from whatever context tried to create the object.
<br></blockquote><div><br></div><div>You use the same word "fail"=
in two different contexts:</div><div>- when object was not completely cons=
tructed because execution left constructor via exception -- yes, from langu=
age perspective object didn't finish constructing; unwinding kicks in a=
nd destroys those subobjects that have been constructed</div><div>- when de=
structor leaves via exception -- there is nothing critical about this from =
language perspective. It is not even "fail" from language perspec=
tive. It still will call dtors of every other subobject (similar to what it=
does in first case)</div><div><br></div><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;">If a dtor fails... I'm SOL. I can't go =
backwards, because there is no
<br>way in C++ to un-destroy objects, plus I'd still be stuck, per prev=
ious
<br>comment. Nor can I go forwards, because later sub-objects may rely on
<br>their predecessors having been destroyed cleanly.
<br>
<br>Just throwing up our hands in despair and saying "oh well" is=
not
<br>acceptable. </blockquote><div><br></div><div>the only place we "th=
row up our hands" is when we call std::terminate() when two exceptions=
meet (well and when we can't allocate memory for exception object). Th=
is is what I'd like to fix</div><div><br></div><div>=C2=A0</div><blockq=
uote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-lef=
t: 1px #ccc solid;padding-left: 1ex;">C++ has never worked that way, and ch=
anging it would be too
<br>great a risk of breaking existing code.</blockquote><div><br></div><div=
>I thought I already demonstrated that existing code won't be affected.=
At all.</div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_qu=
ote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padd=
ing-left: 1ex;">>> That's just nonsense. Failing destructors, esp=
ecially when exceptions=20
<br>>> are in flight, are *bad*.=20
<br>>=20
<br>> I never said dtor failed. You apparently believe that exception me=
ans=20
<br>> failure (whatever that means).
<br>
<br>Yes. So does *everyone but you*.
<br></blockquote><div><br></div><div>I am not aware of your status in this =
forum -- are you qualified to represent everyone?</div><div><br></div><div>=
=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">> For me -- it =
is a way to propagate an error=20
<br>> object up the stack. Just like you do it with C-style error handli=
ng, just=20
<br>> automated.
<br>
<br>But that's *not* what it means. If it were, throwing exceptions wou=
ldn't
<br>cause immediate stack unwinding. The whole point of stack unwinding is
<br>that something went sufficiently wrong that continuing normal execution
<br>is no longer sensible.
<br>
<br>It seems to me that what you want is some sort of automatic global erro=
r
<br>reporting mechanism that lets you write `if_error (blah)`, where
<br>`if_error` is some magic new facility that checks if an error of the
<br>specified type has been emitted and, if so, pulls it off the pile and
<br>handles it.
<br>
<br>You could implement that in a library:
<br>
<br>=C2=A0 foo()
<br>=C2=A0 {
<br>=C2=A0 =C2=A0 ...
<br>=C2=A0 =C2=A0 if (something_went_wrong)
<br>=C2=A0 =C2=A0 =C2=A0 report_error(blah);
<br>=C2=A0 =C2=A0 this_will_still_execute();
<br>=C2=A0 =C2=A0 ...
<br>=C2=A0 }
<br>
<br>=C2=A0 bar()
<br>=C2=A0 {
<br>=C2=A0 =C2=A0 ...
<br>=C2=A0 =C2=A0 foo();
<br>=C2=A0 =C2=A0 if (p =3D pop_error(blah))
<br>=C2=A0 =C2=A0 {
<br>=C2=A0 =C2=A0 =C2=A0 handle_error();
<br>=C2=A0 =C2=A0 }
<br>=C2=A0 }
<br></blockquote><div><br></div><div>That is not what this proposal about.<=
/div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" styl=
e=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left:=
1ex;">>> Exceptions are a mechanism to report *failure*, because som=
ething went=20
<br>>> so sideways that execution in the current context *cannot cont=
inue*.=20
<br>>=20
<br>> No, it is a n alternative flow control mechanism originally design=
ed to=20
<br>> propagate and handle errors. Just like C-style error codes, but wi=
th=20
<br>> propagation automated and handling based off dynamic_cast. Just li=
ke=20
<br>> fclose() can return error -- nothing really prevents dtor to throw=
=20
<br>> exception.
<br>
<br>Since it appears obvious that you are not interested in the collected
<br>wisdom of others on this forum ...<br></blockquote><div><br></div><div>=
....=C2=A0</div><div><br></div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">=
There's probably a psychology term for this...
<br></blockquote><div><br></div><div>You know, I am certainly not looking f=
or *this* type of "collected wisdom". Glad you didn't call me=
Nazi or infidel...</div><div><br></div><div><br></div><div><br></div></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/e924fd1a-4641-4ad4-bfb4-376842d3c21b%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/e924fd1a-4641-4ad4-bfb4-376842d3c21b=
%40isocpp.org</a>.<br />
------=_Part_8524_1644726739.1504036416516--
------=_Part_8523_1746441497.1504036416516--
.
Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Tue, 29 Aug 2017 16:42:52 -0400
Raw View
On 2017-08-29 15:53, crusader.mike@gmail.com wrote:
> On Tuesday, August 29, 2017 at 2:20:43 PM UTC-5, Matthew Woehlke wrote:
>> You asked why it is okay for a ctor to fail but not a dtor.
>
> No, I did not.
You didn't?
You originally asked "so, what is the difference between
'already-constructed' and 'not-yet-destroyed'?", where
"already-constructed" is in reference to preceding sub-objects when a
ctor throws, and "not-yet-destroyed" is in reference to following
sub-objects when a dtor throws.
The only other answer that makes sense to that question as worded is if
the objects precede or follow the sub-object whose ctor/dtor threw an
exception.
If that isn't what you meant either, then I can't figure out what you
are trying to ask.
>> On 2017-08-29 14:44, crusad...@gmail.com <javascript:> wrote:
>>> I never said dtor failed. You apparently believe that exception means
>>> failure (whatever that means).
>>
>> Yes. So does *everyone but you*.
>
> I am not aware of your status in this forum -- are you qualified to
> represent everyone?
Certainly not, but at least in the context of this thread, it's an
observable fact: all three participants in this thread other than
yourself appear to share the same opinion, which is contrary to the one
you have expressed.
>> foo()
>> {
>> ...
>> if (something_went_wrong)
>> report_error(blah);
>> this_will_still_execute();
>> ...
>> }
>>
>> bar()
>> {
>> ...
>> foo();
>> if (p = pop_error(blah))
>> {
>> handle_error();
>> }
>> }
>
> That is not what this proposal about.
Then please explain how your proposal would work. You've been asked to
do that previously; I haven't seen it yet.
>> Since it appears obvious that you are not interested in the collected
>> wisdom of others on this forum ...
>>
>> There's probably a psychology term for this...
>
> You know, I am certainly not looking for *this* type of "collected wisdom".
> Glad you didn't call me Nazi or infidel...
Of course not. I haven't seen anything that would warrant such
name-calling. The ability to ignore evidence from views that do not
align with yours is hardly unusual (or even intentional). Nor would I
place any money that you're the only one in this thread doing so ;-).
My point is, you mentioned that no one has argued meaningfully against
your proposal, while from my perspective, there has been copious
argument against your proposal which to me seems perfectly reasonable.
--
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.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/bdbf8c1e-2330-39cf-13a7-fe51f335b34b%40gmail.com.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Tue, 29 Aug 2017 13:47:01 -0700
Raw View
On Tuesday, 29 August 2017 10:39:21 PDT crusader.mike@gmail.com wrote:
> > If a constructor throws, all of the already-constructed sub-objects get
> > unwound and destroyed. At the end of this, the object is completely
> > destroyed.
> >
> > If a destructor throws, the not-yet-destroyed sub-objects still need to be
> > destroyed.
>
> so, what is the difference between 'already-constructed' and
> 'not-yet-destroyed'? ;)
None. The different terms were used to indicate the order of processing.
The difference is what you do after the exception: if you were constructing,
you undo that and destruct. If you were destroying, you can't undo it (see
Matthew's reply) and you can't reconstruct. You can't unwind a destructor back
to the point where the object is back again at constructed state.
> > To avoid resource leaks, it needs to continue destroying as if the
> > exception hadn't happened. Throwing from a destructor sounds like "in
> > addition
> > to destroying, I found this error, but don't worry, I have completed my
> > work".
>
> Yep, I don't see anything wrong here. Especially considering that all this
> is already in the language. Plus, again -- language doesn't define what
> error is -- user assign this semantic to certain outcomes. He may even
> choose to treat exceptions as normal and normal exit -- as error.
I do. Like Matthew said, you're using the wrong tool for the job.
The problem is not the fact that you're using it for error reporting. It's the
semantic clash that you unwind during destruction and you *still* end up with
a destroyed object. The destruction itself cannot fail, because if it did we'd
end up with resource leakage.
So I repeat what I said before:
> > And hence my question: if the destructor successfully destroyed, why did
> > it
> > need to throw?
>
> To report an error that happened during dtor call. Because instead of "I
> will close file in dtor" semantic, user asserted "I will try to close file
> in dtor" when designing his class.
In my opinion and apparently the opinion of the designers of the C++ language
and current committee people: wrong tool for the job.
You're violating the Scotty's First Law (The right tool for the right job).
> > Sorry, you don't get to question what code is questionable. You're arguing
> > for
> > making code that everyone else thinks is questionable legit.
> >
> > Anyway, a simple example for FILE*: let's say it's a protected member of
> > the
> > class. Also, to avoid fclose() failing, let's say an invariant condition
> > is
> > that every member function flushes the buffer.
>
> A design error -- you can't guarantee that buffer will be flushed --
> therefore you can't guarantee that your invariant won't be violated.
Agreed.
Now note how this applies to destructors throwing.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/5766060.SIuopu40UP%40tjmaciei-mobl1.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Tue, 29 Aug 2017 13:47:57 -0700
Raw View
On Tuesday, 29 August 2017 11:44:33 PDT crusader.mike@gmail.com wrote:
> I never said dtor failed. You apparently believe that exception means
> failure (whatever that means). For me -- it is a way to propagate an error
> object up the stack. Just like you do it with C-style error handling, just
> automated.
Can you find any example of a function succeeding and returning an error
condition at the same time?
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/1531952.ntnhtlKcBD%40tjmaciei-mobl1.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Tue, 29 Aug 2017 13:54:30 -0700
Raw View
On Tuesday, 29 August 2017 10:32:20 PDT crusader.mike@gmail.com wrote:
> > But more importantly in your case, pay attention to your own words
> > "destructor
> > should never fail" and "exception doesn't mean anything failed". If
> > nothing
> > failed, then the destructor didn't fail. So why the hell did it throw?
>
> 'Failure' is defined by user. On language level there is no such this as
> 'failed function call'. I as a user want to return some sort of status
> code, error object from given function call and language doesn't really
> care if dtor exited normally or via exception.
Nothing wrong with the intent. The problem is in the tool.
If you want to return some status code, then you're looking to the user to
handle it somehow. By throwing, you're causing unwinding of everything, making
it that much harder to actually handle.
Let's forget destructors for a moment. Imagine these two functions that can
succeed & throw:
func1();
func2();
How do I write code such that if func1 succeeds (with or without error), func2
gets called?
And how do I write code such that if func1 fails by throwing, func2 does not
get called?
Ok, let's make it more difficult:
func2(func1());
How are you going to make func2 be called if func1 succeeded-and-threw?
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/2857422.kQ0GAdhd8n%40tjmaciei-mobl1.
.
Author: Bengt Gustafsson <bengt.gustafsson@beamways.com>
Date: Tue, 29 Aug 2017 15:40:43 -0700 (PDT)
Raw View
------=_Part_2677_1421918193.1504046443463
Content-Type: multipart/alternative;
boundary="----=_Part_2678_1394827383.1504046443463"
------=_Part_2678_1394827383.1504046443463
Content-Type: text/plain; charset="UTF-8"
I think it would benefit your cause, Mike, to explain exactly what would
happen in case of a destructor exception, in case of multiple destructor
exceptions in sibling member objects etc. Set up a number of relevant cases
and list exactly which code runs and what the resulting set of exceptions
look like, how they can be handled and so on.
So far I have actually not seen any _clear_ description, and therefore also
no clear rebuttal. You also mention "knobs" but these need to be precisely
defined.
I think it may be possible to define exactly how destructor exceptions are
to be handled and how they nest, but without a thorough description it is
too hard to tell. You talk about some kind of general container of
exceptions but then you need to describe where this is, etc. If I suggested
this I would view the excpeptions thrown as a stack. You can only catch the
top of the stack, and pop the stack when the catch clause ends. This means
that handlers must be properly nested compared to the possible throw sites.
This would not work for Nicols A-B-C-D-E example but it would probably
handle most cases and it would be an easy rule to understand. The only
viable alternative I can see is to view the in flight exceptions as a set
where each non-rethrowing catch clause ticks off one exception. I don't
know what would happen if a catch clause matches more than one in flight
exception though.
It does get tricky and that's why I need a very precise description
covering the bases.
Then there is the issue of whether this is an important enough issue to
take up standardization bandwidth with. I don't think so. There are so many
other things with greater impact.
--
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/a32747a3-c378-43cf-b4d3-8a5140362352%40isocpp.org.
------=_Part_2678_1394827383.1504046443463
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">I think it would benefit your cause, Mike, to explain exac=
tly what would happen in case of a destructor exception, in case of multipl=
e destructor exceptions in sibling member objects etc. Set up a number of r=
elevant cases and list exactly which code runs and what the resulting set o=
f exceptions look like, how they can be handled and so on.<div><br></div><d=
iv>So far I have actually not seen any _clear_ description, and therefore a=
lso no clear rebuttal. You also mention "knobs" but these need to=
be precisely defined.</div><div><br></div><div>I think it may be possible =
to define exactly how destructor exceptions are to be handled and how they =
nest, but without a thorough description it is too hard to tell. You talk a=
bout some kind of general container of exceptions but then you need to desc=
ribe where this is, etc. If I suggested this I would view the excpeptions t=
hrown as a stack. You can only catch the top of the stack, and pop the stac=
k when the catch clause ends. This means that handlers must be properly nes=
ted compared to the possible throw sites. This would not work for Nicols A-=
B-C-D-E example but it would probably handle most cases and it would be an =
easy rule to understand. The only viable alternative I can see is to view t=
he in flight exceptions as a set where each non-rethrowing catch clause tic=
ks off one exception. I don't know what would happen if a catch clause =
matches more than one in flight exception though.</div><div><br></div><div>=
It does get tricky and that's why I need a very precise description cov=
ering the bases.</div><div><br></div><div>Then there is the issue of whethe=
r this is an important enough issue to take up standardization bandwidth wi=
th. I don't think so. There are so many other things with greater impac=
t.</div><div><br></div></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/a32747a3-c378-43cf-b4d3-8a5140362352%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/a32747a3-c378-43cf-b4d3-8a5140362352=
%40isocpp.org</a>.<br />
------=_Part_2678_1394827383.1504046443463--
------=_Part_2677_1421918193.1504046443463--
.
Author: Bryce Glover <randomdsdevel@gmail.com>
Date: Tue, 29 Aug 2017 21:01:40 -0400
Raw View
--Apple-Mail=_90CDD029-FDED-41E9-A30F-429BA750893C
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset="UTF-8"
Well, maybe you could undo destruction if you destructively moved=E2=
=80=89=E2=80=94=E2=80=89yes, I know we don=E2=80=99t yet have destructive m=
ove yet, either=E2=80=89=E2=80=94=E2=80=89the object=E2=80=99s contents to =
a side stack to be flushed when the parent destructor finished? Then you c=
ould do a destructive move in the opposite direction to restore the previou=
sly =E2=80=98destroyed=E2=80=99 sub-objects and discard the (then empty, an=
d, thus, no longer necessary, at least for the time being) side cache/stack=
.. In any case, this possible scenario also strikes me as somewhat reminisc=
ent of my vaguest impressions of what might happen if you made your class=
=E2=80=99s destructor into one implemented to take advantage of the upcomin=
g Transactional Memory TS, which would probably only help if failures were =
expected to be intermittent. It=E2=80=99s still probably a horrible idea t=
o even consider cobbling such kludges together instead of properly using an=
out-of-band error-reporting mechanism as has been suggested earlier in thi=
s thread, but I had the thought, so I just thought I=E2=80=99d entertain me=
ntioning it=E2=80=A6
Submerging back into lurkers=E2=80=99 land,=20
Bryce Glover
RandomDSdevel@gmail.com
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/02C58C7A-7950-48FA-94F9-B64EDACAD29E%40gmail.com=
..
--Apple-Mail=_90CDD029-FDED-41E9-A30F-429BA750893C
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""> &nbs=
p;Well, <i class=3D"">maybe</i> you could undo destruction if you destructi=
vely moved=E2=80=89=E2=80=94=E2=80=89yes, I <i class=3D"">know</i> we don=
=E2=80=99t yet have destructive move yet, either=E2=80=89=E2=80=94=E2=80=89=
the object=E2=80=99s contents to a side stack to be flushed when the parent=
destructor finished? Then you could do a destructive move in the opp=
osite direction to restore the previously =E2=80=98destroyed=E2=80=99 sub-o=
bjects and discard the (then empty, and, thus, no longer necessary, at leas=
t for the time being) side cache/stack. In <i class=3D"">any</i> =
;case, this possible scenario also strikes me as somewhat reminiscent of my=
<i class=3D"">vaguest</i> impressions of what <i class=3D"">might</i> =
;happen if you made your class=E2=80=99s destructor into one implemented to=
take advantage of the upcoming Transactional Memory TS, which would probab=
ly only help if failures were expected to be intermittent. It=E2=80=
=99s <i class=3D"">still</i> probably a <i class=3D"">horrible</i> ide=
a to even <i class=3D"">consider</i> cobbling such kludges together in=
stead of properly using an out-of-band error-reporting mechanism as has bee=
n suggested earlier in this thread, but I had the thought, so I just though=
t I=E2=80=99d entertain <i class=3D"">mentioning</i> it=E2=80=A6<br cl=
ass=3D""><br class=3D""><div class=3D"">
<div style=3D"color: rgb(0, 0, 0); letter-spacing: normal; orphans: auto; t=
ext-align: start; text-indent: 0px; text-transform: none; white-space: norm=
al; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-w=
rap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-=
space;" class=3D""><div style=3D"color: rgb(0, 0, 0); letter-spacing: norma=
l; orphans: auto; text-align: start; text-indent: 0px; text-transform: none=
; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke=
-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-=
break: after-white-space;" class=3D""><div style=3D"color: rgb(0, 0, 0); le=
tter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; t=
ext-transform: none; white-space: normal; widows: auto; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><div class=3D"">Su=
bmerging back into lurkers=E2=80=99 land, </div><div class=3D""> =
Bryce Glover</div><div class=3D""> <a href=
=3D"mailto:RandomDSdevel@gmail.com" class=3D"">RandomDSdevel@gmail.com</a><=
/div></div></div></div></div></body></html>
<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/02C58C7A-7950-48FA-94F9-B64EDACAD29E%=
40gmail.com?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/02C58C7A-7950-48FA-94F9-B64EDACAD29E%=
40gmail.com</a>.<br />
--Apple-Mail=_90CDD029-FDED-41E9-A30F-429BA750893C--
.
Author: crusader.mike@gmail.com
Date: Wed, 30 Aug 2017 22:53:36 -0700 (PDT)
Raw View
------=_Part_911_230290860.1504158816808
Content-Type: multipart/alternative;
boundary="----=_Part_912_1585993981.1504158816809"
------=_Part_912_1585993981.1504158816809
Content-Type: text/plain; charset="UTF-8"
On Tuesday, August 29, 2017 at 3:47:10 PM UTC-5, Thiago Macieira wrote:
>
> On Tuesday, 29 August 2017 10:39:21 PDT crusad...@gmail.com <javascript:>
> wrote:
> > > If a constructor throws, all of the already-constructed sub-objects
> get
> > > unwound and destroyed. At the end of this, the object is completely
> > > destroyed.
> > >
> > > If a destructor throws, the not-yet-destroyed sub-objects still need
> to be
> > > destroyed.
> >
> > so, what is the difference between 'already-constructed' and
> > 'not-yet-destroyed'? ;)
>
> None. The different terms were used to indicate the order of processing.
>
> The difference is what you do after the exception: if you were
> constructing,
> you undo that and destruct. If you were destroying, you can't undo it (see
> Matthew's reply) and you can't reconstruct. You can't unwind a destructor
> back
> to the point where the object is back again at constructed state.
>
I was without power for two days. Might have lost some of threads... I'll
make last attempt to explain.
Undoing-by-unwinding is additional semantic you've added. Language doesn't
really mention anything about failing or undoing. Mechanism is very simple
and looks like this:
- for every completed constructor (of local object) an obligation is taken
to call it's sibling (destructor) when execution leaves current scope
That is it -- no more, no less. No "undoing", no "failing". We commonly
associating these with failing to construct, undoing what has been done,
but it doesn't have to be this way. And the fact that you actually can
throw from dtor is a hint.
In particular:
- we call ctors of (sub)object simply because these calls are on our
execution path, specified in certain order
- when ctor throws -- it initiates stack unwinding
- ... which fullfills the obligation to call dtors of every completed
ctor call, not because language expects us to undo smth
- we don't call remaining ctors not because exception is failure to
construct -- it is because we never get to the point where they get called
- when dtor throws -- it initiates stack unwinding too
- ... we do call remaining dtors simply to fulfill the promise -- and
it doesn't care how dtor exited (via stack unwinding or not), promise is a
promise
If you set aside your preconceptions about how this mechanism was meant to
be used -- it should become perfectly clear.
> > > To avoid resource leaks, it needs to continue destroying as if the
> > > exception hadn't happened. Throwing from a destructor sounds like "in
> > > addition
> > > to destroying, I found this error, but don't worry, I have completed
> my
> > > work".
> >
> > Yep, I don't see anything wrong here. Especially considering that all
> this
> > is already in the language. Plus, again -- language doesn't define what
> > error is -- user assign this semantic to certain outcomes. He may even
> > choose to treat exceptions as normal and normal exit -- as error.
>
> I do. Like Matthew said, you're using the wrong tool for the job.
>
> The problem is not the fact that you're using it for error reporting. It's
> the
> semantic clash that you unwind during destruction and you *still* end up
> with
> a destroyed object. The destruction itself cannot fail, because if it did
> we'd
> end up with resource leakage.
>
> So I repeat what I said before:
>
> > > And hence my question: if the destructor successfully destroyed, why
> did
> > > it
> > > need to throw?
> >
> > To report an error that happened during dtor call. Because instead of
> "I
> > will close file in dtor" semantic, user asserted "I will try to close
> file
> > in dtor" when designing his class.
>
> In my opinion and apparently the opinion of the designers of the C++
> language
> and current committee people: wrong tool for the job.
>
> You're violating the Scotty's First Law (The right tool for the right
> job).
>
Sigh... It fits very nicely to that example I gave you (with three pieces
of machinery that have to be switched off on leaving scope). Forcing dtors
to be no-throw forces me to come up with "out-of-band" error reporting and
quite awkward code to guarantee that all of them are attempted 'switch off'.
> > > Sorry, you don't get to question what code is questionable. You're
> arguing
> > > for
> > > making code that everyone else thinks is questionable legit.
> > >
> > > Anyway, a simple example for FILE*: let's say it's a protected member
> of
> > > the
> > > class. Also, to avoid fclose() failing, let's say an invariant
> condition
> > > is
> > > that every member function flushes the buffer.
> >
> > A design error -- you can't guarantee that buffer will be flushed --
> > therefore you can't guarantee that your invariant won't be violated.
>
> Agreed.
>
> Now note how this applies to destructors throwing.
>
It really depends how my invariant is defined, isn't it? If my object was
designed to **try** to drive a device and on first error it switches into
"please reset it and let me know" state -- there is nothing wrong with
using exception from dtor as a way to report an unexpected device behavior.
--
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
>
>
--
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/b91a336b-e3bd-49b5-bcac-dee4b59661a2%40isocpp.org.
------=_Part_912_1585993981.1504158816809
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Tuesday, August 29, 2017 at 3:47:10 PM UTC-5, 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 Tuesda=
y, 29 August 2017 10:39:21 PDT <a href=3D"javascript:" target=3D"_blank" gd=
f-obfuscated-mailto=3D"QD7o5mY4AQAJ" rel=3D"nofollow" onmousedown=3D"this.h=
ref=3D'javascript:';return true;" onclick=3D"this.href=3D'javas=
cript:';return true;">crusad...@gmail.com</a> wrote:
<br>> > If a constructor throws, all of the already-constructed sub-o=
bjects get
<br>> > unwound and destroyed. At the end of this, the object is comp=
letely
<br>> > destroyed.
<br>> >=20
<br>> > If a destructor throws, the not-yet-destroyed sub-objects sti=
ll need to be
<br>> > destroyed.
<br>>=20
<br>> so, what is the difference between 'already-constructed' a=
nd
<br>> 'not-yet-destroyed'? ;)
<br>
<br>None. The different terms were used to indicate the order of processing=
..
<br>
<br>The difference is what you do after the exception: if you were construc=
ting,=20
<br>you undo that and destruct. If you were destroying, you can't undo =
it (see=20
<br>Matthew's reply) and you can't reconstruct. You can't unwin=
d a destructor back=20
<br>to the point where the object is back again at constructed state.
<br></blockquote><div><br></div><div>I was without power for two days. Migh=
t have lost some of threads... I'll make last attempt to explain.</div>=
<div><br></div><div>Undoing-by-unwinding is additional semantic you've =
added. Language doesn't really mention anything about failing or undoin=
g. Mechanism is very simple and looks like this:</div><div>- for every comp=
leted constructor (of local object) an obligation is taken to call it's=
sibling (destructor) when execution leaves current scope<br></div><div><br=
></div><div>That is it -- no more, no less. No "undoing", no &quo=
t;failing". We commonly associating these with failing to construct, u=
ndoing what has been done, but it doesn't have to be this way. And the =
fact that you actually can throw from dtor is a hint.</div><div><br></div><=
div>In particular:</div><div>- we call ctors of (sub)object simply because =
these calls are on our execution path, specified in certain order</div><div=
>- when ctor throws -- it initiates stack unwinding</div><div>=C2=A0 =C2=A0=
- ... which fullfills the obligation to call dtors of every completed ctor=
call, not because language expects us to undo smth</div><div>- we don'=
t call remaining ctors not because exception is failure to construct -- it =
is because we never get to the point where they get called</div><div>- when=
dtor throws -- it initiates stack unwinding too</div><div>=C2=A0 =C2=A0 - =
.... we do call remaining dtors simply to fulfill the promise -- and it does=
n't care how dtor exited (via stack unwinding or not), promise is a pro=
mise</div><div><br></div><div>If you set aside your preconceptions about ho=
w this mechanism was meant to be used -- it should become perfectly clear.<=
/div><div><br><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" =
style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-l=
eft: 1ex;">> > To avoid resource leaks, it needs to continue destroyi=
ng as if the
<br>> > exception hadn't happened. Throwing from a destructor sou=
nds like "in
<br>> > addition
<br>> > to destroying, I found this error, but don't worry, I hav=
e completed my
<br>> > work".
<br>>=20
<br>> Yep, I don't see anything wrong here. Especially considering t=
hat all this
<br>> is already in the language. Plus, again -- language doesn't de=
fine what
<br>> error is -- user assign this semantic to certain outcomes. He may =
even
<br>> choose to treat exceptions as normal and normal exit -- as error.
<br>
<br>I do. Like Matthew said, you're using the wrong tool for the job.
<br>
<br>The problem is not the fact that you're using it for error reportin=
g. It's the=20
<br>semantic clash that you unwind during destruction and you *still* end u=
p with=20
<br>a destroyed object. The destruction itself cannot fail, because if it d=
id we'd=20
<br>end up with resource leakage.
<br>
<br>So I repeat what I said before:
<br>
<br>> > And hence my question: if the destructor successfully destroy=
ed, why did
<br>> > it
<br>> > need to throw?
<br>>=20
<br>> To report an error that happened during dtor call. =C2=A0Because i=
nstead of "I
<br>> will close file in dtor" semantic, user asserted "I will=
try to close file
<br>> in dtor" when designing his class.
<br>
<br>In my opinion and apparently the opinion of the designers of the C++ la=
nguage=20
<br>and current committee people: wrong tool for the job.
<br>
<br>You're violating the Scotty's First Law (The right tool for the=
right job).
<br></blockquote><div><br></div><div>Sigh... It fits very nicely to that ex=
ample I gave you (with three pieces of machinery that have to be switched o=
ff on leaving scope). Forcing dtors to be no-throw forces me to come up wit=
h "out-of-band" error reporting and quite awkward code to guarant=
ee that all of them are attempted 'switch off'.</div><div><br></div=
><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">> > So=
rry, you don't get to question what code is questionable. You're ar=
guing
<br>> > for
<br>> > making code that everyone else thinks is questionable legit.
<br>> >=20
<br>> > Anyway, a simple example for FILE*: let's say it's a =
protected member of
<br>> > the
<br>> > class. Also, to avoid fclose() failing, let's say an inva=
riant condition
<br>> > is
<br>> > that every member function flushes the buffer.
<br>>=20
<br>> A design error -- you can't guarantee that buffer will be flus=
hed --
<br>> therefore you can't guarantee that your invariant won't be=
violated.
<br>
<br>Agreed.
<br>
<br>Now note how this applies to destructors throwing.
<br></blockquote><div><br></div><div>It really depends how my invariant is =
defined, isn't it? If my object was designed to **try** to drive a devi=
ce and on first error it switches into "please reset it and let me kno=
w" state -- there is nothing wrong with using exception from dtor as a=
way to report an unexpected device behavior.</div><div>=C2=A0</div><div><b=
r></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;">--=20
<br>Thiago Macieira - thiago (AT) <a href=3D"http://macieira.info" target=
=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.goo=
gle.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x3dD\x26sntz\x3d1\x26usg\=
x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.hr=
ef=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x=
3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return t=
rue;">macieira.info</a> - thiago (AT) <a href=3D"http://kde.org" target=3D"=
_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.google.=
com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNH=
GRJdo5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'=
http://www.google.com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1=
\x26usg\x3dAFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;">kde.org</a=
>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>
<br></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/b91a336b-e3bd-49b5-bcac-dee4b59661a2%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/b91a336b-e3bd-49b5-bcac-dee4b59661a2=
%40isocpp.org</a>.<br />
------=_Part_912_1585993981.1504158816809--
------=_Part_911_230290860.1504158816808--
.
Author: crusader.mike@gmail.com
Date: Wed, 30 Aug 2017 23:09:14 -0700 (PDT)
Raw View
------=_Part_946_570325432.1504159754456
Content-Type: multipart/alternative;
boundary="----=_Part_947_674198154.1504159754456"
------=_Part_947_674198154.1504159754456
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Tuesday, August 29, 2017 at 8:01:46 PM UTC-5, Bryce Glover wrote:
>
> Well, *maybe* you could undo destruction if you destructively moved=
=20
> =E2=80=94 yes, I *know* we don=E2=80=99t yet have destructive move yet, e=
ither =E2=80=94 the=20
> object=E2=80=99s contents to a side stack to be flushed when the parent d=
estructor=20
> finished? Then you could do a destructive move in the opposite direction=
=20
> to restore the previously =E2=80=98destroyed=E2=80=99 sub-objects and dis=
card the (then=20
> empty, and, thus, no longer necessary, at least for the time being) side=
=20
> cache/stack. In *any* case, this possible scenario also strikes me as=20
> somewhat reminiscent of my *vaguest* impressions of what *might* happen=
=20
> if you made your class=E2=80=99s destructor into one implemented to take =
advantage=20
> of the upcoming Transactional Memory TS, which would probably only help i=
f=20
> failures were expected to be intermittent. It=E2=80=99s *still* probably=
a=20
> *horrible* idea to even *consider* cobbling such kludges together instead=
=20
> of properly using an out-of-band error-reporting mechanism as has been=20
> suggested earlier in this thread,=20
>
Uh... I thought it is rather obvious that mechanism wasn't going to work=20
very well -- I didn't even criticize it. :-) In order for it to work you=20
have to poison your objects with reference to reporting facility (so that=
=20
it's dtor can report the error it ate) or write even less attractive stuff=
=20
like:
void foo()
{
report_obj report;
try
{
my_obj1 o1;
auto o1x =3D on_scope_exit([&]{ try{ o1.switch_off(); } catch(...) =
{=20
report.on_exception_in_o1(); } })
my_obj2 o2;
auto o2x =3D on_scope_exit([&]{ try{ o2.switch_off(); } catch(...) =
{=20
report.on_exception_in_o2(); } })
...
// call ops that can throw too
return;
}
catch(...)
{
report.on_exception();
}
=20
report.throw_combined_result();
}=20
=20
> but I had the thought, so I just thought I=E2=80=99d entertain *mentionin=
g* it=E2=80=A6
>
'Destructing move' isn't going to happen in C++, I think. As long as=20
'object' means 'bunch of bits and memory range they occupy'... and it=20
unlikely to ever change.
=20
>
> Submerging back into lurkers=E2=80=99 land,=20
> Bryce Glover
> Random...@gmail.com <javascript:>
>
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/2ba0a5b9-4a02-4795-8757-14fd3ee080e6%40isocpp.or=
g.
------=_Part_947_674198154.1504159754456
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Tuesday, August 29, 2017 at 8:01:46 PM UTC-5, B=
ryce Glover wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div style=
=3D"word-wrap:break-word">=C2=A0 =C2=A0 =C2=A0Well, <i>maybe</i> you could =
undo destruction if you destructively moved=E2=80=89=E2=80=94=E2=80=89yes, =
I <i>know</i> we don=E2=80=99t yet have destructive move yet, either=E2=80=
=89=E2=80=94=E2=80=89the object=E2=80=99s contents to a side stack to be fl=
ushed when the parent destructor finished? =C2=A0Then you could do a destru=
ctive move in the opposite direction to restore the previously =E2=80=98des=
troyed=E2=80=99 sub-objects and discard the (then empty, and, thus, no long=
er necessary, at least for the time being) side cache/stack. =C2=A0In <i>an=
y</i>=C2=A0case, this possible scenario also strikes me as somewhat reminis=
cent of my <i>vaguest</i> impressions of what <i>might</i>=C2=A0happen if y=
ou made your class=E2=80=99s destructor into one implemented to take advant=
age of the upcoming Transactional Memory TS, which would probably only help=
if failures were expected to be intermittent. =C2=A0It=E2=80=99s <i>still<=
/i>=C2=A0probably a <i>horrible</i> idea to even <i>consider</i>=C2=A0cobbl=
ing such kludges together instead of properly using an out-of-band error-re=
porting mechanism as has been suggested earlier in this thread, </div></blo=
ckquote><div><br></div><div>Uh... I thought it is rather obvious that mecha=
nism wasn't going to work very well -- I didn't even criticize it. =
:-) In order for it to work you have to poison your objects with reference =
to reporting facility (so that it's dtor can report the error it ate) o=
r write even less attractive stuff like:</div><div><br></div><div>void foo(=
)</div><div>{</div><div>=C2=A0 =C2=A0 report_obj report;</div><div><br></di=
v><div>=C2=A0 =C2=A0 try</div><div>=C2=A0 =C2=A0 {</div><div>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 my_obj1 o1;<br></div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 auto o1=
x =3D on_scope_exit([&]{ try{ o1.switch_off(); } catch(...) { report.on=
_exception_in_o1(); } })</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 my_obj2 o2;<=
br></div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 auto o2x =3D on_scope_exit([&=
]{ try{ o2.switch_off(); } catch(...) { report.on_exception_in_o2(); } })</=
div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 ...</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 // call ops that can throw too</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 re=
turn;</div><div>=C2=A0 =C2=A0 }</div><div>=C2=A0 =C2=A0 catch(...)</div><di=
v>=C2=A0 =C2=A0 {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 report.on_exception=
();</div><div>=C2=A0 =C2=A0 }<br></div><div>=C2=A0 =C2=A0=C2=A0<br></div><d=
iv>=C2=A0 =C2=A0 report.throw_combined_result();</div><div>}=C2=A0</div><di=
v><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"mar=
gin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><=
div style=3D"word-wrap:break-word">but I had the thought, so I just thought=
I=E2=80=99d entertain=C2=A0<i>mentioning</i> it=E2=80=A6<br></div></blockq=
uote><div><br></div><div>'Destructing move' isn't going to happ=
en in C++, I think. As long as 'object' means 'bunch of bits an=
d memory range they occupy'... and it unlikely to ever change.</div><di=
v><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"mar=
gin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><=
div style=3D"word-wrap:break-word"><br><div>
<div style=3D"color:rgb(0,0,0);letter-spacing:normal;text-align:start;text-=
indent:0px;text-transform:none;white-space:normal;word-spacing:0px;word-wra=
p:break-word"><div style=3D"color:rgb(0,0,0);letter-spacing:normal;text-ali=
gn:start;text-indent:0px;text-transform:none;white-space:normal;word-spacin=
g:0px;word-wrap:break-word"><div style=3D"color:rgb(0,0,0);letter-spacing:n=
ormal;text-align:start;text-indent:0px;text-transform:none;white-space:norm=
al;word-spacing:0px;word-wrap:break-word"><div>Submerging back into lurkers=
=E2=80=99 land,=C2=A0</div><div>=C2=A0 =C2=A0 =C2=A0Bryce Glover</div><div>=
=C2=A0 =C2=A0 =C2=A0<a href=3D"javascript:" target=3D"_blank" gdf-obfuscate=
d-mailto=3D"_E00lktGAQAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'=
javascript:';return true;" onclick=3D"this.href=3D'javascript:'=
;return true;">Random...@gmail.com</a></div></div></div></div></div></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/2ba0a5b9-4a02-4795-8757-14fd3ee080e6%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/2ba0a5b9-4a02-4795-8757-14fd3ee080e6=
%40isocpp.org</a>.<br />
------=_Part_947_674198154.1504159754456--
------=_Part_946_570325432.1504159754456--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Thu, 31 Aug 2017 00:18:54 -0700
Raw View
On Wednesday, 30 August 2017 22:53:36 PDT crusader.mike@gmail.com wrote:
> > The difference is what you do after the exception: if you were
> > constructing,
> > you undo that and destruct. If you were destroying, you can't undo it (see
> > Matthew's reply) and you can't reconstruct. You can't unwind a destructor
> > back
> > to the point where the object is back again at constructed state.
>
> I was without power for two days. Might have lost some of threads... I'll
> make last attempt to explain.
>
> Undoing-by-unwinding is additional semantic you've added. Language doesn't
> really mention anything about failing or undoing. Mechanism is very simple
> and looks like this:
> - for every completed constructor (of local object) an obligation is taken
> to call it's sibling (destructor) when execution leaves current scope
>
> That is it -- no more, no less. No "undoing", no "failing". We commonly
> associating these with failing to construct, undoing what has been done,
> but it doesn't have to be this way. And the fact that you actually can
> throw from dtor is a hint.
You're arguing that strictly speaking, the technique could be used for
something different. But in reality, the technique was created for one use
only and that's "undo in case of failure" plus a way to transmit some
information about the cause of the failure.
The fact that you can throw from a dtor was a mistake in C++98, one that was
corrected in C++11 by making destructors default to noexcept. You can still
mark them as noexcept(false) to allow throwing, but that is only there to
support prior abuses that already existed.
Yes, I know that this is an interpretation.
> In particular:
> - we call ctors of (sub)object simply because these calls are on our
> execution path, specified in certain order
> - when ctor throws -- it initiates stack unwinding
> - ... which fullfills the obligation to call dtors of every completed
> ctor call, not because language expects us to undo smth
Sorry, no. The entire exception mechanism was designed so that you could undo
and release resoruces acquired in the initialisation path. The fact that you
can (ab)use it for something else does not change the original intention
behind the sequence of rules.
Take a look at the resolution of the defect of what happens when you call a
delegated constructor and it throws (you can look up the DR). The entire
thinking of what the behaviour should be was guided by the "undo" premise.
> - we don't call remaining ctors not because exception is failure to
> construct -- it is because we never get to the point where they get called
Again you're reinterpreting the rules / putting cart ahead of the oxen. The
exception is thrown because we failed to construct, therefore unwinding
happened.
> - when dtor throws -- it initiates stack unwinding too
> - ... we do call remaining dtors simply to fulfill the promise -- and
> it doesn't care how dtor exited (via stack unwinding or not), promise is a
> promise
You see, this is where it breaks down. There is no precedent for exiting the
exit. There's not even a good logical explanation for that in the expression I
used: if you exit the exit, do you reenter? Or did you really exit?
> If you set aside your preconceptions about how this mechanism was meant to
> be used -- it should become perfectly clear.
What's pretty clear to me is that you want to reinterpret the rules and
(ab)use the mechanism for something it was not intended.
Ok, fair enough. Do it. If you want to throw from destructors, do it.
Just don't expect all the other libraries to react well to it. Don't expect
Standard Library containers to do anything but misbehave if you do it.
And don't expect the committee to take your suggestions. So far, everything
related to exceptions has been based on the principle that it's an undo
mechanism. Any changes you want need to be based on that principle too. The
chances of getting any change to the Standard Library on this is almost
definitely zero. On the core language, maybe.
I must have lost sight of the original request... do you need any core
language changes?
> > You're violating the Scotty's First Law (The right tool for the right
> > job).
>
> Sigh... It fits very nicely to that example I gave you (with three pieces
> of machinery that have to be switched off on leaving scope). Forcing dtors
> to be no-throw forces me to come up with "out-of-band" error reporting and
> quite awkward code to guarantee that all of them are attempted 'switch off'.
Like I said, life isn't fair or easy.
But if you want to mark your own destructors noexcept(false), do it. Just
don't ask anyone else to do it.
> > > A design error -- you can't guarantee that buffer will be flushed --
> > > therefore you can't guarantee that your invariant won't be violated.
> >
> > Agreed.
> >
> > Now note how this applies to destructors throwing.
>
> It really depends how my invariant is defined, isn't it? If my object was
> designed to **try** to drive a device and on first error it switches into
> "please reset it and let me know" state -- there is nothing wrong with
> using exception from dtor as a way to report an unexpected device behavior.
If you can choose the invariant, you can choose not to throw in the
destructor.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/4415380.V1RD9en12F%40tjmaciei-mobl1.
.
Author: crusader.mike@gmail.com
Date: Thu, 31 Aug 2017 00:25:06 -0700 (PDT)
Raw View
------=_Part_994_1571569668.1504164306615
Content-Type: multipart/alternative;
boundary="----=_Part_995_1689028466.1504164306619"
------=_Part_995_1689028466.1504164306619
Content-Type: text/plain; charset="UTF-8"
On Monday, August 28, 2017 at 6:16:42 PM UTC-5, Nicol Bolas wrote:
>
> On Monday, August 28, 2017 at 3:09:43 PM UTC-4, crusad...@gmail.com wrote:
>>
>> On Monday, August 28, 2017 at 12:56:32 PM UTC-5, Nicol Bolas wrote:
>>>
>>> On Monday, August 28, 2017 at 12:06:30 PM UTC-4, crusad...@gmail.com
>>> wrote:
>>>>
>>>> Before reading stuff below I suggest to set aside any dogmatic blinders
>>>> you may have, namely:
>>>> - realize that there is nothing particular special about destructors --
>>>> they are just functions that runtime calls automatically in specific
>>>> circumstances and yes, they may want to report an error
>>>>
>>>
>>> Untrue. Destructors provoke the ending of the lifetime of an object.
>>> That makes them special. Much like how constructors signal the beginning of
>>> the lifetime of an object.
>>>
>>
>> It is a function. And it can throw exception as it is right now. It is
>> noexcept right by default, but nothing prevents me to declare it
>> noexcept(false) and it will work. The only case when it won't is when it
>> throws during unwinding. I believe it can be changed and it should be
>> changed to accomodate for a practical situation. And it won't affect
>> existing code at all.
>>
>
> If exception collisions affect the type of exception being caught, then it
> affects any existing code where that user does not control what objects get
> destroyed between themselves and the source of the exception they're
> catching.
>
As long as user is aware of potential magic -- it is fine. It is still
better in sense that it will become an options, while right now it is
std::terminate(). And with noexcept(true) dtors (by default) everyone is
pretty safe.
> - you can't really tell what makes sense or not -- only end user makes
>>>> this decision
>>>>
>>>
>>> The C++ object model is all about defining what "makes sense". That's
>>> why you can't just pretend that an object exists in some memory.
>>>
>>
>> I never said that.
>>
>
> Nor did I accuse you of saying it. My point is that your perspective is
> that of someone who's doesn't care about what a piece of functionality
> *means*; what matters to you is what it can do. It's a perspective of
> trying to view C++, not as a collection of meaningful parts and
> functionality, but an arbitrary assemblage of things onto which you can
> graft your own meaning.
>
'Object model' you mentioned is a result of such grafting, isn't it? What
prevents me from grafting mine, slightly different?
> Destructors mean something to the C++ object model. They're not just a
> function call. Just like constructors mean something to the C++ object
> model. What "makes sense" *matters*.
>
> Nothing prevents me from destroying object with error right now and it
>> will work just fine:
>> void foo()
>> {
>> struct X { ~X() { throw 1; } x;
>> }
>>
>> object still gets destroyed just fine.
>>
>
> That calls `std::terminate`, since you tried to emit an exception through
> a `noexcept` function.
>
Naturally :-). I forgot to add noexcept(false). Still living in the world
of C++03.
> While yes, the object `x` has had its lifetime ended, that happened when
> the destructor *started*. So the throw is essentially irrelevant.
>
> What matters is what the state of the system means in this event.
>
> What logical meaning I associated with 'failed destructor' is my (end
>> user) business.
>>
>
> No, it's not. It's everybody else's business too.
>
> For example, if I put an object with a throwing destructor in my object
> which doesn't have a throwing destructor... what does that mean?
>
Just like with other components of every library -- you need to have some
minimal knowledge to use it. Ideally, compiler should warn you if you have
a call that could throw inside of a no-throw function. But C++ lacks
necessary tools for that, unfortunately -- like a way to declare that given
block isn't going to throw. Smth like this:
vector<int> v;
v.reserve(1);
....
void foo() noexcept
{
noexcept_promise { // code in this scope won't throw, trust me,
compiler
v.push_back(10);
}
}
> And it may make sense to me.
>>
>
> And your code needs to work with the rest of the world.
>
Ok, you just raised first actual problem (from my pov):
class X; // it's dtor can throw
struct S
{
X x;
~S() noexcept(true) {} // no way to intercept exception from x's
dtor
};
this sucks... I wonder if this can be 'fixed' with same thing we can do in
ctors:
~S() noexcept(true)
try
{
}
catch(...) { ... }
> So the standard has every right to decide that circumstance X doesn't make
>>> sense, so we're not going to support it.
>>>
>>> - what is proposed -- is just a tool, whether to use it or not, is up to
>>>> end user
>>>>
>>>
>>> The model that the proposal creates still has to make sense. Which it
>>> does not. Giving people tools that are incoherent and encourage bad coding
>>> is not helpful.
>>>
>>
>> You claim "make no sense" very vigorously, but I've yet to see any good
>> argument for that.
>>
>
> That's because you're looking from a world view where destructors "are
> just functions that runtime calls automatically in specific circumstances".
> It stops making sense once you move to a perspective where there is an
> actual meaning to object destruction besides calling a bunch of functions.
>
Correct. As I said in another message -- I am trying to get you to look at
this from another angle.
I can't help your world view. I understand it, but I do not subscribe to it.
>
As mentioned -- I am very pragmatical. I'll try to use whatever world view
that makes my life easier and gets the job done. I also like nice, compact
solutions.
But I am glad you understand my point. Thank you.
> On Sunday, August 27, 2017 at 9:19:57 PM UTC-5, Nicol Bolas wrote:
>>>>>
>>>>> On Sunday, August 27, 2017 at 9:35:21 PM UTC-4, crusad...@gmail.com
>>>>> wrote:
>>>>>
>>>> No, a throwing destructor is a terrible, horrible, no-good, very-bad
>>>>> idea. Implicitly forbidding it is a good thing, and C++ has absolutely no
>>>>> need to support exception clashing (which can only happen through a
>>>>> throwing destructor).
>>>>>
>>>>> Here are my thoughts:
>>>>>> - both C-style error handling and C++ exceptions do effectively the
>>>>>> same thing -- construct error object and pass it up the call stack,
>>>>>> differences are:
>>>>>>
>>>>>> - C: error type is known to caller and caller is responsible for
>>>>>> allocating memory for error object
>>>>>>
>>>>>> - C: caller is responsible for proper propagation of error
>>>>>>
>>>>>> - EH: caller only knows whether some error can bubble up (ignoring
>>>>>> exception specs here, since they are deprecated)
>>>>>>
>>>>>> - EH: there is a mechanism that automates error propagation (and
>>>>>> matching to related catch clause)
>>>>>>
>>>>>>
>>>>> - EH: Arbitrary code can execute between the generation of the error
>>>>> code and its reception. That code itself can fail.
>>>>>
>>>>
>>>> no, same thing can happen with C-style error handling. It looks rather
>>>> obvious to me
>>>>
>>>
>>> Your analogy says that `return` and the use of the return value are
>>> similar to `throw` and `catch` for that exception. Given that analogy, no,
>>> the same thing cannot happen in C-style error handling. The function that
>>> receives the error is the one that called the function. Between the end of
>>> the initialization of the return value from the function creating the error
>>> code, to the beginning of the initialization of the value that the
>>> receiving function is creating, no user code can be executed.
>>>
>>> Oh, there can be code between the generator of the error and where the
>>> error is *resolved*: that is, where you stop dealing with the error
>>> condition and progress normally. You can return the error code up the
>>> stack, do conditional logic based on it, and all kinds of stuff.
>>>
>>> But there is a lot more that can happen between a `throw` and a `catch`
>>> that cannot happen between a `return` and the use of that returned value.
>>>
>>
>> Again, no. Two situations -- propagation of error to the point where it
>> gets handled through unwinding mechanism is fundamentally the same as
>> propagation of it via "if (auto err = foo()) return err". In both cases
>> anything could happen in-between.
>>
>
> I just realized something. There is one similarity between error code
> propagation and exception-caused stack unwinding. In both cases...
> destructors *cannot* affect an error code being returned by value ;)
>
> No really; go ahead and try to make a destructor change the value of a
> returned error code. Even if you do this:
>
> error_code func()
> {
> error_code ec = ...;
> change_error_code changer(&ec);
> return ec;
> }
>
> `change_error_code` could store a pointer/reference to `ec` and modify it
> in its destructor. But it won't affect the returned value. Because by C++'s
> rules, the return value will be copied/moved out of the expression
> *before* destructors are called. That's why `return ec;` treats `ec` as
> an rvalue.
>
> Why should exceptions be any different? If destructors can't affect error
> codes, why should exceptions?
>
Yes, exception allows dtor to report an error (which you can't do with
C-style error handling). Why not? exception mechanism doesn't require to
imprint error type on function signature, unlike C-style approach. Also the
latter requires explicit return to propagate error object further, where
exception propagation takes care of that automatically. Consider it as a
sign of better design (ducking for cover here ;-)). Ok, I last statement
was a joke, actually. Mostly a joke...
> That being said, I have another perspective on this. Every error mechanism
> has a cost; nothing is free. The question is what cost the cost you're
> willing to pay is.
>
> With error codes, in order to get the error from the source to the
> resolver, every call along the way must *actively* participate in
> transferring the error. That's the price you pay for using error codes.
>
> With exceptions, in order to get the error from the source to the
> resolver, every call along the way must not *inhibit* the flow of the
> error. That's the price you pay for using exceptions.
>
> The error code price means that you have to stick the error code in a
> return value or output parameter. The exception price means that you can't
> emit exceptions during stack unwinding.
>
As of now, yes.
If you need to be able to combine errors arbitrarily like you want, to have
> sequences of failing processes where you accumulate errors and do something
> with them, then you need to use error codes. That kind of specialized
> handling is what they're good at.
>
This doesn't prevent us from introducing default 'combining' mechanism. As
said before -- it won't fit every use case, but will be useful for some.
> - so, if you are "cleaning up" after receiving C-style error --nothing
>>>>>> prevents you from handling second error produced by "cleanup" call (since
>>>>>> propagation is handled by developer anyway). You may choose to replace
>>>>>> older error with new one, chain them together, etc
>>>>>>
>>>>> - with EH language-provided mechanism has no idea what to do with
>>>>>> second error object, so decision was made to call terminate execution since
>>>>>> user allowed error to escape. The idea is that user needs to somehow handle
>>>>>> second error before it "meets" first one. Unfortunately this seriously
>>>>>> limits what you can do -- for example you can't replace old exception with
>>>>>> new one (and continue propagation).
>>>>>>
>>>>>
>>>>> ... why would you want to?
>>>>>
>>>>> Think about this for a second. Your call stack looks like this:
>>>>>
>>>>> A->B->C->D->E
>>>>>
>>>>> Now, E emits an exception. One that is caught by C. That catch
>>>>> provokes stack unwinding down to C.
>>>>>
>>>>> D's unwinding throws an exception. One that is caught by B. That catch
>>>>> provokes stack unwinding down to... where?
>>>>>
>>>>
>>>> exception emitted by E will be replaced by exception emitted by D
>>>> during unwinding (when exception will "meet") and unwinding will continue.
>>>> C may or may not catch it (depending on catch clause).
>>>>
>>>
>>> OK, so let's say that C knows that D can throw something.
>>>
>>> That means C has to look like this:
>>>
>>
>> Wrong. It does not **have** to. You (as end user) certainly can create
>> situation like that, but unless you like to shoot yourself in the foot --
>> you'll come up with better approach
>>
>
> Then what is `C` supposed to look like if it's going to catch *all*
> `E_exception`s that try to pass it?
>
> catch(E_exception &e)
>>> {
>>> //Do stuff for E_exception
>>> }
>>> catch(D_exception &e)
>>> {
>>> //Do stuff for D_exception
>>> throw;
>>> }
>>> catch(E_exception_combined_with_D_exception &e)
>>> {
>>> //Do stuff for E_exception
>>> //Do stuff for D_exception
>>> throw;
>>> }
>>>
>>> That's a lot of repetition.
>>>
>>
>> You literally built a gun, took it in your hands, aimed at your feet and
>> pressed the trigger. What prevents you from catching one base exception?
>>
>
> Your question is like asking "why return X, when you could return a
> `std::any` that maybe contains an X or a Y?"
>
> If I wrote C and E, but not D (E may be a callback/continuation/etc passed
> to D), why would I tie my `E_exception` to whatever D throws? The whole
> point of exception catching is that I choose what to catch, and the
> compiler will find the right handler for the exception.
>
I am getting lost in all these C/D/Es. Point is -- if user knows what to
expect, he'll figure out good way to handle it. If this function declares
that it can throw 'composite' exception in addition to singular ones -- it
can be handled. It may not be always convenient, yes. But such is life of a
coder -- figuring out how to squeeze this logic into something that
actually makes sense.
> In most cases you wouldn't care if it replaced bunch of others --
>> operation failed, here is a result from one of failed sub-operations.
>>
>
> That is an... interesting perspective on how you think people catch
> exceptions and treat their contents.
>
Most of the time in my code I end up catching all or nothing. In fact,
catch is rare construct -- usually located 'at the root' of the thread or
on borders between components (that use different error handling models).
> You may have some additional information if you 'unroll' nested struct.
>> Most of code is unlikely to use throwing dtors and therefore they won't
>> have to deal with this.
>>
>
> But since you don't control all code, you can't know that it won't happen.
> And therefore, every `catch` statement must be written expecting this
> possibility.
>
> Whereas right now, I don't have to care. Throwing destructors during
> unwinding will yield `std::terminate`. And that's not something I have to
> write code for.
>
Which you can continue doing as long as you keep dtors in your code
noexcept :-). This feature is for those who actually need this. Just like
std::current_exception() -- no one really uses it with exception of very
few.
Wrt "one_exception_combined_with_others" check -- I'd like to wrap
> **every** exception into a structure like this,
>
> That would be the fastest way to make everybody stop using exception
> handling.
>
>
>> but this would be breaking change and against the spirit of C++ "you
>> don't pay until you use it". So proposal is to apply wrapper on first
>> instance of "replacing".
>>
> And again -- actual 'combination' logic is not set in stone. What I
>> proposed is just a first attempt.
>>
>
> OK, can we have an attempt that makes sense and is at least theoretically
> usable? Because thus far, even if I *wanted* to have a solution to
> exception collisions, the ideas you've proposed make working with
> exceptions *incredibly tedious*. Having to catch a single type and
> manually fish out of it the type you're maybe interested in, and then
> propagating the rest if any? No, that's horrible code that should be
> handled by the system.
>
> Not having to write that code is precisely why `catch` statements are
> *typed*.
>
you don't have to deal with it until you decide to use it.
> try writing similar logic using EH -- it will be very awkward, lots of
>>>> code.
>>>>
>>>
>>> Please provide a practical example of that. Something from the real
>>> world, where "somehow combine results" is something other than "swallow the
>>> exception".
>>>
>>
>> error_t do_work()
>> {
>> start_device1();
>> // return if failed to start, return array of values (one code per
>> device)
>> start_device2();
>> // if failed: stop_device1, if device1 fails to stop -- set it's
>> error code too
>> start_device3();
>> // if failed: stop_device1, if device1 fails to stop -- set it's
>> error code too
>> // stop_device2, if device2 fails to stop -- set it's
>> error code too
>>
>> // do work using these devices (don't forget to stop them if smth
>> fails during it)
>> ...
>>
>> // time to stop devices
>> code res1 = stop_device3();
>> code res2 = stop_device2();
>> code res3 = stop_device1();
>>
>> // somehow combine results
>> return {res1, res2, res3};
>> }
>>
>> In case if you wonder -- this is not made up situation. I've seen it.
>>
>>
>>
>>>
>>>
>>>> Keep in mind that no matter what each of functions above need to be
>>>> called no matter what.
>>>>
>>>
>>>>
>>> Let's say that each one attempts to switch off a piece of very expensive
>>>> machinery. You can't make it no-fail for physical reasons. And if something
>>>> goes wrong you need to report error(s) upstairs for analysis and associated
>>>> actions.
>>>>
>>>> with this proposal you can put these do_smthN() calls into destructors
>>>> and automatically get "always gets invoked" guarantee along with some
>>>> (hopefully sensible) mechanism that is going to combine these errors for
>>>> propagation up-stack. If user doesn't like default mechanism -- he'll use
>>>> aforementioned knobs to tune it to his liking.
>>>>
>>>> Right now you have to make these dtors silent and accumulate these
>>>> errors elsewhere -- basically turning EH into some weird mix of both styles.
>>>>
>>>
>>> ... OK, I'll play along. You want people to write this:
>>>
>>> try
>>> {
>>> something_doer_3 t3{};
>>> something_doer_2 t2{};
>>> something_doer_1 t1{};
>>> }
>>> catch(something)
>>> {
>>> //Combine the errors
>>> }
>>>
>>> Where the destructors of those three types are what does the work.
>>>
>>
>> rewriting example from above using EH:
>> try
>> {
>> auto_start_stop device1{}; // starts device in ctor, stops in dtor
>> -- both ops can fail with exception
>> auto_start_stop device2{};
>> auto_start_stop device3{};
>>
>> // do work using these devices (which can throw too)
>> }
>> catch(error_base const&)
>> {
>> // entire operation failed, if we want, we could check if this is a
>> combined exception and pull it apart)
>> }
>>
>
> Now, show me the code for this "check if this is a combined exception and
> pull it apart". Then compare it to the error code equivalent. Show me how
> this is in any way better.
>
Ok, you agree that at least content of try block looks cleaner?
Handling can be done like this:
catch(...)
{
process_exception(std::current_exception(), true);
if (std::lead_exception(x)) /// basically a dynamic_cast
for(auto p: std::trailing_exceptions(x))
process_exception(p, false);
}
void process_exception(std::exception_ptr p, bool leading)
{
try
{
rethrow(p);
}
catch(exc1 const& x) { ... }
catch(exc2 const& x) { ... }
}
Not exceptionally clean code, but doable.
> Indeed, this is a perfect example of exactly why your idea doesn't work.
>
> OK, let's say that something in "do work using these devices (which can
> throw too)" throws. The caller of this function catches it, so the stack
> starts unwinding. Those destructors start failing, so a second exception is
> emitted that gets caught right here.
>
Second problem -- "catching" happens before unwinding. I didn't think of
that... Hmm, this means no substitutions... all additional exceptions will
have option to either get discarded or added to a list of trailing
exceptions (or std::terminate of course)
> So... what about the first exception? That exception represents a
> condition that has not yet been resolved (since the code to resolve it has
> not been executed). How does it get to its destination, so that the error
> can be resolved?
>
Once we enter catch block, we'll have exception with list of "trailing"
exceptions -- we could look at all of them and do what user wants to do.
Including further propagation, if necessary.
> Is the catch statement here supposed to extract it and propagate it on, or
> will the system do so automatically? If it requires manual coding, is the
> user able to code it so that it works with *any* exception, or does the
> user have to special-case it for certain exception types?
>
total freedom for user
> Is it possible for this catch statement to effectively swallow *all*
> exceptions, in the event that it throws during unwinding?
>
yes, why not?
> Even taking your idea at face value, there are just too many unknowns
> about it to really give it any consideration.
>
You are correct -- this is just an idea right now... I wanted to see what
kind of reception it'll get (lol) and what arguments could be pitched
against it. Thank you.
> By contrast, with the error code version (or rather the `File::close`
> version, where the destructor and an explicit member can both close, but
> the destructor swallows the error), it just eats the errors as the stack
> unwinds. Nobody gets informed about those problems, but nobody *needs* to
> be either. Does the person receiving the exception from "do work using
> these devices" really need to know if device stopping failed?
>
Yes, this actually may be important. System can try to react to this by
trying to reset each device or informing operator, etc. This whole thing
was result of considering a code that needs to control physical systems
(where any operation can fail). dtor looks like a logical place for all
'must happen' actions, but they could fail and that failure can't be
silently disregarded.
> The case you describe is actually perfect for an out-of-band error
> mechanism (something like `std:errno` or `glGetError`) to report the errors
> from the destructor of the device class. That allows the caller to be able
> to ask whether device stoppage succeeded *without* having to have this
> aggregation of return values. And it works very well with exceptions, since
> the error can still be reported without interfering in the exception
> itself. After all, you're talking about what is a different *channel* of
> error from the original exception.
>
> No one error handling mechanism fits all cases. Even `errno` has its place.
>
Unfortunately then you end up with multiple 'errno' variables (one per
device or libarary) and no knowledge which ones were set. You'll have to
conjure some way of notifying yourself via out-of-band mechanisms or simply
poll all of them.
--
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/f121fc7b-a2e3-4830-8c74-4c5f223af7f0%40isocpp.org.
------=_Part_995_1689028466.1504164306619
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Monday, August 28, 2017 at 6:16:42 PM UTC-5, Ni=
col Bolas 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"lt=
r">On Monday, August 28, 2017 at 3:09:43 PM UTC-4, <a>crusad...@gmail.com</=
a> 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">On Monday=
, August 28, 2017 at 12:56:32 PM UTC-5, Nicol Bolas wrote:<blockquote class=
=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr">On Monday, August 28, 2017 at 12:06=
:30 PM UTC-4, <a>crusad...@gmail.com</a> wrote:<blockquote class=3D"gmail_q=
uote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddin=
g-left:1ex"><div dir=3D"ltr"><div>Before reading stuff below I suggest to s=
et aside any dogmatic blinders you may have, namely:</div><div>- realize th=
at there is nothing particular special about destructors -- they are just f=
unctions that runtime calls automatically in specific circumstances and yes=
, they may want to report an error</div></div></blockquote><div><br>Untrue.=
Destructors provoke the ending of the lifetime of an object. That makes th=
em special. Much like how constructors signal the beginning of the lifetime=
of an object.<br></div></div></blockquote><div><br></div><div>It is a func=
tion. And it can throw exception as it is right now. It is noexcept right b=
y default, but nothing prevents me to declare it noexcept(false) and it wil=
l work. The only case when it won't is when it throws during unwinding.=
I believe it can be changed and it should be changed to accomodate for a p=
ractical situation. And it won't affect existing code at all.</div></di=
v></blockquote><div><br>If exception collisions affect the type of exceptio=
n being caught, then it affects any existing code where that user does not =
control what objects get destroyed between themselves and the source of the=
exception they're catching.<br></div></div></blockquote><div><br></div=
><div>As long as user is aware of potential magic -- it is fine. It is stil=
l better in sense that it will become an options, while right now it is std=
::terminate(). And with noexcept(true) dtors (by default) everyone is prett=
y safe.</div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quo=
te" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddi=
ng-left: 1ex;"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"=
margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><di=
v dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-le=
ft:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-le=
ft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>- you can't r=
eally tell what makes sense or not -- only end user makes this decision</di=
v></div></blockquote><div><br>The C++ object model is all about defining wh=
at "makes sense". That's why you can't just pretend that =
an object exists in some memory.<br></div></div></blockquote><div><br></div=
><div>I never said that.</div></div></blockquote><div><br>Nor did I accuse =
you of saying it. My point is that your perspective is that of someone who&=
#39;s doesn't care about what a piece of functionality=C2=A0<i>means</i=
>; what matters to you is what it can do. It's a perspective of trying =
to view C++, not as a collection of meaningful parts and functionality, but=
an arbitrary assemblage of things onto which you can graft your own meanin=
g.<br></div></div></blockquote><div><br></div><div>'Object model' y=
ou mentioned is a result of such grafting, isn't it? What prevents me f=
rom grafting mine, slightly different?</div><div><br></div><div>=C2=A0</div=
><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>Destruc=
tors mean something to the C++ object model. They're not just a functio=
n call. Just like constructors mean something to the C++ object model. What=
"makes sense" <i>matters</i>.<br><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"><div>Nothing prevents me from destroyin=
g object with error right now and it will work just fine:</div><div>void fo=
o()</div><div>{</div><div>=C2=A0 =C2=A0 struct X { ~X() { throw 1; } x;</di=
v><div>}</div><div><br></div><div>object still gets destroyed just fine.</d=
iv></div></blockquote><div><br>That calls `std::terminate`, since you tried=
to emit an exception through a `noexcept` function. </div></div></blockquo=
te><div><br></div><div>Naturally :-). I forgot to add noexcept(false). Stil=
l living in the world of C++03.</div><div><br></div><div>=C2=A0</div><block=
quote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-le=
ft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>While yes, the=
object `x` has had its lifetime ended, that happened when the destructor <=
i>started</i>. So the throw is essentially irrelevant.<br><br>What matters =
is what the state of the system means in this event.<br><br></div><blockquo=
te class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>What logical meaning I=
associated with 'failed destructor' is my (end user) business.</di=
v></div></blockquote><div><br>No, it's not. It's everybody else'=
;s business too.<br><br>For example, if I put an object with a throwing des=
tructor in my object which doesn't have a throwing destructor... what d=
oes that mean?<br></div></div></blockquote><div><br></div><div>Just like wi=
th other components of every library -- you need to have some minimal knowl=
edge to use it. Ideally, compiler should warn you if you have a call that c=
ould throw inside of a no-throw function. But C++ lacks necessary tools for=
that, unfortunately -- like a way to declare that given block isn't go=
ing to throw. Smth like this:</div><div><br></div><div>vector<int> v;=
</div><div>v.reserve(1);</div><div>...</div><div><br></div><div>void foo() =
noexcept</div><div>{</div><div>=C2=A0 =C2=A0 =C2=A0noexcept_promise { =C2=
=A0 =C2=A0 // code in this scope won't throw, trust me, compiler<br></d=
iv><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 v.push_back(10);</div><div>=C2=
=A0 =C2=A0 =C2=A0}</div><div>}</div><div><br></div><div><br></div><div>=C2=
=A0</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"><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-le=
ft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>And it may make s=
ense to me.</div></div></blockquote><div><br>And your code needs to work wi=
th the rest of the world.<br></div></div></blockquote><div><br></div><div>O=
k, you just raised first actual problem (from my pov):</div><div><br></div>=
<div>class X; =C2=A0 // it's dtor can throw</div><div><br></div><div>st=
ruct S</div><div>{</div><div>=C2=A0 =C2=A0 X x;</div><div><br></div><div>=
=C2=A0 =C2=A0 ~S() noexcept(true) {} =C2=A0 =C2=A0 =C2=A0// no way to inter=
cept exception from x's dtor</div><div>};</div><div><br></div><div>this=
sucks... I wonder if this can be 'fixed' with same thing we can do=
in ctors:</div><div><br></div><div><div>=C2=A0 =C2=A0 ~S() noexcept(true)=
=C2=A0</div><div>=C2=A0 =C2=A0 try</div><div>=C2=A0 =C2=A0 {</div><div>=C2=
=A0 =C2=A0 }</div></div><div>=C2=A0 =C2=A0 catch(...) { ... }</div><div><br=
></div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-lef=
t: 1ex;"><div dir=3D"ltr"><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:0;margin-left:0.=
8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>So t=
he standard has every right to decide that circumstance X doesn't make =
sense, so we're not going to support it.<br><br></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><div>- what is proposed -- is just =
a tool, whether to use it or not, is up to end user</div></div></blockquote=
><div><br>The model that the proposal creates still has to make sense. Whic=
h it does not. Giving people tools that are incoherent and encourage bad co=
ding is not helpful.<br></div></div></blockquote><div><br></div><div>You cl=
aim "make no sense" very vigorously, but I've yet to see any =
good argument for that.</div></div></blockquote><div><br>That's because=
you're looking from a world view where destructors "are just func=
tions that runtime calls automatically in specific circumstances". It =
stops making sense once you move to a perspective where there is an actual =
meaning to object destruction besides calling a bunch of functions.<br></di=
v></div></blockquote><div><br></div><div>Correct. As I said in another mess=
age -- I am trying to get you to look at this from another angle.</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"><div>I can't help your world view. I understand it, but I =
do not subscribe to it.<br></div></div></blockquote><div><br></div><div>As =
mentioned -- I am very pragmatical. I'll try to use whatever world view=
that makes my life easier and gets the job done. I also like nice, compact=
solutions.</div><div><br></div><div>But I am glad you understand my point.=
Thank you.</div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail=
_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;p=
adding-left: 1ex;"><div dir=3D"ltr"><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:0;margi=
n-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">=
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On Sunday, August =
27, 2017 at 9:19:57 PM UTC-5, Nicol Bolas wrote:<blockquote class=3D"gmail_=
quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddi=
ng-left:1ex"><div dir=3D"ltr">On Sunday, August 27, 2017 at 9:35:21 PM UTC-=
4, <a>crusad...@gmail.com</a> wrote:</div></blockquote><div></div><blockquo=
te class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1p=
x #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>No, a throwing destruc=
tor is a terrible, horrible, no-good, very-bad idea. Implicitly forbidding =
it is a good thing, and C++ has absolutely no need to support exception cla=
shing (which can only happen through a throwing destructor).<br><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"><div></div><div>Her=
e are my thoughts:</div><div>- both C-style error handling and C++ exceptio=
ns do effectively the same thing -- construct error object and pass it up t=
he call stack, differences are:</div><div><blockquote style=3D"margin:0 0 0=
40px;border:none;padding:0px"><div>- C: error type is known to caller and =
caller is responsible for allocating memory for error object</div></blockqu=
ote></div><blockquote style=3D"margin:0 0 0 40px;border:none;padding:0px"><=
div><div>- C: caller is responsible for proper propagation of error=C2=A0</=
div></div></blockquote><blockquote style=3D"margin:0 0 0 40px;border:none;p=
adding:0px"><div><div>- EH: caller only knows whether some error can bubble=
up (ignoring exception specs here, since they are deprecated)</div></div><=
/blockquote><blockquote style=3D"margin:0 0 0 40px;border:none;padding:0px"=
><div>- EH: there is a mechanism that automates error propagation (and matc=
hing to related catch clause)</div></blockquote></div></blockquote><div><br=
>- EH: Arbitrary code can execute between the generation of the error code =
and its reception. That code itself can fail.<br></div></div></blockquote><=
div><br></div><div>no, same thing can happen with C-style error handling. I=
t looks rather obvious to me</div></div></blockquote><div><br>Your analogy =
says that `return` and the use of the return value are similar to `throw` a=
nd `catch` for that exception. Given that analogy, no, the same thing canno=
t happen in C-style error handling. The function that receives the error is=
the one that called the function. Between the end of the initialization of=
the return value from the function creating the error code, to the beginni=
ng of the initialization of the value that the receiving function is creati=
ng, no user code can be executed.<br><br>Oh, there can be code between the =
generator of the error and where the error is <i>resolved</i>: that is, whe=
re you stop dealing with the error condition and progress normally. You can=
return the error code up the stack, do conditional logic based on it, and =
all kinds of stuff.<br><br>But there is a lot more that can happen between =
a `throw` and a `catch` that cannot happen between a `return` and the use o=
f that returned value.<br></div></div></blockquote><div><br></div><div>Agai=
n, no. Two situations -- propagation of error to the point where it gets ha=
ndled through unwinding mechanism is fundamentally the same as propagation =
of it via "if (auto err =3D foo()) return err". In both cases any=
thing could happen in-between.</div></div></blockquote><div><br>I just real=
ized something. There is one similarity between error code propagation and =
exception-caused stack unwinding. In both cases... destructors <i>cannot</i=
> affect an error code being returned by value ;)<br><br>No really; go ahea=
d and try to make a destructor change the value of a returned error code. E=
ven if you do this:<br><br><div style=3D"background-color:rgb(250,250,250);=
border-color:rgb(187,187,187);border-style:solid;border-width:1px"><code><d=
iv><span style=3D"color:#000">error_code func</span><span style=3D"color:#6=
60">()</span><span style=3D"color:#000"><br></span><span style=3D"color:#66=
0">{</span><span style=3D"color:#000"><br>=C2=A0 error_code ec </span><span=
style=3D"color:#660">=3D</span><span style=3D"color:#000"> </span><span st=
yle=3D"color:#660">...;</span><span style=3D"color:#000"><br>=C2=A0 change_=
error_code changer</span><span style=3D"color:#660">(&</span><span styl=
e=3D"color:#000">ec</span><span style=3D"color:#660">);</span><span style=
=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#008">return</span><=
span style=3D"color:#000"> ec</span><span style=3D"color:#660">;</span><spa=
n style=3D"color:#000"><br></span><span style=3D"color:#660">}</span><span =
style=3D"color:#000"><br></span></div></code></div><br>`change_error_code` =
could store a pointer/reference to `ec` and modify it in its destructor. Bu=
t it won't affect the returned value. Because by C++'s rules, the r=
eturn value will be copied/moved out of the expression <i>before</i> destru=
ctors are called. That's why `return ec;` treats `ec` as an rvalue.<br>=
<br>Why should exceptions be any different? If destructors can't affect=
error codes, why should exceptions?<br></div></div></blockquote><div>=C2=
=A0</div><div>Yes, exception allows dtor to report an error (which you can&=
#39;t do with C-style error handling). Why not? exception mechanism doesn&#=
39;t require to imprint error type on function signature, unlike C-style ap=
proach. Also the latter requires explicit return to propagate error object =
further, where exception propagation takes care of that automatically. Cons=
ider it as a sign of better design (ducking for cover here ;-)). Ok, I last=
statement was a joke, actually. Mostly a joke...<br></div><div><br></div><=
div>=C2=A0</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"lt=
r"><div></div><div>That being said, I have another perspective on this. Eve=
ry error mechanism has a cost; nothing is free. The question is what cost t=
he cost you're willing to pay is.<br><br>With error codes, in order to =
get the error from the source to the resolver, every call along the way mus=
t <i>actively</i> participate in transferring the error. That's the pri=
ce you pay for using error codes.<br><br>With exceptions, in order to get t=
he error from the source to the resolver, every call along the way must not=
<i>inhibit</i> the flow of the error. That's the price you pay for usi=
ng exceptions.<br><br>The error code price means that you have to stick the=
error code in a return value or output parameter. The exception price mean=
s that you can't emit exceptions during stack unwinding.<br></div></div=
></blockquote><div><br></div><div>As of now, yes.</div><div>=C2=A0</div><di=
v><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><=
div>If you need to be able to combine errors arbitrarily like you want, to =
have sequences of failing processes where you accumulate errors and do some=
thing with them, then you need to use error codes. That kind of specialized=
handling is what they're good at.<br></div></div></blockquote><div><br=
></div><div>This doesn't prevent us from introducing default 'combi=
ning' mechanism. As said before -- it won't fit every use case, but=
will be useful for some.</div><div><br></div><div>=C2=A0</div><blockquote =
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1p=
x #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><blockquote class=3D"gmai=
l_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pad=
ding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"=
margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><di=
v dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-le=
ft:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><blo=
ckquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-le=
ft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"g=
mail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;=
padding-left:1ex"><div dir=3D"ltr"><div>=C2=A0- so, if you are "cleani=
ng up" after receiving C-style error --nothing prevents you from handl=
ing second error produced by "cleanup" call (since propagation is=
handled by developer anyway). You may choose to replace older error with n=
ew one, chain them together, etc</div></div></blockquote><blockquote class=
=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><div>- with EH language-provided me=
chanism has no idea what to do with second error object, so decision was ma=
de to call terminate execution since user allowed error to escape. The idea=
is that user needs to somehow handle second error before it "meets&qu=
ot; first one. Unfortunately this seriously limits what you can do -- for e=
xample you can't replace old exception with new one (and continue propa=
gation).<br></div></div></blockquote><div><br>... why would you want to?<br=
><br>Think about this for a second. Your call stack looks like this:<br><br=
><div style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,1=
87);border-style:solid;border-width:1px"><code><div><span style=3D"color:#0=
00">A</span><span style=3D"color:#660">-></span><span style=3D"color:#00=
0">B</span><span style=3D"color:#660">-></span><span style=3D"color:#000=
">C</span><span style=3D"color:#660">-></span><span style=3D"color:#000"=
>D</span><span style=3D"color:#660">-></span><span style=3D"color:#000">=
E</span></div></code></div><br>Now, E emits an exception. One that is caugh=
t by C. That catch provokes stack unwinding down to C.<br><br>D's unwin=
ding throws an exception. One that is caught by B. That catch provokes stac=
k unwinding down to... where?<br></div></div></blockquote><div><br></div><d=
iv>exception emitted by E will be replaced by exception emitted by D during=
unwinding (when exception will "meet") and unwinding will contin=
ue. C may or may not catch it (depending on catch clause).<br></div></div><=
/blockquote><div><br>OK, so let's say that C knows that D can throw som=
ething.<br><br>That means C has to look like this:<br></div></div></blockqu=
ote><div><br></div><div>Wrong. It does not **have** to. You (as end user) c=
ertainly can create situation like that, but unless you like to shoot yours=
elf in the foot -- you'll come up with better approach</div></div></blo=
ckquote><div><br>Then what is `C` supposed to look like if it's going t=
o catch <i>all</i> `E_exception`s that try to pass it?<br><br></div><blockq=
uote 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></div><blockquote cl=
ass=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><div style=3D"background-co=
lor:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;borde=
r-width:1px"><code><div><span style=3D"color:#008">catch</span><span style=
=3D"color:#660">(</span><span style=3D"color:#000">E_exception </span><span=
style=3D"color:#660">&</span><span style=3D"color:#000">e</span><span =
style=3D"color:#660">)</span><span style=3D"color:#000"><br></span><span st=
yle=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 </span><sp=
an style=3D"color:#800">//Do stuff for E_exception</span><span style=3D"col=
or:#000"><br></span><span style=3D"color:#660">}</span><span style=3D"color=
:#000"><br></span><span style=3D"color:#008">catch</span><span style=3D"col=
or:#660">(</span><span style=3D"color:#000">D_exception </span><span style=
=3D"color:#660">&</span><span style=3D"color:#000">e</span><span style=
=3D"color:#660">)</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 </span><span =
style=3D"color:#800">//Do stuff for D_exception</span><span style=3D"color:=
#000"><br>=C2=A0 </span><span style=3D"color:#008">throw</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#660">}</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#008">catch</span><span style=3D"color:#660">(</span><span style=
=3D"color:#000">E_exception_combined_<wbr>with_D_exception </span><span sty=
le=3D"color:#660">&</span><span style=3D"color:#000">e</span><span styl=
e=3D"color:#660">)</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#660">{</span><span style=3D"color:#000"><br></span><code><span s=
tyle=3D"color:#000">=C2=A0 </span><span style=3D"color:#800">//Do stuff for=
E_exception</span><span style=3D"color:#000"><br></span><span style=3D"col=
or:#000"></span></code><code><span style=3D"color:#000">=C2=A0 </span><span=
style=3D"color:#800">//Do stuff for D_exception</span><span style=3D"color=
:#000"><br></span><span style=3D"color:#000"></span></code><span style=3D"c=
olor:#000">=C2=A0 </span><span style=3D"color:#008">throw</span><span style=
=3D"color:#660">;</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#660">}</span><span style=3D"color:#000"><br></span></div></code>=
</div><br>That's a lot of repetition.<br></div></div></blockquote><div>=
<br></div><div>You literally built a gun, took it in your hands, aimed at y=
our feet and pressed the trigger. What prevents you from catching one base =
exception?</div></div></blockquote><div><br>Your question is like asking &q=
uot;why return X, when you could return a `std::any` that maybe contains an=
X or a Y?"<br><br>If I wrote C and E, but not D (E may be a callback/=
continuation/etc passed to D), why would I tie my `E_exception` to whatever=
D throws? The whole point of exception catching is that I choose what to c=
atch, and the compiler will find the right handler for the exception.<br></=
div></div></blockquote><div><br></div><div>I am getting lost in all these C=
/D/Es. Point is -- if user knows what to expect, he'll figure out good =
way to handle it. If this function declares that it can throw 'composit=
e' exception in addition to singular ones -- it can be handled. It may =
not be always convenient, yes. But such is life of a coder -- figuring out =
how to squeeze this logic into something that actually makes sense.</div><d=
iv><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"ma=
rgin: 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:0;margin=
-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><=
div>In most cases you wouldn't care if it replaced bunch of others -- o=
peration failed, here is a result from one of failed sub-operations.</div><=
/div></blockquote><div><br>That is an... interesting perspective on how you=
think people catch exceptions and treat their contents.<br></div></div></b=
lockquote><div><br></div><div>Most of the time in my code I end up catching=
all or nothing. In fact, catch is rare construct -- usually located 'a=
t the root' of the thread or on borders between components (that use di=
fferent error handling models).</div><div><br></div><div>=C2=A0</div><block=
quote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-le=
ft: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><blockquote class=
=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><div>You may have some additional i=
nformation if you 'unroll' nested struct. Most of code is unlikely =
to use throwing dtors and therefore they won't have to deal with this.<=
/div></div></blockquote><div><br>But since you don't control all code, =
you can't know that it won't happen. And therefore, every `catch` s=
tatement must be written expecting this possibility.<br><br>Whereas right n=
ow, I don't have to care. Throwing destructors during unwinding will yi=
eld `std::terminate`. And that's not something I have to write code for=
..<br></div></div></blockquote><div><br></div><div>Which you can continue do=
ing as long as you keep dtors in your code noexcept :-). This feature is fo=
r those who actually need this. Just like std::current_exception() -- no on=
e really uses it with exception of very few.</div><div>=C2=A0</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"><div>=
=C2=A0Wrt "one_exception_combined_with_<wbr>others" check -- I=
9;d like to wrap **every** exception into a structure like this,</div><div>=
<br>That would be the fastest way to make everybody stop using exception ha=
ndling.<br>=C2=A0</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"><div>but this would be breaking change and against the spirit of C++ &=
quot;you don't pay until you use it". So proposal is to apply wrap=
per on first instance of "replacing".</div></div></blockquote><di=
v></div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div></div=
><div>And again -- actual 'combination' logic is not set in stone. =
What I proposed is just a first attempt. <br></div></div></blockquote><br>O=
K, can we have an attempt that makes sense and is at least theoretically us=
able? Because thus far, even if I <i>wanted</i> to have a solution to excep=
tion collisions, the ideas you've proposed make working with exceptions=
<i>incredibly tedious</i>. Having to catch a single type and manually fish=
out of it the type you're maybe interested in, and then propagating th=
e rest if any? No, that's horrible code that should be handled by the s=
ystem.<br><br>Not having to write that code is precisely why `catch` statem=
ents are <i>typed</i>.<br></div></blockquote><div><br></div><div>you don=
9;t have to deal with it until you decide to use it.</div><div><br></div><d=
iv>=C2=A0</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:0;margin-left:0.8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><blockquote clas=
s=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:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left=
:1ex"><div dir=3D"ltr"><div>try writing similar logic using EH -- it will b=
e very awkward, lots of code.</div></div></blockquote><div><br>Please provi=
de a practical example of that. Something from the real world, where "=
somehow combine results" is something other than "swallow the exc=
eption".<br></div></div></blockquote><div><br></div><div><div>error_t =
do_work()</div><div>{</div><div>=C2=A0 =C2=A0 start_device1();</div><div>=
=C2=A0 =C2=A0 // return if failed to start, return array of values (one cod=
e per device)</div><div>=C2=A0 =C2=A0 start_device2();</div><div>=C2=A0 =C2=
=A0 // if failed: stop_device1, if device1 fails to stop -- set it's er=
ror code too</div><div>=C2=A0 =C2=A0 start_device3();</div><div>=C2=A0 =C2=
=A0 // if failed: stop_device1, if device1 fails to stop -- set it's er=
ror code too</div><div>=C2=A0 =C2=A0 // =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 stop_device2, if device2 fails to stop -- set it's error =
code too</div><div><br></div><div>=C2=A0 =C2=A0// do work using these devic=
es (don't forget to stop them if smth fails during it)</div><div>=C2=A0=
=C2=A0 ...</div><div><br></div><div>=C2=A0 =C2=A0 // time to stop devices<=
/div><div>=C2=A0 =C2=A0 code res1 =3D stop_device3();</div><div>=C2=A0 =C2=
=A0 code res2 =3D stop_device2();</div><div>=C2=A0 =C2=A0 code res3 =3D sto=
p_device1();</div><div><br></div><div>=C2=A0 =C2=A0 // somehow combine resu=
lts</div><div>=C2=A0 =C2=A0 return {res1, res2, res3};</div><div>}<br></div=
></div><div><br></div><div>In case if you wonder -- this is not made up sit=
uation. I've seen it.</div><div><br></div><div>=C2=A0</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"><div>=C2=A0</div><blockquote c=
lass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div dir=3D"ltr"><div>Keep in mind that no matte=
r what each of functions above need to be called no matter what.</div></div=
></blockquote><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px=
0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div>=C2=A0=
</div></blockquote><blockquote class=3D"gmail_quote" style=3D"margin:0;marg=
in-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"=
><div>Let's say that each one attempts to switch off a piece of very ex=
pensive machinery. You can't make it no-fail for physical reasons. And =
if something goes wrong you need to report error(s) upstairs for analysis a=
nd associated actions.</div><div><br></div><div>with this proposal you can =
put these do_smthN() calls into destructors and automatically get "alw=
ays gets invoked" guarantee along with some (hopefully sensible) mecha=
nism that is going to combine these errors for propagation up-stack. If use=
r doesn't like default mechanism -- he'll use aforementioned knobs =
to tune it to his liking.</div><div><br></div><div>Right now you have to ma=
ke these dtors silent and accumulate these errors elsewhere -- basically tu=
rning EH into some weird mix of both styles.</div></div></blockquote><div><=
br>... OK, I'll play along. You want people to write this:<br><br><div =
style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);bo=
rder-style:solid;border-width:1px"><code><div><span style=3D"color:#008">tr=
y</span><span style=3D"color:#000"><br></span><span style=3D"color:#660">{<=
/span><span style=3D"color:#000"><br>=C2=A0 something_doer_3 t3</span><span=
style=3D"color:#660">{};</span><span style=3D"color:#000"><br>=C2=A0 somet=
hing_doer_2 t2</span><span style=3D"color:#660">{};</span><span style=3D"co=
lor:#000"><br>=C2=A0 something_doer_1 t1</span><span style=3D"color:#660">{=
};</span><span style=3D"color:#000"><br></span><span style=3D"color:#660">}=
</span><span style=3D"color:#000"><br></span><span style=3D"color:#008">cat=
ch</span><span style=3D"color:#660">(</span><span style=3D"color:#000">some=
thing</span><span style=3D"color:#660">)</span><span style=3D"color:#000"><=
br></span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br=
>=C2=A0 //Combine the errors<br></span><span style=3D"color:#660">}</span><=
span style=3D"color:#000"><br></span></div></code></div><br>Where the destr=
uctors of those three types are what does the work.<br></div></div></blockq=
uote><div><br></div><div>rewriting example from above using EH:</div><div>t=
ry</div><div>{</div><div>=C2=A0 =C2=A0 auto_start_stop device1{}; =C2=A0 =
=C2=A0// starts device in ctor, stops in dtor -- both ops can fail with exc=
eption</div><div>=C2=A0 =C2=A0 auto_start_stop device2{};</div><div>=C2=A0 =
=C2=A0 auto_start_stop device3{};</div><div><br></div><div>=C2=A0 =C2=A0 //=
do work using these devices (which can throw too)</div><div>}</div><div>ca=
tch(error_base const&)</div><div>{</div><div>=C2=A0 =C2=A0 // entire op=
eration failed, if we want, we could check if this is a combined exception =
and pull it apart)</div><div>}</div></div></blockquote><div><br>Now, show m=
e the code for this "check if this is a combined exception and pull it=
apart". Then compare it to the error code equivalent. Show me how thi=
s is in any way better.<br></div></div></blockquote><div><br></div><div>Ok,=
you agree that at least content of try block looks cleaner?</div><div><br>=
</div><div>Handling can be done like this:</div><div><br></div><div>catch(.=
...)</div><div>{</div><div>=C2=A0 =C2=A0 process_exception(std::current_exce=
ption(), true);</div><div>=C2=A0 =C2=A0 if (std::lead_exception(x)) =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/// basically a dynamic_cast</div>=
<div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 for(auto p: std::trailing_exceptions(x))</=
div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 process_exception(p, fal=
se);</div><div>}<br></div><div><br></div><div>void process_exception(std::e=
xception_ptr p, bool leading)</div><div>{</div><div>=C2=A0 =C2=A0 try</div>=
<div>=C2=A0 =C2=A0 {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 rethrow(p);</div=
><div>=C2=A0 =C2=A0 }</div><div>=C2=A0 =C2=A0 catch(exc1 const& x) { ..=
.. }</div><div>=C2=A0 =C2=A0 catch(exc2 const& x) { ... }</div><div>}</d=
iv><div><br></div><div>Not exceptionally clean code, but doable.</div><div>=
<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margi=
n: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><di=
v dir=3D"ltr"><div>Indeed, this is a perfect example of exactly why your id=
ea doesn't work.<br><br>OK, let's say that something in "do wo=
rk using these devices (which can throw too)" throws. The caller of th=
is function catches it, so the stack starts unwinding. Those destructors st=
art failing, so a second exception is emitted that gets caught right here.<=
br></div></div></blockquote><div><br></div><div>Second problem -- "cat=
ching" happens before unwinding. I didn't think of that... Hmm, th=
is means no substitutions... all additional exceptions will have option to =
either get discarded or added to a list of trailing exceptions (or std::ter=
minate of course)</div><div><br></div><div>=C2=A0</div><blockquote class=3D=
"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc s=
olid;padding-left: 1ex;"><div dir=3D"ltr"><div>So... what about the first e=
xception? That exception represents a condition that has not yet been resol=
ved (since the code to resolve it has not been executed). How does it get t=
o its destination, so that the error can be resolved?</div></div></blockquo=
te><div><br></div><div>Once we enter catch block, we'll have exception =
with list of "trailing" exceptions -- we could look at all of the=
m and do what user wants to do. Including further propagation, if necessary=
..</div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-lef=
t: 1ex;"><div dir=3D"ltr"><div> Is the catch statement here supposed to ext=
ract it and propagate it on, or will the system do so automatically? If it =
requires manual coding, is the user able to code it so that it works with <=
i>any</i> exception, or does the user have to special-case it for certain e=
xception types? </div></div></blockquote><div><br></div><div>total freedom =
for user</div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_qu=
ote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padd=
ing-left: 1ex;"><div dir=3D"ltr"><div>Is it possible for this catch stateme=
nt to effectively swallow <i>all</i> exceptions, in the event that it throw=
s during unwinding?<br></div></div></blockquote><div><br></div><div>yes, wh=
y not?</div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quot=
e" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddin=
g-left: 1ex;"><div dir=3D"ltr"><div>Even taking your idea at face value, th=
ere are just too many unknowns about it to really give it any consideration=
..<br></div></div></blockquote><div><br></div><div>You are correct -- this i=
s just an idea right now... I wanted to see what kind of reception it'l=
l get (lol) and what arguments could be pitched against it. Thank you.</div=
><div><br></div><div>=C2=A0</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"><div>By contrast, with the error code version (or rathe=
r the `File::close` version, where the destructor and an explicit member ca=
n both close, but the destructor swallows the error), it just eats the erro=
rs as the stack unwinds. Nobody gets informed about those problems, but nob=
ody <i>needs</i> to be either. Does the person receiving the exception from=
"do work using these devices" really need to know if device stop=
ping failed?<br></div></div></blockquote><div><br></div><div>Yes, this actu=
ally may be important. System can try to react to this by trying to reset e=
ach device or informing operator, etc. This whole thing was result of consi=
dering a code that needs to control physical systems (where any operation c=
an fail). dtor looks like a logical place for all 'must happen' act=
ions, but they could fail and that failure can't be silently disregarde=
d.</div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" s=
tyle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-le=
ft: 1ex;"><div dir=3D"ltr"><div>The case you describe is actually perfect f=
or an out-of-band error mechanism (something like `std:errno` or `glGetErro=
r`) to report the errors from the destructor of the device class. That allo=
ws the caller to be able to ask whether device stoppage succeeded <i>withou=
t</i> having to have this aggregation of return values. And it works very w=
ell with exceptions, since the error can still be reported without interfer=
ing in the exception itself. After all, you're talking about what is a =
different <i>channel</i> of error from the original exception.<br><br>No on=
e error handling mechanism fits all cases. Even `errno` has its place.<br><=
/div></div></blockquote><div><br></div><div>Unfortunately then you end up w=
ith multiple 'errno' variables (one per device or libarary) and no =
knowledge which ones were set. You'll have to conjure some way of notif=
ying yourself via out-of-band mechanisms or simply poll all of them.</div><=
div>=C2=A0</div></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/f121fc7b-a2e3-4830-8c74-4c5f223af7f0%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/f121fc7b-a2e3-4830-8c74-4c5f223af7f0=
%40isocpp.org</a>.<br />
------=_Part_995_1689028466.1504164306619--
------=_Part_994_1571569668.1504164306615--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Thu, 31 Aug 2017 00:33:06 -0700
Raw View
On Thursday, 31 August 2017 00:25:06 PDT crusader.mike@gmail.com wrote:
> Just like with other components of every library -- you need to have some
> minimal knowledge to use it. Ideally, compiler should warn you if you have
> a call that could throw inside of a no-throw function.
Or it should just be silent, because you meant exactly what you wrote and you
know that either nothing will be thrown under the circumstances surrounding
that call, or that if something does throw, it's supposed to call
std::terminate.
We have both cases in Qt code: a few functions that are marked noexcept but
that do call functions that could throw, just not under those conditions. And
this:
void QMessageLogger::fatal(const char *msg, ...) const Q_DECL_NOTHROW
{
QString message;
va_list ap;
va_start(ap, msg); // use variable arg list
QT_TERMINATE_ON_EXCEPTION(message = qt_message(QtFatalMsg, context, msg,
ap));
va_end(ap);
qt_message_fatal(QtFatalMsg, context, message);
}
That qt_message function can throw std::bad_alloc. But since we're about to
terminate the program anyway, we don't want a fail-to-terminate condition and
thus continue execution. We want to terminate.
That macro, a little surprisingly, is defined as:
# define QT_TERMINATE_ON_EXCEPTION(expr) do { expr; } while (false)
Because the function is already noexcept, there's no need for a try/catch
block.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/5338260.LXCitT5SKg%40tjmaciei-mobl1.
.
Author: crusader.mike@gmail.com
Date: Thu, 31 Aug 2017 00:54:49 -0700 (PDT)
Raw View
------=_Part_994_645065432.1504166089519
Content-Type: multipart/alternative;
boundary="----=_Part_995_1152126929.1504166089519"
------=_Part_995_1152126929.1504166089519
Content-Type: text/plain; charset="UTF-8"
On Thursday, August 31, 2017 at 2:33:10 AM UTC-5, Thiago Macieira wrote:
>
> On Thursday, 31 August 2017 00:25:06 PDT crusad...@gmail.com <javascript:>
> wrote:
> > Just like with other components of every library -- you need to have
> some
> > minimal knowledge to use it. Ideally, compiler should warn you if you
> have
> > a call that could throw inside of a no-throw function.
>
> Or it should just be silent, because you meant exactly what you wrote and
> you
> know that either nothing will be thrown under the circumstances
> surrounding
> that call, or that if something does throw, it's supposed to call
> std::terminate.
>
Often it is hard to tell by looking at the code if it can throw or not.
Compiler's help would be welcome, but then you need an option tlike
noexcept_promise (mentioned in message you quoted). I always leave a
comment explaining why this piece of code will never throw, but code tends
to change and people often don't update these comments. :-(
> We have both cases in Qt code: a few functions that are marked noexcept
> but
> that do call functions that could throw, just not under those conditions.
> And
> this:
>
> void QMessageLogger::fatal(const char *msg, ...) const Q_DECL_NOTHROW
> {
> QString message;
>
> va_list ap;
> va_start(ap, msg); // use variable arg list
> QT_TERMINATE_ON_EXCEPTION(message = qt_message(QtFatalMsg, context,
> msg,
> ap));
> va_end(ap);
>
> qt_message_fatal(QtFatalMsg, context, message);
> }
>
> That qt_message function can throw std::bad_alloc. But since we're about
> to
> terminate the program anyway, we don't want a fail-to-terminate condition
> and
> thus continue execution. We want to terminate.
>
> That macro, a little surprisingly, is defined as:
>
> # define QT_TERMINATE_ON_EXCEPTION(expr) do { expr; } while (false)
>
> Because the function is already noexcept, there's no need for a try/catch
> block.
>
it may make sense to consider producing "no memory" message that is
guaranteed to succeed. But I don't know much about Qt, maybe it doesn't
make sense here.
It is off-topic in this thread, but I don't like noexcept (not because it
is present by default on dtors! :) ) -- it is a promise and
enforcement-of-promise combined into one keyword. Makes some code less
efficient that it would've been if it was only promise -- and if you omit
it, it loses efficiency too (because callers benefit from it's presence).
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
>
>
--
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/05d8aa3e-9a60-4319-873e-b36976275775%40isocpp.org.
------=_Part_995_1152126929.1504166089519
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Thursday, August 31, 2017 at 2:33:10 AM UTC-5, =
Thiago Macieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Thurs=
day, 31 August 2017 00:25:06 PDT <a href=3D"javascript:" target=3D"_blank" =
gdf-obfuscated-mailto=3D"OhnAHDyqAQAJ" rel=3D"nofollow" onmousedown=3D"this=
..href=3D'javascript:';return true;" onclick=3D"this.href=3D'jav=
ascript:';return true;">crusad...@gmail.com</a> wrote:
<br>> Just like with other components of every library -- you need to ha=
ve some
<br>> minimal knowledge to use it. Ideally, compiler should warn you if =
you have
<br>> a call that could throw inside of a no-throw function.
<br>
<br>Or it should just be silent, because you meant exactly what you wrote a=
nd you=20
<br>know that either nothing will be thrown under the circumstances surroun=
ding=20
<br>that call, or that if something does throw, it's supposed to call=
=20
<br>std::terminate.
<br></blockquote><div><br></div><div>Often it is hard to tell by looking at=
the code if it can throw or not. Compiler's help would be welcome, but=
then you need an option tlike noexcept_promise (mentioned in message you q=
uoted). I always leave a comment explaining why this piece of code will nev=
er throw, but code tends to change and people often don't=C2=A0update t=
hese comments. :-(</div><div><br></div><div>=C2=A0</div><blockquote class=
=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #cc=
c solid;padding-left: 1ex;">We have both cases in Qt code: a few functions =
that are marked noexcept but=20
<br>that do call functions that could throw, just not under those condition=
s. And=20
<br>this:
<br>
<br>void QMessageLogger::fatal(const char *msg, ...) const Q_DECL_NOTHROW
<br>{
<br>=C2=A0 =C2=A0 QString message;
<br>
<br>=C2=A0 =C2=A0 va_list ap;
<br>=C2=A0 =C2=A0 va_start(ap, msg); // use variable arg list
<br>=C2=A0 =C2=A0 QT_TERMINATE_ON_EXCEPTION(<wbr>message =3D qt_message(QtF=
atalMsg, context, msg,=20
<br>ap));
<br>=C2=A0 =C2=A0 va_end(ap);
<br>
<br>=C2=A0 =C2=A0 qt_message_fatal(QtFatalMsg, context, message);
<br>}
<br>
<br>That qt_message function can throw std::bad_alloc. But since we're =
about to=20
<br>terminate the program anyway, we don't want a fail-to-terminate con=
dition and=20
<br>thus continue execution. We want to terminate.
<br>
<br>That macro, a little surprisingly, is defined as:
<br>
<br># =C2=A0 =C2=A0define QT_TERMINATE_ON_EXCEPTION(<wbr>expr) do { expr; }=
while (false)
<br>
<br>Because the function is already noexcept, there's no need for a try=
/catch=20
<br>block.
<br></blockquote><div><br></div><div>it may make sense to consider producin=
g "no memory" message that is guaranteed to succeed. But I don=
9;t know much about Qt, maybe it doesn't make sense here.</div><div><br=
></div><div>It is off-topic in this thread, but I don't like noexcept (=
not because it is present by default on dtors! :) ) -- it is a promise and =
enforcement-of-promise combined into one keyword. Makes some code less effi=
cient that it would've been if it was only promise -- and if you omit i=
t, it loses efficiency too (because callers benefit from it's presence)=
..</div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" st=
yle=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-lef=
t: 1ex;">--=20
<br>Thiago Macieira - thiago (AT) <a href=3D"http://macieira.info" target=
=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.goo=
gle.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x3dD\x26sntz\x3d1\x26usg\=
x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.hr=
ef=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x=
3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return t=
rue;">macieira.info</a> - thiago (AT) <a href=3D"http://kde.org" target=3D"=
_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.google.=
com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNH=
GRJdo5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'=
http://www.google.com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1=
\x26usg\x3dAFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;">kde.org</a=
>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>
<br></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/05d8aa3e-9a60-4319-873e-b36976275775%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/05d8aa3e-9a60-4319-873e-b36976275775=
%40isocpp.org</a>.<br />
------=_Part_995_1152126929.1504166089519--
------=_Part_994_645065432.1504166089519--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Thu, 31 Aug 2017 07:54:43 -0700
Raw View
On Thursday, 31 August 2017 00:54:49 PDT crusader.mike@gmail.com wrote:
> it may make sense to consider producing "no memory" message that is
> guaranteed to succeed. But I don't know much about Qt, maybe it doesn't
> make sense here.
It makes sense, but that's easier said than done. That function is way too
complex to operate on a static buffer.
> It is off-topic in this thread, but I don't like noexcept (not because it
> is present by default on dtors! :) ) -- it is a promise and
> enforcement-of-promise combined into one keyword. Makes some code less
> efficient that it would've been if it was only promise -- and if you omit
> it, it loses efficiency too (because callers benefit from it's presence).
Explain. Where do you lose efficiency if it was only a promise?
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/1660941.qzo6rhnlB2%40tjmaciei-mobl1.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 31 Aug 2017 09:00:35 -0700 (PDT)
Raw View
------=_Part_1495_1104364226.1504195235676
Content-Type: multipart/alternative;
boundary="----=_Part_1496_2044020720.1504195235677"
------=_Part_1496_2044020720.1504195235677
Content-Type: text/plain; charset="UTF-8"
On Thursday, August 31, 2017 at 3:25:06 AM UTC-4, crusad...@gmail.com wrote:
>
> On Monday, August 28, 2017 at 6:16:42 PM UTC-5, Nicol Bolas wrote:
>>
>> On Monday, August 28, 2017 at 3:09:43 PM UTC-4, crusad...@gmail.com
>> wrote:
>>>
>>> On Monday, August 28, 2017 at 12:56:32 PM UTC-5, Nicol Bolas wrote:
>>>>
>>>> On Monday, August 28, 2017 at 12:06:30 PM UTC-4, crusad...@gmail.com
>>>> wrote:
>>>>>
>>>>> Before reading stuff below I suggest to set aside any dogmatic
>>>>> blinders you may have, namely:
>>>>> - realize that there is nothing particular special about destructors
>>>>> -- they are just functions that runtime calls automatically in specific
>>>>> circumstances and yes, they may want to report an error
>>>>>
>>>>
>>>> Untrue. Destructors provoke the ending of the lifetime of an object.
>>>> That makes them special. Much like how constructors signal the beginning of
>>>> the lifetime of an object.
>>>>
>>>
>>> It is a function. And it can throw exception as it is right now. It is
>>> noexcept right by default, but nothing prevents me to declare it
>>> noexcept(false) and it will work. The only case when it won't is when it
>>> throws during unwinding. I believe it can be changed and it should be
>>> changed to accomodate for a practical situation. And it won't affect
>>> existing code at all.
>>>
>>
>> If exception collisions affect the type of exception being caught, then
>> it affects any existing code where that user does not control what objects
>> get destroyed between themselves and the source of the exception they're
>> catching.
>>
>
> As long as user is aware of potential magic -- it is fine. It is still
> better in sense that it will become an options, while right now it is
> std::terminate(). And with noexcept(true) dtors (by default) everyone is
> pretty safe.
>
>
>
>> - you can't really tell what makes sense or not -- only end user makes
>>>>> this decision
>>>>>
>>>>
>>>> The C++ object model is all about defining what "makes sense". That's
>>>> why you can't just pretend that an object exists in some memory.
>>>>
>>>
>>> I never said that.
>>>
>>
>> Nor did I accuse you of saying it. My point is that your perspective is
>> that of someone who's doesn't care about what a piece of functionality
>> *means*; what matters to you is what it can do. It's a perspective of
>> trying to view C++, not as a collection of meaningful parts and
>> functionality, but an arbitrary assemblage of things onto which you can
>> graft your own meaning.
>>
>
> 'Object model' you mentioned is a result of such grafting, isn't it?
>
No, it isn't. The C++ object model is an attempt to model an abstract
machine. It is not "arbitrary;" it is carefully designed to fulfill a
specific purpose.
And it may make sense to me.
>>>
>>
>> And your code needs to work with the rest of the world.
>>
>
> Ok, you just raised first actual problem (from my pov):
>
> class X; // it's dtor can throw
>
> struct S
> {
> X x;
>
> ~S() noexcept(true) {} // no way to intercept exception from x's
> dtor
> };
>
> this sucks... I wonder if this can be 'fixed' with same thing we can do in
> ctors:
>
> ~S() noexcept(true)
> try
> {
> }
> catch(...) { ... }
>
FYI: function-level try/catch-blocks cannot swallow exceptions. If you
don't explicitly exit the block via throwing, the system automatically
rethrows what it caught.
They are for doing major cleanup and/or exception translation, not for
eating them.
Keep in mind that no matter what each of functions above need to be called
>>>>> no matter what.
>>>>>
>>>>
>>>>>
>>>> Let's say that each one attempts to switch off a piece of very
>>>>> expensive machinery. You can't make it no-fail for physical reasons. And if
>>>>> something goes wrong you need to report error(s) upstairs for analysis and
>>>>> associated actions.
>>>>>
>>>>> with this proposal you can put these do_smthN() calls into destructors
>>>>> and automatically get "always gets invoked" guarantee along with some
>>>>> (hopefully sensible) mechanism that is going to combine these errors for
>>>>> propagation up-stack. If user doesn't like default mechanism -- he'll use
>>>>> aforementioned knobs to tune it to his liking.
>>>>>
>>>>> Right now you have to make these dtors silent and accumulate these
>>>>> errors elsewhere -- basically turning EH into some weird mix of both styles.
>>>>>
>>>>
>>>> ... OK, I'll play along. You want people to write this:
>>>>
>>>> try
>>>> {
>>>> something_doer_3 t3{};
>>>> something_doer_2 t2{};
>>>> something_doer_1 t1{};
>>>> }
>>>> catch(something)
>>>> {
>>>> //Combine the errors
>>>> }
>>>>
>>>> Where the destructors of those three types are what does the work.
>>>>
>>>
>>> rewriting example from above using EH:
>>> try
>>> {
>>> auto_start_stop device1{}; // starts device in ctor, stops in
>>> dtor -- both ops can fail with exception
>>> auto_start_stop device2{};
>>> auto_start_stop device3{};
>>>
>>> // do work using these devices (which can throw too)
>>> }
>>> catch(error_base const&)
>>> {
>>> // entire operation failed, if we want, we could check if this is a
>>> combined exception and pull it apart)
>>> }
>>>
>>
>> Now, show me the code for this "check if this is a combined exception and
>> pull it apart". Then compare it to the error code equivalent. Show me how
>> this is in any way better.
>>
>
> Ok, you agree that at least content of try block looks cleaner?
>
> Handling can be done like this:
>
> catch(...)
> {
> process_exception(std::current_exception(), true);
> if (std::lead_exception(x)) /// basically a dynamic_cast
> for(auto p: std::trailing_exceptions(x))
> process_exception(p, false);
> }
>
> void process_exception(std::exception_ptr p, bool leading)
> {
> try
> {
> rethrow(p);
> }
> catch(exc1 const& x) { ... }
> catch(exc2 const& x) { ... }
> }
>
> Not exceptionally clean code, but doable.
>
>
>
>> Indeed, this is a perfect example of exactly why your idea doesn't work.
>>
>> OK, let's say that something in "do work using these devices (which can
>> throw too)" throws. The caller of this function catches it, so the stack
>> starts unwinding. Those destructors start failing, so a second exception is
>> emitted that gets caught right here.
>>
>
> Second problem -- "catching" happens before unwinding. I didn't think of
> that... Hmm, this means no substitutions... all additional exceptions will
> have option to either get discarded or added to a list of trailing
> exceptions (or std::terminate of course)
>
OK, so if we have A->B->C->D->E again, but this time E throws something
that gets caught by B. And now, during unwinding D throws something which C
catches. But since the catch happens before the initial unwinding, what D
throws becomes a "trailing exception". Which means that B has to have the
responsibility to handle exceptions thrown by D.
That makes absolutely no sense. C explicitly caught the exception; that *ought
to mean* that the exception of that type *cannot* escape C's try-block
unless it explicitly wishes it to do so. And indeed, if D had thrown at any
time *other than* when unwinding was happening, that's exactly what would
happen.
So in point of fact, despite the code statically showing a throw from D to
be caught by C... we don't even know if C will catch what D throws. How
does that make sense?
This is why `std::terminate` is the correct call here. The code could go to
C or to B, but neither one is the right answer. Therefore, there is no
right answer, your program has go into weirdo-land and needs to be stopped.
Remember: exceptions are supposed to be "handle it or fail" errors. It
should not be possible to swallow an exception *by accident*.
Is it possible for this catch statement to effectively swallow *all*
>> exceptions, in the event that it throws during unwinding?
>>
>
> yes, why not?
>
Because someone else caught that exception. That exception wasn't meant for
that `catch` statement.
Your idea makes a mockery of how `throw`/`catch` is supposed to work. It
ought to be like a `goto` with a label. But since function scopes are
dynamically defined, you can't know that the label exists or where it is at
compile-time. So `throw`ing can fail if the runtime state of the system is
not in a configuration to make the `throw` succeed.
Even `exception_ptr`s exist primarily to be able to transmit exceptions
from their source `throw` to their destination `catch` across non-scoping
boundaries.
The case you describe is actually perfect for an out-of-band error
>> mechanism (something like `std:errno` or `glGetError`) to report the errors
>> from the destructor of the device class. That allows the caller to be able
>> to ask whether device stoppage succeeded *without* having to have this
>> aggregation of return values. And it works very well with exceptions, since
>> the error can still be reported without interfering in the exception
>> itself. After all, you're talking about what is a different *channel* of
>> error from the original exception.
>>
>> No one error handling mechanism fits all cases. Even `errno` has its
>> place.
>>
>
> Unfortunately then you end up with multiple 'errno' variables (one per
> device or libarary) and no knowledge which ones were set. You'll have to
> conjure some way of notifying yourself via out-of-band mechanisms or simply
> poll all of them.
>
And this is exactly why I wanted you to show the code for how you process
your arbitrary collection of exceptions. Because your "trailing exception"
mechanism has almost exactly the same properties you describe here.
"Trailing exceptions" have multiple different types, some of which are the
errors you're looking for and some of which are not. This is exactly
analogous to the "multiple 'errno' variables". And your trailing exceptions
must *all* be polled in order to find which ones you're looking for. You
have to sift through the entire sequence of trailing exceptions, casting
each one in turn to find the one you're looking for.
The main distinction between them is that out-of-band errors for different
systems explicitly have different "channels". By contrast, trailing
exceptions all use the same "channel". But this is actually an *advantage*.
Just look at your processing code. All that rethrowing nonsense just to
check the type. Even if you turned it into a simpler `exception_cast` or
whatever, it's still a lot of processing just to fish out the errors you're
actually interested in.
The handling for out-of-band reporting would look like this:
catch(actual_exception &e)
{
//Handle actual exception
//Handle device failures.
if(did_devices_fail_to_stop())
{
for(auto &device_err : get_device_failures())
{
//Deal with failure for this device.
}
}
}
This is *far* more readable, understandable, and maintainable than the
"trailing exception" version. Your idea does not lead to "nice, compact
solutions". So even if this idea were logically coherent with the meaning
of exceptions, even if we were to find a way to solve the problems it
creates, I submit that it would lead to the writing of crap code.
--
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/d4e3e21e-818e-473b-acc6-ab2d5a8a263e%40isocpp.org.
------=_Part_1496_2044020720.1504195235677
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, August 31, 2017 at 3:25:06 AM UTC-4, crusad..=
..@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"=
ltr">On Monday, August 28, 2017 at 6:16:42 PM UTC-5, Nicol Bolas wrote:<blo=
ckquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-le=
ft:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">On Monday, August 28, =
2017 at 3:09:43 PM UTC-4, <a>crusad...@gmail.com</a> wrote:<blockquote clas=
s=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc =
solid;padding-left:1ex"><div dir=3D"ltr">On Monday, August 28, 2017 at 12:5=
6:32 PM UTC-5, Nicol Bolas wrote:<blockquote class=3D"gmail_quote" style=3D=
"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><d=
iv dir=3D"ltr">On Monday, August 28, 2017 at 12:06:30 PM UTC-4, <a>crusad..=
..@gmail.com</a> wrote:<blockquote class=3D"gmail_quote" style=3D"margin:0;m=
argin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"l=
tr"><div>Before reading stuff below I suggest to set aside any dogmatic bli=
nders you may have, namely:</div><div>- realize that there is nothing parti=
cular special about destructors -- they are just functions that runtime cal=
ls automatically in specific circumstances and yes, they may want to report=
an error</div></div></blockquote><div><br>Untrue. Destructors provoke the =
ending of the lifetime of an object. That makes them special. Much like how=
constructors signal the beginning of the lifetime of an object.<br></div><=
/div></blockquote><div><br></div><div>It is a function. And it can throw ex=
ception as it is right now. It is noexcept right by default, but nothing pr=
events me to declare it noexcept(false) and it will work. The only case whe=
n it won't is when it throws during unwinding. I believe it can be chan=
ged and it should be changed to accomodate for a practical situation. And i=
t won't affect existing code at all.</div></div></blockquote><div><br>I=
f exception collisions affect the type of exception being caught, then it a=
ffects any existing code where that user does not control what objects get =
destroyed between themselves and the source of the exception they're ca=
tching.<br></div></div></blockquote><div><br></div><div>As long as user is =
aware of potential magic -- it is fine. It is still better in sense that it=
will become an options, while right now it is std::terminate(). And with n=
oexcept(true) dtors (by default) everyone is pretty safe.</div><div><br></d=
iv><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0;mar=
gin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr=
"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><blockquote clas=
s=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:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left=
:1ex"><div dir=3D"ltr"><div>- you can't really tell what makes sense or=
not -- only end user makes this decision</div></div></blockquote><div><br>=
The C++ object model is all about defining what "makes sense". Th=
at's why you can't just pretend that an object exists in some memor=
y.<br></div></div></blockquote><div><br></div><div>I never said that.</div>=
</div></blockquote><div><br>Nor did I accuse you of saying it. My point is =
that your perspective is that of someone who's doesn't care about w=
hat a piece of functionality=C2=A0<i>means</i>; what matters to you is what=
it can do. It's a perspective of trying to view C++, not as a collecti=
on of meaningful parts and functionality, but an arbitrary assemblage of th=
ings onto which you can graft your own meaning.<br></div></div></blockquote=
><div><br></div><div>'Object model' you mentioned is a result of su=
ch grafting, isn't it?</div></div></blockquote><div><br>No, it isn'=
t. The C++ object model is an attempt to model an abstract machine. It is n=
ot "arbitrary;" it is carefully designed to fulfill a specific pu=
rpose.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div></div><blockquote class=3D"gmail_quote" style=3D"margin:0;mar=
gin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr=
"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bor=
der-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>And it may =
make sense to me.</div></div></blockquote><div><br>And your code needs to w=
ork with the rest of the world.<br></div></div></blockquote><div><br></div>=
<div>Ok, you just raised first actual problem (from my pov):</div><div><br>=
</div><div>class X; =C2=A0 // it's dtor can throw</div><div><br></div><=
div>struct S</div><div>{</div><div>=C2=A0 =C2=A0 X x;</div><div><br></div><=
div>=C2=A0 =C2=A0 ~S() noexcept(true) {} =C2=A0 =C2=A0 =C2=A0// no way to i=
ntercept exception from x's dtor</div><div>};</div><div><br></div><div>=
this sucks... I wonder if this can be 'fixed' with same thing we ca=
n do in ctors:</div><div><br></div><div><div>=C2=A0 =C2=A0 ~S() noexcept(tr=
ue)=C2=A0</div><div>=C2=A0 =C2=A0 try</div><div>=C2=A0 =C2=A0 {</div><div>=
=C2=A0 =C2=A0 }</div></div><div>=C2=A0 =C2=A0 catch(...) { ... }</div></div=
></blockquote><div><br>FYI: function-level try/catch-blocks cannot swallow =
exceptions. If you don't explicitly exit the block via throwing, the sy=
stem automatically rethrows what it caught.<br><br>They are for doing major=
cleanup and/or exception translation, not for eating them.<br><br></div><b=
lockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;borde=
r-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><div=
></div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8e=
x;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><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></div><blockquote class=
=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><div></div><blockquote class=3D"gma=
il_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;pa=
dding-left:1ex"><div dir=3D"ltr"><div>Keep in mind that no matter what each=
of functions above need to be called no matter what.</div></div></blockquo=
te><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;bord=
er-left:1px solid rgb(204,204,204);padding-left:1ex"><div>=C2=A0</div></blo=
ckquote><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>Let&#=
39;s say that each one attempts to switch off a piece of very expensive mac=
hinery. You can't make it no-fail for physical reasons. And if somethin=
g goes wrong you need to report error(s) upstairs for analysis and associat=
ed actions.</div><div><br></div><div>with this proposal you can put these d=
o_smthN() calls into destructors and automatically get "always gets in=
voked" guarantee along with some (hopefully sensible) mechanism that i=
s going to combine these errors for propagation up-stack. If user doesn'=
;t like default mechanism -- he'll use aforementioned knobs to tune it =
to his liking.</div><div><br></div><div>Right now you have to make these dt=
ors silent and accumulate these errors elsewhere -- basically turning EH in=
to some weird mix of both styles.</div></div></blockquote><div><br>... OK, =
I'll play along. You want people to write this:<br><br><div style=3D"ba=
ckground-color:rgb(250,250,250);border-color:rgb(187,187,187);border-style:=
solid;border-width:1px"><code><div><span style=3D"color:#008">try</span><sp=
an style=3D"color:#000"><br></span><span style=3D"color:#660">{</span><span=
style=3D"color:#000"><br>=C2=A0 something_doer_3 t3</span><span style=3D"c=
olor:#660">{};</span><span style=3D"color:#000"><br>=C2=A0 something_doer_2=
t2</span><span style=3D"color:#660">{};</span><span style=3D"color:#000"><=
br>=C2=A0 something_doer_1 t1</span><span style=3D"color:#660">{};</span><s=
pan style=3D"color:#000"><br></span><span style=3D"color:#660">}</span><spa=
n style=3D"color:#000"><br></span><span style=3D"color:#008">catch</span><s=
pan style=3D"color:#660">(</span><span style=3D"color:#000">something</span=
><span style=3D"color:#660">)</span><span style=3D"color:#000"><br></span><=
span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 //C=
ombine the errors<br></span><span style=3D"color:#660">}</span><span style=
=3D"color:#000"><br></span></div></code></div><br>Where the destructors of =
those three types are what does the work.<br></div></div></blockquote><div>=
<br></div><div>rewriting example from above using EH:</div><div>try</div><d=
iv>{</div><div>=C2=A0 =C2=A0 auto_start_stop device1{}; =C2=A0 =C2=A0// sta=
rts device in ctor, stops in dtor -- both ops can fail with exception</div>=
<div>=C2=A0 =C2=A0 auto_start_stop device2{};</div><div>=C2=A0 =C2=A0 auto_=
start_stop device3{};</div><div><br></div><div>=C2=A0 =C2=A0 // do work usi=
ng these devices (which can throw too)</div><div>}</div><div>catch(error_ba=
se const&)</div><div>{</div><div>=C2=A0 =C2=A0 // entire operation fail=
ed, if we want, we could check if this is a combined exception and pull it =
apart)</div><div>}</div></div></blockquote><div><br>Now, show me the code f=
or this "check if this is a combined exception and pull it apart"=
.. Then compare it to the error code equivalent. Show me how this is in any =
way better.<br></div></div></blockquote><div><br></div><div>Ok, you agree t=
hat at least content of try block looks cleaner?</div><div><br></div><div>H=
andling can be done like this:</div><div><br></div><div>catch(...)</div><di=
v>{</div><div>=C2=A0 =C2=A0 process_exception(std::<wbr>current_exception()=
, true);</div><div>=C2=A0 =C2=A0 if (std::lead_exception(x)) =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0/// basically a dynamic_cast</div><div>=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 for(auto p: std::trailing_exceptions(x))</div><=
div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 process_exception(p, false);<=
/div><div>}<br></div><div><br></div><div>void process_exception(std::<wbr>e=
xception_ptr p, bool leading)</div><div>{</div><div>=C2=A0 =C2=A0 try</div>=
<div>=C2=A0 =C2=A0 {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 rethrow(p);</div=
><div>=C2=A0 =C2=A0 }</div><div>=C2=A0 =C2=A0 catch(exc1 const& x) { ..=
.. }</div><div>=C2=A0 =C2=A0 catch(exc2 const& x) { ... }</div><div>}</d=
iv><div><br></div><div>Not exceptionally clean code, but doable.</div><div>=
<br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margi=
n:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><div>Indeed, this is a perfect example of exactly why your idea do=
esn't work.<br><br>OK, let's say that something in "do work us=
ing these devices (which can throw too)" throws. The caller of this fu=
nction catches it, so the stack starts unwinding. Those destructors start f=
ailing, so a second exception is emitted that gets caught right here.<br></=
div></div></blockquote><div><br></div><div>Second problem -- "catching=
" happens before unwinding. I didn't think of that... Hmm, this me=
ans no substitutions... all additional exceptions will have option to eithe=
r get discarded or added to a list of trailing exceptions (or std::terminat=
e of course)</div></div></blockquote><div><br>OK, so if we have A->B->=
;C->D->E again, but this time E throws something that gets caught by =
B. And now, during unwinding D throws something which C catches. But since =
the catch happens before the initial unwinding, what D throws becomes a &qu=
ot;trailing exception". Which means that B has to have the responsibil=
ity to handle exceptions thrown by D.<br><br>That makes absolutely no sense=
.. C explicitly caught the exception; that <i>ought to mean</i> that the exc=
eption of that type <i>cannot</i> escape C's try-block unless it explic=
itly wishes it to do so. And indeed, if D had thrown at any time <i>other t=
han</i> when unwinding was happening, that's exactly what would happen.=
<br><br>So in point of fact, despite the code statically showing a throw fr=
om D to be caught by C... we don't even know if C will catch what D thr=
ows. How does that make sense?<br><br>This is why `std::terminate` is the c=
orrect call here. The code could go to C or to B, but neither one is the ri=
ght answer. Therefore, there is no right answer, your program has go into w=
eirdo-land and needs to be stopped.<br><br>Remember: exceptions are suppose=
d to be "handle it or fail" errors. It should not be possible to =
swallow an exception <i>by accident</i>.<br><br></div><blockquote class=3D"=
gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc so=
lid;padding-left: 1ex;"><div dir=3D"ltr"><div></div><div></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"><div>Is it possible for this c=
atch statement to effectively swallow <i>all</i> exceptions, in the event t=
hat it throws during unwinding?<br></div></div></blockquote><div><br></div>=
<div>yes, why not?</div></div></blockquote><div><br>Because someone else ca=
ught that exception. That exception wasn't meant for that `catch` state=
ment.<br><br>Your idea makes a mockery of how `throw`/`catch` is supposed t=
o work. It ought to be like a `goto` with a label. But since function scope=
s are dynamically defined, you can't know that the label exists or wher=
e it is at compile-time. So `throw`ing can fail if the runtime state of the=
system is not in a configuration to make the `throw` succeed.<br><br>Even =
`exception_ptr`s exist primarily to be able to transmit exceptions from the=
ir source `throw` to their destination `catch` across non-scoping boundarie=
s.<br><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"lt=
r"><div></div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-le=
ft:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div=
>The case you describe is actually perfect for an out-of-band error mechani=
sm (something like `std:errno` or `glGetError`) to report the errors from t=
he destructor of the device class. That allows the caller to be able to ask=
whether device stoppage succeeded <i>without</i> having to have this aggre=
gation of return values. And it works very well with exceptions, since the =
error can still be reported without interfering in the exception itself. Af=
ter all, you're talking about what is a different <i>channel</i> of err=
or from the original exception.<br><br>No one error handling mechanism fits=
all cases. Even `errno` has its place.<br></div></div></blockquote><div><b=
r></div><div>Unfortunately then you end up with multiple 'errno' va=
riables (one per device or libarary) and no knowledge which ones were set. =
You'll have to conjure some way of notifying yourself via out-of-band m=
echanisms or simply poll all of them.</div></div></blockquote><div><br>And =
this is exactly why I wanted you to show the code for how you process your =
arbitrary collection of exceptions. Because your "trailing exception&q=
uot; mechanism has almost exactly the same properties you describe here.<br=
><br>"Trailing exceptions" have multiple different types, some of=
which are the errors you're looking for and some of which are not. Thi=
s is exactly analogous to the "multiple 'errno' variables"=
;. And your trailing exceptions must <i>all</i> be polled in order to find =
which ones you're looking for. You have to sift through the entire sequ=
ence of trailing exceptions, casting each one in turn to find the one you&#=
39;re looking for.<br><br>The main distinction between them is that out-of-=
band errors for different systems explicitly have different "channels&=
quot;. By contrast, trailing exceptions all use the same "channel"=
;. But this is actually an <i>advantage</i>. Just look at your processing c=
ode. All that rethrowing nonsense just to check the type. Even if you turne=
d it into a simpler `exception_cast` or whatever, it's still a lot of p=
rocessing just to fish out the errors you're actually interested in.<br=
><br>The handling for out-of-band reporting would look like this:<br><br><d=
iv style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 18=
7, 187); border-style: solid; border-width: 1px; overflow-wrap: break-word;=
" class=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"subpretty=
print"><span style=3D"color: #008;" class=3D"styled-by-prettify">catch</spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">actual_exception </span>=
<span style=3D"color: #660;" 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"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><span style=3D"color: #000;" class=3D"=
styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #800;" class=3D=
"styled-by-prettify">//Handle actual exception</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify"><br><br>=C2=A0 </span><span style=3D"co=
lor: #800;" class=3D"styled-by-prettify">//Handle device failures.</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><=
span style=3D"color: #008;" class=3D"styled-by-prettify">if</span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify">did_devices_fail_to_stop</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 </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">for</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008;=
" class=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" clas=
s=3D"styled-by-prettify"> </span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify">&</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify">device_err </span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">:</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y"> get_device_failures</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: #660;" class=3D"styled=
-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #800;" class=3D"=
styled-by-prettify">//Deal with failure for this device.</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"><br>=C2=A0 </span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">}</span></div></code></div><br>This is <i>=
far</i> more readable, understandable, and maintainable than the "trai=
ling exception" version. Your idea does not lead to "nice, compac=
t solutions". So even if this idea were logically coherent with the me=
aning of exceptions, even if we were to find a way to solve the problems it=
creates, I submit that it would lead to the writing of crap code.<br></div=
></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/d4e3e21e-818e-473b-acc6-ab2d5a8a263e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/d4e3e21e-818e-473b-acc6-ab2d5a8a263e=
%40isocpp.org</a>.<br />
------=_Part_1496_2044020720.1504195235677--
------=_Part_1495_1104364226.1504195235676--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 31 Aug 2017 11:18:24 -0700 (PDT)
Raw View
------=_Part_1587_1795121468.1504203504982
Content-Type: multipart/alternative;
boundary="----=_Part_1588_1291478931.1504203504983"
------=_Part_1588_1291478931.1504203504983
Content-Type: text/plain; charset="UTF-8"
On Thursday, August 31, 2017 at 12:00:35 PM UTC-4, Nicol Bolas wrote:
>
> On Thursday, August 31, 2017 at 3:25:06 AM UTC-4, crusad...@gmail.com
> wrote:
>>
>> Ok, you just raised first actual problem (from my pov):
>>
>> class X; // it's dtor can throw
>>
>> struct S
>> {
>> X x;
>>
>> ~S() noexcept(true) {} // no way to intercept exception from x's
>> dtor
>> };
>>
>> this sucks... I wonder if this can be 'fixed' with same thing we can do
>> in ctors:
>>
>> ~S() noexcept(true)
>> try
>> {
>> }
>> catch(...) { ... }
>>
>
> FYI: function-level try/catch-blocks cannot swallow exceptions. If you
> don't explicitly exit the block via throwing, the system automatically
> rethrows what it caught.
>
> They are for doing major cleanup and/or exception translation, not for
> eating them.
>
Two things:
1) destructor-level try-blocks already exist.
2) I was slightly wrong about swallowing exceptions in function-level
blocks. Such blocks will automatically `throw;` at the end if they are
constructor *or destructor* blocks. For regular function blocks, they
`return;` at the end, just like a regular function.
--
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/1c7fe8e8-8653-4830-b55a-c6fdbcaeaf44%40isocpp.org.
------=_Part_1588_1291478931.1504203504983
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, August 31, 2017 at 12:00:35 PM UTC-4, Nicol B=
olas 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">On=
Thursday, August 31, 2017 at 3:25:06 AM UTC-4, <a>crusad...@gmail.com</a> =
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></div><=
div>Ok, you just raised first actual problem (from my pov):</div><div><br><=
/div><div>class X; =C2=A0 // it's dtor can throw</div><div><br></div><d=
iv>struct S</div><div>{</div><div>=C2=A0 =C2=A0 X x;</div><div><br></div><d=
iv>=C2=A0 =C2=A0 ~S() noexcept(true) {} =C2=A0 =C2=A0 =C2=A0// no way to in=
tercept exception from x's dtor</div><div>};</div><div><br></div><div>t=
his sucks... I wonder if this can be 'fixed' with same thing we can=
do in ctors:</div><div><br></div><div><div>=C2=A0 =C2=A0 ~S() noexcept(tru=
e)=C2=A0</div><div>=C2=A0 =C2=A0 try</div><div>=C2=A0 =C2=A0 {</div><div>=
=C2=A0 =C2=A0 }</div></div><div>=C2=A0 =C2=A0 catch(...) { ... }</div></div=
></blockquote><div><br>FYI: function-level try/catch-blocks cannot swallow =
exceptions. If you don't explicitly exit the block via throwing, the sy=
stem automatically rethrows what it caught.<br><br>They are for doing major=
cleanup and/or exception translation, not for eating them.<br></div></div>=
</blockquote><br>Two things:<br><br>1) destructor-level try-blocks already =
exist.<br><br>2) I was slightly wrong about swallowing exceptions in functi=
on-level blocks. Such blocks will automatically `throw;` at the end if they=
are constructor <i>or destructor</i> blocks. For regular function blocks, =
they `return;` at the end, just like a regular function.<br></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/1c7fe8e8-8653-4830-b55a-c6fdbcaeaf44%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/1c7fe8e8-8653-4830-b55a-c6fdbcaeaf44=
%40isocpp.org</a>.<br />
------=_Part_1588_1291478931.1504203504983--
------=_Part_1587_1795121468.1504203504982--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Thu, 31 Aug 2017 13:18:10 -0700
Raw View
On Thursday, 31 August 2017 11:18:24 PDT Nicol Bolas wrote:
> 2) I was slightly wrong about swallowing exceptions in function-level
> blocks. Such blocks will automatically `throw;` at the end if they are
> constructor *or destructor* blocks. For regular function blocks, they
> `return;` at the end, just like a regular function.
That makes absolute sense for a constructor. If you caught at the constructor
level, that means the object failed to initialise. It makes no sense to
swallow the exception and return normally. It must throw.
For the destructor, it's hard to rationalise in terms of failing. The object
is destroyed anyway at the end of the destructor, so why can't a destructor
catch-and-swallow an exception thrown by a sub-object's destructor?
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/2586993.iUZoMPIaJ2%40tjmaciei-mobl1.
.
Author: crusader.mike@gmail.com
Date: Thu, 31 Aug 2017 14:00:10 -0700 (PDT)
Raw View
------=_Part_1827_2049876953.1504213210360
Content-Type: multipart/alternative;
boundary="----=_Part_1828_623957046.1504213210360"
------=_Part_1828_623957046.1504213210360
Content-Type: text/plain; charset="UTF-8"
On Thursday, August 31, 2017 at 9:55:02 AM UTC-5, Thiago Macieira wrote:
>
> > It is off-topic in this thread, but I don't like noexcept (not because
> it
> > is present by default on dtors! :) ) -- it is a promise and
> > enforcement-of-promise combined into one keyword. Makes some code less
> > efficient that it would've been if it was only promise -- and if you
> omit
> > it, it loses efficiency too (because callers benefit from it's
> presence).
>
> Explain. Where do you lose efficiency if it was only a promise?
>
That is the problem -- 'noexcept' specifier is two things in one package
and there is no way to separate them. It is not only the promise, it is
also an enforcement (which is not free). Here are some details:
https://stackoverflow.com/questions/21463119/does-it-make-sense-to-declare-inline-functions-noexcept/39242143#39242143
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
>
>
--
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/c9f0734b-bd3b-43bc-9884-edfcc75d385a%40isocpp.org.
------=_Part_1828_623957046.1504213210360
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, August 31, 2017 at 9:55:02 AM UTC-5, 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;">> It is off-t=
opic in this thread, but I don't like noexcept (not because it
<br>> is present by default on dtors! :) ) -- it is a promise and
<br>> enforcement-of-promise combined into one keyword. Makes some code =
less
<br>> efficient that it would've been if it was only promise -- and =
if you omit
<br>> it, it loses efficiency too (because callers benefit from it's=
presence).
<br>
<br>Explain. Where do you lose efficiency if it was only a promise?
<br></blockquote><div><br></div><div>That is the problem -- 'noexcept&#=
39; specifier is two things in one package and there is no way to separate =
them. It is not only the promise, it is also an enforcement (which is not f=
ree). Here are some details:</div><div>https://stackoverflow.com/questions/=
21463119/does-it-make-sense-to-declare-inline-functions-noexcept/39242143#3=
9242143<br></div><div><br></div><div><br></div><div>=C2=A0</div><blockquote=
class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1=
px #ccc solid;padding-left: 1ex;">--=20
<br>Thiago Macieira - thiago (AT) <a href=3D"http://macieira.info" target=
=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.goo=
gle.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x3dD\x26sntz\x3d1\x26usg\=
x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.hr=
ef=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x=
3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return t=
rue;">macieira.info</a> - thiago (AT) <a href=3D"http://kde.org" target=3D"=
_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.google.=
com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNH=
GRJdo5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'=
http://www.google.com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1=
\x26usg\x3dAFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;">kde.org</a=
>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>
<br></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/c9f0734b-bd3b-43bc-9884-edfcc75d385a%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/c9f0734b-bd3b-43bc-9884-edfcc75d385a=
%40isocpp.org</a>.<br />
------=_Part_1828_623957046.1504213210360--
------=_Part_1827_2049876953.1504213210360--
.
Author: crusader.mike@gmail.com
Date: Thu, 31 Aug 2017 14:19:04 -0700 (PDT)
Raw View
------=_Part_1851_316176998.1504214344670
Content-Type: multipart/alternative;
boundary="----=_Part_1852_1345414792.1504214344671"
------=_Part_1852_1345414792.1504214344671
Content-Type: text/plain; charset="UTF-8"
On Thursday, August 31, 2017 at 11:00:35 AM UTC-5, Nicol Bolas wrote:
Indeed, this is a perfect example of exactly why your idea doesn't work.
>
>
>>> OK, let's say that something in "do work using these devices (which can
>>> throw too)" throws. The caller of this function catches it, so the stack
>>> starts unwinding. Those destructors start failing, so a second exception is
>>> emitted that gets caught right here.
>>>
>>
>> Second problem -- "catching" happens before unwinding. I didn't think of
>> that... Hmm, this means no substitutions... all additional exceptions will
>> have option to either get discarded or added to a list of trailing
>> exceptions (or std::terminate of course)
>>
>
> OK, so if we have A->B->C->D->E again, but this time E throws something
> that gets caught by B. And now, during unwinding D throws something which C
> catches. But since the catch happens before the initial unwinding, what D
> throws becomes a "trailing exception". Which means that B has to have the
> responsibility to handle exceptions thrown by D.
>
> That makes absolutely no sense. C explicitly caught the exception; that *ought
> to mean* that the exception of that type *cannot* escape C's try-block
> unless it explicitly wishes it to do so. And indeed, if D had thrown at any
> time *other than* when unwinding was happening, that's exactly what would
> happen.
>
> So in point of fact, despite the code statically showing a throw from D to
> be caught by C... we don't even know if C will catch what D throws. How
> does that make sense?
>
> This is why `std::terminate` is the correct call here. The code could go
> to C or to B, but neither one is the right answer. Therefore, there is no
> right answer, your program has go into weirdo-land and needs to be stopped.
>
> Remember: exceptions are supposed to be "handle it or fail" errors. It
> should not be possible to swallow an exception *by accident*.
>
> Is it possible for this catch statement to effectively swallow *all*
>>> exceptions, in the event that it throws during unwinding?
>>>
>>
>> yes, why not?
>>
>
> Because someone else caught that exception. That exception wasn't meant
> for that `catch` statement.
>
> Your idea makes a mockery of how `throw`/`catch` is supposed to work. It
> ought to be like a `goto` with a label. But since function scopes are
> dynamically defined, you can't know that the label exists or where it is at
> compile-time. So `throw`ing can fail if the runtime state of the system is
> not in a configuration to make the `throw` succeed.
>
> Even `exception_ptr`s exist primarily to be able to transmit exceptions
> from their source `throw` to their destination `catch` across non-scoping
> boundaries.
>
Ok, let's compare two cases:
- traditional implementation where failure (to switch off a device) in dtor
is swallowed (and reported via out-of-band mechanism)
- where failure in dtor results in exception attaching itself to 'current'
exception
I don't see fundamental difference between these two cases. In both cases
you can catch only first exception, in both cases you'll end up doing
additional work to access information about these additional failures. The
second approach leads to simpler code:
- you don't need to code out-of-band reporting mechanism
- you don't need to swallow exceptions in dtors
> The case you describe is actually perfect for an out-of-band error
>>> mechanism (something like `std:errno` or `glGetError`) to report the errors
>>> from the destructor of the device class. That allows the caller to be able
>>> to ask whether device stoppage succeeded *without* having to have this
>>> aggregation of return values. And it works very well with exceptions, since
>>> the error can still be reported without interfering in the exception
>>> itself. After all, you're talking about what is a different *channel*
>>> of error from the original exception.
>>>
>>> No one error handling mechanism fits all cases. Even `errno` has its
>>> place.
>>>
>>
>> Unfortunately then you end up with multiple 'errno' variables (one per
>> device or libarary) and no knowledge which ones were set. You'll have to
>> conjure some way of notifying yourself via out-of-band mechanisms or simply
>> poll all of them.
>>
>
> And this is exactly why I wanted you to show the code for how you process
> your arbitrary collection of exceptions. Because your "trailing exception"
> mechanism has almost exactly the same properties you describe here.
>
> "Trailing exceptions" have multiple different types, some of which are the
> errors you're looking for and some of which are not. This is exactly
> analogous to the "multiple 'errno' variables". And your trailing exceptions
> must *all* be polled in order to find which ones you're looking for. You
> have to sift through the entire sequence of trailing exceptions, casting
> each one in turn to find the one you're looking for.
>
With one significant difference -- I don't need to poll for every possible
error here. I'll end up iterating over errors that actually happened.
Imagine a case where you drive multiple devices and each one has it's own
library (with some sort of 'errno' mechanism). In case of failure:
- I need to know exactly which device could've been used by a function that
failed
- poll *all* of them to figure out their current state
or
- device an out-of-bound reporting mechanism that will be used in related
places (where exceptions were swallowed) and accumulate related info
somewhere
> The main distinction between them is that out-of-band errors for
> different systems explicitly have different "channels". By contrast,
> trailing exceptions all use the same "channel". But this is actually an
> *advantage*. Just look at your processing code. All that rethrowing
> nonsense just to check the type. Even if you turned it into a simpler
> `exception_cast` or whatever, it's still a lot of processing just to fish
> out the errors you're actually interested in.
>
Yes, processing logic (with rethrowing) is not ideal -- it is simply
inherited problem from std::current_exception and the way
std::exception_ptr machinery is defined. It is not an inherent failure of
'throwing from dtor' idea.
> The handling for out-of-band reporting would look like this:
>
> catch(actual_exception &e)
> {
> //Handle actual exception
>
> //Handle device failures.
> if(did_devices_fail_to_stop())
> {
> for(auto &device_err : get_device_failures())
> {
> //Deal with failure for this device.
> }
> }
> }
>
> This is *far* more readable, understandable, and maintainable than the
> "trailing exception" version. Your idea does not lead to "nice, compact
> solutions".
>
It does in cases when error handling happens in relatively few places -- no
need in out-of-band status reporting (it gets generated by language for
you).
> So even if this idea were logically coherent with the meaning of
> exceptions, even if we were to find a way to solve the problems it creates,
> I submit that it would lead to the writing of crap code.
>
Users will always find a way how to write crap code :-)
--
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/f1bd992e-fd3b-4d2e-98ef-1027eafabea8%40isocpp.org.
------=_Part_1852_1345414792.1504214344671
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Thursday, August 31, 2017 at 11:00:35 AM UTC-5,=
Nicol Bolas wrote:<div>Indeed, this is a perfect example of exactly why yo=
ur idea doesn't work.<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:0;margin-left=
:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><block=
quote 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><br>OK, let's s=
ay that something in "do work using these devices (which can throw too=
)" throws. The caller of this function catches it, so the stack starts=
unwinding. Those destructors start failing, so a second exception is emitt=
ed that gets caught right here.<br></div></div></blockquote><div><br></div>=
<div>Second problem -- "catching" happens before unwinding. I did=
n't think of that... Hmm, this means no substitutions... all additional=
exceptions will have option to either get discarded or added to a list of =
trailing exceptions (or std::terminate of course)</div></div></blockquote><=
div><br>OK, so if we have A->B->C->D->E again, but this time E =
throws something that gets caught by B. And now, during unwinding D throws =
something which C catches. But since the catch happens before the initial u=
nwinding, what D throws becomes a "trailing exception". Which mea=
ns that B has to have the responsibility to handle exceptions thrown by D.<=
br><br>That makes absolutely no sense. C explicitly caught the exception; t=
hat <i>ought to mean</i> that the exception of that type <i>cannot</i> esca=
pe C's try-block unless it explicitly wishes it to do so. And indeed, i=
f D had thrown at any time <i>other than</i> when unwinding was happening, =
that's exactly what would happen.<br><br>So in point of fact, despite t=
he code statically showing a throw from D to be caught by C... we don't=
even know if C will catch what D throws. How does that make sense?<br><br>=
This is why `std::terminate` is the correct call here. The code could go to=
C or to B, but neither one is the right answer. Therefore, there is no rig=
ht answer, your program has go into weirdo-land and needs to be stopped.<br=
><br></div></div></blockquote><blockquote class=3D"gmail_quote" style=3D"ma=
rgin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">=
<div dir=3D"ltr"><div>Remember: exceptions are supposed to be "handle =
it or fail" errors. It should not be possible to swallow an exception =
<i>by accident</i>.<br><br></div><blockquote class=3D"gmail_quote" style=3D=
"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><d=
iv dir=3D"ltr"><div></div><div></div><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex=
"><div dir=3D"ltr"><div>Is it possible for this catch statement to effectiv=
ely swallow <i>all</i> exceptions, in the event that it throws during unwin=
ding?<br></div></div></blockquote><div><br></div><div>yes, why not?</div></=
div></blockquote><div><br>Because someone else caught that exception. That =
exception wasn't meant for that `catch` statement.<br><br>Your idea mak=
es a mockery of how `throw`/`catch` is supposed to work. It ought to be lik=
e a `goto` with a label. But since function scopes are dynamically defined,=
you can't know that the label exists or where it is at compile-time. S=
o `throw`ing can fail if the runtime state of the system is not in a config=
uration to make the `throw` succeed.<br><br>Even `exception_ptr`s exist pri=
marily to be able to transmit exceptions from their source `throw` to their=
destination `catch` across non-scoping boundaries.<br></div></div></blockq=
uote><div><br></div><div>Ok, let's compare two cases:</div><div>- tradi=
tional implementation where failure (to switch off a device) in dtor is swa=
llowed (and reported via out-of-band mechanism)</div><div>- where failure i=
n dtor results in exception attaching itself to 'current' exception=
</div><div><br></div><div>I don't see fundamental difference between th=
ese two cases. In both cases you can catch only first exception, in both ca=
ses you'll end up doing additional work to access information about the=
se additional failures. The second approach leads to simpler code:</div><di=
v>- you don't need to code out-of-band reporting mechanism</div><div>- =
you don't need to swallow exceptions in dtors</div><div><br></div><div>=
=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><=
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:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><div dir=3D"ltr"><div>The case you describe is actua=
lly perfect for an out-of-band error mechanism (something like `std:errno` =
or `glGetError`) to report the errors from the destructor of the device cla=
ss. That allows the caller to be able to ask whether device stoppage succee=
ded <i>without</i> having to have this aggregation of return values. And it=
works very well with exceptions, since the error can still be reported wit=
hout interfering in the exception itself. After all, you're talking abo=
ut what is a different <i>channel</i> of error from the original exception.=
<br><br>No one error handling mechanism fits all cases. Even `errno` has it=
s place.<br></div></div></blockquote><div><br></div><div>Unfortunately then=
you end up with multiple 'errno' variables (one per device or liba=
rary) and no knowledge which ones were set. You'll have to conjure some=
way of notifying yourself via out-of-band mechanisms or simply poll all of=
them.</div></div></blockquote><div><br>And this is exactly why I wanted yo=
u to show the code for how you process your arbitrary collection of excepti=
ons. Because your "trailing exception" mechanism has almost exact=
ly the same properties you describe here.<br><br>"Trailing exceptions&=
quot; have multiple different types, some of which are the errors you'r=
e looking for and some of which are not. This is exactly analogous to the &=
quot;multiple 'errno' variables". And your trailing exceptions=
must <i>all</i> be polled in order to find which ones you're looking f=
or. You have to sift through the entire sequence of trailing exceptions, ca=
sting each one in turn to find the one you're looking for.</div></div><=
/blockquote><div><br></div><div>With one significant difference -- I don=
9;t need to poll for every possible error here. I'll end up iterating o=
ver errors that actually happened. Imagine a case where you drive multiple =
devices and each one has it's own library (with some sort of 'errno=
' mechanism). In case of failure:</div><div>- I need to know exactly wh=
ich device could've been used by a function that failed</div><div>- pol=
l *all* of them to figure out their current state</div><div><br></div><div>=
or</div><div><br></div><div>- device an out-of-bound reporting mechanism th=
at will be used in related places (where exceptions were swallowed) and acc=
umulate related info somewhere</div><div><br></div><div>=C2=A0</div><blockq=
uote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-lef=
t: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div>=C2=A0The main =
distinction between them is that out-of-band errors for different systems e=
xplicitly have different "channels". By contrast, trailing except=
ions all use the same "channel". But this is actually an <i>advan=
tage</i>. Just look at your processing code. All that rethrowing nonsense j=
ust to check the type. Even if you turned it into a simpler `exception_cast=
` or whatever, it's still a lot of processing just to fish out the erro=
rs you're actually interested in.</div></div></blockquote><div><br></di=
v><div>Yes, processing logic (with rethrowing) is not ideal -- it is simply=
inherited problem from std::current_exception and the way std::exception_p=
tr machinery is defined. It is not an inherent failure of 'throwing fro=
m dtor' idea.</div><div><br></div><div>=C2=A0</div><blockquote class=3D=
"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc s=
olid;padding-left: 1ex;"><div dir=3D"ltr"><div>The handling for out-of-band=
reporting would look like this:<br><br><div style=3D"background-color:rgb(=
250,250,250);border-color:rgb(187,187,187);border-style:solid;border-width:=
1px"><code><div><span style=3D"color:#008">catch</span><span style=3D"color=
:#660">(</span><span style=3D"color:#000">actual_exception </span><span sty=
le=3D"color:#660">&</span><span style=3D"color:#000">e</span><span styl=
e=3D"color:#660">)</span><span style=3D"color:#000"><br></span><span style=
=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 </span><span =
style=3D"color:#800">//Handle actual exception</span><span style=3D"color:#=
000"><br><br>=C2=A0 </span><span style=3D"color:#800">//Handle device failu=
res.</span><span style=3D"color:#000"><br>=C2=A0 </span><span style=3D"colo=
r:#008">if</span><span style=3D"color:#660">(</span><span style=3D"color:#0=
00">did_devices_fail_to_stop</span><span style=3D"color:#660">())</span><sp=
an style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#660">{</spa=
n><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:=
#008">for</span><span style=3D"color:#660">(</span><span style=3D"color:#00=
8">auto</span><span style=3D"color:#000"> </span><span style=3D"color:#660"=
>&</span><span style=3D"color:#000">device_err </span><span style=3D"co=
lor:#660">:</span><span style=3D"color:#000"> get_device_failures</span><sp=
an style=3D"color:#660">())</span><span style=3D"color:#000"><br>=C2=A0 =C2=
=A0 </span><span style=3D"color:#660">{</span><span style=3D"color:#000"><b=
r>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#800">//Deal with failur=
e for this device.</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </spa=
n><span style=3D"color:#660">}</span><span style=3D"color:#000"><br>=C2=A0 =
</span><span style=3D"color:#660">}</span><span style=3D"color:#000"><br></=
span><span style=3D"color:#660">}</span></div></code></div><br>This is <i>f=
ar</i> more readable, understandable, and maintainable than the "trail=
ing exception" version. Your idea does not lead to "nice, compact=
solutions".</div></div></blockquote><div><br></div><div>It does in ca=
ses when error handling happens in relatively few places -- no need in out-=
of-band status reporting (it gets generated by language for you).</div><div=
><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"marg=
in: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><d=
iv dir=3D"ltr"><div> So even if this idea were logically coherent with the =
meaning of exceptions, even if we were to find a way to solve the problems =
it creates, I submit that it would lead to the writing of crap code.<br></d=
iv></div></blockquote><div>=C2=A0</div></div><div>Users will always find a =
way how to write crap code :-)</div><div><br></div></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/f1bd992e-fd3b-4d2e-98ef-1027eafabea8%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/f1bd992e-fd3b-4d2e-98ef-1027eafabea8=
%40isocpp.org</a>.<br />
------=_Part_1852_1345414792.1504214344671--
------=_Part_1851_316176998.1504214344670--
.
Author: crusader.mike@gmail.com
Date: Thu, 31 Aug 2017 14:23:37 -0700 (PDT)
Raw View
------=_Part_1810_488992394.1504214617595
Content-Type: multipart/alternative;
boundary="----=_Part_1811_1427746544.1504214617595"
------=_Part_1811_1427746544.1504214617595
Content-Type: text/plain; charset="UTF-8"
On Thursday, August 31, 2017 at 1:18:25 PM UTC-5, Nicol Bolas wrote:
>
> On Thursday, August 31, 2017 at 12:00:35 PM UTC-4, Nicol Bolas wrote:
>>
>> On Thursday, August 31, 2017 at 3:25:06 AM UTC-4, crusad...@gmail.com
>> wrote:
>>>
>>> Ok, you just raised first actual problem (from my pov):
>>>
>>> class X; // it's dtor can throw
>>>
>>> struct S
>>> {
>>> X x;
>>>
>>> ~S() noexcept(true) {} // no way to intercept exception from
>>> x's dtor
>>> };
>>>
>>> this sucks... I wonder if this can be 'fixed' with same thing we can do
>>> in ctors:
>>>
>>> ~S() noexcept(true)
>>> try
>>> {
>>> }
>>> catch(...) { ... }
>>>
>>
>> FYI: function-level try/catch-blocks cannot swallow exceptions. If you
>> don't explicitly exit the block via throwing, the system automatically
>> rethrows what it caught.
>>
>> They are for doing major cleanup and/or exception translation, not for
>> eating them.
>>
>
> Two things:
>
> 1) destructor-level try-blocks already exist.
>
> 2) I was slightly wrong about swallowing exceptions in function-level
> blocks. Such blocks will automatically `throw;` at the end if they are
> constructor *or destructor* blocks. For regular function blocks, they
> `return;` at the end, just like a regular function.
>
Yes, I know both of these :-). Pretty sure auto-throwing from dtor
function-lvl try block can be disabled (i.e. swallow it by default) -- no
one is using it right now and it doesn't make a lot of sense rethrowing in
such case since prevailing ideology right now is that you shouldn't throw
from dtor.
Problem is that this means additional change to the language, which means
more resistance in general.
--
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/cbfedf24-cbe0-4d6f-b744-101964a93f06%40isocpp.org.
------=_Part_1811_1427746544.1504214617595
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Thursday, August 31, 2017 at 1:18:25 PM UTC-5, =
Nicol Bolas wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"=
ltr">On Thursday, August 31, 2017 at 12:00:35 PM UTC-4, Nicol Bolas 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">On Thursday, August=
31, 2017 at 3:25:06 AM UTC-4, <a>crusad...@gmail.com</a> 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></div><div>Ok, you just =
raised first actual problem (from my pov):</div><div><br></div><div>class X=
; =C2=A0 // it's dtor can throw</div><div><br></div><div>struct S</div>=
<div>{</div><div>=C2=A0 =C2=A0 X x;</div><div><br></div><div>=C2=A0 =C2=A0 =
~S() noexcept(true) {} =C2=A0 =C2=A0 =C2=A0// no way to intercept exception=
from x's dtor</div><div>};</div><div><br></div><div>this sucks... I wo=
nder if this can be 'fixed' with same thing we can do in ctors:</di=
v><div><br></div><div><div>=C2=A0 =C2=A0 ~S() noexcept(true)=C2=A0</div><di=
v>=C2=A0 =C2=A0 try</div><div>=C2=A0 =C2=A0 {</div><div>=C2=A0 =C2=A0 }</di=
v></div><div>=C2=A0 =C2=A0 catch(...) { ... }</div></div></blockquote><div>=
<br>FYI: function-level try/catch-blocks cannot swallow exceptions. If you =
don't explicitly exit the block via throwing, the system automatically =
rethrows what it caught.<br><br>They are for doing major cleanup and/or exc=
eption translation, not for eating them.<br></div></div></blockquote><br>Tw=
o things:<br><br>1) destructor-level try-blocks already exist.<br><br>2) I =
was slightly wrong about swallowing exceptions in function-level blocks. Su=
ch blocks will automatically `throw;` at the end if they are constructor <i=
>or destructor</i> blocks. For regular function blocks, they `return;` at t=
he end, just like a regular function.<br></div></blockquote><div><br></div>=
<div>Yes, I know both of these :-). Pretty sure auto-throwing from dtor fun=
ction-lvl try block can be disabled (i.e. swallow it by default) -- no one =
is using it right now and it doesn't make a lot of sense rethrowing in =
such case since prevailing ideology right now is that you shouldn't thr=
ow from dtor.</div><div><br></div><div>Problem is that this means additiona=
l change to the language, which means more resistance in general.</div></di=
v>
<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/cbfedf24-cbe0-4d6f-b744-101964a93f06%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/cbfedf24-cbe0-4d6f-b744-101964a93f06=
%40isocpp.org</a>.<br />
------=_Part_1811_1427746544.1504214617595--
------=_Part_1810_488992394.1504214617595--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Thu, 31 Aug 2017 14:43:03 -0700
Raw View
On Thursday, 31 August 2017 14:00:10 PDT crusader.mike@gmail.com wrote:
> > Explain. Where do you lose efficiency if it was only a promise?
>
> That is the problem -- 'noexcept' specifier is two things in one package
> and there is no way to separate them. It is not only the promise, it is
> also an enforcement (which is not free). Here are some details:
> https://stackoverflow.com/questions/21463119/does-it-make-sense-to-declare-i
> nline-functions-noexcept/39242143#39242143
That's what you get for trusting StackOverflow. On modern implementations,
there's no impact.
See https://godbolt.org/g/JSmTYt for both GCC (IA-64 C++ ABI) and Visual
Studio (MS ABI) for
void throwing() noexcept(false);
void nonthrowing() noexcept
{
throwing();
}
If there was any performance impact with those ABIs, the two compilers
wouldn't have been able to generate the minimal possible code, which is
jmp throwing
Click the .text to see the out-of-line, read-only, sharable Exception Handling
data that GCC generates. That data is needed only if throwing() does throw,
otherwise it may not even be paged in from disk.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/10996692.mQ8HBKWMDA%40tjmaciei-mobl1.
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 31 Aug 2017 16:11:24 -0700 (PDT)
Raw View
------=_Part_1868_1160844970.1504221084662
Content-Type: multipart/alternative;
boundary="----=_Part_1869_614205272.1504221084663"
------=_Part_1869_614205272.1504221084663
Content-Type: text/plain; charset="UTF-8"
On Thursday, August 31, 2017 at 5:19:04 PM UTC-4, crusad...@gmail.com wrote:
>
> On Thursday, August 31, 2017 at 11:00:35 AM UTC-5, Nicol Bolas wrote:
> Indeed, this is a perfect example of exactly why your idea doesn't work.
>>
>>
>>>> OK, let's say that something in "do work using these devices (which can
>>>> throw too)" throws. The caller of this function catches it, so the stack
>>>> starts unwinding. Those destructors start failing, so a second exception is
>>>> emitted that gets caught right here.
>>>>
>>>
>>> Second problem -- "catching" happens before unwinding. I didn't think of
>>> that... Hmm, this means no substitutions... all additional exceptions will
>>> have option to either get discarded or added to a list of trailing
>>> exceptions (or std::terminate of course)
>>>
>>
>> OK, so if we have A->B->C->D->E again, but this time E throws something
>> that gets caught by B. And now, during unwinding D throws something which C
>> catches. But since the catch happens before the initial unwinding, what D
>> throws becomes a "trailing exception". Which means that B has to have the
>> responsibility to handle exceptions thrown by D.
>>
>> That makes absolutely no sense. C explicitly caught the exception; that *ought
>> to mean* that the exception of that type *cannot* escape C's try-block
>> unless it explicitly wishes it to do so. And indeed, if D had thrown at any
>> time *other than* when unwinding was happening, that's exactly what
>> would happen.
>>
>> So in point of fact, despite the code statically showing a throw from D
>> to be caught by C... we don't even know if C will catch what D throws. How
>> does that make sense?
>>
>> This is why `std::terminate` is the correct call here. The code could go
>> to C or to B, but neither one is the right answer. Therefore, there is no
>> right answer, your program has go into weirdo-land and needs to be stopped.
>>
>> Remember: exceptions are supposed to be "handle it or fail" errors. It
>> should not be possible to swallow an exception *by accident*.
>>
>> Is it possible for this catch statement to effectively swallow *all*
>>>> exceptions, in the event that it throws during unwinding?
>>>>
>>>
>>> yes, why not?
>>>
>>
>> Because someone else caught that exception. That exception wasn't meant
>> for that `catch` statement.
>>
>> Your idea makes a mockery of how `throw`/`catch` is supposed to work. It
>> ought to be like a `goto` with a label. But since function scopes are
>> dynamically defined, you can't know that the label exists or where it is at
>> compile-time. So `throw`ing can fail if the runtime state of the system is
>> not in a configuration to make the `throw` succeed.
>>
>> Even `exception_ptr`s exist primarily to be able to transmit exceptions
>> from their source `throw` to their destination `catch` across non-scoping
>> boundaries.
>>
>
> Ok, let's compare two cases:
> - traditional implementation where failure (to switch off a device) in
> dtor is swallowed (and reported via out-of-band mechanism)
> - where failure in dtor results in exception attaching itself to 'current'
> exception
>
> I don't see fundamental difference between these two cases. In both cases
> you can catch only first exception, in both cases you'll end up doing
> additional work to access information about these additional failures. The
> second approach leads to simpler code:
> - you don't need to code out-of-band reporting mechanism
> - you don't need to swallow exceptions in dtors
>
And yet, every example of the *reception* of these errors that you've shown
is not in any way, shape, or form "simpler code" compared to the OOB error
reporting.
Basically, there is nothing stopping you from having the ability to service
destructor failures meaningfully. You can create OOB reporting mechanism
that give you all the functionality you want from this trailing exception
stuff.
You just want the language to create an OOB error reporting mechanism
attached to the exception system.
The case you describe is actually perfect for an out-of-band error
>>>> mechanism (something like `std:errno` or `glGetError`) to report the errors
>>>> from the destructor of the device class. That allows the caller to be able
>>>> to ask whether device stoppage succeeded *without* having to have this
>>>> aggregation of return values. And it works very well with exceptions, since
>>>> the error can still be reported without interfering in the exception
>>>> itself. After all, you're talking about what is a different *channel*
>>>> of error from the original exception.
>>>>
>>>> No one error handling mechanism fits all cases. Even `errno` has its
>>>> place.
>>>>
>>>
>>> Unfortunately then you end up with multiple 'errno' variables (one per
>>> device or libarary) and no knowledge which ones were set. You'll have to
>>> conjure some way of notifying yourself via out-of-band mechanisms or simply
>>> poll all of them.
>>>
>>
>> And this is exactly why I wanted you to show the code for how you process
>> your arbitrary collection of exceptions. Because your "trailing exception"
>> mechanism has almost exactly the same properties you describe here.
>>
>> "Trailing exceptions" have multiple different types, some of which are
>> the errors you're looking for and some of which are not. This is exactly
>> analogous to the "multiple 'errno' variables". And your trailing exceptions
>> must *all* be polled in order to find which ones you're looking for. You
>> have to sift through the entire sequence of trailing exceptions, casting
>> each one in turn to find the one you're looking for.
>>
>
> With one significant difference -- I don't need to poll for every possible
> error here. I'll end up iterating over errors that actually happened.
>
I don't know what you call this:
for(auto p: std::trailing_exceptions(x))
process_exception(p, false);
But that looks suspiciously like "polling for every possible error here" to
me. It most certainly "iterating over errors that actually happened". So
I'm having a hard time seeing this as a "significant difference".
Imagine a case where you drive multiple devices and each one has it's own
> library (with some sort of 'errno' mechanism). In case of failure:
> - I need to know exactly which device could've been used by a function
> that failed
> - poll *all* of them to figure out their current state
>
> or
>
> - device an out-of-bound reporting mechanism that will be used in related
> places (where exceptions were swallowed) and accumulate related info
> somewhere
>
OK, so we're in a world where each device comes from a different system.
This means that, in the "Trailing exceptions" version, each device also
would throw its own exception type that's independent of another.
This means that your receiving code must do this:
for(auto p: std::trailing_exceptions(x))
{
if(auto t1 = exception_cast<T1*>(p); t1)
{
}
else if(auto t2 = exception_cast<T2&>(p); t2)
{
}
else if(auto t3 = exception_cast<T3&>(p); t3)
{
}
...
}
This looks suspiciously like the "manual virtual call" anti-pattern, where
you `dynamic_cast` some object to various possibilities just to call a
function. It's something that you should never do, and we should not make
language features that effectively requires this anti-pattern.
I see no advantage to that code, compared to this:
if(system1::has_error())
{
}
if(system2::has_error())
{
}
if(system3::has_error())
{
}
....
The main distinction between them is that out-of-band errors for different
>> systems explicitly have different "channels". By contrast, trailing
>> exceptions all use the same "channel". But this is actually an
>> *advantage*. Just look at your processing code. All that rethrowing
>> nonsense just to check the type. Even if you turned it into a simpler
>> `exception_cast` or whatever, it's still a lot of processing just to fish
>> out the errors you're actually interested in.
>>
>
> Yes, processing logic (with rethrowing) is not ideal -- it is simply
> inherited problem from std::current_exception and the way
> std::exception_ptr machinery is defined. It is not an inherent failure of
> 'throwing from dtor' idea.
>
Like I said, even if you turn the rethrowing bit into some
`exception_cast`, you're still iterating over every exception that has been
thrown.
The handling for out-of-band reporting would look like this:
>>
>> catch(actual_exception &e)
>> {
>> //Handle actual exception
>>
>> //Handle device failures.
>> if(did_devices_fail_to_stop())
>> {
>> for(auto &device_err : get_device_failures())
>> {
>> //Deal with failure for this device.
>> }
>> }
>> }
>>
>> This is *far* more readable, understandable, and maintainable than the
>> "trailing exception" version. Your idea does not lead to "nice, compact
>> solutions".
>>
>
> It does in cases when error handling happens in relatively few places --
> no need in out-of-band status reporting (it gets generated by language for
> you).
>
Language mechanisms should lead to *better looking* code, not worse
looking. Your exception clash-based code looks like crap. Indeed, it is
exactly why we don't let people do `catch(...)`, then try to repeatedly
cast it to the type they're interested in. We instead let them state the
type up-front, so that their code is easy to read and understand.
That's what a *good* language feature looks like.
So even if this idea were logically coherent with the meaning of
>> exceptions, even if we were to find a way to solve the problems it creates,
>> I submit that it would lead to the writing of crap code.
>>
>
> Users will always find a way how to write crap code :-)
>
Good features can be used poorly, but they can also be used *well*. Thus
far, every example you've shown leads to code that looks worse than what
you could get with a specialized, user-defined mechanism.
--
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/e0a60f39-83c1-4d76-b5d8-137d2550bb4f%40isocpp.org.
------=_Part_1869_614205272.1504221084663
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, August 31, 2017 at 5:19:04 PM UTC-4, crusad..=
..@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"=
ltr">On Thursday, August 31, 2017 at 11:00:35 AM UTC-5, Nicol Bolas wrote:<=
div>Indeed, this is a perfect example of exactly why your idea doesn't =
work.<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 c=
lass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quot=
e" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-l=
eft:1ex"><div dir=3D"ltr"><div><br>OK, let's say that something in &quo=
t;do work using these devices (which can throw too)" throws. The calle=
r of this function catches it, so the stack starts unwinding. Those destruc=
tors start failing, so a second exception is emitted that gets caught right=
here.<br></div></div></blockquote><div><br></div><div>Second problem -- &q=
uot;catching" happens before unwinding. I didn't think of that... =
Hmm, this means no substitutions... all additional exceptions will have opt=
ion to either get discarded or added to a list of trailing exceptions (or s=
td::terminate of course)</div></div></blockquote><div><br>OK, so if we have=
A->B->C->D->E again, but this time E throws something that get=
s caught by B. And now, during unwinding D throws something which C catches=
.. But since the catch happens before the initial unwinding, what D throws b=
ecomes a "trailing exception". Which means that B has to have the=
responsibility to handle exceptions thrown by D.<br><br>That makes absolut=
ely no sense. C explicitly caught the exception; that <i>ought to mean</i> =
that the exception of that type <i>cannot</i> escape C's try-block unle=
ss it explicitly wishes it to do so. And indeed, if D had thrown at any tim=
e <i>other than</i> when unwinding was happening, that's exactly what w=
ould happen.<br><br>So in point of fact, despite the code statically showin=
g a throw from D to be caught by C... we don't even know if C will catc=
h what D throws. How does that make sense?<br><br>This is why `std::termina=
te` is the correct call here. The code could go to C or to B, but neither o=
ne is the right answer. Therefore, there is no right answer, your program h=
as go into weirdo-land and needs to be stopped.<br><br></div></div></blockq=
uote><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>Remember=
: exceptions are supposed to be "handle it or fail" errors. It sh=
ould not be possible to swallow an exception <i>by accident</i>.<br><br></d=
iv><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;bo=
rder-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div></div><div=
></div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8e=
x;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>Is it =
possible for this catch statement to effectively swallow <i>all</i> excepti=
ons, in the event that it throws during unwinding?<br></div></div></blockqu=
ote><div><br></div><div>yes, why not?</div></div></blockquote><div><br>Beca=
use someone else caught that exception. That exception wasn't meant for=
that `catch` statement.<br><br>Your idea makes a mockery of how `throw`/`c=
atch` is supposed to work. It ought to be like a `goto` with a label. But s=
ince function scopes are dynamically defined, you can't know that the l=
abel exists or where it is at compile-time. So `throw`ing can fail if the r=
untime state of the system is not in a configuration to make the `throw` su=
cceed.<br><br>Even `exception_ptr`s exist primarily to be able to transmit =
exceptions from their source `throw` to their destination `catch` across no=
n-scoping boundaries.<br></div></div></blockquote><div><br></div><div>Ok, l=
et's compare two cases:</div><div>- traditional implementation where fa=
ilure (to switch off a device) in dtor is swallowed (and reported via out-o=
f-band mechanism)</div><div>- where failure in dtor results in exception at=
taching itself to 'current' exception</div><div><br></div><div>I do=
n't see fundamental difference between these two cases. In both cases y=
ou can catch only first exception, in both cases you'll end up doing ad=
ditional work to access information about these additional failures. The se=
cond approach leads to simpler code:</div><div>- you don't need to code=
out-of-band reporting mechanism</div><div>- you don't need to swallow =
exceptions in dtors</div></div></div></blockquote><div><br>And yet, every e=
xample of the <i>reception</i> of these errors that you've shown is not=
in any way, shape, or form "simpler code" compared to the OOB er=
ror reporting.<br><br>Basically, there is nothing stopping you from having =
the ability to service destructor failures meaningfully. You can create OOB=
reporting mechanism that give you all the functionality you want from this=
trailing exception stuff.<br><br>You just want the language to create an O=
OB error reporting mechanism attached to the exception system.<br><br></div=
><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><div></=
div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><blockquote cl=
ass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #cc=
c solid;padding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote=
" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-le=
ft:1ex"><div dir=3D"ltr"><div>The case you describe is actually perfect for=
an out-of-band error mechanism (something like `std:errno` or `glGetError`=
) to report the errors from the destructor of the device class. That allows=
the caller to be able to ask whether device stoppage succeeded <i>without<=
/i> having to have this aggregation of return values. And it works very wel=
l with exceptions, since the error can still be reported without interferin=
g in the exception itself. After all, you're talking about what is a di=
fferent <i>channel</i> of error from the original exception.<br><br>No one =
error handling mechanism fits all cases. Even `errno` has its place.<br></d=
iv></div></blockquote><div><br></div><div>Unfortunately then you end up wit=
h multiple 'errno' variables (one per device or libarary) and no kn=
owledge which ones were set. You'll have to conjure some way of notifyi=
ng yourself via out-of-band mechanisms or simply poll all of them.</div></d=
iv></blockquote><div><br>And this is exactly why I wanted you to show the c=
ode for how you process your arbitrary collection of exceptions. Because yo=
ur "trailing exception" mechanism has almost exactly the same pro=
perties you describe here.<br><br>"Trailing exceptions" have mult=
iple different types, some of which are the errors you're looking for a=
nd some of which are not. This is exactly analogous to the "multiple &=
#39;errno' variables". And your trailing exceptions must <i>all</i=
> be polled in order to find which ones you're looking for. You have to=
sift through the entire sequence of trailing exceptions, casting each one =
in turn to find the one you're looking for.</div></div></blockquote><di=
v><br></div><div>With one significant difference -- I don't need to pol=
l for every possible error here. I'll end up iterating over errors that=
actually happened. </div></div></div></blockquote><div><br>I don't kno=
w what you call this:<br><br><div style=3D"background-color: rgb(250, 250, =
250); border-color: rgb(187, 187, 187); border-style: solid; border-width: =
1px; overflow-wrap: break-word;" class=3D"prettyprint"><code class=3D"prett=
yprint"><div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D=
"styled-by-prettify">for</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">(</span><span style=3D"color: #008;" class=3D"styled-by-prett=
ify">auto</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> =
p</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 s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify">trailing_exceptions</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify">x</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">))</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 process_exception</span><span s=
tyle=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">p</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"style=
d-by-prettify">false</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">);</span></div></code></div><br>But that looks suspiciously like =
"polling for every possible error here" to me. It most certainly =
"iterating over errors that actually happened". So I'm having=
a hard time seeing this as a "significant difference".<br><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"><div><div=
>Imagine a case where you drive multiple devices and each one has it's =
own library (with some sort of 'errno' mechanism). In case of failu=
re:</div><div>- I need to know exactly which device could've been used =
by a function that failed</div><div>- poll *all* of them to figure out thei=
r current state</div></div></div></blockquote><div></div><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><div><br></div><div>or</d=
iv><div><br></div><div>- device an out-of-bound reporting mechanism that wi=
ll be used in related places (where exceptions were swallowed) and accumula=
te related info somewhere</div></div></div></blockquote><div><br>OK, so we&=
#39;re in a world where each device comes from a different system. This mea=
ns that, in the "Trailing exceptions" version, each device also w=
ould throw its own exception type that's independent of another.<br><br=
>This means that your receiving code must do this:<br><br><div style=3D"bac=
kground-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border=
-style: solid; border-width: 1px; overflow-wrap: break-word;" class=3D"pret=
typrint"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span st=
yle=3D"color: #008;" class=3D"styled-by-prettify">for</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #0=
08;" class=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> p</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-prett=
ify">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">tra=
iling_exceptions</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">x</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">))</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span sty=
le=3D"color: #660;" class=3D"styled-by-prettify">{</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"co=
lor: #008;" class=3D"styled-by-prettify">if</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> t1 </span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify"> exception_cast</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify"><</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">T1</span><span style=3D"color: #660;" class=3D"styled-by-prettify">*>=
;(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">p</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">);</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> t1</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 </span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">}</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">else</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">if</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</s=
pan><span style=3D"color: #008;" class=3D"styled-by-prettify">auto</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> t2 </span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> exception_cast</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify"><</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify">T2</span><span style=3D"color: #6=
60;" class=3D"styled-by-prettify">&>(</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify">p</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">);</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> t2</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 </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 </span><span style=3D"color: #660;" class=3D"styled-by-prettify">}</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 </sp=
an><span style=3D"color: #008;" class=3D"styled-by-prettify">else</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">if</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #008;"=
class=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"> t3 </span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> exception_cast</span><span style=3D"color: #660;" class=3D"styl=
ed-by-prettify"><</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">T3</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">&>(</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
">p</span><span style=3D"color: #660;" class=3D"styled-by-prettify">);</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> t3</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 </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 </span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;"=
class=3D"styled-by-prettify"><br>=C2=A0 </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"st=
yled-by-prettify">}</span></div></code></div><br>This looks suspiciously li=
ke the "manual virtual call" anti-pattern, where you `dynamic_cas=
t` some object to various possibilities just to call a function. It's s=
omething that you should never do, and we should not make language features=
that effectively requires this anti-pattern.<br><br>I see no advantage to =
that code, compared to this:<br><br><div style=3D"background-color: rgb(250=
, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; border-=
width: 1px; overflow-wrap: break-word;" class=3D"prettyprint"><code class=
=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: #008;"=
class=3D"styled-by-prettify">if</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">system1</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">has_error</span><span style=3D"color: #660;" class=3D"styled-by-prettif=
y">())</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span st=
yle=3D"color: #660;" class=3D"styled-by-prettify">}</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #=
008;" class=3D"styled-by-prettify">if</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">system2</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify">has_error</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">())</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><=
br></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><span style=3D=
"color: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color=
: #008;" class=3D"styled-by-prettify">if</span><span style=3D"color: #660;"=
class=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify">system3</span><span style=3D"color: #660;" class=3D"st=
yled-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify">has_error</span><span style=3D"color: #660;" class=3D"styled-by-p=
rettify">())</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"><br></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><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">...</span></div></code></div><br><=
/div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8e=
x;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr"><div><di=
v></div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8=
ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>=C2=
=A0The main distinction between them is that out-of-band errors for differe=
nt systems explicitly have different "channels". By contrast, tra=
iling exceptions all use the same "channel". But this is actually=
an <i>advantage</i>. Just look at your processing code. All that rethrowin=
g nonsense just to check the type. Even if you turned it into a simpler `ex=
ception_cast` or whatever, it's still a lot of processing just to fish =
out the errors you're actually interested in.</div></div></blockquote><=
div><br></div><div>Yes, processing logic (with rethrowing) is not ideal -- =
it is simply inherited problem from std::current_exception and the way std:=
:exception_ptr machinery is defined. It is not an inherent failure of '=
throwing from dtor' idea.</div></div></div></blockquote><div><br>Like I=
said, even if you turn the rethrowing bit into some `exception_cast`, you&=
#39;re still iterating over every exception that has been thrown.<br><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"><div><div=
></div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8e=
x;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div>The ha=
ndling for out-of-band reporting would look like this:<br><br><div style=3D=
"background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-sty=
le:solid;border-width:1px"><code><div><span style=3D"color:#008">catch</spa=
n><span style=3D"color:#660">(</span><span style=3D"color:#000">actual_exce=
ption </span><span style=3D"color:#660">&</span><span style=3D"color:#0=
00">e</span><span style=3D"color:#660">)</span><span style=3D"color:#000"><=
br></span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br=
>=C2=A0 </span><span style=3D"color:#800">//Handle actual exception</span><=
span style=3D"color:#000"><br><br>=C2=A0 </span><span style=3D"color:#800">=
//Handle device failures.</span><span style=3D"color:#000"><br>=C2=A0 </spa=
n><span style=3D"color:#008">if</span><span style=3D"color:#660">(</span><s=
pan style=3D"color:#000">did_devices_fail_to_stop</span><span style=3D"colo=
r:#660">())</span><span style=3D"color:#000"><br>=C2=A0 </span><span style=
=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 </span=
><span style=3D"color:#008">for</span><span style=3D"color:#660">(</span><s=
pan style=3D"color:#008">auto</span><span style=3D"color:#000"> </span><spa=
n style=3D"color:#660">&</span><span style=3D"color:#000">device_err </=
span><span style=3D"color:#660">:</span><span style=3D"color:#000"> get_dev=
ice_failures</span><span style=3D"color:#660">())</span><span style=3D"colo=
r:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#660">{</span><span s=
tyle=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color:#8=
00">//Deal with failure for this device.</span><span style=3D"color:#000"><=
br>=C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><span style=3D"c=
olor:#000"><br>=C2=A0 </span><span style=3D"color:#660">}</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#660">}</span></div></code>=
</div><br>This is <i>far</i> more readable, understandable, and maintainabl=
e than the "trailing exception" version. Your idea does not lead =
to "nice, compact solutions".</div></div></blockquote><div><br></=
div><div>It does in cases when error handling happens in relatively few pla=
ces -- no need in out-of-band status reporting (it gets generated by langua=
ge for you).</div></div></div></blockquote><div><br>Language mechanisms sho=
uld lead to <i>better looking</i> code, not worse looking. Your exception c=
lash-based code looks like crap. Indeed, it is exactly why we don't let=
people do `catch(...)`, then try to repeatedly cast it to the type they=
9;re interested in. We instead let them state the type up-front, so that th=
eir code is easy to read and understand.<br><br>That's what a <i>good</=
i> language feature looks like.<br><br></div><blockquote class=3D"gmail_quo=
te" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;paddi=
ng-left: 1ex;"><div dir=3D"ltr"><div><div></div><blockquote class=3D"gmail_=
quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddi=
ng-left:1ex"><div dir=3D"ltr"><div> So even if this idea were logically coh=
erent with the meaning of exceptions, even if we were to find a way to solv=
e the problems it creates, I submit that it would lead to the writing of cr=
ap code.<br></div></div></blockquote><div>=C2=A0</div></div><div>Users will=
always find a way how to write crap code :-)</div></div></blockquote><div>=
<br>Good features can be used poorly, but they can also be used <i>well</i>=
.. Thus far, every example you've shown leads to code that looks worse t=
han what you could get with a specialized, user-defined mechanism.<br></div=
></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/e0a60f39-83c1-4d76-b5d8-137d2550bb4f%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/e0a60f39-83c1-4d76-b5d8-137d2550bb4f=
%40isocpp.org</a>.<br />
------=_Part_1869_614205272.1504221084663--
------=_Part_1868_1160844970.1504221084662--
.
Author: crusader.mike@gmail.com
Date: Thu, 31 Aug 2017 16:12:00 -0700 (PDT)
Raw View
------=_Part_1956_389051741.1504221120536
Content-Type: multipart/alternative;
boundary="----=_Part_1957_1009453575.1504221120537"
------=_Part_1957_1009453575.1504221120537
Content-Type: text/plain; charset="UTF-8"
On Thursday, August 31, 2017 at 4:43:08 PM UTC-5, Thiago Macieira wrote:
>
> On Thursday, 31 August 2017 14:00:10 PDT crusad...@gmail.com <javascript:>
> wrote:
> > > Explain. Where do you lose efficiency if it was only a promise?
> >
> > That is the problem -- 'noexcept' specifier is two things in one package
> > and there is no way to separate them. It is not only the promise, it is
> > also an enforcement (which is not free). Here are some details:
> >
> https://stackoverflow.com/questions/21463119/does-it-make-sense-to-declare-i
> > nline-functions-noexcept/39242143#39242143
>
> That's what you get for trusting StackOverflow. On modern implementations,
> there's no impact.
>
> See https://godbolt.org/g/JSmTYt
> <https://www.google.com/url?q=https%3A%2F%2Fgodbolt.org%2Fg%2FJSmTYt&sa=D&sntz=1&usg=AFQjCNEcTLpzyI2VY3aEjRpvDRtnm-OJmQ>
> for both GCC (IA-64 C++ ABI) and Visual
> Studio (MS ABI) for
>
> void throwing() noexcept(false);
> void nonthrowing() noexcept
> {
> throwing();
> }
>
> If there was any performance impact with those ABIs, the two compilers
> wouldn't have been able to generate the minimal possible code, which is
>
> jmp throwing
>
> Click the .text to see the out-of-line, read-only, sharable Exception
> Handling
> data that GCC generates. That data is needed only if throwing() does
> throw,
> otherwise it may not even be paged in from disk.
>
There certainly is some impact (at least for MSVC, try removing
nothrow from nonthrowing()):
https://godbolt.org/g/nQDnxt
notice how code changes (you forgot to specify /EHsc for MSVC)
At the very least -- specifying nothrow on a function (that you know won't
throw, but compiler can't prove that) will cause some overhead (even if it
is in those tables that never get loaded and simply make your executable
slightly bigger). At worst -- reduces optimizations available to compiler
when such function gets inlined.
TBH, I don't want to discuss this in this thread -- it is already diluted
with too many details and detractions.
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
>
>
--
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/de3c8472-329c-467b-a5c2-f76ecf36680e%40isocpp.org.
------=_Part_1957_1009453575.1504221120537
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Thursday, August 31, 2017 at 4:43:08 PM UTC-5, =
Thiago Macieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Thurs=
day, 31 August 2017 14:00:10 PDT <a href=3D"javascript:" target=3D"_blank" =
gdf-obfuscated-mailto=3D"s6vf1p3YAQAJ" rel=3D"nofollow" onmousedown=3D"this=
..href=3D'javascript:';return true;" onclick=3D"this.href=3D'jav=
ascript:';return true;">crusad...@gmail.com</a> wrote:
<br>> > Explain. Where do you lose efficiency if it was only a promis=
e?
<br>>=20
<br>> That is the problem -- 'noexcept' specifier is two things =
in one package
<br>> and there is no way to separate them. It is not only the promise, =
it is
<br>> also an enforcement (which is not free). Here are some details:
<br>> <a href=3D"https://stackoverflow.com/questions/21463119/does-it-ma=
ke-sense-to-declare-i" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"th=
is.href=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2Fstackoverflow.=
com%2Fquestions%2F21463119%2Fdoes-it-make-sense-to-declare-i\x26sa\x3dD\x26=
sntz\x3d1\x26usg\x3dAFQjCNG8PyNh9KEaZaRS9cCDU3Hxiz3Blw';return true;" o=
nclick=3D"this.href=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2Fst=
ackoverflow.com%2Fquestions%2F21463119%2Fdoes-it-make-sense-to-declare-i\x2=
6sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNG8PyNh9KEaZaRS9cCDU3Hxiz3Blw';ret=
urn true;">https://stackoverflow.com/<wbr>questions/21463119/does-it-<wbr>m=
ake-sense-to-declare-i</a>
<br>> nline-functions-noexcept/<wbr>39242143#39242143
<br>
<br>That's what you get for trusting StackOverflow. On modern implement=
ations,=20
<br>there's no impact.
<br>
<br>See <a href=3D"https://www.google.com/url?q=3Dhttps%3A%2F%2Fgodbolt.org=
%2Fg%2FJSmTYt&sa=3DD&sntz=3D1&usg=3DAFQjCNEcTLpzyI2VY3aEjRpvDRt=
nm-OJmQ" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'=
;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgodbolt.org%2Fg%2FJSmTYt\x26=
sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEcTLpzyI2VY3aEjRpvDRtnm-OJmQ';retu=
rn true;" onclick=3D"this.href=3D'https://www.google.com/url?q\x3dhttps=
%3A%2F%2Fgodbolt.org%2Fg%2FJSmTYt\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNE=
cTLpzyI2VY3aEjRpvDRtnm-OJmQ';return true;">https://godbolt.org/g/JSmTYt=
</a> for both GCC (IA-64 C++ ABI) and Visual=20
<br>Studio (MS ABI) for=20
<br>
<br>void throwing() noexcept(false);
<br>void nonthrowing() noexcept
<br>{
<br>=C2=A0 =C2=A0 throwing();
<br>}
<br>
<br>If there was any performance impact with those ABIs, the two compilers=
=20
<br>wouldn't have been able to generate the minimal possible code, whic=
h is
<br>
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0jmp=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0throwing
<br>
<br>Click the .text to see the out-of-line, read-only, sharable Exception H=
andling=20
<br>data that GCC generates. That data is needed only if throwing() does th=
row,=20
<br>otherwise it may not even be paged in from disk.
<br></blockquote><div><br></div><div>There certainly is some impact (at lea=
st for MSVC, try removing nothrow=C2=A0from nonthrowing()):</div><div>https=
://godbolt.org/g/nQDnxt<br></div><div><br></div><div>notice how code change=
s (you forgot to specify /EHsc for MSVC)</div><div><br></div><div>At the ve=
ry least -- specifying nothrow on a function (that you know won't throw=
, but compiler can't prove that) will cause some overhead (even if it i=
s in those tables that never get loaded and simply make your executable sli=
ghtly bigger). At worst -- reduces optimizations available to compiler when=
such function gets inlined.</div><div><br></div><div>TBH, I don't want=
to discuss this in this thread -- it is already diluted with too many deta=
ils and detractions.</div><div>=C2=A0</div><blockquote class=3D"gmail_quote=
" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding=
-left: 1ex;">--=20
<br>Thiago Macieira - thiago (AT) <a href=3D"http://macieira.info" target=
=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.goo=
gle.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x3dD\x26sntz\x3d1\x26usg\=
x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.hr=
ef=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x=
3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return t=
rue;">macieira.info</a> - thiago (AT) <a href=3D"http://kde.org" target=3D"=
_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.google.=
com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNH=
GRJdo5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'=
http://www.google.com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1=
\x26usg\x3dAFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;">kde.org</a=
>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>
<br></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/de3c8472-329c-467b-a5c2-f76ecf36680e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/de3c8472-329c-467b-a5c2-f76ecf36680e=
%40isocpp.org</a>.<br />
------=_Part_1957_1009453575.1504221120537--
------=_Part_1956_389051741.1504221120536--
.
Author: Bryce Glover <randomdsdevel@gmail.com>
Date: Thu, 31 Aug 2017 19:33:02 -0400
Raw View
--Apple-Mail=_101A5CC5-38F7-418E-B566-1D24EDD82BFC
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset="UTF-8"
> On Aug 31, 2017, at 6:19 PM, std-proposals@isocpp.org wrote:
>=20
> crusader.mike@gmail.com <mailto:crusader.mike@gmail.com>: Aug 30 11:09PM =
-0700=20
>=20
> On Tuesday, August 29, 2017 at 8:01:46 PM UTC-5, Bryce Glover wrote:
> > (snipped=E2=80=A6)
> =20
> Uh... I thought it is rather obvious that mechanism wasn=E2=80=99t going =
to work very well =E2=80=94 I didn't even criticize it. :-) =E2=80=A6
This reaction of yours, funnily enough, incidentally seems to ironical=
ly reflect the initial (and sustained) reaction(s) that most participants i=
n this discussion thread on seeing your OP (and its successors.) That=E2=
=80=99s not entirely either here or there, however=E2=80=A6; I was merely s=
etting up a tangential line of inquiry (presented in my original reply befo=
re the part of it which you quoted that I=E2=80=99ve purposely omitted from=
this reply for brevity=E2=80=99s sake) for you pick up on or discard as yo=
u liked, and you seem to have done the latter. (I=E2=80=99m not all that te=
rribly invested in this entire debate=E2=80=89=E2=80=94=E2=80=89to be bruta=
lly honest, I actually wouldn=E2=80=99t care all that much if it just shriv=
eled up and died, ending in stagnation and impasse, since I=E2=80=99d prefe=
r those members of the committee involved here spent more time on C++20 and=
the various TSes=E2=80=89=E2=80=94=E2=80=89other than just as a passing ma=
iling-list lurker of little experience and/or renown, so I don=E2=80=99t mi=
nd your reaction quite as much as you might think, if at all.) As far as s=
aying that ideas along these lines would probably get treated similarly to =
how your idea has been here in this thread goes, that particular sentiment =
was directed not at you, but at other participants in this discussion in a =
bid to deflect criticism with a bit of self-deprecation, as well as in a fo=
cus on yielding to common wisdom instead of thrusting rather blindly ahead =
into uncharted territory. =20
> =E2=80=A6In order for it to work you have to poison your objects with ref=
erence to reporting facility (so that it's dtor can report the error it ate=
) or write even less attractive stuff like:
> =20
> void foo()
> {
> report_obj report;
> =20
> try
> {
> my_obj1 o1;
> auto o1x =3D on_scope_exit([&]{ try{ o1.switch_off(); } catch(...) {=20
> report.on_exception_in_o1(); } })
> my_obj2 o2;
> auto o2x =3D on_scope_exit([&]{ try{ o2.switch_off(); } catch(...) {=20
> report.on_exception_in_o2(); } })
> ...
> // call ops that can throw too
> return;
> }
> catch(...)
> {
> report.on_exception();
> }
>=20
> report.throw_combined_result();
> }=20
>=20
> > (snipped=E2=80=A6)
> =20
> =E2=80=A6
I=E2=80=99m not entirely sure if the person who originally suggested u=
sing an out-of-band error-reporting mechanism intended for it to interact w=
ith whatever exceptions might exist within the state of a program such as o=
ne implementing such logic in quite the way you describe here, but the gene=
ral consensus here seems to persist: complicating the C++ and/or its stand=
ard library just to allow end users such as yourself to mishandle the langu=
age=E2=80=99s exception propagation and delivery mechanisms in the manner y=
ou=E2=80=99ve proposed and deal with the remote edge case you=E2=80=99ve br=
ought up would both lack benefits for a near-unanimous majority of C++ prog=
rammers and go against existing practice. For these reasons, among others =
which I have not summarized here, it=E2=80=99s no wonder you=E2=80=99ve rec=
eived the reaction you have in this thread. Beyond this, I defer to everyo=
ne else here for further explanation of this to you, as I am bowing out of =
this discussion since I would prefer not to get as embroiled in it as its o=
ther participants have, partly since I don=E2=80=99t feel I can contribute =
anything more to the discussion in addition to what I=E2=80=99ve already sa=
id except by bumbling, babbling repetition of unstudied possibilities. =20
> =E2=80=A6
>=20
> 'Destructing move' isn't going to happen in C++, I think. As long as 'obj=
ect' means 'bunch of bits and memory range they occupy'... and it unlikely =
to ever change.
On the contrary, there have been several proposals and involved discus=
sions <https://www.google.com/search?client=3Dsafari&rls=3Den&q=3DC+++destr=
uctive+move&ie=3DUTF-8&oe=3DUTF-8> revolving around the conceit of a(n) (op=
t-in?) destructive version of move semantics, though none of them have gott=
en very far, as far as I=E2=80=99m aware. It=E2=80=99s yet another one of =
those difficult problems that resist solving, but, from what I can tell, im=
portant enough of one to receive temporal considerations within WG21 due to=
the compiler and program optimizations it would enable. =20
Hopefully making his final disappearing act go smoothly,=20
Bryce Glover
RandomDSdevel@gmail.com
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/00A0825A-C7FA-4528-83AD-99F60BADCA38%40gmail.com=
..
--Apple-Mail=_101A5CC5-38F7-418E-B566-1D24EDD82BFC
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><blockquote t=
ype=3D"cite" class=3D""><div class=3D"">On Aug 31, 2017, at 6:19 PM, <a hre=
f=3D"mailto:std-proposals@isocpp.org" class=3D"">std-proposals@isocpp.org</=
a> wrote:</div><br class=3D"Apple-interchange-newline"><div class=3D""><spa=
n style=3D"font-family: arial; font-style: normal; font-variant-caps: norma=
l; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: =
start; text-indent: 0px; text-transform: none; white-space: normal; widows:=
auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color:=
rgb(255, 255, 255); color: rgb(177, 176, 176); font-size: 15px;" class=3D"=
"><a href=3D"mailto:crusader.mike@gmail.com" class=3D"">crusader.mike@gmail=
..com</a>: Aug 30 11:09PM -0700<span class=3D"Apple-converted-space"> <=
/span></span><span style=3D"color: rgb(46, 46, 46); font-family: arial; fon=
t-size: inherit; font-style: normal; font-variant-caps: normal; font-weight=
: normal; letter-spacing: normal; orphans: auto; text-align: start; text-in=
dent: 0px; text-transform: none; white-space: normal; widows: auto; word-sp=
acing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255,=
255); float: none; display: inline !important;" class=3D""></span><br styl=
e=3D"color: rgb(46, 46, 46); font-family: arial; font-style: normal; font-v=
ariant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: =
auto; text-align: start; text-indent: 0px; text-transform: none; white-spac=
e: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;=
background-color: rgb(255, 255, 255);" class=3D""><br style=3D"color: rgb(=
46, 46, 46); font-family: arial; font-style: normal; font-variant-caps: nor=
mal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align=
: start; text-indent: 0px; text-transform: none; white-space: normal; widow=
s: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-colo=
r: rgb(255, 255, 255);" class=3D""><span style=3D"color: rgb(46, 46, 46); f=
ont-family: arial; font-size: inherit; font-style: normal; font-variant-cap=
s: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text=
-align: start; text-indent: 0px; text-transform: none; white-space: normal;=
widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; backgroun=
d-color: rgb(255, 255, 255); float: none; display: inline !important;" clas=
s=3D"">On Tuesday, August 29, 2017 at 8:01:46 PM UTC-5, Bryce Glover wrote:=
</span><br style=3D"color: rgb(46, 46, 46); font-family: arial; font-style:=
normal; font-variant-caps: normal; font-weight: normal; letter-spacing: no=
rmal; orphans: auto; text-align: start; text-indent: 0px; text-transform: n=
one; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-str=
oke-width: 0px; background-color: rgb(255, 255, 255);" class=3D""><span sty=
le=3D"color: rgb(46, 46, 46); font-family: arial; font-size: inherit; font-=
style: normal; font-variant-caps: normal; font-weight: normal; letter-spaci=
ng: normal; orphans: auto; text-align: start; text-indent: 0px; text-transf=
orm: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-te=
xt-stroke-width: 0px; background-color: rgb(255, 255, 255); float: none; di=
splay: inline !important;" class=3D"">> (snipped=E2=80=A6)</span><br sty=
le=3D"color: rgb(46, 46, 46); font-family: arial; font-style: normal; font-=
variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans:=
auto; text-align: start; text-indent: 0px; text-transform: none; white-spa=
ce: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px=
; background-color: rgb(255, 255, 255);" class=3D""><span style=3D"color: r=
gb(46, 46, 46); font-family: arial; font-size: inherit; font-style: normal;=
font-variant-caps: normal; font-weight: normal; letter-spacing: normal; or=
phans: auto; text-align: start; text-indent: 0px; text-transform: none; whi=
te-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-widt=
h: 0px; background-color: rgb(255, 255, 255); float: none; display: inline =
!important;" class=3D""> </span><br style=3D"color: rgb(46, 46, 46); f=
ont-family: arial; font-style: normal; font-variant-caps: normal; font-weig=
ht: normal; letter-spacing: normal; orphans: auto; text-align: start; text-=
indent: 0px; text-transform: none; white-space: normal; widows: auto; word-=
spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 25=
5, 255);" class=3D""><span style=3D"color: rgb(46, 46, 46); font-family: ar=
ial; font-size: inherit; font-style: normal; font-variant-caps: normal; fon=
t-weight: normal; letter-spacing: normal; orphans: auto; text-align: start;=
text-indent: 0px; text-transform: none; white-space: normal; widows: auto;=
word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(2=
55, 255, 255); float: none; display: inline !important;" class=3D"">Uh... I=
thought it is rather obvious that mechanism wasn=E2=80=99t going to work<s=
pan class=3D"Apple-converted-space"> </span></span><span style=3D"colo=
r: rgb(46, 46, 46); font-family: arial; font-size: inherit; font-style: nor=
mal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal=
; orphans: auto; text-align: start; text-indent: 0px; text-transform: none;=
white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-=
width: 0px; background-color: rgb(255, 255, 255); float: none; display: inl=
ine !important;" class=3D"">very well =E2=80=94 I didn't even criticize it.=
:-) =E2=80=A6</span></div></blockquote><div><br class=3D""></div><div>&nbs=
p; <i class=3D"">This</i> reaction of yours, funnily enou=
gh, incidentally seems to ironically reflect the initial (and sustained) re=
action(s) that most participants in this discussion thread on seeing your O=
P (and its successors.) That=E2=80=99s not entirely either here or th=
ere, however=E2=80=A6; I was merely setting up a tangential line of inquiry=
(presented in my original reply before the part of it which you quoted tha=
t I=E2=80=99ve purposely omitted from this reply for brevity=E2=80=99s sake=
) for you pick up on or discard as you liked, and you seem to have done the=
latter. (I=E2=80=99m not all that terribly invested in this entire debate=
=E2=80=89=E2=80=94=E2=80=89to be brutally honest, I actually wouldn=E2=80=
=99t <i class=3D"">care</i> all that much if it just shriveled up and died,=
ending in stagnation and impasse, since I=E2=80=99d prefer those members o=
f the committee involved here spent more time on C++20 and the various TSes=
=E2=80=89=E2=80=94=E2=80=89other than just as a passing mailing-list lurker=
of little experience and/or renown, so I don=E2=80=99t mind your reaction =
quite as much as you might think, if at <i class=3D"">all</i>.) As fa=
r as saying that ideas along these lines would probably get treated similar=
ly to how your idea has been here in this thread goes, <i class=3D"">that</=
i> particular sentiment was directed not at <i class=3D"">you</i>, but=
at <i class=3D"">other</i> participants in this discussion in a bid to def=
lect criticism with a bit of self-deprecation, as well as in a focus on yie=
lding to common wisdom instead of thrusting rather blindly ahead into uncha=
rted territory. </div><br class=3D""><blockquote type=3D"cite" class=
=3D""><div class=3D""><span style=3D"color: rgb(46, 46, 46); font-family: a=
rial; font-size: inherit; font-style: normal; font-variant-caps: normal; fo=
nt-weight: normal; letter-spacing: normal; orphans: auto; text-align: start=
; text-indent: 0px; text-transform: none; white-space: normal; widows: auto=
; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(=
255, 255, 255); float: none; display: inline !important;" class=3D"">=E2=80=
=A6In order for it to work you<span class=3D"Apple-converted-space"> <=
/span></span><span style=3D"color: rgb(46, 46, 46); font-family: arial; fon=
t-size: inherit; font-style: normal; font-variant-caps: normal; font-weight=
: normal; letter-spacing: normal; orphans: auto; text-align: start; text-in=
dent: 0px; text-transform: none; white-space: normal; widows: auto; word-sp=
acing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255,=
255); float: none; display: inline !important;" class=3D"">have to poison =
your objects with reference to reporting facility (so that<span class=3D"Ap=
ple-converted-space"> </span></span><span style=3D"color: rgb(46, 46, =
46); font-family: arial; font-size: inherit; font-style: normal; font-varia=
nt-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto=
; text-align: start; text-indent: 0px; text-transform: none; white-space: n=
ormal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; bac=
kground-color: rgb(255, 255, 255); float: none; display: inline !important;=
" class=3D"">it's dtor can report the error it ate) or write even less attr=
active stuff<span class=3D"Apple-converted-space"> </span></span><span=
style=3D"color: rgb(46, 46, 46); font-family: arial; font-size: inherit; f=
ont-style: normal; font-variant-caps: normal; font-weight: normal; letter-s=
pacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-tr=
ansform: none; white-space: normal; widows: auto; word-spacing: 0px; -webki=
t-text-stroke-width: 0px; background-color: rgb(255, 255, 255); float: none=
; display: inline !important;" class=3D"">like:</span><br style=3D"color: r=
gb(46, 46, 46); font-family: arial; font-style: normal; font-variant-caps: =
normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-al=
ign: start; text-indent: 0px; text-transform: none; white-space: normal; wi=
dows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-c=
olor: rgb(255, 255, 255);" class=3D""><span style=3D"color: rgb(46, 46, 46)=
; font-family: arial; font-size: inherit; font-style: normal; font-variant-=
caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; t=
ext-align: start; text-indent: 0px; text-transform: none; white-space: norm=
al; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; backgr=
ound-color: rgb(255, 255, 255); float: none; display: inline !important;" c=
lass=3D""> </span><br style=3D"color: rgb(46, 46, 46); font-family: ar=
ial; font-style: normal; font-variant-caps: normal; font-weight: normal; le=
tter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; t=
ext-transform: none; white-space: normal; widows: auto; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);" clas=
s=3D""><span style=3D"color: rgb(46, 46, 46); font-family: arial; font-size=
: inherit; font-style: normal; font-variant-caps: normal; font-weight: norm=
al; letter-spacing: normal; orphans: auto; text-align: start; text-indent: =
0px; text-transform: none; white-space: normal; widows: auto; word-spacing:=
0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);=
float: none; display: inline !important;" class=3D"">void foo()</span><br =
style=3D"color: rgb(46, 46, 46); font-family: arial; font-style: normal; fo=
nt-variant-caps: normal; font-weight: normal; letter-spacing: normal; orpha=
ns: auto; text-align: start; text-indent: 0px; text-transform: none; white-=
space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: =
0px; background-color: rgb(255, 255, 255);" class=3D""><span style=3D"color=
: rgb(46, 46, 46); font-family: arial; font-size: inherit; font-style: norm=
al; font-variant-caps: normal; font-weight: normal; letter-spacing: normal;=
orphans: auto; text-align: start; text-indent: 0px; text-transform: none; =
white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-w=
idth: 0px; background-color: rgb(255, 255, 255); float: none; display: inli=
ne !important;" class=3D"">{</span><br style=3D"color: rgb(46, 46, 46); fon=
t-family: arial; font-style: normal; font-variant-caps: normal; font-weight=
: normal; letter-spacing: normal; orphans: auto; text-align: start; text-in=
dent: 0px; text-transform: none; white-space: normal; widows: auto; word-sp=
acing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255,=
255);" class=3D""><span style=3D"color: rgb(46, 46, 46); font-family: aria=
l; font-size: inherit; font-style: normal; font-variant-caps: normal; font-=
weight: normal; letter-spacing: normal; orphans: auto; text-align: start; t=
ext-indent: 0px; text-transform: none; white-space: normal; widows: auto; w=
ord-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255=
, 255, 255); float: none; display: inline !important;" class=3D"">report_ob=
j report;</span><br style=3D"color: rgb(46, 46, 46); font-family: arial; fo=
nt-style: normal; font-variant-caps: normal; font-weight: normal; letter-sp=
acing: normal; orphans: auto; text-align: start; text-indent: 0px; text-tra=
nsform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit=
-text-stroke-width: 0px; background-color: rgb(255, 255, 255);" class=3D"">=
<span style=3D"color: rgb(46, 46, 46); font-family: arial; font-size: inher=
it; font-style: normal; font-variant-caps: normal; font-weight: normal; let=
ter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; te=
xt-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -=
webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); float:=
none; display: inline !important;" class=3D""> </span><br style=3D"co=
lor: rgb(46, 46, 46); font-family: arial; font-style: normal; font-variant-=
caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; t=
ext-align: start; text-indent: 0px; text-transform: none; white-space: norm=
al; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; backgr=
ound-color: rgb(255, 255, 255);" class=3D""><span style=3D"color: rgb(46, 4=
6, 46); font-family: arial; font-size: inherit; font-style: normal; font-va=
riant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: a=
uto; text-align: start; text-indent: 0px; text-transform: none; white-space=
: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; =
background-color: rgb(255, 255, 255); float: none; display: inline !importa=
nt;" class=3D"">try</span><br style=3D"color: rgb(46, 46, 46); font-family:=
arial; font-style: normal; font-variant-caps: normal; font-weight: normal;=
letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px=
; text-transform: none; white-space: normal; widows: auto; word-spacing: 0p=
x; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);" c=
lass=3D""><span style=3D"color: rgb(46, 46, 46); font-family: arial; font-s=
ize: inherit; font-style: normal; font-variant-caps: normal; font-weight: n=
ormal; letter-spacing: normal; orphans: auto; text-align: start; text-inden=
t: 0px; text-transform: none; white-space: normal; widows: auto; word-spaci=
ng: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 25=
5); float: none; display: inline !important;" class=3D"">{</span><br style=
=3D"color: rgb(46, 46, 46); font-family: arial; font-style: normal; font-va=
riant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: a=
uto; text-align: start; text-indent: 0px; text-transform: none; white-space=
: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; =
background-color: rgb(255, 255, 255);" class=3D""><span style=3D"color: rgb=
(46, 46, 46); font-family: arial; font-size: inherit; font-style: normal; f=
ont-variant-caps: normal; font-weight: normal; letter-spacing: normal; orph=
ans: auto; text-align: start; text-indent: 0px; text-transform: none; white=
-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width:=
0px; background-color: rgb(255, 255, 255); float: none; display: inline !i=
mportant;" class=3D"">my_obj1 o1;</span><br style=3D"color: rgb(46, 46, 46)=
; font-family: arial; font-style: normal; font-variant-caps: normal; font-w=
eight: normal; letter-spacing: normal; orphans: auto; text-align: start; te=
xt-indent: 0px; text-transform: none; white-space: normal; widows: auto; wo=
rd-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255,=
255, 255);" class=3D""><span style=3D"color: rgb(46, 46, 46); font-family:=
arial; font-size: inherit; font-style: normal; font-variant-caps: normal; =
font-weight: normal; letter-spacing: normal; orphans: auto; text-align: sta=
rt; text-indent: 0px; text-transform: none; white-space: normal; widows: au=
to; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rg=
b(255, 255, 255); float: none; display: inline !important;" class=3D"">auto=
o1x =3D on_scope_exit([&]{ try{ o1.switch_off(); } catch(...) {<span c=
lass=3D"Apple-converted-space"> </span></span><br style=3D"color: rgb(=
46, 46, 46); font-family: arial; font-style: normal; font-variant-caps: nor=
mal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align=
: start; text-indent: 0px; text-transform: none; white-space: normal; widow=
s: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-colo=
r: rgb(255, 255, 255);" class=3D""><span style=3D"color: rgb(46, 46, 46); f=
ont-family: arial; font-size: inherit; font-style: normal; font-variant-cap=
s: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text=
-align: start; text-indent: 0px; text-transform: none; white-space: normal;=
widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; backgroun=
d-color: rgb(255, 255, 255); float: none; display: inline !important;" clas=
s=3D"">report.on_exception_in_o1(); } })</span><br style=3D"color: rgb(46, =
46, 46); font-family: arial; font-style: normal; font-variant-caps: normal;=
font-weight: normal; letter-spacing: normal; orphans: auto; text-align: st=
art; text-indent: 0px; text-transform: none; white-space: normal; widows: a=
uto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: r=
gb(255, 255, 255);" class=3D""><span style=3D"color: rgb(46, 46, 46); font-=
family: arial; font-size: inherit; font-style: normal; font-variant-caps: n=
ormal; font-weight: normal; letter-spacing: normal; orphans: auto; text-ali=
gn: start; text-indent: 0px; text-transform: none; white-space: normal; wid=
ows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-co=
lor: rgb(255, 255, 255); float: none; display: inline !important;" class=3D=
"">my_obj2 o2;</span><br style=3D"color: rgb(46, 46, 46); font-family: aria=
l; font-style: normal; font-variant-caps: normal; font-weight: normal; lett=
er-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; tex=
t-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -w=
ebkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);" class=
=3D""><span style=3D"color: rgb(46, 46, 46); font-family: arial; font-size:=
inherit; font-style: normal; font-variant-caps: normal; font-weight: norma=
l; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0=
px; text-transform: none; white-space: normal; widows: auto; word-spacing: =
0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); =
float: none; display: inline !important;" class=3D"">auto o2x =3D on_scope_=
exit([&]{ try{ o2.switch_off(); } catch(...) {<span class=3D"Apple-conv=
erted-space"> </span></span><br style=3D"color: rgb(46, 46, 46); font-=
family: arial; font-style: normal; font-variant-caps: normal; font-weight: =
normal; letter-spacing: normal; orphans: auto; text-align: start; text-inde=
nt: 0px; text-transform: none; white-space: normal; widows: auto; word-spac=
ing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 2=
55);" class=3D""><span style=3D"color: rgb(46, 46, 46); font-family: arial;=
font-size: inherit; font-style: normal; font-variant-caps: normal; font-we=
ight: normal; letter-spacing: normal; orphans: auto; text-align: start; tex=
t-indent: 0px; text-transform: none; white-space: normal; widows: auto; wor=
d-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, =
255, 255); float: none; display: inline !important;" class=3D"">report.on_e=
xception_in_o2(); } })</span><br style=3D"color: rgb(46, 46, 46); font-fami=
ly: arial; font-style: normal; font-variant-caps: normal; font-weight: norm=
al; letter-spacing: normal; orphans: auto; text-align: start; text-indent: =
0px; text-transform: none; white-space: normal; widows: auto; word-spacing:=
0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);=
" class=3D""><span style=3D"color: rgb(46, 46, 46); font-family: arial; fon=
t-size: inherit; font-style: normal; font-variant-caps: normal; font-weight=
: normal; letter-spacing: normal; orphans: auto; text-align: start; text-in=
dent: 0px; text-transform: none; white-space: normal; widows: auto; word-sp=
acing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255,=
255); float: none; display: inline !important;" class=3D"">...</span><br s=
tyle=3D"color: rgb(46, 46, 46); font-family: arial; font-style: normal; fon=
t-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphan=
s: auto; text-align: start; text-indent: 0px; text-transform: none; white-s=
pace: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0=
px; background-color: rgb(255, 255, 255);" class=3D""><span style=3D"color:=
rgb(46, 46, 46); font-family: arial; font-size: inherit; font-style: norma=
l; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; =
orphans: auto; text-align: start; text-indent: 0px; text-transform: none; w=
hite-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-wi=
dth: 0px; background-color: rgb(255, 255, 255); float: none; display: inlin=
e !important;" class=3D"">// call ops that can throw too</span><br style=3D=
"color: rgb(46, 46, 46); font-family: arial; font-style: normal; font-varia=
nt-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto=
; text-align: start; text-indent: 0px; text-transform: none; white-space: n=
ormal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; bac=
kground-color: rgb(255, 255, 255);" class=3D""><span style=3D"color: rgb(46=
, 46, 46); font-family: arial; font-size: inherit; font-style: normal; font=
-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans=
: auto; text-align: start; text-indent: 0px; text-transform: none; white-sp=
ace: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0p=
x; background-color: rgb(255, 255, 255); float: none; display: inline !impo=
rtant;" class=3D"">return;</span><br style=3D"color: rgb(46, 46, 46); font-=
family: arial; font-style: normal; font-variant-caps: normal; font-weight: =
normal; letter-spacing: normal; orphans: auto; text-align: start; text-inde=
nt: 0px; text-transform: none; white-space: normal; widows: auto; word-spac=
ing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 2=
55);" class=3D""><span style=3D"color: rgb(46, 46, 46); font-family: arial;=
font-size: inherit; font-style: normal; font-variant-caps: normal; font-we=
ight: normal; letter-spacing: normal; orphans: auto; text-align: start; tex=
t-indent: 0px; text-transform: none; white-space: normal; widows: auto; wor=
d-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, =
255, 255); float: none; display: inline !important;" class=3D"">}</span><br=
style=3D"color: rgb(46, 46, 46); font-family: arial; font-style: normal; f=
ont-variant-caps: normal; font-weight: normal; letter-spacing: normal; orph=
ans: auto; text-align: start; text-indent: 0px; text-transform: none; white=
-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width:=
0px; background-color: rgb(255, 255, 255);" class=3D""><span style=3D"colo=
r: rgb(46, 46, 46); font-family: arial; font-size: inherit; font-style: nor=
mal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal=
; orphans: auto; text-align: start; text-indent: 0px; text-transform: none;=
white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-=
width: 0px; background-color: rgb(255, 255, 255); float: none; display: inl=
ine !important;" class=3D"">catch(...)</span><br style=3D"color: rgb(46, 46=
, 46); font-family: arial; font-style: normal; font-variant-caps: normal; f=
ont-weight: normal; letter-spacing: normal; orphans: auto; text-align: star=
t; text-indent: 0px; text-transform: none; white-space: normal; widows: aut=
o; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb=
(255, 255, 255);" class=3D""><span style=3D"color: rgb(46, 46, 46); font-fa=
mily: arial; font-size: inherit; font-style: normal; font-variant-caps: nor=
mal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align=
: start; text-indent: 0px; text-transform: none; white-space: normal; widow=
s: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-colo=
r: rgb(255, 255, 255); float: none; display: inline !important;" class=3D""=
>{</span><br style=3D"color: rgb(46, 46, 46); font-family: arial; font-styl=
e: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: =
normal; orphans: auto; text-align: start; text-indent: 0px; text-transform:=
none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-s=
troke-width: 0px; background-color: rgb(255, 255, 255);" class=3D""><span s=
tyle=3D"color: rgb(46, 46, 46); font-family: arial; font-size: inherit; fon=
t-style: normal; font-variant-caps: normal; font-weight: normal; letter-spa=
cing: normal; orphans: auto; text-align: start; text-indent: 0px; text-tran=
sform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-=
text-stroke-width: 0px; background-color: rgb(255, 255, 255); float: none; =
display: inline !important;" class=3D"">report.on_exception();</span><br st=
yle=3D"color: rgb(46, 46, 46); font-family: arial; font-style: normal; font=
-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans=
: auto; text-align: start; text-indent: 0px; text-transform: none; white-sp=
ace: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0p=
x; background-color: rgb(255, 255, 255);" class=3D""><span style=3D"color: =
rgb(46, 46, 46); font-family: arial; font-size: inherit; font-style: normal=
; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; o=
rphans: auto; text-align: start; text-indent: 0px; text-transform: none; wh=
ite-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-wid=
th: 0px; background-color: rgb(255, 255, 255); float: none; display: inline=
!important;" class=3D"">}</span><br style=3D"color: rgb(46, 46, 46); font-=
family: arial; font-style: normal; font-variant-caps: normal; font-weight: =
normal; letter-spacing: normal; orphans: auto; text-align: start; text-inde=
nt: 0px; text-transform: none; white-space: normal; widows: auto; word-spac=
ing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 2=
55);" class=3D""><br style=3D"color: rgb(46, 46, 46); font-family: arial; f=
ont-style: normal; font-variant-caps: normal; font-weight: normal; letter-s=
pacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-tr=
ansform: none; white-space: normal; widows: auto; word-spacing: 0px; -webki=
t-text-stroke-width: 0px; background-color: rgb(255, 255, 255);" class=3D""=
><span style=3D"color: rgb(46, 46, 46); font-family: arial; font-size: inhe=
rit; font-style: normal; font-variant-caps: normal; font-weight: normal; le=
tter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; t=
ext-transform: none; white-space: normal; widows: auto; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); float=
: none; display: inline !important;" class=3D"">report.throw_combined_resul=
t();</span><br style=3D"color: rgb(46, 46, 46); font-family: arial; font-st=
yle: normal; font-variant-caps: normal; font-weight: normal; letter-spacing=
: normal; orphans: auto; text-align: start; text-indent: 0px; text-transfor=
m: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text=
-stroke-width: 0px; background-color: rgb(255, 255, 255);" class=3D""><span=
style=3D"color: rgb(46, 46, 46); font-family: arial; font-size: inherit; f=
ont-style: normal; font-variant-caps: normal; font-weight: normal; letter-s=
pacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-tr=
ansform: none; white-space: normal; widows: auto; word-spacing: 0px; -webki=
t-text-stroke-width: 0px; background-color: rgb(255, 255, 255); float: none=
; display: inline !important;" class=3D"">}<span class=3D"Apple-converted-s=
pace"> </span></span><br style=3D"color: rgb(46, 46, 46); font-family:=
arial; font-style: normal; font-variant-caps: normal; font-weight: normal;=
letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px=
; text-transform: none; white-space: normal; widows: auto; word-spacing: 0p=
x; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);" c=
lass=3D""><br style=3D"color: rgb(46, 46, 46); font-family: arial; font-sty=
le: normal; font-variant-caps: normal; font-weight: normal; letter-spacing:=
normal; orphans: auto; text-align: start; text-indent: 0px; text-transform=
: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-=
stroke-width: 0px; background-color: rgb(255, 255, 255);" class=3D""><span =
style=3D"color: rgb(46, 46, 46); font-family: arial; font-size: inherit; fo=
nt-style: normal; font-variant-caps: normal; font-weight: normal; letter-sp=
acing: normal; orphans: auto; text-align: start; text-indent: 0px; text-tra=
nsform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit=
-text-stroke-width: 0px; background-color: rgb(255, 255, 255); float: none;=
display: inline !important;" class=3D"">> (snipped=E2=80=A6)</span><br =
style=3D"color: rgb(46, 46, 46); font-family: arial; font-style: normal; fo=
nt-variant-caps: normal; font-weight: normal; letter-spacing: normal; orpha=
ns: auto; text-align: start; text-indent: 0px; text-transform: none; white-=
space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: =
0px; background-color: rgb(255, 255, 255);" class=3D""><span style=3D"color=
: rgb(46, 46, 46); font-family: arial; font-size: inherit; font-style: norm=
al; font-variant-caps: normal; font-weight: normal; letter-spacing: normal;=
orphans: auto; text-align: start; text-indent: 0px; text-transform: none; =
white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-w=
idth: 0px; background-color: rgb(255, 255, 255); float: none; display: inli=
ne !important;" class=3D""> </span><br style=3D"color: rgb(46, 46, 46)=
; font-family: arial; font-style: normal; font-variant-caps: normal; font-w=
eight: normal; letter-spacing: normal; orphans: auto; text-align: start; te=
xt-indent: 0px; text-transform: none; white-space: normal; widows: auto; wo=
rd-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255,=
255, 255);" class=3D""></div></blockquote><div><blockquote type=3D"cite" c=
lass=3D"">=E2=80=A6</blockquote></div><div><br class=3D""></div><div> =
I=E2=80=99m not entirely sure if the person who originally su=
ggested using an out-of-band error-reporting mechanism intended for it to i=
nteract with whatever exceptions might exist within the state of a program =
such as one implementing such logic in quite the way you describe here, but=
the general consensus here seems to persist: complicating the C++ an=
d/or its standard library just to allow end users such as yourself to misha=
ndle the language=E2=80=99s exception propagation and delivery mechanisms i=
n the manner you=E2=80=99ve proposed and deal with the remote edge case you=
=E2=80=99ve brought up would both lack benefits for a near-unanimous majori=
ty of C++ programmers and go against existing practice. For these rea=
sons, among others which I have not summarized here, it=E2=80=99s no <i cla=
ss=3D"">wonder</i> you=E2=80=99ve received the reaction you have in this th=
read. Beyond this, I defer to everyone else here for further explanat=
ion of this to you, as I am bowing out of this discussion since I would pre=
fer not to get as embroiled in it as its other participants have, partly si=
nce I don=E2=80=99t feel I can contribute anything more to the discussion i=
n addition to what I=E2=80=99ve already said except by bumbling, babbling r=
epetition of unstudied possibilities. </div><div><br class=3D""></div=
><blockquote type=3D"cite" class=3D"">=E2=80=A6</blockquote><blockquote typ=
e=3D"cite" class=3D""><br class=3D""></blockquote><blockquote type=3D"cite"=
class=3D""><div class=3D""><span style=3D"color: rgb(46, 46, 46); font-fam=
ily: arial; font-size: inherit; font-style: normal; font-variant-caps: norm=
al; font-weight: normal; letter-spacing: normal; orphans: auto; text-align:=
start; text-indent: 0px; text-transform: none; white-space: normal; widows=
: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color=
: rgb(255, 255, 255); float: none; display: inline !important;" class=3D"">=
'Destructing move' isn't going to happen in C++, I think. As long as<span c=
lass=3D"Apple-converted-space"> </span></span><span style=3D"color: rg=
b(46, 46, 46); font-family: arial; font-size: inherit; font-style: normal; =
font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orp=
hans: auto; text-align: start; text-indent: 0px; text-transform: none; whit=
e-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width=
: 0px; background-color: rgb(255, 255, 255); float: none; display: inline !=
important;" class=3D"">'object' means 'bunch of bits and memory range they =
occupy'... and it<span class=3D"Apple-converted-space"> </span></span>=
<span style=3D"color: rgb(46, 46, 46); font-family: arial; font-size: inher=
it; font-style: normal; font-variant-caps: normal; font-weight: normal; let=
ter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; te=
xt-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -=
webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); float:=
none; display: inline !important;" class=3D"">unlikely to ever change.</sp=
an><br style=3D"color: rgb(46, 46, 46); font-family: arial; font-style: nor=
mal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal=
; orphans: auto; text-align: start; text-indent: 0px; text-transform: none;=
white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-=
width: 0px; background-color: rgb(255, 255, 255);" class=3D""></div></block=
quote></div><br class=3D""><div class=3D""> On the contr=
ary, there have been <a href=3D"https://www.google.com/search?client=
=3Dsafari&rls=3Den&q=3DC+++destructive+move&ie=3DUTF-8&oe=
=3DUTF-8" class=3D"">several proposals and involved discussions</a> re=
volving around the conceit of a(n) (opt-in?) destructive version of move se=
mantics, though none of them have gotten very far, as far as I=E2=80=99m aw=
are. It=E2=80=99s yet another one of those difficult problems that re=
sist solving, but, from what I can tell, important enough of one to receive=
temporal considerations within WG21 due to the compiler and program optimi=
zations it would enable. </div><div class=3D""><br class=3D""></div><=
div class=3D"">
<div style=3D"color: rgb(0, 0, 0); letter-spacing: normal; orphans: auto; t=
ext-align: start; text-indent: 0px; text-transform: none; white-space: norm=
al; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; word-w=
rap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-=
space;" class=3D""><div style=3D"color: rgb(0, 0, 0); letter-spacing: norma=
l; orphans: auto; text-align: start; text-indent: 0px; text-transform: none=
; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke=
-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-=
break: after-white-space;" class=3D""><div style=3D"color: rgb(0, 0, 0); le=
tter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; t=
ext-transform: none; white-space: normal; widows: auto; word-spacing: 0px; =
-webkit-text-stroke-width: 0px; word-wrap: break-word; -webkit-nbsp-mode: s=
pace; -webkit-line-break: after-white-space;" class=3D""><div class=3D"">Ho=
pefully making his final disappearing act go smoothly, </div><div clas=
s=3D""> Bryce Glover</div><div class=3D""> =
<a href=3D"mailto:RandomDSdevel@gmail.com" class=3D"">RandomDSdevel@g=
mail.com</a></div></div></div></div></div></body></html>
<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/00A0825A-C7FA-4528-83AD-99F60BADCA38%=
40gmail.com?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/00A0825A-C7FA-4528-83AD-99F60BADCA38%=
40gmail.com</a>.<br />
--Apple-Mail=_101A5CC5-38F7-418E-B566-1D24EDD82BFC--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Thu, 31 Aug 2017 16:52:19 -0700
Raw View
On Thursday, 31 August 2017 16:12:00 PDT crusader.mike@gmail.com wrote:
> There certainly is some impact (at least for MSVC, try removing
> nothrow from nonthrowing()):
> https://godbolt.org/g/nQDnxt
>
> notice how code changes (you forgot to specify /EHsc for MSVC)
So it does, I forgot exceptions are disabled by default there.
The difference is the stack alignment and that npad, which is just a NOP
instruction. The impact is negligible.
What's more, this doesn't prove that the changes are required by the ABI. It
could be just the optimiser failing. A second opinion (clang -target x86_64-
windows) is required. It shows saving -2 at a point in the stack, so I assume
that is required by the ABI.
> At the very least -- specifying nothrow on a function (that you know won't
> throw, but compiler can't prove that) will cause some overhead (even if it
> is in those tables that never get loaded and simply make your executable
> slightly bigger). At worst -- reduces optimizations available to compiler
> when such function gets inlined.
Yes, current EH ABI will generate those exception tables, but that's not a
requirement for all of them. It just happens that they were designed 10 or
more years ago and optimised for the case. If they were redesigned today, it's
entirely possible the choice would be different.
Also, at least for the IA-64 ABI, you may have unwind tables even if you don't
use exceptions or C++. See https://codereview.qt-project.org/182894 for
numbers showing executable size improvement even on top of -fno-exceptions.
But I really don't see how it could reduce optimisations available.
> TBH, I don't want to discuss this in this thread -- it is already diluted
> with too many details and detractions.
Ok.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/40751268.ohxfr39Msy%40tjmaciei-mobl1.
.
Author: crusader.mike@gmail.com
Date: Thu, 31 Aug 2017 17:41:37 -0700 (PDT)
Raw View
------=_Part_2036_1705408488.1504226497287
Content-Type: multipart/alternative;
boundary="----=_Part_2037_953488655.1504226497289"
------=_Part_2037_953488655.1504226497289
Content-Type: text/plain; charset="UTF-8"
On Thursday, August 31, 2017 at 6:11:24 PM UTC-5, Nicol Bolas wrote:
>
> You just want the language to create an OOB error reporting mechanism
> attached to the exception system.
>
Effectively yes, but I object calling this "OOB error reporting mechanism".
> "Trailing exceptions" have multiple different types, some of which are the
>>> errors you're looking for and some of which are not. This is exactly
>>> analogous to the "multiple 'errno' variables". And your trailing exceptions
>>> must *all* be polled in order to find which ones you're looking for.
>>> You have to sift through the entire sequence of trailing exceptions,
>>> casting each one in turn to find the one you're looking for.
>>>
>>
>> With one significant difference -- I don't need to poll for every
>> possible error here. I'll end up iterating over errors that actually
>> happened.
>>
>
> I don't know what you call this:
>
> for(auto p: std::trailing_exceptions(x))
> process_exception(p, false);
>
> But that looks suspiciously like "polling for every possible error here"
> to me. It most certainly "iterating over errors that actually happened". So
> I'm having a hard time seeing this as a "significant difference".
>
as stated before -- instead of iterating over every possible source of
error, I'll iterate over all error that actually happened. User will have
an option to specify carrying source identifying information on the
exception.
> Imagine a case where you drive multiple devices and each one has it's own
>> library (with some sort of 'errno' mechanism). In case of failure:
>> - I need to know exactly which device could've been used by a function
>> that failed
>> - poll *all* of them to figure out their current state
>>
>
>> or
>>
>> - device an out-of-bound reporting mechanism that will be used in related
>> places (where exceptions were swallowed) and accumulate related info
>> somewhere
>>
>
> OK, so we're in a world where each device comes from a different system.
> This means that, in the "Trailing exceptions" version, each device also
> would throw its own exception type that's independent of another.
>
> This means that your receiving code must do this:
>
> for(auto p: std::trailing_exceptions(x))
> {
> if(auto t1 = exception_cast<T1*>(p); t1)
> {
> }
> else if(auto t2 = exception_cast<T2&>(p); t2)
> {
> }
> else if(auto t3 = exception_cast<T3&>(p); t3)
> {
> }
> ...
> }
>
> This looks suspiciously like the "manual virtual call" anti-pattern, where
> you `dynamic_cast` some object to various possibilities just to call a
> function. It's something that you should never do, and we should not make
> language features that effectively requires this anti-pattern.
>
It is a typical problem with exceptions -- all these catch blocks are
effectively "exception_cast"s. My point -- I simply inherit this from
existing facilities, not adding it to the language.
Plus, again -- user will have certain flexibility here. For example he can
introduce base class shared by all exception types that carries device-id
-- in this case processing function can be considerably simpler (depending
on what user wants to do)/
> I see no advantage to that code, compared to this:
>
> if(system1::has_error())
> {
> }
> if(system2::has_error())
> {
> }
> if(system3::has_error())
> {
> }
> ...
>
Same as before -- no need to know how many systems given function *might
have* touched. No need to poll each one of them.
> The main distinction between them is that out-of-band errors for
>>> different systems explicitly have different "channels". By contrast,
>>> trailing exceptions all use the same "channel". But this is actually an
>>> *advantage*. Just look at your processing code. All that rethrowing
>>> nonsense just to check the type. Even if you turned it into a simpler
>>> `exception_cast` or whatever, it's still a lot of processing just to fish
>>> out the errors you're actually interested in.
>>>
>>
>> Yes, processing logic (with rethrowing) is not ideal -- it is simply
>> inherited problem from std::current_exception and the way
>> std::exception_ptr machinery is defined. It is not an inherent failure of
>> 'throwing from dtor' idea.
>>
>
> Like I said, even if you turn the rethrowing bit into some
> `exception_cast`, you're still iterating over every exception that has been
> thrown.
>
Of course, you'll probably want to inspect each error produced by given
function call.
> The handling for out-of-band reporting would look like this:
>>>
>>> catch(actual_exception &e)
>>> {
>>> //Handle actual exception
>>>
>>> //Handle device failures.
>>> if(did_devices_fail_to_stop())
>>> {
>>> for(auto &device_err : get_device_failures())
>>> {
>>> //Deal with failure for this device.
>>> }
>>> }
>>> }
>>>
>>> This is *far* more readable, understandable, and maintainable than the
>>> "trailing exception" version. Your idea does not lead to "nice, compact
>>> solutions".
>>>
>>
>> It does in cases when error handling happens in relatively few places --
>> no need in out-of-band status reporting (it gets generated by language for
>> you).
>>
>
> Language mechanisms should lead to *better looking* code, not worse
> looking.
>
Function that throws these exceptions becomes better looking without manual
OOB reporting mechanism.
> Your exception clash-based code looks like crap. Indeed, it is exactly why
> we don't let people do `catch(...)`, then try to repeatedly cast it to the
> type they're interested in. We instead let them state the type up-front, so
> that their code is easy to read and understand.
>
Even assuming this is the case (it is certainly possible to design it in
such way that it is less of an eyesore) -- at least I have to do this crap
at the point of processing error, not at the every site that might produce
these errors.
> That's what a *good* language feature looks like.
>
> So even if this idea were logically coherent with the meaning of
>>> exceptions, even if we were to find a way to solve the problems it creates,
>>> I submit that it would lead to the writing of crap code.
>>>
>>
>> Users will always find a way how to write crap code :-)
>>
>
> Good features can be used poorly, but they can also be used *well*. Thus
> far, every example you've shown leads to code that looks worse than what
> you could get with a specialized, user-defined mechanism.
>
--
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/dcdf2c2d-00b9-4ba0-90bd-645adefaaabc%40isocpp.org.
------=_Part_2037_953488655.1504226497289
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, August 31, 2017 at 6:11:24 PM UTC-5, Nicol Bo=
las 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">You=
just want the language to create an OOB error reporting mechanism attached=
to the exception system.<br></div></blockquote><div><br></div><div>Effecti=
vely yes, but I object calling this "OOB error reporting mechanism&quo=
t;.</div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" =
style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-l=
eft: 1ex;"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"marg=
in:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div di=
r=3D"ltr"><div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-l=
eft:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><di=
v>"Trailing exceptions" have multiple different types, some of wh=
ich are the errors you're looking for and some of which are not. This i=
s exactly analogous to the "multiple 'errno' variables". =
And your trailing exceptions must <i>all</i> be polled in order to find whi=
ch ones you're looking for. You have to sift through the entire sequenc=
e of trailing exceptions, casting each one in turn to find the one you'=
re looking for.</div></div></blockquote><div><br></div><div>With one signif=
icant difference -- I don't need to poll for every possible error here.=
I'll end up iterating over errors that actually happened. </div></div>=
</div></blockquote><div><br>I don't know what you call this:<br><br><di=
v style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);=
border-style:solid;border-width:1px"><code><div><span style=3D"color:#008">=
for</span><span style=3D"color:#660">(</span><span style=3D"color:#008">aut=
o</span><span style=3D"color:#000"> p</span><span style=3D"color:#660">:</s=
pan><span style=3D"color:#000"> std</span><span style=3D"color:#660">::</sp=
an><span style=3D"color:#000">trailing_exceptions</span><span style=3D"colo=
r:#660">(</span><span style=3D"color:#000">x</span><span style=3D"color:#66=
0">))</span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 process_exception<=
/span><span style=3D"color:#660">(</span><span style=3D"color:#000">p</span=
><span style=3D"color:#660">,</span><span style=3D"color:#000"> </span><spa=
n style=3D"color:#008">false</span><span style=3D"color:#660">);</span></di=
v></code></div><br>But that looks suspiciously like "polling for every=
possible error here" to me. It most certainly "iterating over er=
rors that actually happened". So I'm having a hard time seeing thi=
s as a "significant difference".<br></div></div></blockquote><div=
><br></div><div>as stated before -- instead of iterating over every possibl=
e source of error, I'll iterate over all error that actually happened. =
User will have an option to specify carrying source identifying information=
on the exception.</div><div><br></div><div>=C2=A0<br></div><blockquote cla=
ss=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_q=
uote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;paddin=
g-left:1ex"><div dir=3D"ltr"><div><div>Imagine a case where you drive multi=
ple devices and each one has it's own library (with some sort of 'e=
rrno' mechanism). In case of failure:</div><div>- I need to know exactl=
y which device could've been used by a function that failed</div><div>-=
poll *all* of them to figure out their current state</div></div></div></bl=
ockquote><div></div><blockquote class=3D"gmail_quote" style=3D"margin:0;mar=
gin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr=
"><div><div><br></div><div>or</div><div><br></div><div>- device an out-of-b=
ound reporting mechanism that will be used in related places (where excepti=
ons were swallowed) and accumulate related info somewhere</div></div></div>=
</blockquote><div><br>OK, so we're in a world where each device comes f=
rom a different system. This means that, in the "Trailing exceptions&q=
uot; version, each device also would throw its own exception type that'=
s independent of another.<br><br>This means that your receiving code must d=
o this:<br><br><div style=3D"background-color:rgb(250,250,250);border-color=
:rgb(187,187,187);border-style:solid;border-width:1px"><code><div><span sty=
le=3D"color:#008">for</span><span style=3D"color:#660">(</span><span style=
=3D"color:#008">auto</span><span style=3D"color:#000"> p</span><span style=
=3D"color:#660">:</span><span style=3D"color:#000"> std</span><span style=
=3D"color:#660">::</span><span style=3D"color:#000">trailing_exceptions</sp=
an><span style=3D"color:#660">(</span><span style=3D"color:#000">x</span><s=
pan style=3D"color:#660">))</span><span style=3D"color:#000"><br></span><sp=
an style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 </spa=
n><span style=3D"color:#008">if</span><span style=3D"color:#660">(</span><s=
pan style=3D"color:#008">auto</span><span style=3D"color:#000"> t1 </span><=
span style=3D"color:#660">=3D</span><span style=3D"color:#000"> exception_c=
ast</span><span style=3D"color:#660"><</span><span style=3D"color:#000">=
T1</span><span style=3D"color:#660">*>(</span><span style=3D"color:#000"=
>p</span><span style=3D"color:#660">);</span><span style=3D"color:#000"> t1=
</span><span style=3D"color:#660">)</span><span style=3D"color:#000"><br>=
=C2=A0 </span><span style=3D"color:#660">{</span><span style=3D"color:#000"=
><br>=C2=A0 </span><span style=3D"color:#660">}</span><span style=3D"color:=
#000"><br>=C2=A0 </span><span style=3D"color:#008">else</span><span style=
=3D"color:#000"> </span><span style=3D"color:#008">if</span><span style=3D"=
color:#660">(</span><span style=3D"color:#008">auto</span><span style=3D"co=
lor:#000"> t2 </span><span style=3D"color:#660">=3D</span><span style=3D"co=
lor:#000"> exception_cast</span><span style=3D"color:#660"><</span><span=
style=3D"color:#000">T2</span><span style=3D"color:#660">&>(</span>=
<span style=3D"color:#000">p</span><span style=3D"color:#660">);</span><spa=
n style=3D"color:#000"> t2</span><span style=3D"color:#660">)</span><span s=
tyle=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#660">{</span><s=
pan style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#660">}</sp=
an><span style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#008">=
else</span><span style=3D"color:#000"> </span><span style=3D"color:#008">if=
</span><span style=3D"color:#660">(</span><span style=3D"color:#008">auto</=
span><span style=3D"color:#000"> t3 </span><span style=3D"color:#660">=3D</=
span><span style=3D"color:#000"> exception_cast</span><span style=3D"color:=
#660"><</span><span style=3D"color:#000">T3</span><span style=3D"color:#=
660">&>(</span><span style=3D"color:#000">p</span><span style=3D"col=
or:#660">);</span><span style=3D"color:#000"> t3</span><span style=3D"color=
:#660">)</span><span style=3D"color:#000"><br>=C2=A0 </span><span style=3D"=
color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 </span><span styl=
e=3D"color:#660">}</span><span style=3D"color:#000"><br>=C2=A0 </span><span=
style=3D"color:#660">...</span><span style=3D"color:#000"><br></span><span=
style=3D"color:#660">}</span></div></code></div><br>This looks suspiciousl=
y like the "manual virtual call" anti-pattern, where you `dynamic=
_cast` some object to various possibilities just to call a function. It'=
;s something that you should never do, and we should not make language feat=
ures that effectively requires this anti-pattern.<br></div></div></blockquo=
te><div><br></div><div>It is a typical problem with exceptions -- all these=
catch blocks are effectively "exception_cast"s. My point -- I si=
mply inherit this from existing facilities, not adding it to the language.<=
/div><div><br></div><div>Plus, again -- user will have certain flexibility =
here. For example he can introduce base class shared by all exception types=
that carries device-id -- in this case processing function can be consider=
ably simpler (depending on what user wants to do)/</div><div><br></div><div=
>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"ltr">=
<div>I see no advantage to that code, compared to this:<br><br><div style=
=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);border-=
style:solid;border-width:1px"><code><div><span style=3D"color:#008">if</spa=
n><span style=3D"color:#660">(</span><span style=3D"color:#000">system1</sp=
an><span style=3D"color:#660">::</span><span style=3D"color:#000">has_error=
</span><span style=3D"color:#660">())</span><span style=3D"color:#000"><br>=
</span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br></=
span><span style=3D"color:#660">}</span><span style=3D"color:#000"><br></sp=
an><span style=3D"color:#008">if</span><span style=3D"color:#660">(</span><=
span style=3D"color:#000">system2</span><span style=3D"color:#660">::</span=
><span style=3D"color:#000">has_error</span><span style=3D"color:#660">())<=
/span><span style=3D"color:#000"><br></span><span style=3D"color:#660">{</s=
pan><span style=3D"color:#000"><br></span><span style=3D"color:#660">}</spa=
n><span style=3D"color:#000"><br></span><span style=3D"color:#008">if</span=
><span style=3D"color:#660">(</span><span style=3D"color:#000">system3</spa=
n><span style=3D"color:#660">::</span><span style=3D"color:#000">has_error<=
/span><span style=3D"color:#660">())</span><span style=3D"color:#000"><br><=
/span><span style=3D"color:#660">{</span><span style=3D"color:#000"><br></s=
pan><span style=3D"color:#660">}</span><span style=3D"color:#000"><br></spa=
n><span style=3D"color:#660">...</span></div></code></div></div></div></blo=
ckquote><div><br></div><div>Same as before -- no need to know how many syst=
ems given function *might have* touched. No need to poll each one of them.<=
/div><div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" styl=
e=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left:=
1ex;"><div dir=3D"ltr"><div></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"><div><div></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"><div>=C2=A0The main distinction between them is that out-=
of-band errors for different systems explicitly have different "channe=
ls". By contrast, trailing exceptions all use the same "channel&q=
uot;. But this is actually an <i>advantage</i>. Just look at your processin=
g code. All that rethrowing nonsense just to check the type. Even if you tu=
rned it into a simpler `exception_cast` or whatever, it's still a lot o=
f processing just to fish out the errors you're actually interested in.=
</div></div></blockquote><div><br></div><div>Yes, processing logic (with re=
throwing) is not ideal -- it is simply inherited problem from std::current_=
exception and the way std::exception_ptr machinery is defined. It is not an=
inherent failure of 'throwing from dtor' idea.</div></div></div></=
blockquote><div><br>Like I said, even if you turn the rethrowing bit into s=
ome `exception_cast`, you're still iterating over every exception that =
has been thrown.<br></div></div></blockquote><div><br></div><div>Of course,=
you'll probably want to inspect each error produced by given function =
call.</div><div><br></div><div>=C2=A0</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"ma=
rgin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div =
dir=3D"ltr"><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"><=
div>The handling for out-of-band reporting would look like this:<br><br><di=
v style=3D"background-color:rgb(250,250,250);border-color:rgb(187,187,187);=
border-style:solid;border-width:1px"><code><div><span style=3D"color:#008">=
catch</span><span style=3D"color:#660">(</span><span style=3D"color:#000">a=
ctual_exception </span><span style=3D"color:#660">&</span><span style=
=3D"color:#000">e</span><span style=3D"color:#660">)</span><span style=3D"c=
olor:#000"><br></span><span style=3D"color:#660">{</span><span style=3D"col=
or:#000"><br>=C2=A0 </span><span style=3D"color:#800">//Handle actual excep=
tion</span><span style=3D"color:#000"><br><br>=C2=A0 </span><span style=3D"=
color:#800">//Handle device failures.</span><span style=3D"color:#000"><br>=
=C2=A0 </span><span style=3D"color:#008">if</span><span style=3D"color:#660=
">(</span><span style=3D"color:#000">did_devices_fail_to_stop</span><span s=
tyle=3D"color:#660">())</span><span style=3D"color:#000"><br>=C2=A0 </span>=
<span style=3D"color:#660">{</span><span style=3D"color:#000"><br>=C2=A0 =
=C2=A0 </span><span style=3D"color:#008">for</span><span style=3D"color:#66=
0">(</span><span style=3D"color:#008">auto</span><span style=3D"color:#000"=
> </span><span style=3D"color:#660">&</span><span style=3D"color:#000">=
device_err </span><span style=3D"color:#660">:</span><span style=3D"color:#=
000"> get_device_failures</span><span style=3D"color:#660">())</span><span =
style=3D"color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#660">{<=
/span><span style=3D"color:#000"><br>=C2=A0 =C2=A0 =C2=A0 </span><span styl=
e=3D"color:#800">//Deal with failure for this device.</span><span style=3D"=
color:#000"><br>=C2=A0 =C2=A0 </span><span style=3D"color:#660">}</span><sp=
an style=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#660">}</spa=
n><span style=3D"color:#000"><br></span><span style=3D"color:#660">}</span>=
</div></code></div><br>This is <i>far</i> more readable, understandable, an=
d maintainable than the "trailing exception" version. Your idea d=
oes not lead to "nice, compact solutions".</div></div></blockquot=
e><div><br></div><div>It does in cases when error handling happens in relat=
ively few places -- no need in out-of-band status reporting (it gets genera=
ted by language for you).</div></div></div></blockquote><div><br>Language m=
echanisms should lead to <i>better looking</i> code, not worse looking.</di=
v></div></blockquote><div><br></div><div>Function that throws these excepti=
ons becomes better looking without manual OOB reporting mechanism.</div><di=
v><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"mar=
gin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><=
div dir=3D"ltr"><div> Your exception clash-based code looks like crap. Inde=
ed, it is exactly why we don't let people do `catch(...)`, then try to =
repeatedly cast it to the type they're interested in. We instead let th=
em state the type up-front, so that their code is easy to read and understa=
nd.<br></div></div></blockquote><div><br></div><div>Even assuming this is t=
he case (it is certainly possible to design it in such way that it is less =
of an eyesore) -- at least I have to do this crap at the point of processin=
g error, not at the every site that might produce these errors.=C2=A0</div>=
<div><br></div><div>=C2=A0</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"><div>That's what a <i>good</i> language feature look=
s like.<br><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0;ma=
rgin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"lt=
r"><div><div></div><blockquote class=3D"gmail_quote" style=3D"margin:0;marg=
in-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"=
><div> So even if this idea were logically coherent with the meaning of exc=
eptions, even if we were to find a way to solve the problems it creates, I =
submit that it would lead to the writing of crap code.<br></div></div></blo=
ckquote><div>=C2=A0</div></div><div>Users will always find a way how to wri=
te crap code :-)</div></div></blockquote><div><br>Good features can be used=
poorly, but they can also be used <i>well</i>. Thus far, every example you=
've shown leads to code that looks worse than what you could get with a=
specialized, user-defined mechanism.<br></div></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/dcdf2c2d-00b9-4ba0-90bd-645adefaaabc%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/dcdf2c2d-00b9-4ba0-90bd-645adefaaabc=
%40isocpp.org</a>.<br />
------=_Part_2037_953488655.1504226497289--
------=_Part_2036_1705408488.1504226497287--
.
Author: crusader.mike@gmail.com
Date: Thu, 31 Aug 2017 18:05:17 -0700 (PDT)
Raw View
------=_Part_2216_58483889.1504227917493
Content-Type: multipart/alternative;
boundary="----=_Part_2217_1875370918.1504227917493"
------=_Part_2217_1875370918.1504227917493
Content-Type: text/plain; charset="UTF-8"
On Thursday, August 31, 2017 at 6:52:24 PM UTC-5, Thiago Macieira wrote:
>
> On Thursday, 31 August 2017 16:12:00 PDT crusad...@gmail.com <javascript:>
> wrote:
> > There certainly is some impact (at least for MSVC, try removing
> > nothrow from nonthrowing()):
> > https://godbolt.org/g/nQDnxt
> >
> > notice how code changes (you forgot to specify /EHsc for MSVC)
>
> So it does, I forgot exceptions are disabled by default there.
>
> The difference is the stack alignment and that npad, which is just a NOP
> instruction. The impact is negligible.
>
Not sure about negligibility... In this case <https://godbolt.org/g/ggPGPJ>
we end up with 24 bytes of code vs 5 bytes. It is very likely to have
different performance.
> What's more, this doesn't prove that the changes are required by the ABI.
> It
> could be just the optimiser failing.
True. But even if it is the case -- for end user it doesn't matter(until it
is fixed). That is why in my code almost every inline no-throw function
looks like this:
void foo() // noexcept (with explanation why, where needed)
{
....
}
:-)
> A second opinion (clang -target x86_64-
> windows) is required. It shows saving -2 at a point in the stack, so I
> assume
> that is required by the ABI.
>
> > At the very least -- specifying nothrow on a function (that you know
> won't
> > throw, but compiler can't prove that) will cause some overhead (even if
> it
> > is in those tables that never get loaded and simply make your executable
> > slightly bigger). At worst -- reduces optimizations available to
> compiler
> > when such function gets inlined.
>
> Yes, current EH ABI will generate those exception tables, but that's not a
> requirement for all of them. It just happens that they were designed 10 or
> more years ago and optimised for the case. If they were redesigned today,
> it's
> entirely possible the choice would be different.
>
> Also, at least for the IA-64 ABI, you may have unwind tables even if you
> don't
> use exceptions or C++. See https://codereview.qt-project.org/182894 for
> numbers showing executable size improvement even on top of
> -fno-exceptions.
>
> But I really don't see how it could reduce optimisations available.
I could be wrong here. I don't have a solid answer, just a hunch.
> > TBH, I don't want to discuss this in this thread -- it is already
> diluted
> > with too many details and detractions.
>
> Ok.
>
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
>
>
--
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/29176443-9258-4495-a7b5-fe18feb4cbb7%40isocpp.org.
------=_Part_2217_1875370918.1504227917493
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Thursday, August 31, 2017 at 6:52:24 PM UTC-5, =
Thiago Macieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Thurs=
day, 31 August 2017 16:12:00 PDT <a href=3D"javascript:" target=3D"_blank" =
gdf-obfuscated-mailto=3D"8lbyyavfAQAJ" rel=3D"nofollow" onmousedown=3D"this=
..href=3D'javascript:';return true;" onclick=3D"this.href=3D'jav=
ascript:';return true;">crusad...@gmail.com</a> wrote:
<br>> There certainly is some impact (at least for MSVC, try removing
<br>> nothrow from nonthrowing()):
<br>> <a href=3D"https://godbolt.org/g/nQDnxt" target=3D"_blank" rel=3D"=
nofollow" onmousedown=3D"this.href=3D'https://www.google.com/url?q\x3dh=
ttps%3A%2F%2Fgodbolt.org%2Fg%2FnQDnxt\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQ=
jCNG_nlxuEQ9KKUWNv5rlI8sjr6l4bg';return true;" onclick=3D"this.href=3D&=
#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgodbolt.org%2Fg%2FnQDnxt\=
x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNG_nlxuEQ9KKUWNv5rlI8sjr6l4bg';r=
eturn true;">https://godbolt.org/g/nQDnxt</a>
<br>>
<br>> notice how code changes (you forgot to specify /EHsc for MSVC)
<br>
<br>So it does, I forgot exceptions are disabled by default there.
<br>
<br>The difference is the stack alignment and that npad, which is just a NO=
P=20
<br>instruction. The impact is negligible.
<br></blockquote><div><br></div><div>Not sure about negligibility... In <a =
href=3D"https://godbolt.org/g/ggPGPJ">this case</a> we end up with 24 bytes=
of code vs 5 bytes. It is very likely to have different performance.</div>=
<div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"=
margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;=
">What's more, this doesn't prove that the changes are required by =
the ABI. It=20
<br>could be just the optimiser failing. </blockquote><div><br></div><div>T=
rue. But even if it is the case -- for end user it doesn't matter(until=
it is fixed). That is why in my code almost every inline=C2=A0no-throw fun=
ction looks like this:</div><div><br></div><div>void foo() // noexcept (wit=
h explanation why, where needed)</div><div>{</div><div>...</div><div>}</div=
><div><br></div><div>:-)</div><div><br></div><div>=C2=A0</div><blockquote c=
lass=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px=
#ccc solid;padding-left: 1ex;">A second opinion (clang -target x86_64-
<br>windows) is required. It shows saving -2 at a point in the stack, so I =
assume=20
<br>that is required by the ABI.
<br>
<br>> At the very least -- specifying nothrow on a function (that you kn=
ow won't
<br>> throw, but compiler can't prove that) will cause some overhead=
(even if it
<br>> is in those tables that never get loaded and simply make your exec=
utable
<br>> slightly bigger). At worst -- reduces optimizations available to c=
ompiler
<br>> when such function gets inlined.
<br>
<br>Yes, current EH ABI will generate those exception tables, but that'=
s not a=20
<br>requirement for all of them. It just happens that they were designed 10=
or=20
<br>more years ago and optimised for the case. If they were redesigned toda=
y, it's=20
<br>entirely possible the choice would be different.
<br>
<br>Also, at least for the IA-64 ABI, you may have unwind tables even if yo=
u don't=20
<br>use exceptions or C++. See <a href=3D"https://codereview.qt-project.org=
/182894" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'=
;https://www.google.com/url?q\x3dhttps%3A%2F%2Fcodereview.qt-project.org%2F=
182894\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNED9G8UTKAhdEYXJvD1iEp395gWbQ=
';return true;" onclick=3D"this.href=3D'https://www.google.com/url?=
q\x3dhttps%3A%2F%2Fcodereview.qt-project.org%2F182894\x26sa\x3dD\x26sntz\x3=
d1\x26usg\x3dAFQjCNED9G8UTKAhdEYXJvD1iEp395gWbQ';return true;">https://=
codereview.qt-project.<wbr>org/182894</a> for=20
<br>numbers showing executable size improvement even on top of -fno-excepti=
ons.
<br>
<br>But I really don't see how it could reduce optimisations available.=
=C2=A0</blockquote><div><br></div><div>I could be wrong here. I don't h=
ave a solid answer, just a hunch.</div><div><br></div><div>=C2=A0</div><blo=
ckquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-=
left: 1px #ccc solid;padding-left: 1ex;">> TBH, I don't want to disc=
uss this in this thread -- it is already diluted
<br>> with too many details and detractions.
<br>
<br>Ok.
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a href=3D"http://macieira.info" target=
=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.goo=
gle.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x3dD\x26sntz\x3d1\x26usg\=
x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.hr=
ef=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x=
3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return t=
rue;">macieira.info</a> - thiago (AT) <a href=3D"http://kde.org" target=3D"=
_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.google.=
com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNH=
GRJdo5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'=
http://www.google.com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1=
\x26usg\x3dAFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;">kde.org</a=
>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>
<br></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/29176443-9258-4495-a7b5-fe18feb4cbb7%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/29176443-9258-4495-a7b5-fe18feb4cbb7=
%40isocpp.org</a>.<br />
------=_Part_2217_1875370918.1504227917493--
------=_Part_2216_58483889.1504227917493--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Thu, 31 Aug 2017 19:19:22 -0700
Raw View
On Thursday, 31 August 2017 18:05:17 PDT crusader.mike@gmail.com wrote:
> > The difference is the stack alignment and that npad, which is just a NOP
> > instruction. The impact is negligible.
>
> Not sure about negligibility... In this case <https://godbolt.org/g/ggPGPJ>
> we end up with 24 bytes of code vs 5 bytes. It is very likely to have
> different performance.
The only relevant impact is the saving of -2 to memory. The NOP instructions
are retired very quickly and don't occupy any processing; the subtraction will
have a small but measurable impact in a micro-benchmark.
> > What's more, this doesn't prove that the changes are required by the ABI.
> > It
> > could be just the optimiser failing.
>
> True. But even if it is the case -- for end user it doesn't matter(until it
> is fixed). That is why in my code almost every inline no-throw function
> looks like this:
>
> void foo() // noexcept (with explanation why, where needed)
> {
> ...
> }
Indeed, this is actually something that the C++ language should fix. We find
ourselves violating DRY all the time to declare functions noexcept.
Except... legacy.
I'd really welcome noexcept(auto).
> > But I really don't see how it could reduce optimisations available.
>
> I could be wrong here. I don't have a solid answer, just a hunch.
Sorry, I simply don't see how it would reduce optimisations available inside
the function declared noexcept. A hunch won't cut here.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/4494918.FaW8VcH3o6%40tjmaciei-mobl1.
.
Author: crusader.mike@gmail.com
Date: Thu, 31 Aug 2017 19:27:23 -0700 (PDT)
Raw View
------=_Part_2087_2112015556.1504232843698
Content-Type: multipart/alternative;
boundary="----=_Part_2088_1394814677.1504232843698"
------=_Part_2088_1394814677.1504232843698
Content-Type: text/plain; charset="UTF-8"
On Thursday, August 31, 2017 at 9:19:26 PM UTC-5, Thiago Macieira wrote:
>
> On Thursday, 31 August 2017 18:05:17 PDT crusad...@gmail.com <javascript:>
> wrote:
> > > But I really don't see how it could reduce optimisations available.
> >
> > I could be wrong here. I don't have a solid answer, just a hunch.
>
> Sorry, I simply don't see how it would reduce optimisations available
> inside
> the function declared noexcept. A hunch won't cut here.
>
I except missing optimization opportunities when this function (that is
declared nothrow) gets inlined and it's instructions mix with instructions
of caller. Again, just a hunch -- nothing solid. Probably wrong.
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
>
>
--
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/ddb3d1d4-8b5f-40cc-9b84-9a97a5533f58%40isocpp.org.
------=_Part_2088_1394814677.1504232843698
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, August 31, 2017 at 9:19:26 PM UTC-5, 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;">On Thursday, 31 =
August 2017 18:05:17 PDT <a href=3D"javascript:" target=3D"_blank" gdf-obfu=
scated-mailto=3D"mDJl2LHnAQAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D=
'javascript:';return true;" onclick=3D"this.href=3D'javascript:=
';return true;">crusad...@gmail.com</a> wrote:
<br>> > But I really don't see how it could reduce optimisations =
available.
<br>>=20
<br>> I could be wrong here. I don't have a solid answer, just a hun=
ch.
<br>
<br>Sorry, I simply don't see how it would reduce optimisations availab=
le inside=20
<br>the function declared noexcept. A hunch won't cut here.
<br></blockquote><div><br></div><div>I except missing optimization opportun=
ities when this function (that is declared nothrow) gets inlined and it'=
;s instructions mix with instructions of caller. Again, just a hunch -- not=
hing solid. Probably wrong.</div><div><br></div><div>=C2=A0</div><blockquot=
e class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: =
1px #ccc solid;padding-left: 1ex;">--=20
<br>Thiago Macieira - thiago (AT) <a href=3D"http://macieira.info" target=
=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.goo=
gle.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x3dD\x26sntz\x3d1\x26usg\=
x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.hr=
ef=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x=
3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return t=
rue;">macieira.info</a> - thiago (AT) <a href=3D"http://kde.org" target=3D"=
_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.google.=
com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNH=
GRJdo5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'=
http://www.google.com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1=
\x26usg\x3dAFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;">kde.org</a=
>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>
<br></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/ddb3d1d4-8b5f-40cc-9b84-9a97a5533f58%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/ddb3d1d4-8b5f-40cc-9b84-9a97a5533f58=
%40isocpp.org</a>.<br />
------=_Part_2088_1394814677.1504232843698--
------=_Part_2087_2112015556.1504232843698--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Thu, 31 Aug 2017 19:51:29 -0700
Raw View
On Thursday, 31 August 2017 19:27:23 PDT crusader.mike@gmail.com wrote:
> I except missing optimization opportunities when this function (that is
> declared nothrow) gets inlined and it's instructions mix with instructions
> of caller. Again, just a hunch -- nothing solid. Probably wrong.
That depends a lot on the EH encoding information. I don't see any reason why
you can't mark blocks of instructions as noexcept and others as having
exception handlers or be unwindable.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/1976870.VZa7UkFZy1%40tjmaciei-mobl1.
.
Author: crusader.mike@gmail.com
Date: Fri, 1 Sep 2017 14:17:24 -0700 (PDT)
Raw View
------=_Part_3082_419965760.1504300645049
Content-Type: multipart/alternative;
boundary="----=_Part_3083_1199663277.1504300645049"
------=_Part_3083_1199663277.1504300645049
Content-Type: text/plain; charset="UTF-8"
On Thursday, August 31, 2017 at 9:51:34 PM UTC-5, Thiago Macieira wrote:
>
> On Thursday, 31 August 2017 19:27:23 PDT crusad...@gmail.com <javascript:>
> wrote:
> > I except missing optimization opportunities when this function (that is
> > declared nothrow) gets inlined and it's instructions mix with
> instructions
> > of caller. Again, just a hunch -- nothing solid. Probably wrong.
>
> That depends a lot on the EH encoding information. I don't see any reason
> why
> you can't mark blocks of instructions as noexcept and others as having
> exception handlers or be unwindable.
>
I had different consideration in mind:
if you have a function:
void foo() noexcept
{
A; B; C;
}
and it gets inlined into:
void bar()
{
X;
foo();
Y;
}
you'll end up with (close equivalent of):
void bar()
{
X;
try{ A; B; C; } catch(...) {std::terminate();}
Y;
}
on the other hand, since you know that foo() won't throw (but compiler
can't prove it) -- you can remove 'noexcept' and you'll end up with:
void bar()
{
X;
A; B; C;
Y;
}
that try/catch block is expected to have a non-zero price.
(I know that it is not precise equivalent because noexcept doesn't require
unwinding to happen).
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
>
>
--
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/db6e2ef8-48c1-4af7-b19c-3a6a9d00efb3%40isocpp.org.
------=_Part_3083_1199663277.1504300645049
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Thursday, August 31, 2017 at 9:51:34 PM UTC-5, =
Thiago Macieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Thurs=
day, 31 August 2017 19:27:23 PDT <a href=3D"javascript:" target=3D"_blank" =
gdf-obfuscated-mailto=3D"jEwNvnLpAQAJ" rel=3D"nofollow" onmousedown=3D"this=
..href=3D'javascript:';return true;" onclick=3D"this.href=3D'jav=
ascript:';return true;">crusad...@gmail.com</a> wrote:
<br>> I except missing optimization opportunities when this function (th=
at is
<br>> declared nothrow) gets inlined and it's instructions mix with =
instructions
<br>> of caller. Again, just a hunch -- nothing solid. Probably wrong.
<br>
<br>That depends a lot on the EH encoding information. I don't see any =
reason why=20
<br>you can't mark blocks of instructions as noexcept and others as hav=
ing=20
<br>exception handlers or be unwindable.
<br></blockquote><div><br></div><div>I had different consideration in mind:=
</div><div><br></div><div>if you have a function:</div><div><br></div><div>=
void foo() noexcept</div><div>{</div><div>=C2=A0 =C2=A0 A; B; C;</div><div>=
}</div><div><br></div><div>and it gets inlined into:</div><div><br></div><d=
iv>void bar()</div><div>{</div><div>=C2=A0 =C2=A0X;</div><div>=C2=A0 =C2=A0=
foo();</div><div>=C2=A0 =C2=A0Y;</div><div>}</div><div><br></div><div>you&#=
39;ll end up with (close equivalent of):</div><div><br></div><div><div>void=
bar()</div><div>{</div><div>=C2=A0 =C2=A0X;</div><div>=C2=A0 =C2=A0try{ A;=
B; C; } catch(...)=C2=A0 {std::terminate();}</div><div>=C2=A0 =C2=A0Y;</di=
v><div>}</div></div><div><br></div><div>on the other hand, since you know t=
hat foo() won't throw (but compiler can't prove it) -- you can remo=
ve 'noexcept' and you'll end up with:</div><div><br></div><div>=
<div><div>void bar()</div><div>{</div><div>=C2=A0 =C2=A0X;</div><div>=C2=A0=
=C2=A0A; B; C;</div><div>=C2=A0 =C2=A0Y;</div><div>}</div></div></div><div=
><br></div><div>that try/catch block is expected to have a non-zero price.<=
/div><div><br></div><div>(I know that it is not precise equivalent because =
noexcept doesn't require unwinding to happen).</div><div><br></div><div=
>=C2=A0<br></div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">--=20
<br>Thiago Macieira - thiago (AT) <a href=3D"http://macieira.info" target=
=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.goo=
gle.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x3dD\x26sntz\x3d1\x26usg\=
x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.hr=
ef=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x=
3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return t=
rue;">macieira.info</a> - thiago (AT) <a href=3D"http://kde.org" target=3D"=
_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.google.=
com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNH=
GRJdo5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'=
http://www.google.com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1=
\x26usg\x3dAFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;">kde.org</a=
>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>
<br></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/db6e2ef8-48c1-4af7-b19c-3a6a9d00efb3%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/db6e2ef8-48c1-4af7-b19c-3a6a9d00efb3=
%40isocpp.org</a>.<br />
------=_Part_3083_1199663277.1504300645049--
------=_Part_3082_419965760.1504300645049--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Fri, 01 Sep 2017 14:40:06 -0700
Raw View
On Friday, 1 September 2017 14:17:24 PDT crusader.mike@gmail.com wrote:
> that try/catch block is expected to have a non-zero price.
It's supposed to have a zero price.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/7328799.KZ0yWJap2m%40tjmaciei-mobl1.
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Sat, 2 Sep 2017 01:07:24 +0300
Raw View
On 2 September 2017 at 00:40, Thiago Macieira <thiago@macieira.org> wrote:
> On Friday, 1 September 2017 14:17:24 PDT crusader.mike@gmail.com wrote:
>> that try/catch block is expected to have a non-zero price.
>
> It's supposed to have a zero price.
Noexcept can surprise you:
https://groups.google.com/a/isocpp.org/d/msg/std-proposals/9epHRTc9904/d_z3-WQ1DgAJ
--
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/CAFk2RUYPFNBNbABNCwk%2BUywBMm-0NRFC-SALzNCYGuaKKes3Yw%40mail.gmail.com.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Fri, 01 Sep 2017 16:05:22 -0700
Raw View
On Friday, 1 September 2017 15:07:24 PDT Ville Voutilainen wrote:
> On 2 September 2017 at 00:40, Thiago Macieira <thiago@macieira.org> wrote:
> > On Friday, 1 September 2017 14:17:24 PDT crusader.mike@gmail.com wrote:
> >> that try/catch block is expected to have a non-zero price.
> >
> > It's supposed to have a zero price.
>
> Noexcept can surprise you:
> https://groups.google.com/a/isocpp.org/d/msg/std-proposals/9epHRTc9904/d_z3-> WQ1DgAJ
That's the pre-condition (narrow contract) and wide contract rule. As for the
example code generation, Howard needs to get a better compiler. We've already
established that for the IA-64 Portabe C++ ABI, there's no need to explicitly
call std::terminate() or handle unwind, since the unwinder runtime will simply
use the information in the EH tables to conclude the function was noexcept and
no unwinding should happen. See https://godbolt.org/g/rW9VxU.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/5412150.rcNZqFduuh%40tjmaciei-mobl1.
.
Author: Howard Hinnant <howard.hinnant@gmail.com>
Date: Fri, 1 Sep 2017 22:24:53 -0400
Raw View
--Apple-Mail=_7A4162FC-AB25-4EF2-B0F5-108465DCF1DA
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset="UTF-8"
On Sep 1, 2017, at 7:05 PM, Thiago Macieira <thiago@macieira.org> wrote:
>=20
> On Friday, 1 September 2017 15:07:24 PDT Ville Voutilainen wrote:
>> On 2 September 2017 at 00:40, Thiago Macieira <thiago@macieira.org> wrot=
e:
>>> On Friday, 1 September 2017 14:17:24 PDT crusader.mike@gmail.com wrote:
>>>> that try/catch block is expected to have a non-zero price.
>>>=20
>>> It's supposed to have a zero price.
>>=20
>> Noexcept can surprise you:
>> https://groups.google.com/a/isocpp.org/d/msg/std-proposals/9epHRTc9904/d=
_z3-> WQ1DgAJ
>=20
> That's the pre-condition (narrow contract) and wide contract rule. As for=
the
> example code generation, Howard needs to get a better compiler. We've alr=
eady
> established that for the IA-64 Portabe C++ ABI, there's no need to explic=
itly
> call std::terminate() or handle unwind, since the unwinder runtime will s=
imply
> use the information in the EH tables to conclude the function was noexcep=
t and
> no unwinding should happen. See https://godbolt.org/g/rW9VxU.
I=E2=80=99m confused. What are the significant differences between the cod=
e I show in my 2015-12-19 post and the code you show at https://godbolt.org=
/g/rW9VxU ?
When I look at both, they both show that foo() doesn=E2=80=99t need an exce=
ption handling table, and no call to terminate(), and bar() generates an ex=
ception handling table and a call to terminate().
Now compilers definitely do improve with time. I have no doubt that today=
=E2=80=99s clang is better than the clang of late 2015. But there=E2=80=99=
s no getting around the fact that then and now, bar() needs to be prepared =
to call terminate() and foo() can optimize that possibility away, both in c=
lang and gcc.
Howard
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/3CC0D975-D7CE-433A-B50B-5FCF2B054973%40gmail.com=
..
--Apple-Mail=_7A4162FC-AB25-4EF2-B0F5-108465DCF1DA
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename=signature.asc
Content-Type: application/pgp-signature;
name=signature.asc
Content-Description: Message signed with OpenPGP
-----BEGIN PGP SIGNATURE-----
iQIcBAEBCAAGBQJZqhZ2AAoJEGbcHCxKqhWCO0oP/1/JUA0H61TKqswj423K/S4V
RcAlpWyA0V7K2hPdU23erW/M5EIs4xUb70g6JAzBhxyWnh+I4LaXd6AIIYdxEbrj
wTvQgJNZNM3kbhACxYQsnXfnzxXnPeiG6XwWd7wCWM5Z/BqRRDCEkynS+GgXEBNk
JjV4AtlLTUi9hgXUB8bl77DzgHZOfLl75BbU3QDQ069oDIIzX9JYX3vg57tGJSBa
BiblBCYZDrhNosQ/Ue8PqVGQNacyouGNmgBoULODTD3K3aLgO9Ua+CN/GuIXSHud
tdJbqYxLExekgp/Xj/hYbiUHudX00wANNahm1UtVkj36/Y2PJ6xTXlkcm+0SvgPb
Y3w/l3dawTteiMOoA74Ko096YMi4lH1ukUB5RDhlWF/4AmZHufjAU1T3s7Yb4KrI
R4QS9T1ZyNBYJXhL9K2wS5izyslzf76KVBFKv7fjNTUlvyQDBMgWaOV9NJppDeVU
qoFwgQ8X+55Y+h7v55ojf7Ts0MNyur4Z4wrwrXPzmNYq1VgDpnmCkEobBxdlFa8q
pMwAeFbuFHKI+g+dXjlwE8fP6VwHEzqqCQkgJJhNV9ifJjKZW+EPjRqz2xwNbZgW
IL8hEG/HJPE/xpC3PVZw49Hlfmx6Cstzm80sHvFr9CAa50bxSZA43d2u4U1mcNjj
rZnBn2CY81kwaQjW/YPw
=n87x
-----END PGP SIGNATURE-----
--Apple-Mail=_7A4162FC-AB25-4EF2-B0F5-108465DCF1DA--
.
Author: Howard Hinnant <howard.hinnant@gmail.com>
Date: Fri, 1 Sep 2017 22:32:31 -0400
Raw View
--Apple-Mail=_B27DA664-3714-492E-8EBA-4C970FB3964D
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset="UTF-8"
On Sep 1, 2017, at 10:24 PM, Howard Hinnant <howard.hinnant@gmail.com> wrot=
e:
>=20
> On Sep 1, 2017, at 7:05 PM, Thiago Macieira <thiago@macieira.org> wrote:
>>=20
>> On Friday, 1 September 2017 15:07:24 PDT Ville Voutilainen wrote:
>>> On 2 September 2017 at 00:40, Thiago Macieira <thiago@macieira.org> wro=
te:
>>>> On Friday, 1 September 2017 14:17:24 PDT crusader.mike@gmail.com wrote=
:
>>>>> that try/catch block is expected to have a non-zero price.
>>>>=20
>>>> It's supposed to have a zero price.
>>>=20
>>> Noexcept can surprise you:
>>> https://groups.google.com/a/isocpp.org/d/msg/std-proposals/9epHRTc9904/=
d_z3-> WQ1DgAJ
>>=20
>> That's the pre-condition (narrow contract) and wide contract rule. As fo=
r the
>> example code generation, Howard needs to get a better compiler. We've al=
ready
>> established that for the IA-64 Portabe C++ ABI, there's no need to expli=
citly
>> call std::terminate() or handle unwind, since the unwinder runtime will =
simply
>> use the information in the EH tables to conclude the function was noexce=
pt and
>> no unwinding should happen. See https://godbolt.org/g/rW9VxU.
>=20
> I=E2=80=99m confused. What are the significant differences between the c=
ode I show in my 2015-12-19 post and the code you show at https://godbolt.o=
rg/g/rW9VxU ?
>=20
> When I look at both, they both show that foo() doesn=E2=80=99t need an ex=
ception handling table, and no call to terminate(), and bar() generates an =
exception handling table and a call to terminate().
>=20
> Now compilers definitely do improve with time. I have no doubt that toda=
y=E2=80=99s clang is better than the clang of late 2015. But there=E2=80=
=99s no getting around the fact that then and now, bar() needs to be prepar=
ed to call terminate() and foo() can optimize that possibility away, both i=
n clang and gcc.
I stand corrected. I misread the godbolt link, and realized my mistake as =
I was hitting send (as always!).
I must admit that I do not yet see how the code generation for might_throw =
is going to be smart enough to call terminate(). Looking further=E2=80=A6
Howard
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/EC078D5F-2D62-4DE7-AC8E-2E4A1A775273%40gmail.com=
..
--Apple-Mail=_B27DA664-3714-492E-8EBA-4C970FB3964D
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename=signature.asc
Content-Type: application/pgp-signature;
name=signature.asc
Content-Description: Message signed with OpenPGP
-----BEGIN PGP SIGNATURE-----
iQIcBAEBCAAGBQJZqhhAAAoJEGbcHCxKqhWCGLUQALVK6KiFQRvpcbhqkK4UISEH
k4br6ttU4+heafTExVH/Smhk9PO0Ccp67D0W7LE7BfsC/rnNAYTI4OmCi/RB+odv
xFoJ478wF4yH0qrk13b4HD+8lLaMdWS5leBsjKTls3ANC7i0NtMUckY9LIq7PIon
4LCbwqza5dIWI6LvI8qmibF7wZjt4PA7sYaxzbaFwtPR4jXLQNQbHvN37t48h8p6
UvgscXT+ZKgNfYwv+mmGM66Dzy+cNfxUN2XeczW+CNaoIBQatvUFpAJWF5GWvY6b
RO+OQbQAPtgN51YzKbUAaaK+uX9VImuWyAWNWMuuimUyLhUOELm5LFCZoHE8cRZZ
paOWSDYiVdquHH6jK9LhH/xLZGJyEQMpNXH8vMgariPJGKBglDEqk4gjFpz3lK9u
FRsFKVRy5jiJxruQ6LJPxb8ETw+So92kpFHjaPt8Q/3/7bBr51z8qlHdhp0X9sXe
ZCNdbRDH2QBuyhSFtEweIsy+Wu3/lF5LYexumMfhHCxNWHlEnu1uE8p1b1VeC5D6
z/tnzaoCKce94aZvgGX8uE73FLA3Lk0e0HKQFSdDTzrlURbYfsPr2YiFPYKFPzAZ
1pz1N9F6LXcrTSbsEEzckqKTh3xXiDf8opDlgSx+aILTSHehCebo/AFdY3mQ09Cu
XCfElgfHGK6tRZqCbAVe
=n4Fm
-----END PGP SIGNATURE-----
--Apple-Mail=_B27DA664-3714-492E-8EBA-4C970FB3964D--
.
Author: Howard Hinnant <howard.hinnant@gmail.com>
Date: Fri, 1 Sep 2017 22:55:44 -0400
Raw View
--Apple-Mail=_46583CB6-2B01-4CD1-9EAB-31965610FB86
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset="UTF-8"
On Sep 1, 2017, at 10:32 PM, Howard Hinnant <howard.hinnant@gmail.com> wrot=
e:
>=20
> On Sep 1, 2017, at 10:24 PM, Howard Hinnant <howard.hinnant@gmail.com> wr=
ote:
>>=20
>> On Sep 1, 2017, at 7:05 PM, Thiago Macieira <thiago@macieira.org> wrote:
>>>=20
>>> On Friday, 1 September 2017 15:07:24 PDT Ville Voutilainen wrote:
>>>> On 2 September 2017 at 00:40, Thiago Macieira <thiago@macieira.org> wr=
ote:
>>>>> On Friday, 1 September 2017 14:17:24 PDT crusader.mike@gmail.com wrot=
e:
>>>>>> that try/catch block is expected to have a non-zero price.
>>>>>=20
>>>>> It's supposed to have a zero price.
>>>>=20
>>>> Noexcept can surprise you:
>>>> https://groups.google.com/a/isocpp.org/d/msg/std-proposals/9epHRTc9904=
/d_z3-> WQ1DgAJ
>>>=20
>>> That's the pre-condition (narrow contract) and wide contract rule. As f=
or the
>>> example code generation, Howard needs to get a better compiler. We've a=
lready
>>> established that for the IA-64 Portabe C++ ABI, there's no need to expl=
icitly
>>> call std::terminate() or handle unwind, since the unwinder runtime will=
simply
>>> use the information in the EH tables to conclude the function was noexc=
ept and
>>> no unwinding should happen. See https://godbolt.org/g/rW9VxU.
>>=20
>> I=E2=80=99m confused. What are the significant differences between the =
code I show in my 2015-12-19 post and the code you show at https://godbolt.=
org/g/rW9VxU ?
>>=20
>> When I look at both, they both show that foo() doesn=E2=80=99t need an e=
xception handling table, and no call to terminate(), and bar() generates an=
exception handling table and a call to terminate().
>>=20
>> Now compilers definitely do improve with time. I have no doubt that tod=
ay=E2=80=99s clang is better than the clang of late 2015. But there=E2=80=
=99s no getting around the fact that then and now, bar() needs to be prepar=
ed to call terminate() and foo() can optimize that possibility away, both i=
n clang and gcc.
>=20
> I stand corrected. I misread the godbolt link, and realized my mistake a=
s I was hitting send (as always!).
>=20
> I must admit that I do not yet see how the code generation for might_thro=
w is going to be smart enough to call terminate(). Looking further=E2=80=
=A6
Agreed. I need a better compiler. Thanks for the education.
Howard
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/EB5A36E0-1F13-4C24-9D3C-F7437885F47C%40gmail.com=
..
--Apple-Mail=_46583CB6-2B01-4CD1-9EAB-31965610FB86
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename=signature.asc
Content-Type: application/pgp-signature;
name=signature.asc
Content-Description: Message signed with OpenPGP
-----BEGIN PGP SIGNATURE-----
iQIcBAEBCAAGBQJZqh2wAAoJEGbcHCxKqhWCRhsP/R/MAE/7dtNPRB/EkA88I+l1
e2uG8wP9WkpULsOFfKu7TsZosw/lXvAaK6838CKwdwQSU+bsLqZwk0mN4FcaAMU+
EJ//XigD2PnArNESCMvSaw6gC/g4pVE7/rnz2fUj6XdHQsfe/OVcAOidYyYf8SLR
9GceEg/nN4GoZKdEgrckpjYSS+v7K4oir/ZIgwoG2HoLcH3kmU/6lrbF97oEMpYi
CTJ0CZdNvFMn0jrAysFmOO2cteGVNAW1OJ9kXzOfIH1Z+eL6xdj24LUjqcnKo1oQ
cC6wOT3g+G4NP42iEHeXn/WqgBhniRfl5M0iydk4bJ7EVczH3NEsN2YAkmYrHXja
XPyNAdWoyM2trOiKFdnHs9uP0LP7fpTt0mip0nvCdMWsRGziuPx6w9/HwIHdsQRs
+YbRySDZOzQ6cLdOkVAC7gwJP65o0kHXJG0WthdHSvBgyd3uwq6ERaFdpsdXGbBq
MzLEzhEIjOdYyXuJxoCYoISiFxEetbf2ABU5B7HI3C7CvDN+8W5IrJ2Q0QiKcO+6
R/T9hoNd1OgAl995i16ktjUhbj4KQ3++/fhIlIdNzgqlbUOJqLNilZXDFLcF5dUD
ZsJlGEh/H9zcxu5A2ANCCpZtV0jMWiIfEWhtGFJnL6LzhIz43lgBL6tHnTgTXUFK
P2pLftnlHPitjlftx7DP
=Ef1B
-----END PGP SIGNATURE-----
--Apple-Mail=_46583CB6-2B01-4CD1-9EAB-31965610FB86--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Fri, 01 Sep 2017 23:44:06 -0700
Raw View
On Friday, 1 September 2017 19:32:31 PDT Howard Hinnant wrote:
> I must admit that I do not yet see how the code generation for might_thro=
w
> is going to be smart enough to call terminate(). Looking further=E2=80=
=A6
Yeah, took me a while to figure it out too.
First, the compiler does not need to generate an explicit call to=20
std::terminate() (or clang's trampoline __clang_call_terminate). This is wh=
at=20
I was arguing to Ville and Crusader.Mike: the EH table is sufficient, descr=
ibing=20
what kind of exception is allowed to leave that scope and how (destructors =
to=20
be run), or which ones have handlers for. In the specific case of noexcept,=
the=20
table is simple: no exception can leave it=C2=B9. So the compiler simply ma=
rks the=20
entire function from begin to end (hence the ".LFBn" and ".LFEn" labels) wi=
th=20
one attribute.
If the throwing function does throw, when the unwinder unwinds back to bar(=
),=20
it will notice that this frame is noexcept and therefore the unwinder itsel=
f=C2=B2=20
will call std::terminate().
But what really bugged me for a while was the fact that GCC generated a tai=
l-
call optimisation. Under some other conditions I tried, the function genera=
ted=20
was:
sub %rsp, 8
call might_throw()
retq
In this case it's quite clear and is what I mentioned before. But the funct=
ion=20
generated was:
jmp might_throw()
The problem with this is that there IS NO frame to be unwound in the first=
=20
place. There's no EH table because the unwinder would never find stack trac=
e=20
leading to this instruction=C2=B3. So how does the unwinder know that it sh=
ouldn't=20
propagate the exception?
Here's how it could work in theory: the compiler knows that bar() is noexce=
pt,=20
so wherever it is called, it can surround the code with enough EH tables to=
=20
indicate that the unwinding should stop and std::terminate() be called. Thi=
s=20
way, the tail-call optimisation can be performed and we don't have loss of=
=20
performance, and still have noexcept support.
That's what I thought GCC was doing. When I tested (just now, to write this=
=20
email), it turns out that it doesn't actually work:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D82081
[1] GCC has one type of unswallowable (read, "must rethrow") exception and=
=20
that's the POSIX synchronous thread termination. Since it can't be swallowe=
d,=20
what happens if a POSIX cancellation point function is called and does canc=
el?=20
Experimentation needed.
[2] Actually, the personality routine, which is what tells libunwind how to=
=20
deal with C++ exceptions. The unwinder can be used for other languages too.
[3] Technically, the next instruction.
--=20
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/2012927.WGKi1cKNH1%40tjmaciei-mobl1.
.
Author: Howard Hinnant <howard.hinnant@gmail.com>
Date: Sat, 2 Sep 2017 09:05:30 -0400
Raw View
--Apple-Mail=_65A3576D-1F18-444D-AF98-59CC08125DCD
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset="UTF-8"
On Sep 2, 2017, at 2:44 AM, Thiago Macieira <thiago@macieira.org> wrote:
>=20
>=20
> That's what I thought GCC was doing. When I tested (just now, to write th=
is
> email), it turns out that it doesn't actually work:
>=20
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D82081
>=20
>=20
> [1] GCC has one type of unswallowable (read, "must rethrow") exception an=
d
> that's the POSIX synchronous thread termination. Since it can't be swallo=
wed,
> what happens if a POSIX cancellation point function is called and does ca=
ncel?
> Experimentation needed.
>=20
> [2] Actually, the personality routine, which is what tells libunwind how =
to
> deal with C++ exceptions. The unwinder can be used for other languages to=
o.
>=20
> [3] Technically, the next instruction.
It=E2=80=99s been too long since I was heavily involved in this area for me=
to recall the details. It is up to others to improve (or not) clang/libc+=
+abi in this area now. And for anyone that wants to get involved, and real=
ly understand exception handling tables and what a =E2=80=9Cpersonality rou=
tine=E2=80=9D does with them, here is a comment which summarizes my underst=
anding at the time:
https://github.com/llvm-mirror/libcxxabi/blob/master/src/cxa_personality.cp=
p#L40-L135
Howard
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/D277BEE6-D792-48F4-9547-9477C2250453%40gmail.com=
..
--Apple-Mail=_65A3576D-1F18-444D-AF98-59CC08125DCD
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename=signature.asc
Content-Type: application/pgp-signature;
name=signature.asc
Content-Description: Message signed with OpenPGP
-----BEGIN PGP SIGNATURE-----
iQIcBAEBCAAGBQJZqqybAAoJEGbcHCxKqhWCopIP/2HWUiG0EHlbYycI60apXUW8
LzG/nzqGx4rNqk3k3lG8Ed+x62LI88PUgGtXODmfA09feblp5fpUVv1pml1UtCqR
AQVZxz6zT2aBgHsg+nyZGGXugTmaaYY2pZmESLURlfuKeTG2RHEKuqKM21/JB+v+
gOgBPECqsRlBQAEzdG/68OySqSDDzLxPn/5bq2wTg8OaXwcT6lk5VuwMb/dc6FHZ
tVmMRHw61aowQhF/9HZMRZj6rPdHTzMRlvrjHSgQ1BfByD32toFWNfkTHkqSKxe1
LhBOV/Sov/3m5Znd5AfrLPxuzMt/xF2wiESlB4QdtFF1efw4b17q/05Fv2ln7DEn
Z3gz6LkcyzVqjdmc7uKuLYYUATpZf7mxTT+/QJP5Sv1jWkjGTTNX7iSN+TnzkWjR
n5x/BfO7pQbk36Iw5SFoLXfnE61Yrn5ZgUM/95NV8na4kFBUSpzZMtm1QfqnA7+0
Ui05PkEXMNNhqwNic44Je1hJRZUaIbA2l41W3JhlGTG6rEifsu/5K5QFSRaPeSk7
NkfDa3OZ7Bxg8rbfHHaiWpYrxQlD5+k7dWx2DlwwGXPlqp4GMZGU02g+0T+ejN4o
iaVYLmjfSaFIjkCetpl/jsWKFx/Uz+3c/EOwCdSE2vxrPehMRVn+PMkWFpi4Hm7C
FuYFeaIDHnuH5mOx01J0
=kUwR
-----END PGP SIGNATURE-----
--Apple-Mail=_65A3576D-1F18-444D-AF98-59CC08125DCD--
.
Author: Patrice Roy <patricer@gmail.com>
Date: Sat, 2 Sep 2017 09:06:30 -0400
Raw View
--94eb2c054182d3eada0558348b25
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
@crusader.mike : should you decide to push forward with a proposal, I
suggest you make sure the following case is discussed :
X *p =3D new X[10];
// suppose new[](10 * sizeof(X)) succeeds
// suppose X::X() is non-trivial and succeeds for p[0]..p[7], say
// suppose X::X() throws for p[8]
// X::~X() is applied to p[7], p[6], ... but throws for p[3]... Ouch
Currently, we then reach a point where we terminate things as it does not
seem reasonable to keep up fighting to hold the program together :) If you
think throwing destructors are a sane thing to push for and support (I
remain unconvinced, based on such cases in large part), I think this
situation will deserve some careful discussion. I have no idea what we
could make of program state past that point.
Cheers!
2017-09-02 2:44 GMT-04:00 Thiago Macieira <thiago@macieira.org>:
> On Friday, 1 September 2017 19:32:31 PDT Howard Hinnant wrote:
> > I must admit that I do not yet see how the code generation for
> might_throw
> > is going to be smart enough to call terminate(). Looking further=E2=80=
=A6
>
> Yeah, took me a while to figure it out too.
>
> First, the compiler does not need to generate an explicit call to
> std::terminate() (or clang's trampoline __clang_call_terminate). This is
> what
> I was arguing to Ville and Crusader.Mike: the EH table is sufficient,
> describing
> what kind of exception is allowed to leave that scope and how (destructor=
s
> to
> be run), or which ones have handlers for. In the specific case of
> noexcept, the
> table is simple: no exception can leave it=C2=B9. So the compiler simply =
marks
> the
> entire function from begin to end (hence the ".LFBn" and ".LFEn" labels)
> with
> one attribute.
>
> If the throwing function does throw, when the unwinder unwinds back to
> bar(),
> it will notice that this frame is noexcept and therefore the unwinder
> itself=C2=B2
> will call std::terminate().
>
>
> But what really bugged me for a while was the fact that GCC generated a
> tail-
> call optimisation. Under some other conditions I tried, the function
> generated
> was:
> sub %rsp, 8
> call might_throw()
> retq
>
> In this case it's quite clear and is what I mentioned before. But the
> function
> generated was:
>
> jmp might_throw()
>
> The problem with this is that there IS NO frame to be unwound in the firs=
t
> place. There's no EH table because the unwinder would never find stack
> trace
> leading to this instruction=C2=B3. So how does the unwinder know that it
> shouldn't
> propagate the exception?
>
> Here's how it could work in theory: the compiler knows that bar() is
> noexcept,
> so wherever it is called, it can surround the code with enough EH tables =
to
> indicate that the unwinding should stop and std::terminate() be called.
> This
> way, the tail-call optimisation can be performed and we don't have loss o=
f
> performance, and still have noexcept support.
>
> That's what I thought GCC was doing. When I tested (just now, to write th=
is
> email), it turns out that it doesn't actually work:
>
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D82081
>
>
> [1] GCC has one type of unswallowable (read, "must rethrow") exception an=
d
> that's the POSIX synchronous thread termination. Since it can't be
> swallowed,
> what happens if a POSIX cancellation point function is called and does
> cancel?
> Experimentation needed.
>
> [2] Actually, the personality routine, which is what tells libunwind how =
to
> deal with C++ exceptions. The unwinder can be used for other languages to=
o.
>
> [3] Technically, the next instruction.
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
>
> --
> 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/2012927.WGKi1cKNH1%40tjmaciei-mobl1.
>
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CAKiZDp0SU%3D2fvG3Pi7AS%2Bd6XtUR%2BFBeYAVsdSnifE=
AbxNZfZww%40mail.gmail.com.
--94eb2c054182d3eada0558348b25
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><div><div><div><div><div><div><div>@crusader.mike : should=
you decide to push forward with a proposal, I suggest you make sure the fo=
llowing case is discussed :<br><br></div>X *p =3D new X[10];<br></div>// su=
ppose new[](10 * sizeof(X)) succeeds<br></div>// suppose X::X() is non-triv=
ial and succeeds for p[0]..p[7], say<br></div>// suppose X::X() throws for =
p[8]<br></div>// X::~X() is applied to p[7], p[6], ... but throws for p[3].=
... Ouch<br><br></div>Currently, we then reach a point where we terminate th=
ings as it does not seem reasonable to keep up fighting to hold the program=
together :) If you think throwing destructors are a sane thing to push for=
and support (I remain unconvinced, based on such cases in large part), I t=
hink this situation will deserve some careful discussion. I have no idea wh=
at we could make of program state past that point.<br><br></div>Cheers!<br>=
</div><div class=3D"gmail_extra"><br><div class=3D"gmail_quote">2017-09-02 =
2:44 GMT-04:00 Thiago Macieira <span dir=3D"ltr"><<a href=3D"mailto:thia=
go@macieira.org" target=3D"_blank">thiago@macieira.org</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 Friday, 1 September 2017 =
19:32:31 PDT Howard Hinnant wrote:<br>
> I must admit that I do not yet see how the code generation for might_t=
hrow<br>
> is going to be smart enough to call terminate().=C2=A0 Looking further=
=E2=80=A6<br>
<br>
</span>Yeah, took me a while to figure it out too.<br>
<br>
First, the compiler does not need to generate an explicit call to<br>
std::terminate() (or clang's trampoline __clang_call_terminate). This i=
s what<br>
I was arguing to Ville and Crusader.Mike: the EH table is sufficient, descr=
ibing<br>
what kind of exception is allowed to leave that scope and how (destructors =
to<br>
be run), or which ones have handlers for. In the specific case of noexcept,=
the<br>
table is simple: no exception can leave it=C2=B9. So the compiler simply ma=
rks the<br>
entire function from begin to end (hence the ".LFBn" and ".L=
FEn" labels) with<br>
one attribute.<br>
<br>
If the throwing function does throw, when the unwinder unwinds back to bar(=
),<br>
it will notice that this frame is noexcept and therefore the unwinder itsel=
f=C2=B2<br>
will call std::terminate().<br>
<br>
<br>
But what really bugged me for a while was the fact that GCC generated a tai=
l-<br>
call optimisation. Under some other conditions I tried, the function genera=
ted<br>
was:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 sub=C2=A0 =C2=A0 =C2=A0%rsp, 8<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 call=C2=A0 =C2=A0 might_throw()<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 retq<br>
<br>
In this case it's quite clear and is what I mentioned before. But the f=
unction<br>
generated was:<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 jmp=C2=A0 =C2=A0 =C2=A0might_throw()<br>
<br>
The problem with this is that there IS NO frame to be unwound in the first<=
br>
place. There's no EH table because the unwinder would never find stack =
trace<br>
leading to this instruction=C2=B3. So how does the unwinder know that it sh=
ouldn't<br>
propagate the exception?<br>
<br>
Here's how it could work in theory: the compiler knows that bar() is no=
except,<br>
so wherever it is called, it can surround the code with enough EH tables to=
<br>
indicate that the unwinding should stop and std::terminate() be called. Thi=
s<br>
way, the tail-call optimisation can be performed and we don't have loss=
of<br>
performance, and still have noexcept support.<br>
<br>
That's what I thought GCC was doing. When I tested (just now, to write =
this<br>
email), it turns out that it doesn't actually work:<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 <a href=3D"https://gcc.gnu.org/bugzilla/show_bu=
g.cgi?id=3D82081" rel=3D"noreferrer" target=3D"_blank">https://gcc.gnu.org/=
bugzilla/<wbr>show_bug.cgi?id=3D82081</a><br>
<br>
<br>
[1] GCC has one type of unswallowable (read, "must rethrow") exce=
ption and<br>
that's the POSIX synchronous thread termination. Since it can't be =
swallowed,<br>
what happens if a POSIX cancellation point function is called and does canc=
el?<br>
Experimentation needed.<br>
<br>
[2] Actually, the personality routine, which is what tells libunwind how to=
<br>
deal with C++ exceptions. The unwinder can be used for other languages too.=
<br>
<br>
[3] Technically, the next instruction.<br>
<span class=3D"">--<br>
Thiago Macieira - thiago (AT) <a href=3D"http://macieira.info" rel=3D"noref=
errer" target=3D"_blank">macieira.info</a> - thiago (AT) <a href=3D"http://=
kde.org" rel=3D"noreferrer" target=3D"_blank">kde.org</a><br>
=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center<br>
<br>
</span><span class=3D"">--<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%2Bunsubscribe@isocpp.org">std-propo=
sals+unsubscribe@<wbr>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>
</span>To view this discussion on the web visit <a href=3D"https://groups.g=
oogle.com/a/isocpp.org/d/msgid/std-proposals/2012927.WGKi1cKNH1%40tjmaciei-=
mobl1" rel=3D"noreferrer" target=3D"_blank">https://groups.google.com/a/<wb=
r>isocpp.org/d/msgid/std-<wbr>proposals/2012927.WGKi1cKNH1%<wbr>40tjmaciei-=
mobl1</a>.<br>
</blockquote></div><br></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/CAKiZDp0SU%3D2fvG3Pi7AS%2Bd6XtUR%2BFB=
eYAVsdSnifEAbxNZfZww%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoote=
r">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAKiZDp0SU%=
3D2fvG3Pi7AS%2Bd6XtUR%2BFBeYAVsdSnifEAbxNZfZww%40mail.gmail.com</a>.<br />
--94eb2c054182d3eada0558348b25--
.
Author: crusader.mike@gmail.com
Date: Sat, 2 Sep 2017 21:40:22 -0700 (PDT)
Raw View
------=_Part_3990_736158931.1504413622667
Content-Type: multipart/alternative;
boundary="----=_Part_3991_328162609.1504413622668"
------=_Part_3991_328162609.1504413622668
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Saturday, September 2, 2017 at 8:06:33 AM UTC-5, Patrice Roy wrote:
>
> @crusader.mike : should you decide to push forward with a proposal, I=20
> suggest you make sure the following case is discussed :
>
> X *p =3D new X[10];
> // suppose new[](10 * sizeof(X)) succeeds
> // suppose X::X() is non-trivial and succeeds for p[0]..p[7], say
> // suppose X::X() throws for p[8]
> // X::~X() is applied to p[7], p[6], ... but throws for p[3]... Ouch
>
This particular scenario will work just fine -- exception thrown by p[8]=20
ctor will be leading, exception thrown by p[3] dtor will be trailing.
=20
> Currently, we then reach a point where we terminate things as it does not=
=20
> seem reasonable to keep up fighting to hold the program together :)=20
>
You operate on assumption that exception from dtor means "destruction=20
failed". User can choose to design a class that *tries* to do smth. I.e. in=
=20
dtor it tries to shutdown the reactor and that attempt is guaranteed to=20
complete (i.e. object done it's work and can be discarded) with certain=20
outcome (which is, if bad, reported via exception for further processing).=
=20
Similar to fclose() in C.
Curios thing:
http://coliru.stacked-crooked.com/a/3087134b6fa07625
Can't figure out why uncommenting throw statement causes "~S1" to disappear=
=20
from the output... Overzealous optimizer?
=20
> If you think throwing destructors are a sane thing to push for and suppor=
t=20
> (I remain unconvinced, based on such cases in large part), I think this=
=20
> situation will deserve some careful discussion. I have no idea what we=20
> could make of program state past that point.
>
It certainly makes certain type of code simpler. But I need to sit on this=
=20
for a while... Maybe instead of "attaching exception" to lead one -- come=
=20
up with explicit OOB reporting mechanism (preferably triggered by escaped=
=20
exception). Maybe this will produce more favorable reaction.
Besides, it has been a long time since I needed smth like this. I can live=
=20
without it.
=20
> Cheers!
>
> 2017-09-02 2:44 GMT-04:00 Thiago Macieira <thi...@macieira.org=20
> <javascript:>>:
>
>> On Friday, 1 September 2017 19:32:31 PDT Howard Hinnant wrote:
>> > I must admit that I do not yet see how the code generation for=20
>> might_throw
>> > is going to be smart enough to call terminate(). Looking further=E2=
=80=A6
>>
>> Yeah, took me a while to figure it out too.
>>
>> First, the compiler does not need to generate an explicit call to
>> std::terminate() (or clang's trampoline __clang_call_terminate). This is=
=20
>> what
>> I was arguing to Ville and Crusader.Mike: the EH table is sufficient,=20
>> describing
>> what kind of exception is allowed to leave that scope and how=20
>> (destructors to
>> be run), or which ones have handlers for. In the specific case of=20
>> noexcept, the
>> table is simple: no exception can leave it=C2=B9. So the compiler simply=
marks=20
>> the
>> entire function from begin to end (hence the ".LFBn" and ".LFEn" labels)=
=20
>> with
>> one attribute.
>>
>> If the throwing function does throw, when the unwinder unwinds back to=
=20
>> bar(),
>> it will notice that this frame is noexcept and therefore the unwinder=20
>> itself=C2=B2
>> will call std::terminate().
>>
>>
>> But what really bugged me for a while was the fact that GCC generated a=
=20
>> tail-
>> call optimisation. Under some other conditions I tried, the function=20
>> generated
>> was:
>> sub %rsp, 8
>> call might_throw()
>> retq
>>
>> In this case it's quite clear and is what I mentioned before. But the=20
>> function
>> generated was:
>>
>> jmp might_throw()
>>
>> The problem with this is that there IS NO frame to be unwound in the fir=
st
>> place. There's no EH table because the unwinder would never find stack=
=20
>> trace
>> leading to this instruction=C2=B3. So how does the unwinder know that it=
=20
>> shouldn't
>> propagate the exception?
>>
>> Here's how it could work in theory: the compiler knows that bar() is=20
>> noexcept,
>> so wherever it is called, it can surround the code with enough EH tables=
=20
>> to
>> indicate that the unwinding should stop and std::terminate() be called.=
=20
>> This
>> way, the tail-call optimisation can be performed and we don't have loss =
of
>> performance, and still have noexcept support.
>>
>> That's what I thought GCC was doing. When I tested (just now, to write=
=20
>> this
>> email), it turns out that it doesn't actually work:
>>
>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D82081
>>
>>
>> [1] GCC has one type of unswallowable (read, "must rethrow") exception a=
nd
>> that's the POSIX synchronous thread termination. Since it can't be=20
>> swallowed,
>> what happens if a POSIX cancellation point function is called and does=
=20
>> cancel?
>> Experimentation needed.
>>
>> [2] Actually, the personality routine, which is what tells libunwind how=
=20
>> to
>> deal with C++ exceptions. The unwinder can be used for other languages=
=20
>> too.
>>
>> [3] Technically, the next instruction.
>> --
>> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
>> Software Architect - Intel Open Source Technology Center
>>
>> --
>> You received this message because you are subscribed to the Google Group=
s=20
>> "ISO C++ Standard - Future Proposals" group.
>> To unsubscribe from this group and stop receiving emails from it, send a=
n=20
>> email to std-proposal...@isocpp.org <javascript:>.
>> To post to this group, send email to std-pr...@isocpp.org <javascript:>.
>> To view this discussion on the web visit=20
>> https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/2012927.WGK=
i1cKNH1%40tjmaciei-mobl1
>> .
>>
>
>
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/43cad6c5-27b5-4924-8276-4e82516524ba%40isocpp.or=
g.
------=_Part_3991_328162609.1504413622668
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Saturday, September 2, 2017 at 8:06:33 AM UTC-5=
, Patrice Roy wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr"><div><div><div><div><div><div><div>@crusader.mike : should you dec=
ide to push forward with a proposal, I suggest you make sure the following =
case is discussed :<br><br></div>X *p =3D new X[10];<br></div>// suppose ne=
w[](10 * sizeof(X)) succeeds<br></div>// suppose X::X() is non-trivial and =
succeeds for p[0]..p[7], say<br></div>// suppose X::X() throws for p[8]<br>=
</div>// X::~X() is applied to p[7], p[6], ... but throws for p[3]... Ouch<=
br></div></div></div></blockquote><div><br></div><div>This particular scena=
rio will work just fine -- exception thrown by p[8] ctor will be leading, e=
xception thrown by p[3] dtor will be trailing.</div><div><br></div><div>=C2=
=A0</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"><div=
><div>Currently, we then reach a point where we terminate things as it does=
not seem reasonable to keep up fighting to hold the program together :) </=
div></div></div></blockquote><div><br></div><div>You operate on assumption =
that exception from dtor means "destruction failed". User can cho=
ose to design a class that *tries* to do smth. I.e. in dtor it tries to shu=
tdown the reactor and that attempt is guaranteed to complete (i.e. object d=
one it's work and can be discarded) with certain outcome (which is, if =
bad, reported via exception for further processing). Similar to fclose() in=
C.</div><div><br></div><div>Curios thing:</div><div>http://coliru.stacked-=
crooked.com/a/3087134b6fa07625<br></div><div><br></div><div>Can't figur=
e out why uncommenting throw statement causes "~S1" to disappear =
from the output... Overzealous optimizer?</div><div><br></div><div>=C2=A0</=
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"><div><div=
>If you think throwing destructors are a sane thing to push for and support=
(I remain unconvinced, based on such cases in large part), I think this si=
tuation will deserve some careful discussion. I have no idea what we could =
make of program state past that point.<br></div></div></div></blockquote><d=
iv><br></div><div>It certainly makes certain type of code simpler. But I ne=
ed to sit on this for a while... Maybe instead of "attaching exception=
" to lead one -- come up with explicit OOB reporting mechanism (prefer=
ably triggered by escaped exception). Maybe this will produce more favorabl=
e reaction.</div><div><br></div><div>Besides, it has been a long time since=
I needed smth like this. I can live without it.</div><div><br></div><div><=
br></div><div>=C2=A0</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"><div><div></div></div>Cheers!<br></div><div><br><div class=3D"=
gmail_quote">2017-09-02 2:44 GMT-04:00 Thiago Macieira <span dir=3D"ltr">&l=
t;<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"E53jed=
lIAAAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:';r=
eturn true;" onclick=3D"this.href=3D'javascript:';return true;">thi=
....@macieira.org</a>></span>:<br><blockquote class=3D"gmail_quote" style=
=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span>On=
Friday, 1 September 2017 19:32:31 PDT Howard Hinnant wrote:<br>
> I must admit that I do not yet see how the code generation for might_t=
hrow<br>
> is going to be smart enough to call terminate().=C2=A0 Looking further=
=E2=80=A6<br>
<br>
</span>Yeah, took me a while to figure it out too.<br>
<br>
First, the compiler does not need to generate an explicit call to<br>
std::terminate() (or clang's trampoline __clang_call_terminate). This i=
s what<br>
I was arguing to Ville and Crusader.Mike: the EH table is sufficient, descr=
ibing<br>
what kind of exception is allowed to leave that scope and how (destructors =
to<br>
be run), or which ones have handlers for. In the specific case of noexcept,=
the<br>
table is simple: no exception can leave it=C2=B9. So the compiler simply ma=
rks the<br>
entire function from begin to end (hence the ".LFBn" and ".L=
FEn" labels) with<br>
one attribute.<br>
<br>
If the throwing function does throw, when the unwinder unwinds back to bar(=
),<br>
it will notice that this frame is noexcept and therefore the unwinder itsel=
f=C2=B2<br>
will call std::terminate().<br>
<br>
<br>
But what really bugged me for a while was the fact that GCC generated a tai=
l-<br>
call optimisation. Under some other conditions I tried, the function genera=
ted<br>
was:<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 sub=C2=A0 =C2=A0 =C2=A0%rsp, 8<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 call=C2=A0 =C2=A0 might_throw()<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 retq<br>
<br>
In this case it's quite clear and is what I mentioned before. But the f=
unction<br>
generated was:<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 jmp=C2=A0 =C2=A0 =C2=A0might_throw()<br>
<br>
The problem with this is that there IS NO frame to be unwound in the first<=
br>
place. There's no EH table because the unwinder would never find stack =
trace<br>
leading to this instruction=C2=B3. So how does the unwinder know that it sh=
ouldn't<br>
propagate the exception?<br>
<br>
Here's how it could work in theory: the compiler knows that bar() is no=
except,<br>
so wherever it is called, it can surround the code with enough EH tables to=
<br>
indicate that the unwinding should stop and std::terminate() be called. Thi=
s<br>
way, the tail-call optimisation can be performed and we don't have loss=
of<br>
performance, and still have noexcept support.<br>
<br>
That's what I thought GCC was doing. When I tested (just now, to write =
this<br>
email), it turns out that it doesn't actually work:<br>
<br>
=C2=A0 =C2=A0 =C2=A0 =C2=A0 <a href=3D"https://gcc.gnu.org/bugzilla/show_bu=
g.cgi?id=3D82081" rel=3D"nofollow" target=3D"_blank" onmousedown=3D"this.hr=
ef=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2Fgcc.gnu.org%2Fbugzi=
lla%2Fshow_bug.cgi%3Fid%3D82081\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFQi=
XY2A6IuvEdo_gC_xvZwTPOpaQ';return true;" onclick=3D"this.href=3D'ht=
tps://www.google.com/url?q\x3dhttps%3A%2F%2Fgcc.gnu.org%2Fbugzilla%2Fshow_b=
ug.cgi%3Fid%3D82081\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFQiXY2A6IuvEdo_=
gC_xvZwTPOpaQ';return true;">https://gcc.gnu.org/bugzilla/<wbr>show_bug=
..cgi?id=3D82081</a><br>
<br>
<br>
[1] GCC has one type of unswallowable (read, "must rethrow") exce=
ption and<br>
that's the POSIX synchronous thread termination. Since it can't be =
swallowed,<br>
what happens if a POSIX cancellation point function is called and does canc=
el?<br>
Experimentation needed.<br>
<br>
[2] Actually, the personality routine, which is what tells libunwind how to=
<br>
deal with C++ exceptions. The unwinder can be used for other languages too.=
<br>
<br>
[3] Technically, the next instruction.<br>
<span>--<br>
Thiago Macieira - thiago (AT) <a href=3D"http://macieira.info" rel=3D"nofol=
low" target=3D"_blank" onmousedown=3D"this.href=3D'http://www.google.co=
m/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQ=
jCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.href=3D&=
#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x3dD\x2=
6sntz\x3d1\x26usg\x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;">=
macieira.info</a> - thiago (AT) <a href=3D"http://kde.org" rel=3D"nofollow"=
target=3D"_blank" onmousedown=3D"this.href=3D'http://www.google.com/ur=
l?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNHGRJdo5=
_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'http:/=
/www.google.com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1\x26us=
g\x3dAFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;">kde.org</a><br>
=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center<br>
<br>
</span><span>--<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"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"=
E53jedlIAAAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:&=
#39;;return true;" onclick=3D"this.href=3D'javascript:';return true=
;">std-proposal...@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"javascript:" target=3D"_bla=
nk" gdf-obfuscated-mailto=3D"E53jedlIAAAJ" rel=3D"nofollow" onmousedown=3D"=
this.href=3D'javascript:';return true;" onclick=3D"this.href=3D'=
;javascript:';return true;">std-pr...@isocpp.org</a>.<br>
</span>To view this discussion on the web visit <a href=3D"https://groups.g=
oogle.com/a/isocpp.org/d/msgid/std-proposals/2012927.WGKi1cKNH1%40tjmaciei-=
mobl1" rel=3D"nofollow" target=3D"_blank" onmousedown=3D"this.href=3D'h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/2012927.WGKi1cK=
NH1%40tjmaciei-mobl1';return true;" onclick=3D"this.href=3D'https:/=
/groups.google.com/a/isocpp.org/d/msgid/std-proposals/2012927.WGKi1cKNH1%40=
tjmaciei-mobl1';return true;">https://groups.google.com/a/<wbr>isocpp.o=
rg/d/msgid/std-<wbr>proposals/2012927.WGKi1cKNH1%<wbr>40tjmaciei-mobl1</a>.=
<br>
</blockquote></div><br></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/43cad6c5-27b5-4924-8276-4e82516524ba%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/43cad6c5-27b5-4924-8276-4e82516524ba=
%40isocpp.org</a>.<br />
------=_Part_3991_328162609.1504413622668--
------=_Part_3990_736158931.1504413622667--
.
Author: crusader.mike@gmail.com
Date: Sat, 2 Sep 2017 21:52:58 -0700 (PDT)
Raw View
------=_Part_1093_1623242325.1504414378769
Content-Type: multipart/alternative;
boundary="----=_Part_1094_1980224200.1504414378769"
------=_Part_1094_1980224200.1504414378769
Content-Type: text/plain; charset="UTF-8"
On Saturday, September 2, 2017 at 11:40:22 PM UTC-5, crusad...@gmail.com
wrote:
>
> On Saturday, September 2, 2017 at 8:06:33 AM UTC-5, Patrice Roy wrote:
>>
>> @crusader.mike : should you decide to push forward with a proposal, I
>> suggest you make sure the following case is discussed :
>>
>> X *p = new X[10];
>> // suppose new[](10 * sizeof(X)) succeeds
>> // suppose X::X() is non-trivial and succeeds for p[0]..p[7], say
>> // suppose X::X() throws for p[8]
>> // X::~X() is applied to p[7], p[6], ... but throws for p[3]... Ouch
>>
>
> This particular scenario will work just fine -- exception thrown by p[8]
> ctor will be leading, exception thrown by p[3] dtor will be trailing.
>
Note:
Coding anything that calls in-place dtor in a loop won't be fun... I just
realized that this is what you probably had in mind
--
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/5caa3a8a-02ad-4dd4-95a1-52a139514f49%40isocpp.org.
------=_Part_1094_1980224200.1504414378769
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Saturday, September 2, 2017 at 11:40:22 PM UTC-5, crusa=
d...@gmail.com wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;m=
argin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=
=3D"ltr">On Saturday, September 2, 2017 at 8:06:33 AM UTC-5, Patrice Roy wr=
ote:<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr"><div><div><div=
><div><div><div><div>@crusader.mike : should you decide to push forward wit=
h a proposal, I suggest you make sure the following case is discussed :<br>=
<br></div>X *p =3D new X[10];<br></div>// suppose new[](10 * sizeof(X)) suc=
ceeds<br></div>// suppose X::X() is non-trivial and succeeds for p[0]..p[7]=
, say<br></div>// suppose X::X() throws for p[8]<br></div>// X::~X() is app=
lied to p[7], p[6], ... but throws for p[3]... Ouch<br></div></div></div></=
blockquote><div><br></div><div>This particular scenario will work just fine=
-- exception thrown by p[8] ctor will be leading, exception thrown by p[3]=
dtor will be trailing.</div></div></blockquote><div><br></div><div>Note:</=
div><div>Coding anything that calls in-place dtor in a loop won't be fu=
n... I just realized that this is what you probably had in mind</div><div>=
=C2=A0</div></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/5caa3a8a-02ad-4dd4-95a1-52a139514f49%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/5caa3a8a-02ad-4dd4-95a1-52a139514f49=
%40isocpp.org</a>.<br />
------=_Part_1094_1980224200.1504414378769--
------=_Part_1093_1623242325.1504414378769--
.
Author: crusader.mike@gmail.com
Date: Sat, 2 Sep 2017 22:04:38 -0700 (PDT)
Raw View
------=_Part_3981_313594337.1504415078504
Content-Type: multipart/alternative;
boundary="----=_Part_3982_979448064.1504415078505"
------=_Part_3982_979448064.1504415078505
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
On Saturday, September 2, 2017 at 1:44:12 AM UTC-5, Thiago Macieira wrote:
>
> On Friday, 1 September 2017 19:32:31 PDT Howard Hinnant wrote:=20
> > I must admit that I do not yet see how the code generation for=20
> might_throw=20
> > is going to be smart enough to call terminate(). Looking further=E2=80=
=A6=20
>
> Yeah, took me a while to figure it out too.=20
>
> First, the compiler does not need to generate an explicit call to=20
> std::terminate() (or clang's trampoline __clang_call_terminate). This is=
=20
> what=20
> I was arguing to Ville and Crusader.Mike: the EH table is sufficient,=20
> describing=20
> what kind of exception is allowed to leave that scope and how (destructor=
s=20
> to=20
> be run), or which ones have handlers for. In the specific case of=20
> noexcept, the=20
> table is simple: no exception can leave it=C2=B9. So the compiler simply =
marks=20
> the=20
> entire function from begin to end (hence the ".LFBn" and ".LFEn" labels)=
=20
> with=20
> one attribute.=20
>
> If the throwing function does throw, when the unwinder unwinds back to=20
> bar(),=20
> it will notice that this frame is noexcept and therefore the unwinder=20
> itself=C2=B2=20
> will call std::terminate().=20
>
>
> But what really bugged me for a while was the fact that GCC generated a=
=20
> tail-=20
> call optimisation. Under some other conditions I tried, the function=20
> generated=20
> was:=20
> sub %rsp, 8=20
> call might_throw()=20
> retq=20
>
> In this case it's quite clear and is what I mentioned before. But the=20
> function=20
> generated was:=20
>
> jmp might_throw()=20
>
> The problem with this is that there IS NO frame to be unwound in the firs=
t=20
> place. There's no EH table because the unwinder would never find stack=20
> trace=20
> leading to this instruction=C2=B3. So how does the unwinder know that it=
=20
> shouldn't=20
> propagate the exception?=20
>
> Here's how it could work in theory: the compiler knows that bar() is=20
> noexcept,=20
> so wherever it is called, it can surround the code with enough EH tables=
=20
> to=20
> indicate that the unwinding should stop and std::terminate() be called.=
=20
> This=20
> way, the tail-call optimisation can be performed and we don't have loss o=
f=20
> performance, and still have noexcept support.=20
>
> That's what I thought GCC was doing. When I tested (just now, to write=20
> this=20
> email), it turns out that it doesn't actually work:=20
>
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D82081=20
>
Wait a second... Does it mean that that ideal code (that only GCC=20
generates) is the result of a bug in optimization? I.e. in reality -- there=
=20
is a non-zero price for 'enforcing' noexcept even with GCC?
Isn't it what Andrew's reply implies?
=20
> [1] GCC has one type of unswallowable (read, "must rethrow") exception an=
d=20
> that's the POSIX synchronous thread termination. Since it can't be=20
> swallowed,=20
> what happens if a POSIX cancellation point function is called and does=20
> cancel?=20
> Experimentation needed.=20
>
> [2] Actually, the personality routine, which is what tells libunwind how=
=20
> to=20
> deal with C++ exceptions. The unwinder can be used for other languages=20
> too.=20
>
> [3] Technically, the next instruction.=20
> --=20
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org=20
> Software Architect - Intel Open Source Technology Center=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/8d92aa1f-b5f7-43de-8f33-73d1a50dfcc3%40isocpp.or=
g.
------=_Part_3982_979448064.1504415078505
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Saturday, September 2, 2017 at 1:44:12 AM UTC-5=
, Thiago Macieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: =
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Fri=
day, 1 September 2017 19:32:31 PDT Howard Hinnant wrote:
<br>> I must admit that I do not yet see how the code generation for mig=
ht_throw
<br>> is going to be smart enough to call terminate(). =C2=A0Looking fur=
ther=E2=80=A6
<br>
<br>Yeah, took me a while to figure it out too.
<br>
<br>First, the compiler does not need to generate an explicit call to=20
<br>std::terminate() (or clang's trampoline __clang_call_terminate). Th=
is is what=20
<br>I was arguing to Ville and Crusader.Mike: the EH table is sufficient, d=
escribing=20
<br>what kind of exception is allowed to leave that scope and how (destruct=
ors to=20
<br>be run), or which ones have handlers for. In the specific case of noexc=
ept, the=20
<br>table is simple: no exception can leave it=C2=B9. So the compiler simpl=
y marks the=20
<br>entire function from begin to end (hence the ".LFBn" and &quo=
t;.LFEn" labels) with=20
<br>one attribute.
<br>
<br>If the throwing function does throw, when the unwinder unwinds back to =
bar(),=20
<br>it will notice that this frame is noexcept and therefore the unwinder i=
tself=C2=B2=20
<br>will call std::terminate().
<br>
<br>
<br>But what really bugged me for a while was the fact that GCC generated a=
tail-
<br>call optimisation. Under some other conditions I tried, the function ge=
nerated=20
<br>was:
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0sub=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0%rsp, 8
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0call=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0might_<wbr>throw()
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0retq
<br>
<br>In this case it's quite clear and is what I mentioned before. But t=
he function=20
<br>generated was:
<br>
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0jmp=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0might_<wbr>throw()
<br>
<br>The problem with this is that there IS NO frame to be unwound in the fi=
rst=20
<br>place. There's no EH table because the unwinder would never find st=
ack trace=20
<br>leading to this instruction=C2=B3. So how does the unwinder know that i=
t shouldn't=20
<br>propagate the exception?
<br>
<br>Here's how it could work in theory: the compiler knows that bar() i=
s noexcept,=20
<br>so wherever it is called, it can surround the code with enough EH table=
s to=20
<br>indicate that the unwinding should stop and std::terminate() be called.=
This=20
<br>way, the tail-call optimisation can be performed and we don't have =
loss of=20
<br>performance, and still have noexcept support.
<br>
<br>That's what I thought GCC was doing. When I tested (just now, to wr=
ite this=20
<br>email), it turns out that it doesn't actually work:
<br>
<br>=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0<a href=3D"https://gcc.=
gnu.org/bugzilla/show_bug.cgi?id=3D82081" target=3D"_blank" rel=3D"nofollow=
" onmousedown=3D"this.href=3D'https://www.google.com/url?q\x3dhttps%3A%=
2F%2Fgcc.gnu.org%2Fbugzilla%2Fshow_bug.cgi%3Fid%3D82081\x26sa\x3dD\x26sntz\=
x3d1\x26usg\x3dAFQjCNFQiXY2A6IuvEdo_gC_xvZwTPOpaQ';return true;" onclic=
k=3D"this.href=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2Fgcc.gnu=
..org%2Fbugzilla%2Fshow_bug.cgi%3Fid%3D82081\x26sa\x3dD\x26sntz\x3d1\x26usg\=
x3dAFQjCNFQiXY2A6IuvEdo_gC_xvZwTPOpaQ';return true;">https://gcc.gnu.or=
g/<wbr>bugzilla/show_bug.cgi?id=3D82081</a>
<br></blockquote><div><br></div><div>Wait a second... Does it mean that tha=
t ideal code (that only GCC generates) is the result of a bug in optimizati=
on? I.e. in reality -- there is a non-zero price for 'enforcing' no=
except even with GCC?</div><div><br></div><div>Isn't it what Andrew'=
;s reply implies?</div><div><br></div><div>=C2=A0</div><blockquote class=3D=
"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc s=
olid;padding-left: 1ex;">[1] GCC has one type of unswallowable (read, "=
;must rethrow") exception and=20
<br>that's the POSIX synchronous thread termination. Since it can't=
be swallowed,=20
<br>what happens if a POSIX cancellation point function is called and does =
cancel?=20
<br>Experimentation needed.
<br>
<br>[2] Actually, the personality routine, which is what tells libunwind ho=
w to=20
<br>deal with C++ exceptions. The unwinder can be used for other languages =
too.
<br>
<br>[3] Technically, the next instruction.
<br>--=20
<br>Thiago Macieira - thiago (AT) <a href=3D"http://macieira.info" target=
=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.goo=
gle.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x3dD\x26sntz\x3d1\x26usg\=
x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.hr=
ef=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x=
3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return t=
rue;">macieira.info</a> - thiago (AT) <a href=3D"http://kde.org" target=3D"=
_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.google.=
com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNH=
GRJdo5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'=
http://www.google.com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1=
\x26usg\x3dAFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;">kde.org</a=
>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>
<br></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/8d92aa1f-b5f7-43de-8f33-73d1a50dfcc3%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/8d92aa1f-b5f7-43de-8f33-73d1a50dfcc3=
%40isocpp.org</a>.<br />
------=_Part_3982_979448064.1504415078505--
------=_Part_3981_313594337.1504415078504--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Sun, 3 Sep 2017 12:30:49 +0300
Raw View
On 3 September 2017 at 07:40, <crusader.mike@gmail.com> wrote:
>
>
> On Saturday, September 2, 2017 at 8:06:33 AM UTC-5, Patrice Roy wrote:
>>
>> @crusader.mike : should you decide to push forward with a proposal, I
>> suggest you make sure the following case is discussed :
>>
>> X *p = new X[10];
>> // suppose new[](10 * sizeof(X)) succeeds
>> // suppose X::X() is non-trivial and succeeds for p[0]..p[7], say
>> // suppose X::X() throws for p[8]
>> // X::~X() is applied to p[7], p[6], ... but throws for p[3]... Ouch
>
>
> This particular scenario will work just fine -- exception thrown by p[8]
> ctor will be leading, exception thrown by p[3] dtor will be trailing.
This particular scenario will lead to the end result that some
elements of the array were
destroyed and some were not, with no way to know which ones were and
which ones weren't.
I have no trouble finding users who would say that's not 'fine'.
--
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/CAFk2RUaeAo%2BJC7OA6rtLs2eRxYfhzXuJNdZYL5khkBo%3D8XTe2A%40mail.gmail.com.
.
Author: Bengt Gustafsson <bengt.gustafsson@beamways.com>
Date: Sun, 3 Sep 2017 04:15:39 -0700 (PDT)
Raw View
------=_Part_4144_1871325886.1504437339513
Content-Type: multipart/alternative;
boundary="----=_Part_4145_275888679.1504437339513"
------=_Part_4145_275888679.1504437339513
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
Den s=C3=B6ndag 3 september 2017 kl. 11:30:52 UTC+2 skrev Ville Voutilainen=
:
>
> On 3 September 2017 at 07:40, <crusad...@gmail.com <javascript:>> wrote:=
=20
> >=20
> >=20
> > On Saturday, September 2, 2017 at 8:06:33 AM UTC-5, Patrice Roy wrote:=
=20
> >>=20
> >> @crusader.mike : should you decide to push forward with a proposal, I=
=20
> >> suggest you make sure the following case is discussed :=20
> >>=20
> >> X *p =3D new X[10];=20
> >> // suppose new[](10 * sizeof(X)) succeeds=20
> >> // suppose X::X() is non-trivial and succeeds for p[0]..p[7], say=20
> >> // suppose X::X() throws for p[8]=20
> >> // X::~X() is applied to p[7], p[6], ... but throws for p[3]... Ouch=
=20
> >=20
> >=20
> > This particular scenario will work just fine -- exception thrown by p[8=
]=20
> > ctor will be leading, exception thrown by p[3] dtor will be trailing.=
=20
>
>
> This particular scenario will lead to the end result that some=20
> elements of the array were=20
> destroyed and some were not, with no way to know which ones were and=20
> which ones weren't.=20
>
No, I don't think so:
If a destructor exception is thrown while an exception is already in flight=
=20
the intention is to abort execution of _user defined_ destructor code=20
(containing the secondary throw), attach the new exception to the already=
=20
present exception(s) and then continue the unwinding with the next=20
destructor. In this case, if X is a type which has some members with=20
destructors and which in itself has a destructor that just threw for the=20
p[3] object, the unwinding would continue by destroying the members of=20
p[3], then calling the X dtor for p[2] with two exceptions in flight. I see=
=20
no principal issue with this, all members of all X instances in the array=
=20
have had their destructors called. I suspect this is how it already works=
=20
in current compilers if the first exception thrown is for an array element,=
=20
although I'm not sure if it is well defined in the standard.
The hard part is specifyig the catching side, where there is still=20
significant work to do to define the rules. With arrays this becomes nasty=
=20
as there may easily be several exceptions of the same type in flight. I=20
have no good answers to this, but here is a sketch:
When unwinding hits a try block it examines each catch clause. As soon as a=
=20
matching one is found for _any_ of the exceptions in flight the catch=20
clause is executed for the matching exception. If the exception is not=20
rethrown it is dropped from the active exception list and destroyed=20
(hopefully without a destructor exception). Then the procedure restarts on=
=20
the first catch clause with the remaining exceptions. This definition=20
prevents exceptions from ever escaping a matching catch block, which is=20
important. If a catch clause rethrows the exception it is processing it=20
must be prevented from being reprocessed by the same catch again but is not=
=20
permanently removed from the set of in-flight exceptions.
Well, I see lots of practical problems with using such a complicated system=
=20
in reality, as well as lots of extra hidden code for compilers to generate=
=20
for each try block, but it seems to be possible to specify at least. Not=20
that I think it is warranted, which the complexity of even a strawman=20
description like mine shows.=20
Handling destructor exceptions in the exception objects, exceptions in=20
functions called by destructors with exceptions already in flight are areas=
=20
which also need thorough investigation. I think the latter may be a=20
showstopper as such exceptions may be intended to be caught before returned=
=20
to the original destructor _without catching the original in flight=20
exception_. These raise formidable problems to specify, I think. This is=20
why I prompted the original proposer to write a little more formal text and=
=20
more examples showing such cases and how they can be reasonably resolved,=
=20
but I haven't seen any.
=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/9fbd78fd-a141-41e6-8448-25cb97fe9f58%40isocpp.or=
g.
------=_Part_4145_275888679.1504437339513
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Den s=C3=B6ndag 3 september 2017 kl. 11:30:52 UTC+2 skrev =
Ville Voutilainen:<blockquote class=3D"gmail_quote" style=3D"margin: 0;marg=
in-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 3 Septemb=
er 2017 at 07:40, =C2=A0<<a href=3D"javascript:" target=3D"_blank" gdf-o=
bfuscated-mailto=3D"YVnoCKmLAAAJ" rel=3D"nofollow" onmousedown=3D"this.href=
=3D'javascript:';return true;" onclick=3D"this.href=3D'javascri=
pt:';return true;">crusad...@gmail.com</a>> wrote:
<br>>
<br>>
<br>> On Saturday, September 2, 2017 at 8:06:33 AM UTC-5, Patrice Roy wr=
ote:
<br>>>
<br>>> @crusader.mike : should you decide to push forward with a prop=
osal, I
<br>>> suggest you make sure the following case is discussed :
<br>>>
<br>>> X *p =3D new X[10];
<br>>> // suppose new[](10 * sizeof(X)) succeeds
<br>>> // suppose X::X() is non-trivial and succeeds for p[0]..p[7], =
say
<br>>> // suppose X::X() throws for p[8]
<br>>> // X::~X() is applied to p[7], p[6], ... but throws for p[3]..=
.. Ouch
<br>>
<br>>
<br>> This particular scenario will work just fine -- exception thrown b=
y p[8]
<br>> ctor will be leading, exception thrown by p[3] dtor will be traili=
ng.
<br>
<br>
<br>This particular scenario will lead to the end result that some
<br>elements of the array were
<br>destroyed and some were not, with no way to know which ones were and
<br>which ones weren't.
<br></blockquote><div><br></div>No, I don't think so:<div><br></div><di=
v>If a destructor exception is thrown while an exception is already in flig=
ht the intention is to abort execution of _user defined_ destructor code (c=
ontaining the secondary throw), attach the new exception to the already pre=
sent exception(s) and then continue the unwinding with the next destructor.=
In this case, if X is a type which has some members with destructors and w=
hich in itself has a destructor that just threw for the p[3] object, the un=
winding would continue by destroying the members of p[3], then calling the =
X dtor for p[2] with two exceptions in flight. I see no principal issue wit=
h this, all members of all X instances in the array have had their destruct=
ors called. I suspect this is how it already works in current compilers if =
the first exception thrown is for an array element, although I'm not su=
re if it is well defined in the standard.</div><div><br></div><div>The hard=
part is specifyig the catching side, where there is still significant work=
to do to define the rules. With arrays this becomes nasty as there may eas=
ily be several exceptions of the same type in flight. I have no good answer=
s to this, but here is a sketch:</div><div><br></div><div>When unwinding hi=
ts a try block it examines each catch clause. As soon as a matching one is =
found for _any_ of the exceptions in flight the catch clause is executed fo=
r the matching exception. If the exception is not rethrown it is dropped fr=
om the active exception list and destroyed (hopefully without a destructor =
exception). Then the procedure restarts on the first catch clause with the =
remaining exceptions. This definition prevents exceptions from ever escapin=
g a matching catch block, which is important. If a catch clause rethrows th=
e exception it is processing it must be prevented from being reprocessed by=
the same catch again but is not permanently removed from the set of in-fli=
ght exceptions.</div><div><br></div><div>Well, I see lots of practical prob=
lems with using such a complicated system in reality, as well as lots of ex=
tra hidden code for compilers to generate for each try block, but it seems =
to be possible to specify at least. Not that I think it is warranted, which=
the complexity of even a strawman description like mine shows.=C2=A0</div>=
<div><br></div><div>Handling destructor exceptions in the exception objects=
, exceptions in functions called by destructors with exceptions already=C2=
=A0in flight are areas which also need thorough investigation. I think the =
latter may be a showstopper as such exceptions may be intended to be caught=
before returned to the original destructor _without catching the original =
in flight exception_. These raise formidable problems to specify, I think. =
This is why I prompted the original proposer to write a little more formal =
text and more examples showing such cases and how they can be reasonably re=
solved, but I haven't seen any.</div><div><br><br></div><div>=C2=A0<br>=
</div></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/9fbd78fd-a141-41e6-8448-25cb97fe9f58%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/9fbd78fd-a141-41e6-8448-25cb97fe9f58=
%40isocpp.org</a>.<br />
------=_Part_4145_275888679.1504437339513--
------=_Part_4144_1871325886.1504437339513--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Sun, 3 Sep 2017 14:32:26 +0300
Raw View
On 3 September 2017 at 14:15, Bengt Gustafsson
<bengt.gustafsson@beamways.com> wrote:
> Den s=C3=B6ndag 3 september 2017 kl. 11:30:52 UTC+2 skrev Ville Voutilain=
en:
>>
>> On 3 September 2017 at 07:40, <crusad...@gmail.com> wrote:
>> >
>> >
>> > On Saturday, September 2, 2017 at 8:06:33 AM UTC-5, Patrice Roy wrote:
>> >>
>> >> @crusader.mike : should you decide to push forward with a proposal, I
>> >> suggest you make sure the following case is discussed :
>> >>
>> >> X *p =3D new X[10];
>> >> // suppose new[](10 * sizeof(X)) succeeds
>> >> // suppose X::X() is non-trivial and succeeds for p[0]..p[7], say
>> >> // suppose X::X() throws for p[8]
>> >> // X::~X() is applied to p[7], p[6], ... but throws for p[3]... Ouch
>> >
>> >
>> > This particular scenario will work just fine -- exception thrown by p[=
8]
>> > ctor will be leading, exception thrown by p[3] dtor will be trailing.
>>
>>
>> This particular scenario will lead to the end result that some
>> elements of the array were
>> destroyed and some were not, with no way to know which ones were and
>> which ones weren't.
>
>
> No, I don't think so:
>
> If a destructor exception is thrown while an exception is already in flig=
ht
> the intention is to abort execution of _user defined_ destructor code
> (containing the secondary throw), attach the new exception to the already
> present exception(s) and then continue the unwinding with the next
> destructor. In this case, if X is a type which has some members with
> destructors and which in itself has a destructor that just threw for the
> p[3] object, the unwinding would continue by destroying the members of p[=
3],
> then calling the X dtor for p[2] with two exceptions in flight. I see no
> principal issue with this, all members of all X instances in the array ha=
ve
> had their destructors called. I suspect this is how it already works in
> current compilers if the first exception thrown is for an array element,
> although I'm not sure if it is well defined in the standard.
>
> The hard part is specifyig the catching side, where there is still
> significant work to do to define the rules. With arrays this becomes nast=
y
> as there may easily be several exceptions of the same type in flight. I h=
ave
> no good answers to this, but here is a sketch:
>
> When unwinding hits a try block it examines each catch clause. As soon as=
a
> matching one is found for _any_ of the exceptions in flight the catch cla=
use
> is executed for the matching exception. If the exception is not rethrown =
it
> is dropped from the active exception list and destroyed (hopefully withou=
t a
> destructor exception). Then the procedure restarts on the first catch cla=
use
> with the remaining exceptions. This definition prevents exceptions from e=
ver
> escaping a matching catch block, which is important. If a catch clause
> rethrows the exception it is processing it must be prevented from being
> reprocessed by the same catch again but is not permanently removed from t=
he
> set of in-flight exceptions.
>
> Well, I see lots of practical problems with using such a complicated syst=
em
> in reality, as well as lots of extra hidden code for compilers to generat=
e
> for each try block, but it seems to be possible to specify at least. Not
> that I think it is warranted, which the complexity of even a strawman
> description like mine shows.
Possible, yes. Now that we have what I described as status quo, the
follow-up question
I had in mind is this:
Assuming that this facility handles that array case so that nothing
leaks, with what
overhead will it do so?
I have heard all sorts of aspiring proposal authors say "this idea
will make throwing
an exception a heavier operation than it is today, but since it's so
heavy already, that's
not a problem". To that, I say "good luck". :)
>
> Handling destructor exceptions in the exception objects, exceptions in
> functions called by destructors with exceptions already in flight are are=
as
> which also need thorough investigation. I think the latter may be a
> showstopper as such exceptions may be intended to be caught before return=
ed
> to the original destructor _without catching the original in flight
> exception_. These raise formidable problems to specify, I think. This is =
why
> I prompted the original proposer to write a little more formal text and m=
ore
> examples showing such cases and how they can be reasonably resolved, but =
I
> haven't seen any.
Show me an implementation that is ABI-compatible with what we have
today. I don't
consider a formal specification that hasn't been tested anywhere near
sufficient.
--=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/CAFk2RUZzK1k9gTtaegXe6%3D1p%3DUMnui4dYDZannqvakV=
aAeRzTQ%40mail.gmail.com.
.
Author: Bengt Gustafsson <bengt.gustafsson@beamways.com>
Date: Sun, 3 Sep 2017 11:48:50 -0700 (PDT)
Raw View
------=_Part_871_1282896509.1504464530329
Content-Type: multipart/alternative;
boundary="----=_Part_872_2031259929.1504464530330"
------=_Part_872_2031259929.1504464530330
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
The change would still be limited to nothrow(false) destructors so it is=20
opt-in which I think kills the performance reduction argument.
By the way I had a question regarding nothrow(false): Is this automatically=
=20
transitive to classes having by value members with nothrow(false)=20
destructors? Or is it an error to omit it?
Den s=C3=B6ndag 3 september 2017 kl. 13:32:29 UTC+2 skrev Ville Voutilainen=
:
>
> On 3 September 2017 at 14:15, Bengt Gustafsson=20
> <bengt.gu...@beamways.com <javascript:>> wrote:=20
> > Den s=C3=B6ndag 3 september 2017 kl. 11:30:52 UTC+2 skrev Ville Voutila=
inen:=20
> >>=20
> >> On 3 September 2017 at 07:40, <crusad...@gmail.com> wrote:=20
> >> >=20
> >> >=20
> >> > On Saturday, September 2, 2017 at 8:06:33 AM UTC-5, Patrice Roy=20
> wrote:=20
> >> >>=20
> >> >> @crusader.mike : should you decide to push forward with a proposal,=
=20
> I=20
> >> >> suggest you make sure the following case is discussed :=20
> >> >>=20
> >> >> X *p =3D new X[10];=20
> >> >> // suppose new[](10 * sizeof(X)) succeeds=20
> >> >> // suppose X::X() is non-trivial and succeeds for p[0]..p[7], say=
=20
> >> >> // suppose X::X() throws for p[8]=20
> >> >> // X::~X() is applied to p[7], p[6], ... but throws for p[3]... Ouc=
h=20
> >> >=20
> >> >=20
> >> > This particular scenario will work just fine -- exception thrown by=
=20
> p[8]=20
> >> > ctor will be leading, exception thrown by p[3] dtor will be trailing=
..=20
> >>=20
> >>=20
> >> This particular scenario will lead to the end result that some=20
> >> elements of the array were=20
> >> destroyed and some were not, with no way to know which ones were and=
=20
> >> which ones weren't.=20
> >=20
> >=20
> > No, I don't think so:=20
> >=20
> > If a destructor exception is thrown while an exception is already in=20
> flight=20
> > the intention is to abort execution of _user defined_ destructor code=
=20
> > (containing the secondary throw), attach the new exception to the=20
> already=20
> > present exception(s) and then continue the unwinding with the next=20
> > destructor. In this case, if X is a type which has some members with=20
> > destructors and which in itself has a destructor that just threw for th=
e=20
> > p[3] object, the unwinding would continue by destroying the members of=
=20
> p[3],=20
> > then calling the X dtor for p[2] with two exceptions in flight. I see n=
o=20
> > principal issue with this, all members of all X instances in the array=
=20
> have=20
> > had their destructors called. I suspect this is how it already works in=
=20
> > current compilers if the first exception thrown is for an array element=
,=20
> > although I'm not sure if it is well defined in the standard.=20
> >=20
> > The hard part is specifyig the catching side, where there is still=20
> > significant work to do to define the rules. With arrays this becomes=20
> nasty=20
> > as there may easily be several exceptions of the same type in flight. I=
=20
> have=20
> > no good answers to this, but here is a sketch:=20
> >=20
> > When unwinding hits a try block it examines each catch clause. As soon=
=20
> as a=20
> > matching one is found for _any_ of the exceptions in flight the catch=
=20
> clause=20
> > is executed for the matching exception. If the exception is not rethrow=
n=20
> it=20
> > is dropped from the active exception list and destroyed (hopefully=20
> without a=20
> > destructor exception). Then the procedure restarts on the first catch=
=20
> clause=20
> > with the remaining exceptions. This definition prevents exceptions from=
=20
> ever=20
> > escaping a matching catch block, which is important. If a catch clause=
=20
> > rethrows the exception it is processing it must be prevented from being=
=20
> > reprocessed by the same catch again but is not permanently removed from=
=20
> the=20
> > set of in-flight exceptions.=20
> >=20
> > Well, I see lots of practical problems with using such a complicated=20
> system=20
> > in reality, as well as lots of extra hidden code for compilers to=20
> generate=20
> > for each try block, but it seems to be possible to specify at least. No=
t=20
> > that I think it is warranted, which the complexity of even a strawman=
=20
> > description like mine shows.=20
>
> Possible, yes. Now that we have what I described as status quo, the=20
> follow-up question=20
> I had in mind is this:=20
>
> Assuming that this facility handles that array case so that nothing=20
> leaks, with what=20
> overhead will it do so?=20
>
> I have heard all sorts of aspiring proposal authors say "this idea=20
> will make throwing=20
> an exception a heavier operation than it is today, but since it's so=20
> heavy already, that's=20
> not a problem". To that, I say "good luck". :)=20
>
>
> >=20
> > Handling destructor exceptions in the exception objects, exceptions in=
=20
> > functions called by destructors with exceptions already in flight are=
=20
> areas=20
> > which also need thorough investigation. I think the latter may be a=20
> > showstopper as such exceptions may be intended to be caught before=20
> returned=20
> > to the original destructor _without catching the original in flight=20
> > exception_. These raise formidable problems to specify, I think. This i=
s=20
> why=20
> > I prompted the original proposer to write a little more formal text and=
=20
> more=20
> > examples showing such cases and how they can be reasonably resolved, bu=
t=20
> I=20
> > haven't seen any.=20
>
> Show me an implementation that is ABI-compatible with what we have=20
> today. I don't=20
> consider a formal specification that hasn't been tested anywhere near=20
> sufficient.=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.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/28321799-6e8e-471e-9387-f1b6b7b10bdb%40isocpp.or=
g.
------=_Part_872_2031259929.1504464530330
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">The change would still be limited to nothrow(false) destru=
ctors so it is opt-in which I think kills the performance reduction argumen=
t.<div><br></div><div>By the way I had a question regarding nothrow(false):=
Is this automatically transitive to classes having by value members with n=
othrow(false) destructors? Or is it an error to omit it?</div><div><br><br>=
Den s=C3=B6ndag 3 september 2017 kl. 13:32:29 UTC+2 skrev Ville Voutilainen=
:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;">On 3 September 2017 at 14:15,=
Bengt Gustafsson
<br><<a href=3D"javascript:" target=3D"_blank" gdf-obfuscated-mailto=3D"=
0lzX-UuSAAAJ" rel=3D"nofollow" onmousedown=3D"this.href=3D'javascript:&=
#39;;return true;" onclick=3D"this.href=3D'javascript:';return true=
;">bengt.gu...@beamways.com</a><wbr>> wrote:
<br>> Den s=C3=B6ndag 3 september 2017 kl. 11:30:52 UTC+2 skrev Ville Vo=
utilainen:
<br>>>
<br>>> On 3 September 2017 at 07:40, =C2=A0<<a>crusad...@gmail.com=
</a>> wrote:
<br>>> >
<br>>> >
<br>>> > On Saturday, September 2, 2017 at 8:06:33 AM UTC-5, Patri=
ce Roy wrote:
<br>>> >>
<br>>> >> @crusader.mike : should you decide to push forward wi=
th a proposal, I
<br>>> >> suggest you make sure the following case is discussed=
:
<br>>> >>
<br>>> >> X *p =3D new X[10];
<br>>> >> // suppose new[](10 * sizeof(X)) succeeds
<br>>> >> // suppose X::X() is non-trivial and succeeds for p[0=
]..p[7], say
<br>>> >> // suppose X::X() throws for p[8]
<br>>> >> // X::~X() is applied to p[7], p[6], ... but throws f=
or p[3]... Ouch
<br>>> >
<br>>> >
<br>>> > This particular scenario will work just fine -- exception=
thrown by p[8]
<br>>> > ctor will be leading, exception thrown by p[3] dtor will =
be trailing.
<br>>>
<br>>>
<br>>> This particular scenario will lead to the end result that some
<br>>> elements of the array were
<br>>> destroyed and some were not, with no way to know which ones we=
re and
<br>>> which ones weren't.
<br>>
<br>>
<br>> No, I don't think so:
<br>>
<br>> If a destructor exception is thrown while an exception is already =
in flight
<br>> the intention is to abort execution of _user defined_ destructor c=
ode
<br>> (containing the secondary throw), attach the new exception to the =
already
<br>> present exception(s) and then continue the unwinding with the next
<br>> destructor. In this case, if X is a type which has some members wi=
th
<br>> destructors and which in itself has a destructor that just threw f=
or the
<br>> p[3] object, the unwinding would continue by destroying the member=
s of p[3],
<br>> then calling the X dtor for p[2] with two exceptions in flight. I =
see no
<br>> principal issue with this, all members of all X instances in the a=
rray have
<br>> had their destructors called. I suspect this is how it already wor=
ks in
<br>> current compilers if the first exception thrown is for an array el=
ement,
<br>> although I'm not sure if it is well defined in the standard.
<br>>
<br>> The hard part is specifyig the catching side, where there is still
<br>> significant work to do to define the rules. With arrays this becom=
es nasty
<br>> as there may easily be several exceptions of the same type in flig=
ht. I have
<br>> no good answers to this, but here is a sketch:
<br>>
<br>> When unwinding hits a try block it examines each catch clause. As =
soon as a
<br>> matching one is found for _any_ of the exceptions in flight the ca=
tch clause
<br>> is executed for the matching exception. If the exception is not re=
thrown it
<br>> is dropped from the active exception list and destroyed (hopefully=
without a
<br>> destructor exception). Then the procedure restarts on the first ca=
tch clause
<br>> with the remaining exceptions. This definition prevents exceptions=
from ever
<br>> escaping a matching catch block, which is important. If a catch cl=
ause
<br>> rethrows the exception it is processing it must be prevented from =
being
<br>> reprocessed by the same catch again but is not permanently removed=
from the
<br>> set of in-flight exceptions.
<br>>
<br>> Well, I see lots of practical problems with using such a complicat=
ed system
<br>> in reality, as well as lots of extra hidden code for compilers to =
generate
<br>> for each try block, but it seems to be possible to specify at leas=
t. Not
<br>> that I think it is warranted, which the complexity of even a straw=
man
<br>> description like mine shows.
<br>
<br>Possible, yes. Now that we have what I described as status quo, the
<br>follow-up question
<br>I had in mind is this:
<br>
<br>Assuming that this facility handles that array case so that nothing
<br>leaks, with what
<br>overhead will it do so?
<br>
<br>I have heard all sorts of aspiring proposal authors say "this idea
<br>will make throwing
<br>an exception a heavier operation than it is today, but since it's s=
o
<br>heavy already, that's
<br>not a problem". To that, I say "good luck". :)
<br>
<br>
<br>>
<br>> Handling destructor exceptions in the exception objects, exception=
s in
<br>> functions called by destructors with exceptions already in flight =
are areas
<br>> which also need thorough investigation. I think the latter may be =
a
<br>> showstopper as such exceptions may be intended to be caught before=
returned
<br>> to the original destructor _without catching the original in fligh=
t
<br>> exception_. These raise formidable problems to specify, I think. T=
his is why
<br>> I prompted the original proposer to write a little more formal tex=
t and more
<br>> examples showing such cases and how they can be reasonably resolve=
d, but I
<br>> haven't seen any.
<br>
<br>Show me an implementation that is ABI-compatible with what we have
<br>today. I don't
<br>consider a formal specification that hasn't been tested anywhere ne=
ar
<br>sufficient.
<br></blockquote></div></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/28321799-6e8e-471e-9387-f1b6b7b10bdb%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/28321799-6e8e-471e-9387-f1b6b7b10bdb=
%40isocpp.org</a>.<br />
------=_Part_872_2031259929.1504464530330--
------=_Part_871_1282896509.1504464530329--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Sun, 3 Sep 2017 22:10:24 +0300
Raw View
On 3 September 2017 at 21:48, Bengt Gustafsson
<bengt.gustafsson@beamways.com> wrote:
> By the way I had a question regarding nothrow(false): Is this automatically
> transitive to classes having by value members with nothrow(false)
> destructors? Or is it an error to omit it?
It's automatically transitive.
--
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/CAFk2RUbtykZn33yKcFfiQEwGXGO-_5RA3%2Bk7ZFwQ3BdW1zgKwg%40mail.gmail.com.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Sun, 03 Sep 2017 21:23:12 -0300
Raw View
On Sunday, 3 September 2017 01:40:22 -03 crusader.mike@gmail.com wrote:
> You operate on assumption that exception from dtor means "destruction
> failed". User can choose to design a class that *tries* to do smth. I.e. in
> dtor it tries to shutdown the reactor and that attempt is guaranteed to
> complete (i.e. object done it's work and can be discarded) with certain
> outcome (which is, if bad, reported via exception for further processing).
> Similar to fclose() in C.
That's not what fclose() does.
If fclose() fails, then it may or may not have properly destroyed the object.
In some implementations, you may be allowed to retry -- but it's not a
portable assumption, which is why this API is bad.
What is portable is the conclusion that if it failed, then it failed to
destroy properly.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/3263913.0vlgrHRD03%40tjmaciei-mobl1.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Sun, 03 Sep 2017 21:27:39 -0300
Raw View
On Sunday, 3 September 2017 21:23:12 -03 Thiago Macieira wrote:
> On Sunday, 3 September 2017 01:40:22 -03 crusader.mike@gmail.com wrote:
> > You operate on assumption that exception from dtor means "destruction
> > failed". User can choose to design a class that *tries* to do smth. I.e.
> > in
> > dtor it tries to shutdown the reactor and that attempt is guaranteed to
> > complete (i.e. object done it's work and can be discarded) with certain
> > outcome (which is, if bad, reported via exception for further processing).
> > Similar to fclose() in C.
>
> That's not what fclose() does.
>
> If fclose() fails, then it may or may not have properly destroyed the
> object. In some implementations, you may be allowed to retry -- but it's
> not a portable assumption, which is why this API is bad.
Let me rephrase: if fclose() fails, then it may or may not have actually
destroyed the object, properly or not. It did definitely fail to destroy
properly.
> What is portable is the conclusion that if it failed, then it failed to
> destroy properly.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/1675260.MHDbycJtGJ%40tjmaciei-mobl1.
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Sun, 03 Sep 2017 21:34:43 -0300
Raw View
On Sunday, 3 September 2017 02:04:38 -03 crusader.mike@gmail.com wrote:
> > That's what I thought GCC was doing. When I tested (just now, to write
> > this
> >
> > email), it turns out that it doesn't actually work:
> > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82081
>
> Wait a second... Does it mean that that ideal code (that only GCC
> generates) is the result of a bug in optimization?
Yes. The optimiser optimised too much. The way the current EH code is
generated requires the frame to exist and the jmp instruction replaced the
caller's frame with the callee's.
> I.e. in reality -- there
> is a non-zero price for 'enforcing' noexcept even with GCC?
No, that's not a correct conclusion. See my bug report: there are two possible
solutions to the problem, one which implies expanding the EH tables for all
callers of noexcept functions (to enforce the noexceptness) and one that
implies retaining the stack frame so it can be found by the unwinder. Only
this latter solution would have an impact in execution code size and therefore
a theoretical impact on execution performance.
One solution is the dual of the other and will solve the problem for only have
of a mixed-rebuild codebase. So it's not a given which one the GCC (and
probably all IA-64 C++ ABI folks) will choose.
Also note that this only applies to optimisations that replace a stack frame
with another, which is what tail call optimisation does. There could be other
things that do the same (SJLJ comes to mind, but needs investigation).
Finally, note the "theoretical". Replacing a tail call optimisation with a
sub/call/ret sequence may not have any real, measurable impact in performance
in the real world.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/1698798.OptzhlgWUC%40tjmaciei-mobl1.
.
Author: crusader.mike@gmail.com
Date: Wed, 6 Sep 2017 15:35:59 -0700 (PDT)
Raw View
------=_Part_0_1978240628.1504737359369
Content-Type: multipart/alternative;
boundary="----=_Part_1_1508653455.1504737359372"
------=_Part_1_1508653455.1504737359372
Content-Type: text/plain; charset="UTF-8"
On Sunday, September 3, 2017 at 7:34:49 PM UTC-5, Thiago Macieira wrote:
>
> On Sunday, 3 September 2017 02:04:38 -03 crusad...@gmail.com <javascript:>
> wrote:
> > > That's what I thought GCC was doing. When I tested (just now, to write
> > > this
> > >
> > > email), it turns out that it doesn't actually work:
> > > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82081
> >
> > Wait a second... Does it mean that that ideal code (that only GCC
> > generates) is the result of a bug in optimization?
>
> Yes. The optimiser optimised too much. The way the current EH code is
> generated requires the frame to exist and the jmp instruction replaced the
> caller's frame with the callee's.
>
> > I.e. in reality -- there
> > is a non-zero price for 'enforcing' noexcept even with GCC?
>
> No, that's not a correct conclusion. See my bug report: there are two
> possible
> solutions to the problem, one which implies expanding the EH tables for
> all
> callers of noexcept functions (to enforce the noexceptness) and one that
> implies retaining the stack frame so it can be found by the unwinder. Only
> this latter solution would have an impact in execution code size and
> therefore
> a theoretical impact on execution performance.
Yes, I read entire bug report and (I think) understood both solutions you
proposed. If GCC folks decide to choose second approach -- this means
enforcing noexcept will have non-zero cost (regardless how small it is). Is
it correct?
About first approach -- will it work in case when function gets inlined?
I.e. can GCC "mark" block of code as noexcept (as opposed to marking
function as noexcept)?
One solution is the dual of the other and will solve the problem for only
> have
> of a mixed-rebuild codebase. So it's not a given which one the GCC (and
> probably all IA-64 C++ ABI folks) will choose.
>
> Also note that this only applies to optimisations that replace a stack
> frame
> with another, which is what tail call optimisation does. There could be
> other
> things that do the same (SJLJ comes to mind, but needs investigation).
>
It is kind of confirms my gut feeling -- noexcept affects optimizations
available to compiler (and therefore in general case incurs non-zero cost).
Now, once function is inlined this could be offset by the fact that
compiler can reorder certain operations if he knows that some of them will
never trigger unwinding. Unfortunately I lack knowledge to have a strong
opinion on this case.
In any case (with exception of latest GCC versions) most implementations
seem to have non-zero noexcept enforcement costs and therefore original
statement (about avoiding noexcept on inline functions) is still correct,
it seems. That is until these implementations get fixed. If they ever
will...
> Finally, note the "theoretical". Replacing a tail call optimisation with a
> sub/call/ret sequence may not have any real, measurable impact in
> performance
> in the real world.
>
> --
> Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
> Software Architect - Intel Open Source Technology Center
>
>
--
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/1c24b01c-c1e8-4538-8268-2f8907f3035e%40isocpp.org.
------=_Part_1_1508653455.1504737359372
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Sunday, September 3, 2017 at 7:34:49 PM UTC-5, =
Thiago Macieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;=
margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On Sunda=
y, 3 September 2017 02:04:38 -03 <a href=3D"javascript:" target=3D"_blank" =
gdf-obfuscated-mailto=3D"h1UIJf28AAAJ" rel=3D"nofollow" onmousedown=3D"this=
..href=3D'javascript:';return true;" onclick=3D"this.href=3D'jav=
ascript:';return true;">crusad...@gmail.com</a> wrote:
<br>> > That's what I thought GCC was doing. When I tested (just =
now, to write
<br>> > this
<br>> >=20
<br>> > email), it turns out that it doesn't actually work:
<br>> > =C2=A0 =C2=A0 =C2=A0 =C2=A0 <a href=3D"https://gcc.gnu.org/bu=
gzilla/show_bug.cgi?id=3D82081" target=3D"_blank" rel=3D"nofollow" onmoused=
own=3D"this.href=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2Fgcc.g=
nu.org%2Fbugzilla%2Fshow_bug.cgi%3Fid%3D82081\x26sa\x3dD\x26sntz\x3d1\x26us=
g\x3dAFQjCNFQiXY2A6IuvEdo_gC_xvZwTPOpaQ';return true;" onclick=3D"this.=
href=3D'https://www.google.com/url?q\x3dhttps%3A%2F%2Fgcc.gnu.org%2Fbug=
zilla%2Fshow_bug.cgi%3Fid%3D82081\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNF=
QiXY2A6IuvEdo_gC_xvZwTPOpaQ';return true;">https://gcc.gnu.org/bugzilla=
/<wbr>show_bug.cgi?id=3D82081</a>
<br>>=20
<br>> Wait a second... Does it mean that that ideal code (that only GCC
<br>> generates) is the result of a bug in optimization?=20
<br>
<br>Yes. The optimiser optimised too much. The way the current EH code is=
=20
<br>generated requires the frame to exist and the jmp instruction replaced =
the=20
<br>caller's frame with the callee's.
<br>
<br>> I.e. in reality -- there
<br>> is a non-zero price for 'enforcing' noexcept even with GCC=
?
<br>
<br>No, that's not a correct conclusion. See my bug report: there are t=
wo possible=20
<br>solutions to the problem, one which implies expanding the EH tables for=
all=20
<br>callers of noexcept functions (to enforce the noexceptness) and one tha=
t=20
<br>implies retaining the stack frame so it can be found by the unwinder. O=
nly=20
<br>this latter solution would have an impact in execution code size and th=
erefore=20
<br>a theoretical impact on execution performance. </blockquote><div><br></=
div><div>Yes, I read entire bug report and (I think) understood both soluti=
ons you proposed. If GCC folks decide to choose second approach -- this mea=
ns enforcing noexcept will have non-zero cost (regardless how small it is).=
Is it correct?</div><div><br></div><div>About first approach -- will it wo=
rk in case when function gets inlined? I.e. can GCC "mark" block =
of code as noexcept (as opposed to marking function as noexcept)?</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;">One =
solution is the dual of the other and will solve the problem for only have=
=20
<br>of a mixed-rebuild codebase. So it's not a given which one the GCC =
(and=20
<br>probably all IA-64 C++ ABI folks) will choose.
<br>
<br>Also note that this only applies to optimisations that replace a stack =
frame=20
<br>with another, which is what tail call optimisation does. There could be=
other=20
<br>things that do the same (SJLJ comes to mind, but needs investigation).
<br></blockquote><div><br></div><div>It is kind of confirms my gut feeling =
-- noexcept affects optimizations available to compiler (and therefore in g=
eneral case incurs non-zero cost). Now, once function is inlined this could=
be offset by the fact that compiler can reorder certain operations if he k=
nows that some of them will never trigger unwinding. Unfortunately I lack k=
nowledge to have a strong opinion on this case.</div><div><br></div><div>In=
any case (with exception of latest GCC versions) most implementations seem=
to have non-zero noexcept enforcement costs and therefore original stateme=
nt (about avoiding noexcept on inline functions) is still correct, it seems=
.. That is until these implementations get fixed. If they ever will...</div>=
<div><br></div><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"=
margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;=
">Finally, note the "theoretical". Replacing a tail call optimisa=
tion with a=20
<br>sub/call/ret sequence may not have any real, measurable impact in perfo=
rmance=20
<br>in the real world.
<br>
<br>--=20
<br>Thiago Macieira - thiago (AT) <a href=3D"http://macieira.info" target=
=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.goo=
gle.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x3dD\x26sntz\x3d1\x26usg\=
x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return true;" onclick=3D"this.hr=
ef=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fmacieira.info\x26sa\x=
3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEswDUBNCNanbu7euhqLn_62FW8ag';return t=
rue;">macieira.info</a> - thiago (AT) <a href=3D"http://kde.org" target=3D"=
_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http://www.google.=
com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNH=
GRJdo5_JYG1DowztwAHAKs80XSA';return true;" onclick=3D"this.href=3D'=
http://www.google.com/url?q\x3dhttp%3A%2F%2Fkde.org\x26sa\x3dD\x26sntz\x3d1=
\x26usg\x3dAFQjCNHGRJdo5_JYG1DowztwAHAKs80XSA';return true;">kde.org</a=
>
<br>=C2=A0 =C2=A0Software Architect - Intel Open Source Technology Center
<br>
<br></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/1c24b01c-c1e8-4538-8268-2f8907f3035e%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/1c24b01c-c1e8-4538-8268-2f8907f3035e=
%40isocpp.org</a>.<br />
------=_Part_1_1508653455.1504737359372--
------=_Part_0_1978240628.1504737359369--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Wed, 06 Sep 2017 20:41:42 -0300
Raw View
On Wednesday, 6 September 2017 19:35:59 -03 crusader.mike@gmail.com wrote:
> > No, that's not a correct conclusion. See my bug report: there are two
> > possible
> > solutions to the problem, one which implies expanding the EH tables for
> > all
> > callers of noexcept functions (to enforce the noexceptness) and one that
> > implies retaining the stack frame so it can be found by the unwinder. Only
> > this latter solution would have an impact in execution code size and
> > therefore
> > a theoretical impact on execution performance.
>
> Yes, I read entire bug report and (I think) understood both solutions you
> proposed. If GCC folks decide to choose second approach -- this means
> enforcing noexcept will have non-zero cost (regardless how small it is). Is
> it correct?
Yes, it would forbid tail-call optimisation, if -fexceptions is active.
> About first approach -- will it work in case when function gets inlined?
> I.e. can GCC "mark" block of code as noexcept (as opposed to marking
> function as noexcept)?
If it's inlined, it's equal to the first solution: use EH tables to ensure any
exception in that code does not escape and does lead to std::terminate().
Whether the optimiser is able to make such calls is an open question, but it's
theoretically possible and permitted by the ABI.
> > Also note that this only applies to optimisations that replace a stack
> > frame
> > with another, which is what tail call optimisation does. There could be
> > other
> > things that do the same (SJLJ comes to mind, but needs investigation).
>
> It is kind of confirms my gut feeling -- noexcept affects optimizations
> available to compiler (and therefore in general case incurs non-zero cost).
I've already proven that it's theoretically possible to have zero cost,
assuming the ABI permits it. I've come with hard facts, you have gut feeling.
This part of the discussion is closed.
Whether the current optimisers are able to take this into account is a
different question. But even if they aren't, since it's theoretically
possible, a future version could.
> In any case (with exception of latest GCC versions) most implementations
> seem to have non-zero noexcept enforcement costs and therefore original
> statement (about avoiding noexcept on inline functions) is still correct,
> it seems. That is until these implementations get fixed. If they ever
> will...
Please replace "with the exception of latest GCC versions, most
implementations" with "MSVC". The IA-64 C++ ABI has zero runtime cost[*] for
exception tables, including that for noexcept functions. The only cost is file
size.
Aside from the IA-64 C++ ABI and MSVC's, with Oracle axing Sun products today,
the only other ABI of relevance I can think of is IBM's on AIX.
[*] compared to code with exceptions & unwinding enabled. If you disable the
ability to unwind, on some architectures the compiler does have a little more
freedom for optimisations.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/2373039.LilWhWGyaG%40tjmaciei-mobl1.
.
Author: crusader.mike@gmail.com
Date: Wed, 6 Sep 2017 17:05:35 -0700 (PDT)
Raw View
------=_Part_11_1412917699.1504742735297
Content-Type: multipart/alternative;
boundary="----=_Part_12_454352163.1504742735297"
------=_Part_12_454352163.1504742735297
Content-Type: text/plain; charset="UTF-8"
On Wednesday, September 6, 2017 at 6:41:49 PM UTC-5, Thiago Macieira wrote:
>
> On Wednesday, 6 September 2017 19:35:59 -03 crusad...@gmail.com
> <javascript:> wrote:
> > In any case (with exception of latest GCC versions) most implementations
> > seem to have non-zero noexcept enforcement costs and therefore original
> > statement (about avoiding noexcept on inline functions) is still
> correct,
> > it seems. That is until these implementations get fixed. If they ever
> > will...
>
> Please replace "with the exception of latest GCC versions, most
> implementations" with "MSVC". The IA-64 C++ ABI has zero runtime cost[*]
> for
> exception tables, including that for noexcept functions. The only cost is
> file
> size.
>
> Aside from the IA-64 C++ ABI and MSVC's, with Oracle axing Sun products
> today,
> the only other ABI of relevance I can think of is IBM's on AIX.
>
True. :-/
> [*] compared to code with exceptions & unwinding enabled. If you disable
> the
> ability to unwind, on some architectures the compiler does have a little
> more
> freedom for optimisations.
>
Actually I had a question about this -- since noexcept doesn't require
unwind, does it mean that (at least theoretically) code within noexcept
function can be compiled with 'ability to unwind' disabled?
Do you know if GCC actually takes advantage of that?
Thanks for info, btw. It is very much appreciated.
Regards,
Michael.
--
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/dc2d44eb-fac0-45df-bc58-7063f7250a5b%40isocpp.org.
------=_Part_12_454352163.1504742735297
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, September 6, 2017 at 6:41:49 PM UTC-=
5, Thiago Macieira wrote:<blockquote class=3D"gmail_quote" style=3D"margin:=
0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On We=
dnesday, 6 September 2017 19:35:59 -03 <a href=3D"javascript:" target=3D"_b=
lank" gdf-obfuscated-mailto=3D"KEjPJdbhCgAJ" rel=3D"nofollow" onmousedown=
=3D"this.href=3D'javascript:';return true;" onclick=3D"this.href=3D=
'javascript:';return true;">crusad...@gmail.com</a> wrote:
<br>> In any case (with exception of latest GCC versions) most implement=
ations
<br>> seem to have non-zero noexcept enforcement costs and therefore ori=
ginal
<br>> statement (about avoiding noexcept on inline functions) is still c=
orrect,
<br>> it seems. That is until these implementations get fixed. If they e=
ver
<br>> will...
<br>
<br>Please replace "with the exception of latest GCC versions, most=20
<br>implementations" with "MSVC". The IA-64 C++ ABI has zero=
runtime cost[*] for=20
<br>exception tables, including that for noexcept functions. The only cost =
is file=20
<br>size.
<br>
<br>Aside from the IA-64 C++ ABI and MSVC's, with Oracle axing Sun prod=
ucts today,=20
<br>the only other ABI of relevance I can think of is IBM's on AIX.
<br></blockquote><div><br></div><div>True. :-/</div><div><br></div><div>=C2=
=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: =
0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">[*] compared to code =
with exceptions & unwinding enabled. If you disable the=20
<br>ability to unwind, on some architectures the compiler does have a littl=
e more=20
<br>freedom for optimisations.
<br></blockquote><div><br></div><div>Actually I had a question about this -=
- since noexcept doesn't require unwind, does it mean that (at least th=
eoretically) code within noexcept function can be compiled with 'abilit=
y to unwind' disabled?=C2=A0</div><div><br></div><div>Do you know if GC=
C actually takes advantage of that?</div><div><br></div><div>Thanks for inf=
o, btw. It is very much appreciated.</div><div><br></div><div>Regards,</div=
><div>Michael.</div></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/dc2d44eb-fac0-45df-bc58-7063f7250a5b%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/dc2d44eb-fac0-45df-bc58-7063f7250a5b=
%40isocpp.org</a>.<br />
------=_Part_12_454352163.1504742735297--
------=_Part_11_1412917699.1504742735297--
.
Author: Thiago Macieira <thiago@macieira.org>
Date: Thu, 07 Sep 2017 07:51:10 -0300
Raw View
On Wednesday, 6 September 2017 21:05:35 -03 crusader.mike@gmail.com wrote:
> > [*] compared to code with exceptions & unwinding enabled. If you disable
> > the
> > ability to unwind, on some architectures the compiler does have a little
> > more
> > freedom for optimisations.
>
> Actually I had a question about this -- since noexcept doesn't require
> unwind, does it mean that (at least theoretically) code within noexcept
> function can be compiled with 'ability to unwind' disabled?
>
> Do you know if GCC actually takes advantage of that?
noexcept still requires the ability to tell the compiler to call
std::terminate if something is thrown. Removing unwind information is
equivalent to UB: if we remove the frame pointer, the unwinder can't tell that
there was a frame there, so it may skip it and go to the next frame, which
could in turn have a handler.
Or it could just crash.
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
--
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/1798819.QJT2ozuKSo%40tjmaciei-mobl1.
.