Topic: Catch block without try block
Author: Hans Erickson <hans.p.erickson@gmail.com>
Date: Fri, 29 Apr 2016 11:03:10 -0700 (PDT)
Raw View
------=_Part_1469_506123617.1461952990939
Content-Type: multipart/alternative;
boundary="----=_Part_1470_1761067899.1461952990940"
------=_Part_1470_1761067899.1461952990940
Content-Type: text/plain; charset=UTF-8
I have an idea for exception handling that I am informally proposing to
gauge interest and also to see if anyone knows of any similar existing
proposals. If there is interest, I can write up something that is more
formal.
Basically, I am proposing allowing a stand-alone catch block without a
corresponding try block that would catch exceptions whenever
std::uncaught_exceptions() is greater than zero. This could be called "RAII
catch" or "destructor catch." The motivation for this comes from the case
where a class or set of classes needs to catch one of a set of exceptions,
map that exception to one in a second set, and then throw an exception from
that second set.
For example, if a class is implemented using a vendor library that throws a
certain set of vendor-specific exceptions but the developer of the class
doesn't want to expose the clients of the class to the exceptions that are
defined in the vendor library, a reasonable thing to do might be to define
a second set of exceptions that the clients do know about. Then the class
could catch each vendor-specific exception and throw an exception that the
clients know about.
This tends to be tedious and error-prone, however, if more than one method
in the class needs to do the same mapping. If the mapping changes, it may
be necessary to duplicate those changes for each method in the class.
My proposed solution would be to allow a catch block that would only catch
exceptions that were already in the process of being thrown, meaning that
they would only be useful in destructors. That way, the developer for the
class could create an RAII class containing a map in the destructor,
instantiate that class at the beginning of each method for which the
mapping must be done, and modify only that RAII class when the mapping
needs to change. Below I give a very simple example of how a destructor for
such a class might be implemented. To avoid confusing these catch
statements with the normal try-catch statements, I have prefixed each of
these with a tilde, though the syntax is negotiable.
RaiiCatch::~RaiiCatch()
{
~catch (const vendor::file_not_found_error& e)
{
throw mynamespace::file_not_found_error(e.filename());
}
~catch (const vendor::network_error& e)
{
throw mynamespace::network_error(mynamespace::map_network_error(e.type
()));
}
}
I haven't written up a formal proposal because I wanted to get some
feedback first.
So basically,
-
Is this a good idea or a dumb idea?
-
Has this problem already been solved a different way?
-
Could this problem be solved in a better way?
Thanks,
- Hans
--
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/30eb53c3-4ac8-4275-9dba-5f195ff8b634%40isocpp.org.
------=_Part_1470_1761067899.1461952990940
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;ma=
rgin-bottom:0pt;" id=3D"docs-internal-guid-713921f8-6327-88fe-eb3e-b9b76e5d=
4090"><span style=3D"font-size:14.666666666666666px;font-family:Arial;color=
:#000000;background-color:transparent;font-weight:400;font-style:normal;fon=
t-variant:normal;text-decoration:none;vertical-align:baseline;">I have an i=
dea for exception handling that I am informally proposing to gauge interest=
and also to see if anyone knows of any similar existing proposals. If ther=
e is interest, I can write up something that is more formal.</span></p><br>=
<p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt;"=
><span style=3D"font-size:14.666666666666666px;font-family:Arial;color:#000=
000;background-color:transparent;font-weight:400;font-style:normal;font-var=
iant:normal;text-decoration:none;vertical-align:baseline;">Basically, I am =
proposing allowing a stand-alone catch block without a corresponding try bl=
ock that would catch exceptions whenever std::uncaught_exceptions() is grea=
ter than zero. This could be called "RAII catch" or "destruc=
tor catch." The motivation for this comes from the case where a class =
or set of classes needs to catch one of a set of exceptions, map that excep=
tion to one in a second set, and then throw an exception from that second s=
et.</span></p><br><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;m=
argin-bottom:0pt;"><span style=3D"font-size:14.666666666666666px;font-famil=
y:Arial;color:#000000;background-color:transparent;font-weight:400;font-sty=
le:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;=
">For example, if a class is implemented using a vendor library that throws=
a certain set of vendor-specific exceptions but the developer of the class=
doesn't want to expose the clients of the class to the exceptions that=
are defined in the vendor library, a reasonable thing to do might be to de=
fine a second set of exceptions that the clients do know about. Then the cl=
ass could catch each vendor-specific exception and throw an exception that =
the clients know about.</span></p><br><p dir=3D"ltr" style=3D"line-height:1=
..38;margin-top:0pt;margin-bottom:0pt;"><span style=3D"font-size:14.66666666=
6666666px;font-family:Arial;color:#000000;background-color:transparent;font=
-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vert=
ical-align:baseline;">This tends to be tedious and error-prone, however, if=
more than one method in the class needs to do the same mapping. If the map=
ping changes, it may be necessary to duplicate those changes for each metho=
d in the class.</span></p><br><p dir=3D"ltr" style=3D"line-height:1.38;marg=
in-top:0pt;margin-bottom:0pt;"><span style=3D"font-size:14.666666666666666p=
x;font-family:Arial;color:#000000;background-color:transparent;font-weight:=
400;font-style:normal;font-variant:normal;text-decoration:none;vertical-ali=
gn:baseline;">My proposed solution would be to allow a catch block that wou=
ld only catch exceptions that were already in the process of being thrown, =
meaning that they would only be useful in destructors. That way, the develo=
per for the class could create an RAII class containing a map in the destru=
ctor, instantiate that class at the beginning of each method for which the =
mapping must be done, and modify only that RAII class when the mapping need=
s to change. Below I give a very simple example of how a destructor for suc=
h a class might be implemented. To avoid confusing these catch statements w=
ith the normal try-catch statements, I have prefixed each of these with a t=
ilde, though the syntax is negotiable.</span></p><p dir=3D"ltr" style=3D"li=
ne-height:1.38;margin-top:0pt;margin-bottom:0pt;"><br><span style=3D"font-s=
ize:14.666666666666666px;font-family:Arial;color:#000000;background-color:t=
ransparent;font-weight:400;font-style:normal;font-variant:normal;text-decor=
ation:none;vertical-align:baseline;"></span></p><div class=3D"prettyprint" =
style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, 187, =
187); border-style: solid; border-width: 1px; word-wrap: break-word;"><code=
class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"color: =
#606;" class=3D"styled-by-prettify">RaiiCatch</span><span style=3D"color: #=
660;" class=3D"styled-by-prettify">::~</span><span style=3D"color: #606;" c=
lass=3D"styled-by-prettify">RaiiCatch</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">()</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"><br></span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br>=C2=A0 </span><span style=3D"color: #660;" class=3D"styled-by-prett=
ify">~</span><span style=3D"color: #008;" class=3D"styled-by-prettify">catc=
h</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span styl=
e=3D"color: #008;" class=3D"styled-by-prettify">const</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify"> vendor</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify">file_not_found_error</span><span style=3D"c=
olor: #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>=C2=A0 </span><span style=3D"color: #660;" class=3D=
"styled-by-prettify">{</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">throw</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> mynamespace</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify">file_not_found_error</span><span style=3D"color: #660;" class=3D"s=
tyled-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">filename=
</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 </spa=
n><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span s=
tyle=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: #008;" class=3D"styled-by-prettify">catch</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">(</span><span style=3D"color: #008;" class=3D"=
styled-by-prettify">const</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify"> vendor</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">network_error</span><span style=3D"color: #660;" class=3D"styled-by-pre=
ttify">&</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
"> e</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: #660;" class=3D"styled-by-prettify">{</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </spa=
n><span style=3D"color: #008;" class=3D"styled-by-prettify">throw</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"> mynamespace</span><=
span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify">network_error</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"=
color: #000;" class=3D"styled-by-prettify">mynamespace</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">::</span><span style=3D"color: =
#000;" class=3D"styled-by-prettify">map_network_error</span><span style=3D"=
color: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify">e</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">.</span><span style=3D"color: #000;" class=3D"styl=
ed-by-prettify">type</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 </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><=
/div></code></div><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;m=
argin-bottom:0pt;"><span style=3D"font-size:14.666666666666666px;font-famil=
y:'Courier New';color:#000000;background-color:transparent;font-wei=
ght:400;font-style:normal;font-variant:normal;text-decoration:none;vertical=
-align:baseline;"><br></span></p><p dir=3D"ltr" style=3D"line-height:1.38;m=
argin-top:0pt;margin-bottom:0pt;" id=3D"docs-internal-guid-713921f8-6328-f8=
b8-7914-57a8745a0ee8"><span style=3D"font-size:14.666666666666666px;font-fa=
mily:Arial;color:#000000;background-color:transparent;font-weight:400;font-=
style:normal;font-variant:normal;text-decoration:none;vertical-align:baseli=
ne;">I haven't written up a formal proposal because I wanted to get som=
e feedback first.</span></p><p dir=3D"ltr" style=3D"line-height:1.38;margin=
-top:0pt;margin-bottom:0pt;"><span style=3D"font-size:14.666666666666666px;=
font-family:Arial;color:#000000;background-color:transparent;font-weight:40=
0;font-style:normal;font-variant:normal;text-decoration:none;vertical-align=
:baseline;">So basically,</span></p><ul style=3D"margin-top:0pt;margin-bott=
om:0pt;"><li dir=3D"ltr" style=3D"list-style-type:disc;font-size:14.6666666=
66666666px;font-family:Arial;color:#000000;background-color:transparent;fon=
t-weight:400;font-style:normal;font-variant:normal;text-decoration:none;ver=
tical-align:baseline;"><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:=
0pt;margin-bottom:0pt;"><span style=3D"font-size:14.666666666666666px;font-=
family:Arial;color:#000000;background-color:transparent;font-weight:400;fon=
t-style:normal;font-variant:normal;text-decoration:none;vertical-align:base=
line;">Is this a good idea or a dumb idea?</span></p></li><li dir=3D"ltr" s=
tyle=3D"list-style-type:disc;font-size:14.666666666666666px;font-family:Ari=
al;color:#000000;background-color:transparent;font-weight:400;font-style:no=
rmal;font-variant:normal;text-decoration:none;vertical-align:baseline;"><p =
dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><s=
pan style=3D"font-size:14.666666666666666px;font-family:Arial;color:#000000=
;background-color:transparent;font-weight:400;font-style:normal;font-varian=
t:normal;text-decoration:none;vertical-align:baseline;">Has this problem al=
ready been solved a different way?</span></p></li><li dir=3D"ltr" style=3D"=
list-style-type:disc;font-size:14.666666666666666px;font-family:Arial;color=
:#000000;background-color:transparent;font-weight:400;font-style:normal;fon=
t-variant:normal;text-decoration:none;vertical-align:baseline;"><p dir=3D"l=
tr" style=3D"line-height:1.38;margin-top:0pt;margin-bottom:0pt;"><span styl=
e=3D"font-size:14.666666666666666px;font-family:Arial;color:#000000;backgro=
und-color:transparent;font-weight:400;font-style:normal;font-variant:normal=
;text-decoration:none;vertical-align:baseline;">Could this problem be solve=
d in a better way?</span></p></li></ul><p><br></p><p>Thanks,</p><p><br></p>=
<p>- Hans<br></p><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;ma=
rgin-bottom:0pt;"><br><span style=3D"font-size:14.666666666666666px;font-fa=
mily:'Courier New';color:#000000;background-color:transparent;font-=
weight:400;font-style:normal;font-variant:normal;text-decoration:none;verti=
cal-align:baseline;"></span></p></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/30eb53c3-4ac8-4275-9dba-5f195ff8b634%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/30eb53c3-4ac8-4275-9dba-5f195ff8b634=
%40isocpp.org</a>.<br />
------=_Part_1470_1761067899.1461952990940--
------=_Part_1469_506123617.1461952990939--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 29 Apr 2016 11:38:14 -0700 (PDT)
Raw View
------=_Part_9438_1739970509.1461955094396
Content-Type: multipart/alternative;
boundary="----=_Part_9439_1736506344.1461955094396"
------=_Part_9439_1736506344.1461955094396
Content-Type: text/plain; charset=UTF-8
On Friday, April 29, 2016 at 2:03:11 PM UTC-4, Hans Erickson wrote:
> The motivation for this comes from the case where a class or set of
> classes needs to catch one of a set of exceptions, map that exception to
> one in a second set, and then throw an exception from that second set.
>
>
For example, if a class is implemented using a vendor library that throws a
> certain set of vendor-specific exceptions but the developer of the class
> doesn't want to expose the clients of the class to the exceptions that are
> defined in the vendor library, a reasonable thing to do might be to define
> a second set of exceptions that the clients do know about. Then the class
> could catch each vendor-specific exception and throw an exception that the
> clients know about.
>
Let me express my understanding of the situation as you seem to have
described it.
There is a system X. And system X offers functions (classes don't throw
exceptions; functions do) which throw exceptions defined in system X.
There is a system Y which offers a number of functions that, as an
implementation detail, call into system X. Since system X is an
implementation detail, system Y wants to make sure that its users do not
have to know about system X or have any direct dependency on it. Therefore,
when system Y calls a system X function that can throw something, system Y
needs to catch the exception and either handle it or convert it into system
Y's exception(s).
> My proposed solution would be to allow a catch block that would only catch
> exceptions that were already in the process of being thrown, meaning that
> they would only be useful in destructors.
>
Given the previous understanding of the situation, what you are proposing *does
not solve the problem*. Allow me to demonstrate:
namespace systemY
{
void func()
{
RaiiCatch converter;
systemX::otherFunc();
}
}
You presumably intend for `converter` to be able to convert exceptions
thrown by the call to `systemX::otherFunc()`. Well, that's just not how
exception handling works.
The order of operations for exception handling is:
1: Function throws exception.
2: Compiler-generated code looks through the call stack for a `try` block
with a `catch` block for that exception type.
3: If an appropriate `catch` block is found, the stack is unwound to that
point.
4: Execution continues from the `catch` block.
`RaiiCatch::~RaiiCatch` will only be called *at step 3*, when the stack is
unwound. By that point, the `catch` block you're going to has already been
decided on. Stack unwinding doesn't happen until you already know where
you're going. And if no `catch` block is found in step 2, `std::terminate`
will be called *without* the stack having been unwound.
What you seem to intend is for `RaiiCatch::~RaiiCatch` to somehow interfere
in step 2.
What you really want is to be able to define a named sequence of catch
blocks, then impose those catch blocks on an arbitrary function. That
*cannot* be done through object destructors. You need some kind of language
syntax for that, probably based on function-level try blocks
<http://en.cppreference.com/w/cpp/language/function-try-block>.
Of course, you could use macros with function try blocks. The macro would
declare the sequence of `catch` statements, and would have to be manually
applied to the end of each function (along with the initial `try`).
--
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/ce3231c1-dc25-4967-9bf1-50aadc99239d%40isocpp.org.
------=_Part_9439_1736506344.1461955094396
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, April 29, 2016 at 2:03:11 PM UTC-4, Hans Ericks=
on wrote:<br><div></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"><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-b=
ottom:0pt"><span style=3D"font-size:14.666666666666666px;font-family:Arial;=
color:#000000;background-color:transparent;font-weight:400;font-style:norma=
l;font-variant:normal;text-decoration:none;vertical-align:baseline">The mot=
ivation for this comes from the case where a class or set of classes needs =
to catch one of a set of exceptions, map that exception to one in a second =
set, and then throw an exception from that second set.</span></p></div></bl=
ockquote><blockquote style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px s=
olid rgb(204, 204, 204); padding-left: 1ex;" class=3D"gmail_quote"><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"><p dir=3D"ltr" style=3D"line-height:1.38;margin-top:0pt;margin-bot=
tom:0pt"><span style=3D"font-size:14.666666666666666px;font-family:Arial;co=
lor:#000000;background-color:transparent;font-weight:400;font-style:normal;=
font-variant:normal;text-decoration:none;vertical-align:baseline">For examp=
le, if a class is implemented using a vendor library that throws a certain =
set of vendor-specific exceptions but the developer of the class doesn'=
t want to expose the clients of the class to the exceptions that are define=
d in the vendor library, a reasonable thing to do might be to define a seco=
nd set of exceptions that the clients do know about. Then the class could c=
atch each vendor-specific exception and throw an exception that the clients=
know about.</span></p></div></blockquote><div><br>Let me express my unders=
tanding of the situation as you seem to have described it.<br><br>There
is a system X. And system X offers functions (classes don't throw=20
exceptions; functions do) which throw exceptions defined in system X.<br><b=
r>There
is a system Y which offers a number of functions that, as an=20
implementation detail, call into system X. Since system X is an=20
implementation detail, system Y wants to make sure that its users do not
have to know about system X or have any direct dependency on it. Therefore=
,=20
when system Y calls a system X function that can throw something, system
Y needs to catch the exception and either handle it or convert it into=20
system Y's exception(s).<br>=C2=A0<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"><span style=3D"font-size:14.666666666666=
666px;font-family:Arial;color:#000000;background-color:transparent;font-wei=
ght:400;font-style:normal;font-variant:normal;text-decoration:none;vertical=
-align:baseline">My proposed solution would be to allow a catch block that =
would only catch exceptions that were already in the process of being throw=
n, meaning that they would only be useful in destructors.</span></div></blo=
ckquote><div><br>Given the previous understanding of the situation, what yo=
u are proposing <i>does not solve the problem</i>. Allow me to demonstrate:=
<br><br><div class=3D"prettyprint" style=3D"background-color: rgb(250, 250,=
250); border-color: rgb(187, 187, 187); border-style: solid; border-width:=
1px; word-wrap: break-word;"><code class=3D"prettyprint"><div class=3D"sub=
prettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">name=
space</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> syst=
emY<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: #008;" class=3D"styled-by-prettify">void</span>=
<span style=3D"color: #000;" class=3D"styled-by-prettify"> func</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 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: #606;" class=3D"styled-by-prettify">RaiiCatch</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> converter</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 =C2=A0 systemX</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">otherFunc</span><span style=
=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: #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">}</span></div></code></div><br>You presumably int=
end for `converter` to be able to convert exceptions thrown by the call to =
`systemX::otherFunc()`. Well, that's just not how exception handling wo=
rks.<br><br>The order of operations for exception handling is:<br><br>1: Fu=
nction throws exception.<br>2: Compiler-generated code looks through the ca=
ll stack for a `try` block with a `catch` block for that exception type.<br=
>3: If an appropriate `catch` block is found, the stack is unwound to that =
point.<br>4: Execution continues from the `catch` block.<br><br>`RaiiCatch:=
:~RaiiCatch` will only be called <i>at step 3</i>, when the stack is unwoun=
d. By that point, the `catch` block you're going to has already been de=
cided on. Stack unwinding doesn't happen until you already know where y=
ou're going. And if no `catch` block is found in step 2, `std::terminat=
e` will be called <i>without</i> the stack having been unwound.<br><br>What=
you seem to intend is for `RaiiCatch::~RaiiCatch` to somehow interfere in =
step 2.<br><br>What you really want is to be able to define a named sequenc=
e of catch blocks, then impose those catch blocks on an arbitrary function.=
That <i>cannot</i> be done through object destructors. You need some kind =
of language syntax for that, probably based on <a href=3D"http://en.cpprefe=
rence.com/w/cpp/language/function-try-block">function-level try blocks</a>.=
<br><br>Of course, you could use macros with function try blocks. The macro=
would declare the sequence of `catch` statements, and would have to be man=
ually applied to the end of each function (along with the initial `try`).</=
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/ce3231c1-dc25-4967-9bf1-50aadc99239d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/ce3231c1-dc25-4967-9bf1-50aadc99239d=
%40isocpp.org</a>.<br />
------=_Part_9439_1736506344.1461955094396--
------=_Part_9438_1739970509.1461955094396--
.
Author: Moritz Klammler <moritz.klammler@gmail.com>
Date: Fri, 29 Apr 2016 20:53:28 +0200
Raw View
I'm not quite sure how this is supposed to work. Do you mean that your
feature would be used like this?
void
do_something(const std::string& s)
{
RaiiCatch guard {};
third_party::do_something(s);
}
I'm afraid it would havoc the semantics of stack unwinding. Currently,
when a destructor `throw`s during stack unwinding while already handling
another exception, `std::terminate` is called.
It seems to me that the destructor is a particularly bad place to
handle exceptions.
The currently recommended practice is to use this idiom
void
do_something(const std::string& s)
{
try
{
third_party::do_something(s);
}
catch (...)
{
translate_current_exception();
}
}
where `translate_current_exception` is defined like this and can be
re-used as often as needed.
void
translate_current_exception()
{
try
{
throw; // re-throw current exception
}
catch (const third_party::some_error& e)
{
throw my::first_error {};
}
catch (const third_party::some_other_error& e)
{
throw my::second_error {};
}
catch (const std::exception& e)
{
throw my::generic_error {e.what()};
}
}
It's not significantly more typing and makes it explicit what is going
on. Would your proposed feature be able to do something this technique
can't achieve?
Hans Erickson <hans.p.erickson@gmail.com> writes:
> I have an idea for exception handling that I am informally proposing to
> gauge interest and also to see if anyone knows of any similar existing
> proposals. If there is interest, I can write up something that is more
> formal.
>
> Basically, I am proposing allowing a stand-alone catch block without a
> corresponding try block that would catch exceptions whenever
> std::uncaught_exceptions() is greater than zero. This could be called "RAII
> catch" or "destructor catch." The motivation for this comes from the case
> where a class or set of classes needs to catch one of a set of exceptions,
> map that exception to one in a second set, and then throw an exception from
> that second set.
>
> For example, if a class is implemented using a vendor library that throws a
> certain set of vendor-specific exceptions but the developer of the class
> doesn't want to expose the clients of the class to the exceptions that are
> defined in the vendor library, a reasonable thing to do might be to define
> a second set of exceptions that the clients do know about. Then the class
> could catch each vendor-specific exception and throw an exception that the
> clients know about.
>
> This tends to be tedious and error-prone, however, if more than one method
> in the class needs to do the same mapping. If the mapping changes, it may
> be necessary to duplicate those changes for each method in the class.
>
> My proposed solution would be to allow a catch block that would only catch
> exceptions that were already in the process of being thrown, meaning that
> they would only be useful in destructors. That way, the developer for the
> class could create an RAII class containing a map in the destructor,
> instantiate that class at the beginning of each method for which the
> mapping must be done, and modify only that RAII class when the mapping
> needs to change. Below I give a very simple example of how a destructor for
> such a class might be implemented. To avoid confusing these catch
> statements with the normal try-catch statements, I have prefixed each of
> these with a tilde, though the syntax is negotiable.
>
>
> RaiiCatch::~RaiiCatch()
> {
> ~catch (const vendor::file_not_found_error& e)
> {
> throw mynamespace::file_not_found_error(e.filename());
> }
> ~catch (const vendor::network_error& e)
> {
> throw mynamespace::network_error(mynamespace::map_network_error(e.type
> ()));
> }
> }
>
>
> I haven't written up a formal proposal because I wanted to get some
> feedback first.
>
> So basically,
>
> -
>
> Is this a good idea or a dumb idea?
> -
>
> Has this problem already been solved a different way?
> -
>
> Could this problem be solved in a better way?
>
>
> Thanks,
>
>
> - Hans
--
OpenPGP:
Public Key: http://openpgp.klammler.eu
Fingerprint: 2732 DA32 C8D0 EEEC A081 BE9D CF6C 5166 F393 A9C0
--
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/87y47w1c2f.fsf%40gmail.com.
.