Topic: [Expected/Result] How much detail does an example
Author: Niall Douglas <nialldouglas14@gmail.com>
Date: Tue, 8 Aug 2017 17:11:34 -0700 (PDT)
Raw View
------=_Part_4732_412713503.1502237494352
Content-Type: multipart/alternative;
boundary="----=_Part_4733_1456750613.1502237494352"
------=_Part_4733_1456750613.1502237494352
Content-Type: text/plain; charset="UTF-8"
Hi,
My first proposal here, so please go easy on me!
I feel it would be beneficial to LEWG and WG21 to write up a summary report
of the Boost.Outcome peer review last May
(https://lists.boost.org/boost-announce/2017/06/0510.php) explaining why I
have concluded that both a result<T, E> AND an expected<T, E> ought to
become standardised. Before anyone asks, yes Vicente is aware of this, and
he has already privately made very useful comments on my draft
paper D0762R0 "Report from the Boost.Outcome peer review in May 2017, and
what could happen next wrt P0323 Expected and P0650 C++ Monadic interface".
He believes that LEWG ought to consider my report before thinking about
sending Expected off to the LWG next WG21 meeting.
As part of my report, I provide a reference result<T, E> implementation
written in C++ 20, so only GCC trunk with concepts enabled will work
correctly. It is very short, shorter and much simpler than an Expected
implementation:
https://github.com/ned14/outcome/blob/develop/include/outcome/experimental/result.hpp
Regarding this reference implementation, can I ask the following:
1. Is the source readily understandable, or do I need to write more into
comments before each API? Remember, I'm NOT proposing result<T, E> for
standardisation yet, rather I'm asking LEWG whether they want (i) Result
AND Expected, or (ii) Expected to be a "one size fits all" primitive.
2. Is this source code implementation sufficient to explain Result, or do
you need example Standardese for it as well?
3. Is a link to a godbolt edition where people can play with it online
useful?
What I'm really asking here is whether WG21 LEWG thinks about proposals in
terms of code or in terms of Standardese? Knowing this will help me to
shape the Report so it makes sense to more people, because the nuances
separating Result and Expected are hard to explain easily. Even between
myself and Vicente, two domain experts in this primitive, communicating
clearly has proven to be hard, and I know trying to persuade LEWG that the
differences in design are important enough to warrant two objects rather
than one object will be hard.
Anyway many thanks in advance for your time and feedback.
Niall
--
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/2e7d918c-43a5-4dc6-98d2-1f4c89a77045%40isocpp.org.
------=_Part_4733_1456750613.1502237494352
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">Hi,<div><br></div><div>My first proposal here, so please g=
o easy on me!</div><div><br></div><div>I feel it would be beneficial to LEW=
G and WG21 to write up a summary report of the Boost.Outcome peer review la=
st May (https://lists.boost.org/boost-announce/2017/06/0510.php) explaining=
why I have concluded that both a result<T, E> AND an expected<T, =
E> ought to become standardised. Before anyone asks, yes Vicente is awar=
e of this, and he has already privately made very useful comments on my dra=
ft paper=C2=A0D0762R0 "Report from the Boost.Outcome peer review in Ma=
y 2017, and what could happen next wrt P0323 Expected and P0650 C++ Monadic=
interface". He believes that LEWG ought to consider my report before =
thinking about sending Expected off to the LWG next WG21 meeting.</div><div=
><br></div><div>As part of my report, I provide a reference result<T, E&=
gt; implementation written in C++ 20, so only GCC trunk with concepts enabl=
ed will work correctly. It is very short, shorter and much simpler than an =
Expected implementation:</div><div><br></div><div>https://github.com/ned14/=
outcome/blob/develop/include/outcome/experimental/result.hpp<br></div><div>=
<br></div><div>Regarding this reference implementation, can I ask the follo=
wing:</div><div><br></div><div>1. Is the source readily understandable, or =
do I need to write more into comments before each API? Remember, I'm NO=
T proposing result<T, E> for standardisation yet, rather I'm aski=
ng LEWG whether they want (i) Result AND Expected, or (ii) Expected to be a=
"one size fits all" primitive.</div><div><br></div><div>2. Is th=
is source code implementation sufficient to explain Result, or do you need =
example Standardese for it as well?</div><div><br></div><div>3. Is a link t=
o a godbolt edition where people can play with it online useful?</div><div>=
<br></div><div><br></div><div>What I'm really asking here is whether WG=
21 LEWG thinks about proposals in terms of code or in terms of Standardese?=
Knowing this will help me to shape the Report so it makes sense to more pe=
ople, because the nuances separating Result and Expected are hard to explai=
n easily. Even between myself and Vicente, two domain experts in this primi=
tive, communicating clearly has proven to be hard, and I know trying to per=
suade LEWG that the differences in design are important enough to warrant t=
wo objects rather than one object will be hard.</div><div><br></div><div>An=
yway many thanks in advance for your time and feedback.</div><div><br></div=
><div>Niall</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/2e7d918c-43a5-4dc6-98d2-1f4c89a77045%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/2e7d918c-43a5-4dc6-98d2-1f4c89a77045=
%40isocpp.org</a>.<br />
------=_Part_4733_1456750613.1502237494352--
------=_Part_4732_412713503.1502237494352--
.
Author: Nevin Liber <nevin@eviloverlord.com>
Date: Tue, 8 Aug 2017 21:16:01 -0500
Raw View
--001a11473b1eb3f588055648ab03
Content-Type: text/plain; charset="UTF-8"
On Tue, Aug 8, 2017 at 7:11 PM, Niall Douglas <nialldouglas14@gmail.com>
wrote:
> What I'm really asking here is whether WG21 LEWG thinks about proposals in
> terms of code or in terms of Standardese?
>
This is, of course, only my opinion. And while I've skimmed your links, I
haven't looked at them in detail.
Both code and standardese are nice, but neither are necessary.
It really boils down to what questions do you want LEWG to answer. What
helps you achieve your goal of
both a result<T, E> AND an expected<T, E> ought to become standardised.
You already have enough code to show that it is feasible to implement
result. The other thing a reference implementation can be good for is
benchmarking, but that doesn't seem applicable at this point.
Since you aren't proposing that this goes to LWG yet, the standardese isn't
critical; just make a decent first attempt at the interface.
> Knowing this will help me to shape the Report so it makes sense to more
> people, because the nuances separating Result and Expected are hard to
> explain easily. Even between myself and Vicente, two domain experts in this
> primitive, communicating clearly has proven to be hard, and I know trying
> to persuade LEWG that the differences in design are important enough to
> warrant two objects rather than one object will be hard.
>
But that really is the essence of what you need to do! You convince LEWG,
and the committee convinces the world (by publishing it). :-)
Why do we need two different types? What are their semantic differences,
and why are they important? Why do they need to be standardized at the
same time?
If you can come up with good, simple examples illustrating those points, it
helps.
It also helps that Vincente believes LEWG ought to think about this before
sending expected to LWG because it directly relates to his proposal.
Good luck!
--
Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> +1-847-691-1404
<(847)%20691-1404>
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAGg_6%2BO3k4Zw2GqwEEp8-NaP4h%3DOcivzPRbXs_XpdDujSoajJw%40mail.gmail.com.
--001a11473b1eb3f588055648ab03
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Tue, Aug 8, 2017 at 7:11 PM, Niall Douglas <span dir=3D=
"ltr"><<a href=3D"mailto:nialldouglas14@gmail.com" target=3D"_blank">nia=
lldouglas14@gmail.com</a>></span> wrote:<br><div class=3D"gmail_extra"><=
div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"margin=
:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-lef=
t-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div>What I'=
;m really asking here is whether WG21 LEWG thinks about proposals in terms =
of code or in terms of Standardese?</div></div></blockquote><div><br></div>=
<div>This is, of course, only my opinion.=C2=A0 And while I've skimmed =
your links, I haven't looked at them in detail.</div><div><br></div><di=
v>Both code and standardese are nice, but neither are necessary.</div><div>=
<br></div><div>It really boils down to what questions do you want LEWG to a=
nswer.=C2=A0 What helps you achieve your goal of</div><div><br></div><block=
quote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left-w=
idth:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding=
-left:1ex"><span style=3D"font-size:12.800000190734863px">both a result<=
T, E> AND an expected<T, E> ought to become standardised.</span></=
blockquote><div><br></div><div><br></div><div>You already have enough code =
to show that it is feasible to implement result.=C2=A0 The other thing a re=
ference implementation can be good for is benchmarking, but that doesn'=
t seem applicable at this point.</div><div><br></div><div>Since you aren=
9;t proposing that this goes to LWG yet, the standardese isn't critical=
; just make a decent first attempt at the interface.</div><div>=C2=A0</div>=
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-=
left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);p=
adding-left:1ex"><div dir=3D"ltr"><div> Knowing this will help me to shape =
the Report so it makes sense to more people, because the nuances separating=
Result and Expected are hard to explain easily. Even between myself and Vi=
cente, two domain experts in this primitive, communicating clearly has prov=
en to be hard, and I know trying to persuade LEWG that the differences in d=
esign are important enough to warrant two objects rather than one object wi=
ll be hard.</div></div></blockquote><div><br></div><div>But that really is =
the essence of what you need to do!=C2=A0 You convince LEWG, and the commit=
tee convinces the world (by publishing it). :-)</div><div><br></div><div><b=
r></div><div>Why do we need two different types?=C2=A0 What are their seman=
tic differences, and why are they important?=C2=A0 Why do they need to be s=
tandardized at the same time?</div><div><br></div><div>If you can come up w=
ith good, simple examples illustrating those points, it helps.</div><div><b=
r></div><div>It also helps that Vincente believes LEWG ought to think about=
this before sending expected to LWG because it directly relates to his pro=
posal.</div><div><br></div><div>Good luck!</div></div>-- <br><div class=3D"=
m_7141566937207203954gmail_signature"><div dir=3D"ltr"><div><div dir=3D"ltr=
"><div>=C2=A0Nevin ":-)" Liber=C2=A0 <mailto:<a href=3D"mailto=
:nevin@eviloverlord.com" target=3D"_blank">nevin@eviloverlord.com</a><wbr>&=
gt; =C2=A0<a href=3D"tel:(847)%20691-1404" value=3D"+18476911404" target=3D=
"_blank">+1-847-691-1404</a></div></div></div></div></div>
</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/CAGg_6%2BO3k4Zw2GqwEEp8-NaP4h%3DOcivz=
PRbXs_XpdDujSoajJw%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter"=
>https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAGg_6%2BO3k4=
Zw2GqwEEp8-NaP4h%3DOcivzPRbXs_XpdDujSoajJw%40mail.gmail.com</a>.<br />
--001a11473b1eb3f588055648ab03--
.
Author: Niall Douglas <nialldouglas14@gmail.com>
Date: Tue, 8 Aug 2017 21:03:30 -0700 (PDT)
Raw View
------=_Part_4965_1272260615.1502251410774
Content-Type: multipart/alternative;
boundary="----=_Part_4966_1535398728.1502251410774"
------=_Part_4966_1535398728.1502251410774
Content-Type: text/plain; charset="UTF-8"
>
>
> It really boils down to what questions do you want LEWG to answer. What
> helps you achieve your goal of
>
> both a result<T, E> AND an expected<T, E> ought to become standardised.
>
>
>
> You already have enough code to show that it is feasible to implement
> result. The other thing a reference implementation can be good for is
> benchmarking, but that doesn't seem applicable at this point.
>
Performance difference at runtime is statistically insignificant. Type E in
Result is bound to one of four options, all small in size and thus in
impact.
Compile time difference might be large with today's compilers, but might be
insignificant with future compilers. And I have too few data points to draw
statistically significant results unfortunately, though I do report on my
two Outcome-using libraries.
>
>
>> Knowing this will help me to shape the Report so it makes sense to more
>> people, because the nuances separating Result and Expected are hard to
>> explain easily. Even between myself and Vicente, two domain experts in this
>> primitive, communicating clearly has proven to be hard, and I know trying
>> to persuade LEWG that the differences in design are important enough to
>> warrant two objects rather than one object will be hard.
>>
>
> But that really is the essence of what you need to do! You convince LEWG,
> and the committee convinces the world (by publishing it). :-)
>
I'll certainly try my best. I expect to fail and there will be a single
primitive object, but down the line it won't bother me as much because I
tried my best to change it. These arguments are very nuanced, there is no
obvious right nor wrong. Nor any ability to prove an opinion is correct.
But I'll try anyway.
>
> Why do we need two different types? What are their semantic differences,
> and why are they important? Why do they need to be standardized at the
> same time?
>
They don't have to be strictly speaking. But Result is much simpler than
Expected, almost a subset except for the wide vs narrow difference, and the
implicit vs explicit difference. Despite the relative simplicity, where it
differs in design we know from the Boost peer review it generates
significant individual differences in opinion. I hope to fairly capture
those disagreements in the report I send in, and maybe LEWG can figure it
out.
>
> If you can come up with good, simple examples illustrating those points,
> it helps.
>
> It also helps that Vincente believes LEWG ought to think about this before
> sending expected to LWG because it directly relates to his proposal.
>
It's a strange thing but when you remove all the obviously contentious
stuff and pare back a design to the bare minimum, you end up somewhere
where there are no obvious answers. Vicente's in a similar place. I cannot
honestly say if Expected as of P0323R2 is correct, I can only point out
obvious glaring incorrectness which can be proved with argument, and there
is very little of that remaining now. It's very much coming down to
personal opinion now, without possible proof of rightness or wrongness.
Only that both I and Vicente have been using these objects in the wild for
many years now, and we have ended up 95% in the same place. It's just what
to do about that 5%: is it important? Ten years from now will we regret
some decision or lack of decision? It's very ephemeral.
Thanks for the feedback and support Nevin. It is appreciated.
Niall
--
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/abb39174-935b-4b9d-bc8d-459984b33e48%40isocpp.org.
------=_Part_4966_1535398728.1502251410774
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div><div class=3D"gmail_quote"><div><br></div><div>It really boils dow=
n to what questions do you want LEWG to answer.=C2=A0 What helps you achiev=
e your goal of</div><div><br></div><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;=
border-left-color:rgb(204,204,204);padding-left:1ex"><span style=3D"font-si=
ze:12.800000190734863px">both a result<T, E> AND an expected<T, E&=
gt; ought to become standardised.</span></blockquote><div><br></div><div><b=
r></div><div>You already have enough code to show that it is feasible to im=
plement result.=C2=A0 The other thing a reference implementation can be goo=
d for is benchmarking, but that doesn't seem applicable at this point.<=
/div></div></div></div></blockquote><div><br></div><div>Performance differe=
nce at runtime is statistically insignificant. Type E in Result is bound to=
one of four options, all small in size and thus in impact.</div><div><br><=
/div><div>Compile time difference might be large with today's compilers=
, but might be insignificant with future compilers. And I have too few data=
points to draw statistically significant results unfortunately, though I d=
o report on my two Outcome-using libraries.</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;"><div dir=3D"ltr"><div><div class=3D"gma=
il_quote"><div>=C2=A0</div><blockquote class=3D"gmail_quote" style=3D"margi=
n:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-le=
ft-color:rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div> Knowing =
this will help me to shape the Report so it makes sense to more people, bec=
ause the nuances separating Result and Expected are hard to explain easily.=
Even between myself and Vicente, two domain experts in this primitive, com=
municating clearly has proven to be hard, and I know trying to persuade LEW=
G that the differences in design are important enough to warrant two object=
s rather than one object will be hard.</div></div></blockquote><div><br></d=
iv><div>But that really is the essence of what you need to do!=C2=A0 You co=
nvince LEWG, and the committee convinces the world (by publishing it). :-)<=
/div></div></div></div></blockquote><div><br></div><div>I'll certainly =
try my best. I expect to fail and there will be a single primitive object, =
but down the line it won't bother me as much because I tried my best to=
change it. These arguments are very nuanced, there is no obvious right nor=
wrong. Nor any ability to prove an opinion is correct. But I'll try an=
yway.</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><div class=3D"gmail_quote"><div><br></div><div>Why do w=
e need two different types?=C2=A0 What are their semantic differences, and =
why are they important?=C2=A0 Why do they need to be standardized at the sa=
me time?</div></div></div></div></blockquote><div><br></div><div>They don&#=
39;t have to be strictly speaking. But Result is much simpler than Expected=
, almost a subset except for the wide vs narrow difference, and the implici=
t vs explicit difference. Despite the relative simplicity, where it differs=
in design we know from the Boost peer review it generates significant indi=
vidual differences in opinion. I hope to fairly capture those disagreements=
in the report I send in, and maybe LEWG can figure it out.</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 class=3D"gmail_quote"><div><br></div><div>If you can come up with goo=
d, simple examples illustrating those points, it helps.</div><div><br></div=
><div>It also helps that Vincente believes LEWG ought to think about this b=
efore sending expected to LWG because it directly relates to his proposal.<=
/div><div></div></div></div></div></blockquote><div><br></div><div>It's=
a strange thing but when you remove all the obviously contentious stuff an=
d pare back a design to the bare minimum, you end up somewhere where there =
are no obvious answers. Vicente's in a similar place. I cannot honestly=
say if Expected as of P0323R2 is correct, I can only point out obvious gla=
ring incorrectness which can be proved with argument, and there is very lit=
tle of that remaining now. It's very much coming down to personal opini=
on now, without possible proof of rightness or wrongness. Only that both I =
and Vicente have been using these objects in the wild for many years now, a=
nd we have ended up 95% in the same place. It's just what to do about t=
hat 5%: is it important? Ten years from now will we regret some decision or=
lack of decision? It's very ephemeral.</div><div><br></div><div>Thanks=
for the feedback and support Nevin. It is appreciated.</div><div><br></div=
><div>Niall</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/abb39174-935b-4b9d-bc8d-459984b33e48%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/abb39174-935b-4b9d-bc8d-459984b33e48=
%40isocpp.org</a>.<br />
------=_Part_4966_1535398728.1502251410774--
------=_Part_4965_1272260615.1502251410774--
.
Author: "Vicente J. Botet Escriba" <vicente.botet@wanadoo.fr>
Date: Wed, 9 Aug 2017 13:12:19 +0200
Raw View
This is a multi-part message in MIME format.
--------------AD2BF82A17F2B27D6CB89B70
Content-Type: text/plain; charset="UTF-8"; format=flowed
Content-Transfer-Encoding: quoted-printable
Le 09/08/2017 =C3=A0 06:03, Niall Douglas a =C3=A9crit :
>
>
> It really boils down to what questions do you want LEWG to
> answer. What helps you achieve your goal of
>
> both a result<T, E> AND an expected<T, E> ought to become
> standardised.
>
>
>
> You already have enough code to show that it is feasible to
> implement result. The other thing a reference implementation can
> be good for is benchmarking, but that doesn't seem applicable at
> this point.
>
>
> Performance difference at runtime is statistically insignificant. Type=20
> E in Result is bound to one of four options, all small in size and=20
> thus in impact.
>
> Compile time difference might be large with today's compilers, but=20
> might be insignificant with future compilers. And I have too few data=20
> points to draw statistically significant results unfortunately, though=20
> I do report on my two Outcome-using libraries.
>
> Knowing this will help me to shape the Report so it makes
> sense to more people, because the nuances separating Result
> and Expected are hard to explain easily. Even between myself
> and Vicente, two domain experts in this primitive,
> communicating clearly has proven to be hard, and I know trying
> to persuade LEWG that the differences in design are important
> enough to warrant two objects rather than one object will be hard=
..
>
>
> But that really is the essence of what you need to do! You
> convince LEWG, and the committee convinces the world (by
> publishing it). :-)
>
>
> I'll certainly try my best. I expect to fail and there will be a=20
> single primitive object, but down the line it won't bother me as much=20
> because I tried my best to change it. These arguments are very=20
> nuanced, there is no obvious right nor wrong. Nor any ability to prove=20
> an opinion is correct. But I'll try anyway.
>
>
> Why do we need two different types? What are their semantic
> differences, and why are they important? Why do they need to be
> standardized at the same time?
>
>
> They don't have to be strictly speaking. But Result is much simpler=20
> than Expected, almost a subset except for the wide vs narrow=20
> difference, and the implicit vs explicit difference. Despite the=20
> relative simplicity, where it differs in design we know from the Boost=20
> peer review it generates significant individual differences in=20
> opinion. I hope to fairly capture those disagreements in the report I=20
> send in, and maybe LEWG can figure it out.
I'm wondering if once we remove the non-significant differences, we=20
couldn't have that the single major difference between expected<T,E> and=20
result<T,E> is his representation and the missing default construction.
I don't know if the representation could be considered as an=20
implementation detail (QOI) or if the result<T,E>representation is a=20
must in order to satisfy some specific requirements. What I mean is that=20
an implementation could use the result<T,E> representation for some=20
specific E types (small default constructible E types) if this=20
representation can be more efficient.
So maybe at the end, the single difference would be the default=20
construction.
Note, that I don't see any reason why the wide/narrow observers should=20
be named differently. I don't see neither the need fro specific=20
construction of result<T,E> from specific errors. Others think=20
differently. If we needed them, maybe we could add them by specializing=20
expected<T,E> for some specifics E types.
>
>
> If you can come up with good, simple examples illustrating those
> points, it helps.
>
> It also helps that Vincente believes LEWG ought to think about
> this before sending expected to LWG because it directly relates to
> his proposal.
>
>
> It's a strange thing but when you remove all the obviously contentious=20
> stuff and pare back a design to the bare minimum, you end up somewhere=20
> where there are no obvious answers. Vicente's in a similar place. I=20
> cannot honestly say if Expected as of P0323R2 is correct, I can only=20
> point out obvious glaring incorrectness which can be proved with=20
> argument, and there is very little of that remaining now. It's very=20
> much coming down to personal opinion now, without possible proof of=20
> rightness or wrongness. Only that both I and Vicente have been using=20
> these objects in the wild for many years now, and we have ended up 95%=20
> in the same place. It's just what to do about that 5%: is it=20
> important? Ten years from now will we regret some decision or lack of=20
> decision? It's very ephemeral.
>
There is not a single valid approach. The question is if we need to=20
standardize all. The user can define other ValueOrError types.
What are the unavoidable design differences between expected and result?=20
Once we know them, we could decide if it is worth standardizing one, the=20
other or both?
So Niall, could we concentrate on the major differences?
Vicente
--=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/2fb62104-50d7-505e-89be-bb0679eec727%40wanadoo.f=
r.
--------------AD2BF82A17F2B27D6CB89B70
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<html>
<head>
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf-8=
">
</head>
<body text=3D"#000000" bgcolor=3D"#FFFFFF">
<div class=3D"moz-cite-prefix">Le 09/08/2017 =C3=A0 06:03, Niall Dougla=
s a
=C3=A9crit=C2=A0:<br>
</div>
<blockquote type=3D"cite"
cite=3D"mid:abb39174-935b-4b9d-bc8d-459984b33e48@isocpp.org">
<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 class=3D"gmail_quote">
<div><br>
</div>
<div>It really boils down to what questions do you want
LEWG to answer.=C2=A0 What helps you achieve your goal of=
</div>
<div><br>
</div>
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px
0px
0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(2=
04,204,204);padding-left:1ex"><span
style=3D"font-size:12.800000190734863px">both a
result<T, E> AND an expected<T, E> ought
to become standardised.</span></blockquote>
<div><br>
</div>
<div><br>
</div>
<div>You already have enough code to show that it is
feasible to implement result.=C2=A0 The other thing a
reference implementation can be good for is
benchmarking, but that doesn't seem applicable at this
point.</div>
</div>
</div>
</div>
</blockquote>
<div><br>
</div>
<div>Performance difference at runtime is statistically
insignificant. Type E in Result is bound to one of four
options, all small in size and thus in impact.</div>
<div><br>
</div>
<div>Compile time difference might be large with today's
compilers, but might be insignificant with future compilers.
And I have too few data points to draw statistically
significant results unfortunately, though I do report on my
two Outcome-using libraries.</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 class=3D"gmail_quote">
<div>=C2=A0</div>
<blockquote class=3D"gmail_quote" style=3D"margin:0px 0px
0px
0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(2=
04,204,204);padding-left:1ex">
<div dir=3D"ltr">
<div> Knowing this will help me to shape the Report
so it makes sense to more people, because the
nuances separating Result and Expected are hard to
explain easily. Even between myself and Vicente,
two domain experts in this primitive,
communicating clearly has proven to be hard, and I
know trying to persuade LEWG that the differences
in design are important enough to warrant two
objects rather than one object will be hard.</div>
</div>
</blockquote>
<div><br>
</div>
<div>But that really is the essence of what you need to
do!=C2=A0 You convince LEWG, and the committee convinces
the world (by publishing it). :-)</div>
</div>
</div>
</div>
</blockquote>
<div><br>
</div>
<div>I'll certainly try my best. I expect to fail and there will
be a single primitive object, but down the line it won't
bother me as much because I tried my best to change it. These
arguments are very nuanced, there is no obvious right nor
wrong. Nor any ability to prove an opinion is correct. But
I'll try anyway.</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 class=3D"gmail_quote">
<div><br>
</div>
<div>Why do we need two different types?=C2=A0 What are the=
ir
semantic differences, and why are they important?=C2=A0 W=
hy
do they need to be standardized at the same time?</div>
</div>
</div>
</div>
</blockquote>
<div><br>
</div>
<div>They don't have to be strictly speaking. But Result is much
simpler than Expected, almost a subset except for the wide vs
narrow difference, and the implicit vs explicit difference.
Despite the relative simplicity, where it differs in design we
know from the Boost peer review it generates significant
individual differences in opinion. I hope to fairly capture
those disagreements in the report I send in, and maybe LEWG
can figure it out.</div>
</div>
</blockquote>
I'm wondering if once we remove the non-significant differences, we
couldn't have that the single major difference between
expected<T,E> and result<T,E> is his representation and
the missing default construction.<br>
I don't know if the representation could be considered as an
implementation detail (QOI) or if the
result<T,E>representation is a must in order to satisfy some
specific requirements. What I mean is that an implementation could
use the result<T,E> representation for some specific E types
(small default constructible E types) if this representation can be
more efficient.<br>
<br>
So maybe at the end, the single difference would be the default
construction.<br>
<br>
Note, that I don't see any reason why the wide/narrow observers
should be named differently. I don't see neither the need fro
specific construction of result<T,E> from specific errors.
Others think differently. If we needed them, maybe we could add them
by specializing expected<T,E> for some specifics E types.<br>
<blockquote type=3D"cite"
cite=3D"mid:abb39174-935b-4b9d-bc8d-459984b33e48@isocpp.org">
<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>
<div class=3D"gmail_quote">
<div><br>
</div>
<div>If you can come up with good, simple examples
illustrating those points, it helps.</div>
<div><br>
</div>
<div>It also helps that Vincente believes LEWG ought to
think about this before sending expected to LWG
because it directly relates to his proposal.</div>
</div>
</div>
</div>
</blockquote>
<div><br>
</div>
<div>It's a strange thing but when you remove all the obviously
contentious stuff and pare back a design to the bare minimum,
you end up somewhere where there are no obvious answers.
Vicente's in a similar place. I cannot honestly say if
Expected as of P0323R2 is correct, I can only point out
obvious glaring incorrectness which can be proved with
argument, and there is very little of that remaining now. It's
very much coming down to personal opinion now, without
possible proof of rightness or wrongness. Only that both I and
Vicente have been using these objects in the wild for many
years now, and we have ended up 95% in the same place. It's
just what to do about that 5%: is it important? Ten years from
now will we regret some decision or lack of decision? It's
very ephemeral.</div>
<div><br>
</div>
</div>
</blockquote>
There is not a single valid approach. The question is if we need to
standardize all. The user can define other ValueOrError types.<br>
What are the unavoidable design differences between expected and
result? Once we know them, we could decide if it is worth
standardizing one, the other or both?<br>
<br>
So Niall, could we concentrate on the major differences?<br>
<br>
Vicente<br>
</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/2fb62104-50d7-505e-89be-bb0679eec727%=
40wanadoo.fr?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/2fb62104-50d7-505e-89be-bb0679eec727=
%40wanadoo.fr</a>.<br />
--------------AD2BF82A17F2B27D6CB89B70--
.
Author: Niall Douglas <nialldouglas14@gmail.com>
Date: Wed, 9 Aug 2017 06:32:19 -0700 (PDT)
Raw View
------=_Part_5311_205165091.1502285539258
Content-Type: multipart/alternative;
boundary="----=_Part_5312_1066401366.1502285539258"
------=_Part_5312_1066401366.1502285539258
Content-Type: text/plain; charset="UTF-8"
>
>
>
>
>>
>> Why do we need two different types? What are their semantic differences,
>> and why are they important? Why do they need to be standardized at the
>> same time?
>>
>
> They don't have to be strictly speaking. But Result is much simpler than
> Expected, almost a subset except for the wide vs narrow difference, and the
> implicit vs explicit difference. Despite the relative simplicity, where it
> differs in design we know from the Boost peer review it generates
> significant individual differences in opinion. I hope to fairly capture
> those disagreements in the report I send in, and maybe LEWG can figure it
> out.
>
> I'm wondering if once we remove the non-significant differences, we
> couldn't have that the single major difference between expected<T,E> and
> result<T,E> is his representation and the missing default construction.
>
There is also the difference that type E is locked into one of error_code,
exception_ptr, is_error_code_enum or is_error_condition_enum. That lock in
allows Result to directly throw the failure without any intermediate
wrapper of bad_expected_access, and thus Result is better suited to use as
a function return type. Also because we know that sizeof E is small, the
non-union storage is safe. And because we know what E must be, all implicit
construction is safe, which lets us safely use syntax short cuts when
returning from functions etc.
Of course, there is nothing stopping Expected treating those four
categories of E the same way, and anything else gets wrapped into
bad_expected_access<E>. But me personally, I think that when the type
behaves differently, it should be named differently. And adding that sort
of cleverness to Expected would impact compile times when simply adding
another type implementing the ValueOrError Concept same as Expected would
be much more sensible.
> I don't know if the representation could be considered as an
> implementation detail (QOI) or if the result<T,E>representation is a must
> in order to satisfy some specific requirements. What I mean is that an
> implementation could use the result<T,E> representation for some specific E
> types (small default constructible E types) if this representation can be
> more efficient.
>
> So maybe at the end, the single difference would be the default
> construction.
>
> Note, that I don't see any reason why the wide/narrow observers should be
> named differently. I don't see neither the need fro specific construction
> of result<T,E> from specific errors. Others think differently. If we needed
> them, maybe we could add them by specializing expected<T,E> for some
> specifics E types.
>
I'm pretty much in agreement. This is all "dotting i's, crossing t's" stuff.
> There is not a single valid approach. The question is if we need to
> standardize all. The user can define other ValueOrError types.
> What are the unavoidable design differences between expected and result?
> Once we know them, we could decide if it is worth standardizing one, the
> other or both?
>
> So Niall, could we concentrate on the major differences?
>
> Well, let's not short circuit the process we're currently on. I'm
currently rewriting D0762R0 to incorporate your feedback. Once that's done
I'll send it to you and the usual suspects privately. Once we reach a point
we can't refine it much more, I'll send it to boost-dev as after all I'm
trying to write a report on what all of them said. After another round of
feedback and change, I'll send it here, and finally into John Spicer for
the Albuquerque meeting.
As I said to you privately, I have no wish to interrupt or prevent Expected
being standardised. I just want LEWG to consider the Boost peer review
feedback before sending to the LWG, it was after all very ample and there's
plenty of experienced devs on there. Many of them want an *even simpler* vocab
type here, with even fewer features and less complexity.
Niall
--
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/f72c55ed-01fe-4744-b1e1-ea1de03fbec4%40isocpp.org.
------=_Part_5312_1066401366.1502285539258
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bor=
der-left: 1px #ccc solid;padding-left: 1ex;"><div text=3D"#000000" bgcolor=
=3D"#FFFFFF"><blockquote type=3D"cite"><div dir=3D"ltr"><br>
<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">
<div dir=3D"ltr">
<div>
<div class=3D"gmail_quote">
<div><br>
</div>
<div>Why do we need two different types?=C2=A0 What are the=
ir
semantic differences, and why are they important?=C2=A0 W=
hy
do they need to be standardized at the same time?</div>
</div>
</div>
</div>
</blockquote>
<div><br>
</div>
<div>They don't have to be strictly speaking. But Result is muc=
h
simpler than Expected, almost a subset except for the wide vs
narrow difference, and the implicit vs explicit difference.
Despite the relative simplicity, where it differs in design we
know from the Boost peer review it generates significant
individual differences in opinion. I hope to fairly capture
those disagreements in the report I send in, and maybe LEWG
can figure it out.</div>
</div>
</blockquote>
I'm wondering if once we remove the non-significant differences, we
couldn't have that the single major difference between
expected<T,E> and result<T,E> is his representation and
the missing default construction.<br></div></blockquote><div><br></div>=
<div>There is also the difference that type E is locked into one of error_c=
ode, exception_ptr, is_error_code_enum or is_error_condition_enum. That loc=
k in allows Result to directly throw the failure without any intermediate w=
rapper of bad_expected_access, and thus Result is better suited to use as a=
function return type. Also because we know that sizeof E is small, the non=
-union storage is safe. And because we know what E must be, all implicit co=
nstruction is safe, which lets us safely use syntax short cuts when returni=
ng from functions etc.</div><div><br></div><div>Of course, there is nothing=
stopping Expected treating those four categories of E the same way, and an=
ything else gets wrapped into bad_expected_access<E>. But me personal=
ly, I think that when the type behaves differently, it should be named diff=
erently. And adding that sort of cleverness to Expected would impact compil=
e times when simply adding another type implementing the ValueOrError Conce=
pt same as Expected would be much more sensible.</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;"><div text=3D"#000000" bgcolor=3D"#=
FFFFFF">
I don't know if the representation could be considered as an
implementation detail (QOI) or if the
result<T,E>representation is a must in order to satisfy some
specific requirements. What I mean is that an implementation could
use the result<T,E> representation for some specific E types
(small default constructible E types) if this representation can be
more efficient.<br>
<br>
So maybe at the end, the single difference would be the default
construction.=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 text=3D"#000000" bgcolor=3D"#FFFFFF">
<br>
Note, that I don't see any reason why the wide/narrow observers
should be named differently. I don't see neither the need fro
specific construction of result<T,E> from specific errors.
Others think differently. If we needed them, maybe we could add them
by specializing expected<T,E> for some specifics E types.<br></di=
v></blockquote><div><br></div><div>I'm pretty much in agreement. This i=
s all "dotting i's, crossing t's" stuff.</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;"><div text=3D"#000000" bg=
color=3D"#FFFFFF">
There is not a single valid approach. The question is if we need to
standardize all. The user can define other ValueOrError types.<br>
What are the unavoidable design differences between expected and
result? Once we know them, we could decide if it is worth
standardizing one, the other or both?<br>
<br>
So Niall, could we concentrate on the major differences?<br>
<br></div></blockquote><div>Well, let's not short circuit the proce=
ss we're currently on. I'm currently rewriting D0762R0 to incorpora=
te your feedback. Once that's done I'll send it to you and the usua=
l suspects privately. Once we reach a point we can't refine it much mor=
e, I'll send it to boost-dev as after all I'm trying to write a rep=
ort on what all of them said. After another round of feedback and change, I=
'll send it here, and finally into John Spicer for the Albuquerque meet=
ing.</div><div><br></div><div>As I said to you privately, I have no wish to=
interrupt or prevent Expected being standardised. I just want LEWG to cons=
ider the Boost peer review feedback before sending to the LWG, it was after=
all very ample and there's plenty of experienced devs on there. Many o=
f them want an <i>even simpler</i>=C2=A0vocab type here, with even fewer fe=
atures and less complexity.</div><div><br></div><div>Niall</div><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/f72c55ed-01fe-4744-b1e1-ea1de03fbec4%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/f72c55ed-01fe-4744-b1e1-ea1de03fbec4=
%40isocpp.org</a>.<br />
------=_Part_5312_1066401366.1502285539258--
------=_Part_5311_205165091.1502285539258--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 9 Aug 2017 08:23:54 -0700 (PDT)
Raw View
------=_Part_5552_948853355.1502292234519
Content-Type: multipart/alternative;
boundary="----=_Part_5553_1362263834.1502292234520"
------=_Part_5553_1362263834.1502292234520
Content-Type: text/plain; charset="UTF-8"
On Wednesday, August 9, 2017 at 9:32:19 AM UTC-4, Niall Douglas wrote:
>
>
>>
>>
>>>
>>> Why do we need two different types? What are their semantic
>>> differences, and why are they important? Why do they need to be
>>> standardized at the same time?
>>>
>>
>> They don't have to be strictly speaking. But Result is much simpler than
>> Expected, almost a subset except for the wide vs narrow difference, and the
>> implicit vs explicit difference. Despite the relative simplicity, where it
>> differs in design we know from the Boost peer review it generates
>> significant individual differences in opinion. I hope to fairly capture
>> those disagreements in the report I send in, and maybe LEWG can figure it
>> out.
>>
>> I'm wondering if once we remove the non-significant differences, we
>> couldn't have that the single major difference between expected<T,E> and
>> result<T,E> is his representation and the missing default construction.
>>
>
> There is also the difference that type E is locked into one of error_code,
> exception_ptr, is_error_code_enum or is_error_condition_enum. That lock in
> allows Result to directly throw the failure without any intermediate
> wrapper of bad_expected_access, and thus Result is better suited to use as
> a function return type. Also because we know that sizeof E is small, the
> non-union storage is safe. And because we know what E must be, all implicit
> construction is safe, which lets us safely use syntax short cuts when
> returning from functions etc.
>
Why exactly would you want to catch those? With the exception of
`exception_ptr`, none of those are good exceptions to catch. They're just
numbers, and which one you catch tells you very little about the actual
cause of the exception.
And `exception_ptr` is *not cheap* to throw around. Creating one is a heap
allocation, and allocating memory for a local problem is not the best way
to deal with such things.
At least `bad_expected_access` allows you to tell the difference between
"Oops, I forgot to check whether the result was valid" and "Yes, I really
did mean to throw this".
--
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/807dda0f-1eac-4f12-b9ca-8033f467b5bb%40isocpp.org.
------=_Part_5553_1362263834.1502292234520
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><br>On Wednesday, August 9, 2017 at 9:32:19 AM UTC-4, =
Niall Douglas wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;ma=
rgin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><blockquot=
e class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px=
#ccc solid;padding-left:1ex"><div text=3D"#000000" bgcolor=3D"#FFFFFF"><bl=
ockquote type=3D"cite"><div dir=3D"ltr"><br>
<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">
<div dir=3D"ltr">
<div>
<div class=3D"gmail_quote">
<div><br>
</div>
<div>Why do we need two different types?=C2=A0 What are the=
ir
semantic differences, and why are they important?=C2=A0 W=
hy
do they need to be standardized at the same time?</div>
</div>
</div>
</div>
</blockquote>
<div><br>
</div>
<div>They don't have to be strictly speaking. But Result is muc=
h
simpler than Expected, almost a subset except for the wide vs
narrow difference, and the implicit vs explicit difference.
Despite the relative simplicity, where it differs in design we
know from the Boost peer review it generates significant
individual differences in opinion. I hope to fairly capture
those disagreements in the report I send in, and maybe LEWG
can figure it out.</div>
</div>
</blockquote>
I'm wondering if once we remove the non-significant differences, we
couldn't have that the single major difference between
expected<T,E> and result<T,E> is his representation and
the missing default construction.<br></div></blockquote><div><br></div>=
<div>There is also the difference that type E is locked into one of error_c=
ode, exception_ptr, is_error_code_enum or is_error_condition_enum. That loc=
k in allows Result to directly throw the failure without any intermediate w=
rapper of bad_expected_access, and thus Result is better suited to use as a=
function return type. Also because we know that sizeof E is small, the non=
-union storage is safe. And because we know what E must be, all implicit co=
nstruction is safe, which lets us safely use syntax short cuts when returni=
ng from functions etc.</div></blockquote><div><br>Why exactly would you wan=
t to catch those? With the exception of `exception_ptr`, none of those are =
good exceptions to catch. They're just numbers, and which one you catch=
tells you very little about the actual cause of the exception.<br><br>And =
`exception_ptr` is <i>not cheap</i> to throw around. Creating one is a heap=
allocation, and allocating memory for a local problem is not the best way =
to deal with such things.<br><br>At least `bad_expected_access` allows you =
to tell the difference between
"Oops, I forgot to check whether the result was valid" and "=
;Yes, I really did mean
to throw this".<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/807dda0f-1eac-4f12-b9ca-8033f467b5bb%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/807dda0f-1eac-4f12-b9ca-8033f467b5bb=
%40isocpp.org</a>.<br />
------=_Part_5553_1362263834.1502292234520--
------=_Part_5552_948853355.1502292234519--
.
Author: Niall Douglas <nialldouglas14@gmail.com>
Date: Wed, 9 Aug 2017 09:13:07 -0700 (PDT)
Raw View
------=_Part_5721_1807375814.1502295187805
Content-Type: multipart/alternative;
boundary="----=_Part_5722_494420280.1502295187805"
------=_Part_5722_494420280.1502295187805
Content-Type: text/plain; charset="UTF-8"
>
>
>> There is also the difference that type E is locked into one of
>> error_code, exception_ptr, is_error_code_enum or is_error_condition_enum.
>> That lock in allows Result to directly throw the failure without any
>> intermediate wrapper of bad_expected_access, and thus Result is better
>> suited to use as a function return type. Also because we know that sizeof E
>> is small, the non-union storage is safe. And because we know what E must
>> be, all implicit construction is safe, which lets us safely use syntax
>> short cuts when returning from functions etc.
>>
>
> Why exactly would you want to catch those? With the exception of
> `exception_ptr`, none of those are good exceptions to catch. They're just
> numbers, and which one you catch tells you very little about the actual
> cause of the exception.
>
The underlying design pattern is that the lowest level kernel adjacent code
does not return failure via throwing exceptions as a try-catch cycle costs
15,000 to 30,000 CPU cycles. It returns failure via std::error_code.
However there is a point as one traverses from lowest level code to
application code where you want to traverse from std::error_code to C++
exception throws as the latter are more convenient.
You are also very wrong that error_code tells you very little about the
actual cause of the exception. error_code lets you propagate the *original* error
without losing information. That error is typically whatever the OS kernel
tells you it is. It is very valuable information to retain, unmodified,
right up to the topmost layer of code.
Generally speaking with Expected the layer which turns error codes into
exception throws needs to be something like:
expected<Foo, std::error_code> _out = low_level_function();
if(!_out)
throw std::system_error(_out.error());
Foo &out = _out.value();
This gets tedious after a while. With Result, you instead do:
Foo out = low_level_function().value();
.... and you get reasonably sane default behaviour.
>
> And `exception_ptr` is *not cheap* to throw around. Creating one is a
> heap allocation, and allocating memory for a local problem is not the best
> way to deal with such things.
>
exception_ptr is still much cheaper than throwing and catching an exception.
exception_ptr is specifically available because many folk like to store
extra metadata with their exception type, and type erase it into an
exception_ptr. The Filesystem TS does this for example with
filesystem_error.
>
> At least `bad_expected_access` allows you to tell the difference between
> "Oops, I forgot to check whether the result was valid" and "Yes, I really
> did mean to throw this".
>
You strike exactly at one of the reasons why I think you need two types
each with different behaviours here. Seeing a bad_expected_access thrown
usually means a logic error: the programmer has written bad code.
This is also exactly why I think Expected's .value() needs to have a narrow
contract by default so static analysis tooling can pick up on the logic
error at compile time, instead of throwing exceptions at runtime.
I personally think Expected needs to lose all exception throwing entirely,
and bad_expected_access can be removed.
Niall
--
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/6b76fd79-c542-4c42-9bea-23108bef3a45%40isocpp.org.
------=_Part_5722_494420280.1502295187805
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<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 c=
lass=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #c=
cc solid;padding-left:1ex"><div><br></div><div>There is also the difference=
that type E is locked into one of error_code, exception_ptr, is_error_code=
_enum or is_error_condition_enum. That lock in allows Result to directly th=
row the failure without any intermediate wrapper of bad_expected_access, an=
d thus Result is better suited to use as a function return type. Also becau=
se we know that sizeof E is small, the non-union storage is safe. And becau=
se we know what E must be, all implicit construction is safe, which lets us=
safely use syntax short cuts when returning from functions etc.</div></blo=
ckquote><div><br>Why exactly would you want to catch those? With the except=
ion of `exception_ptr`, none of those are good exceptions to catch. They=
9;re just numbers, and which one you catch tells you very little about the =
actual cause of the exception.<br></div></div></blockquote><div><br></div><=
div>The underlying design pattern is that the lowest level kernel adjacent =
code does not return failure via throwing exceptions as a try-catch cycle c=
osts 15,000 to 30,000 CPU cycles. It returns failure via std::error_code.</=
div><div><br></div><div>However there is a point as one traverses from lowe=
st level code to application code where you want to traverse from std::erro=
r_code to C++ exception throws as the latter are more convenient.</div><div=
><br></div><div>You are also very wrong that error_code tells you very litt=
le about the actual cause of the exception. error_code lets you propagate t=
he <i>original</i>=C2=A0error without losing information. That error is typ=
ically whatever the OS kernel tells you it is. It is very valuable informat=
ion to retain, unmodified, right up to the topmost layer of code.</div><div=
><br></div><div>Generally speaking with Expected the layer which turns erro=
r codes into exception throws needs to be something like:</div><div><br></d=
iv><div>expected<Foo, std::error_code> _out =3D low_level_function();=
</div><div>if(!_out)</div><div>=C2=A0 throw std::system_error(_out.error())=
;</div><div>Foo &out =3D _out.value();</div><div><br></div><div>This ge=
ts tedious after a while. With Result, you instead do:</div><div><br></div>=
<div>Foo out =3D low_level_function().value();</div><div><br></div><div>...=
and you get reasonably sane default behaviour.</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><br>And `exce=
ption_ptr` is <i>not cheap</i> to throw around. Creating one is a heap allo=
cation, and allocating memory for a local problem is not the best way to de=
al with such things.<br></div></div></blockquote><div><br></div><div>except=
ion_ptr is still much cheaper than throwing and catching an exception.</div=
><div><br></div><div>exception_ptr is specifically available because many f=
olk like to store extra metadata with their exception type, and type erase =
it into an exception_ptr. The Filesystem TS does this for example with file=
system_error.</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><br>At least `bad_expected_access` allows you t=
o tell the difference between
"Oops, I forgot to check whether the result was valid" and "=
;Yes, I really did mean
to throw this".<br></div></div></blockquote><div><br></div><div>You s=
trike exactly at one of the reasons why I think you need two types each wit=
h different behaviours here. Seeing a bad_expected_access thrown usually me=
ans a logic error: the programmer has written bad code.</div><div><br></div=
><div>This is also exactly why I think Expected's .value() needs to hav=
e a narrow contract by default so static analysis tooling can pick up on th=
e logic error at compile time, instead of throwing exceptions at runtime.</=
div><div><br></div><div>I personally think Expected needs to lose all excep=
tion throwing entirely, and bad_expected_access can be removed.</div><div><=
br></div><div>Niall=C2=A0</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/6b76fd79-c542-4c42-9bea-23108bef3a45%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/6b76fd79-c542-4c42-9bea-23108bef3a45=
%40isocpp.org</a>.<br />
------=_Part_5722_494420280.1502295187805--
------=_Part_5721_1807375814.1502295187805--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 9 Aug 2017 13:11:42 -0700 (PDT)
Raw View
------=_Part_146_2001163800.1502309502898
Content-Type: multipart/alternative;
boundary="----=_Part_147_1922791418.1502309502899"
------=_Part_147_1922791418.1502309502899
Content-Type: text/plain; charset="UTF-8"
On Wednesday, August 9, 2017 at 12:13:07 PM UTC-4, Niall Douglas wrote:
>
>
>>> There is also the difference that type E is locked into one of
>>> error_code, exception_ptr, is_error_code_enum or is_error_condition_enum.
>>> That lock in allows Result to directly throw the failure without any
>>> intermediate wrapper of bad_expected_access, and thus Result is better
>>> suited to use as a function return type. Also because we know that sizeof E
>>> is small, the non-union storage is safe. And because we know what E must
>>> be, all implicit construction is safe, which lets us safely use syntax
>>> short cuts when returning from functions etc.
>>>
>>
>> Why exactly would you want to catch those? With the exception of
>> `exception_ptr`, none of those are good exceptions to catch. They're just
>> numbers, and which one you catch tells you very little about the actual
>> cause of the exception.
>>
>
> The underlying design pattern is that the lowest level kernel adjacent
> code does not return failure via throwing exceptions as a try-catch cycle
> costs 15,000 to 30,000 CPU cycles. It returns failure via std::error_code.
>
> However there is a point as one traverses from lowest level code to
> application code where you want to traverse from std::error_code to C++
> exception throws as the latter are more convenient.
>
> You are also very wrong that error_code tells you very little about the
> actual cause of the exception. error_code lets you propagate the
> *original* error without losing information. That error is typically
> whatever the OS kernel tells you it is. It is very valuable information to
> retain, unmodified, right up to the topmost layer of code.
>
>
Generally speaking with Expected the layer which turns error codes into
> exception throws needs to be something like:
>
> expected<Foo, std::error_code> _out = low_level_function();
> if(!_out)
> throw std::system_error(_out.error());
> Foo &out = _out.value();
>
> This gets tedious after a while.
>
Do people ever actually write this code? I know I've never had reason to do
so.
Consider `from_chars`, which effectively returns a bulky `expected<T, E>`.
If I were writing a throwing `from_chars` wrapper, it would look like this:
auto result = from_chars(range.begin, range.end, value, ...)
if(!result)
throw std::from_chars_failure(range.begin, range.end, result.ec); //
return result.ptr;
I would never throw `result.ec` directly. It makes absolutely no sense.
Let's say I've got a string. And this string is expected to be
comma-separated groups of 3 integer. A `from_chars` exception can happen
anywhere during that process. But I'm only going to bother to catch it
higher up in the code, when I call the whole function.
try
{
read_integer_vecs(vec, text_data);
}
catch()
{
}
Now, if I catch `std::errc` here, what do I know? Pretty much nothing. I
have no idea which value was being read, I have no idea what the data was,
nada.
If I instead caught a `from_chars_error`, I'd have access to a lot of
things. The error would store the pointers, just in case they're still
valid at the point where the exception is caught. But if they're not valid,
it would *also* store a copy of the string it attempted to convert.
Now, you might say "clearly, `read_integer_chars` should have caught the
exception and done the conversion itself." But the *whole point* of an
exception is that it can be handled anywhere that it's reasonable to handle
them. If the only place you can handle an exception is in the function that
directly called it, then you wouldn't need exception handling.
You'd only need an error code.
This also goes back to your "[whatever the OS kernel tells you] is very
valuable information to retain, unmodified, right up to the topmost layer
of code," statement. It's simply not true. Or rather, that information
*alone* is not "valuable information".
What good is a `std::error_code` to main? What can it know about the
process that produced it? Oh sure, you've got the `error_category`, but all
that will tell you is that it's from the "system" or "iostream" or
whatever. It says nothing about the particulars of the problem. And without
the particulars, you know nothing about reporting that error to a human
being.
The most you can do is shut everything down or restart the general task
with some generic error report. And that recovery would not use any of the
information from the exception object, so `catch(...)` would be no worse in
such a case.
With Result, you instead do:
>
> Foo out = low_level_function().value();
>
> ... and you get reasonably sane default behaviour.
>
>
And `exception_ptr` is *not cheap* to throw around. Creating one is a heap
>> allocation, and allocating memory for a local problem is not the best way
>> to deal with such things.
>>
>
> exception_ptr is still much cheaper than throwing and catching an
> exception.
>
So if `to_chars` were to return a `result<char*, std::exception_ptr>`, you
would feel that that's a perfectly valid, reasonable interface? Of course
not; `to_chars` should never, *ever* be allocating memory, regardless of
error states. And generally speaking, any API that would otherwise return
an error code rather than real error objects is too low-level to be
allocating memory on its own recognizance.
The only place where `result<Something, std::exception_ptr>` is a
reasonable answer is something involving communication where failure is
signaled by an exception. An example would be getting a value from a
`future<T>`, which can either return `T` or throw. Thus, a `result`-based
interface could delay the throwing of the exception.
But again, `expected<Something, std::exception_ptr>` is just as good an
interface.
exception_ptr is specifically available because many folk like to store
> extra metadata with their exception type, and type erase it into an
> exception_ptr. The Filesystem TS does this for example with
> filesystem_error.
>
Nobody ever claimed that the FileSystem TS was the pinnacle of reasonable
C++ error handling ;)
My feeling with error handling is essentially this: If you are willing to
pay the price to do memory allocation in order to get a serious error
object, then you're probably willing to pay the price of exception handling
too. And conversely, if you are unwilling to pay the price to do memory
allocation, then you're unwilling to pay the price to do exception handling.
Also, if you're willing to pay the price to have an error object that
retains significant state about the cause of the error, you *also* care
about making sure that the error can be handled non-locally. `result` and
`expected` are primarily for *local* error handling; you're not expected to
store objects in an indeterminate state around long-term. Exceptions are
the primary C++ tool for non-local error handling.
So again, why would you be throwing an integer error code?
At least `bad_expected_access` allows you to tell the difference between
>> "Oops, I forgot to check whether the result was valid" and "Yes, I really
>> did mean to throw this".
>>
>
> You strike exactly at one of the reasons why I think you need two types
> each with different behaviours here. Seeing a bad_expected_access thrown
> usually means a logic error: the programmer has written bad code.
>
> This is also exactly why I think Expected's .value() needs to have a
> narrow contract by default so static analysis tooling can pick up on the
> logic error at compile time, instead of throwing exceptions at runtime.
>
Just because `vector::at` will throw on out-of-bounds does not mean that
static analysis tools should assume that you* expect* to be passing
out-of-bounds values. The same goes here; expected::value has
well-specified behavior when it is in an error state, but static analysis
should not consider such paths to necessarily be valid.
I personally think Expected needs to lose all exception throwing entirely,
> and bad_expected_access can be removed.
>
You should be able to recover from logic errors in your code, if you would
like to. That's part of what `vector::at` is for. Now maybe there should be
an alternative function to get the value that also throws
`bad_expected_access`, with `expected::value` not throwing. But we should
still have the exception, for those who want to check such things.
--
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/4d1e3153-a022-48f4-99ea-1f06e8c9997b%40isocpp.org.
------=_Part_147_1922791418.1502309502899
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, August 9, 2017 at 12:13:07 PM UTC-4, Niall D=
ouglas wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-le=
ft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><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><br></div><div>There is also the difference that type E is locked=
into one of error_code, exception_ptr, is_error_code_enum or is_error_cond=
ition_enum. That lock in allows Result to directly throw the failure withou=
t any intermediate wrapper of bad_expected_access, and thus Result is bette=
r suited to use as a function return type. Also because we know that sizeof=
E is small, the non-union storage is safe. And because we know what E must=
be, all implicit construction is safe, which lets us safely use syntax sho=
rt cuts when returning from functions etc.</div></blockquote><div><br>Why e=
xactly would you want to catch those? With the exception of `exception_ptr`=
, none of those are good exceptions to catch. They're just numbers, and=
which one you catch tells you very little about the actual cause of the ex=
ception.<br></div></div></blockquote><div><br></div><div>The underlying des=
ign pattern is that the lowest level kernel adjacent code does not return f=
ailure via throwing exceptions as a try-catch cycle costs 15,000 to 30,000 =
CPU cycles. It returns failure via std::error_code.</div><div><br></div><di=
v>However there is a point as one traverses from lowest level code to appli=
cation code where you want to traverse from std::error_code to C++ exceptio=
n throws as the latter are more convenient.</div></blockquote><blockquote c=
lass=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px s=
olid rgb(204, 204, 204); padding-left: 1ex;"><div><br></div></blockquote><b=
lockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;borde=
r-left: 1px #ccc solid;padding-left: 1ex;"><div></div><div>You are also ver=
y wrong that error_code tells you very little about the actual cause of the=
exception. error_code lets you propagate the <i>original</i>=C2=A0error wi=
thout losing information. That error is typically whatever the OS kernel te=
lls you it is. It is very valuable information to retain, unmodified, right=
up to the topmost layer of code.</div></blockquote><blockquote class=3D"gm=
ail_quote" style=3D"margin: 0px 0px 0px 0.8ex; border-left: 1px solid rgb(2=
04, 204, 204); padding-left: 1ex;"><div>=C2=A0</div></blockquote><div></div=
><blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-left: 0.8ex;bo=
rder-left: 1px #ccc solid;padding-left: 1ex;"><div></div><div>Generally spe=
aking with Expected the layer which turns error codes into exception throws=
needs to be something like:</div><div><br></div><div>expected<Foo, std:=
:error_code> _out =3D low_level_function();</div><div>if(!_out)</div><di=
v>=C2=A0 throw std::system_error(_out.error()<wbr>);</div><div>Foo &out=
=3D _out.value();</div><div><br></div><div>This gets tedious after a while=
..</div></blockquote><div><br>Do people ever actually write this code? I kno=
w I've never had reason to do so.<br><br>Consider `from_chars`, which e=
ffectively returns a bulky `expected<T, E>`. If I were writing a thro=
wing `from_chars` wrapper, it would look like this:<br><br><div style=3D"ba=
ckground-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); borde=
r-style: solid; border-width: 1px; overflow-wrap: break-word;" class=3D"pre=
ttyprint"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span s=
tyle=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> result </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"col=
or: #000;" class=3D"styled-by-prettify"> from_chars</span><span style=3D"co=
lor: #660;" class=3D"styled-by-prettify">(</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify">range</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">.</span><span style=3D"color: #008;" class=3D"st=
yled-by-prettify">begin</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">,</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> range</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
..</span><span style=3D"color: #008;" class=3D"styled-by-prettify">end</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"> value</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">,</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #660;" =
class=3D"styled-by-prettify">...)</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" class=3D"st=
yled-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=
">result</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">throw</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> std</span><spa=
n style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">from_chars_failure</span><sp=
an style=3D"color: #660;" class=3D"styled-by-prettify">(</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">range</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color: #00=
8;" class=3D"styled-by-prettify">begin</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> range</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">.</span><span style=3D"color: #008;" class=3D"styled-by-pret=
tify">end</span><span style=3D"color: #660;" class=3D"styled-by-prettify">,=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> result</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify">ec</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">);</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #800;"=
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"st=
yled-by-prettify">return</span><span style=3D"color: #000;" class=3D"styled=
-by-prettify"> result</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-prettify=
">ptr</span><span style=3D"color: #660;" class=3D"styled-by-prettify">;</sp=
an></div></code></div><br>I would never throw `result.ec` directly. It make=
s absolutely no sense.<br><br>Let's say I've got a string. And this=
string is expected to be comma-separated groups of 3 integer. A `from_char=
s` exception can happen anywhere during that process. But I'm only goin=
g to bother to catch it higher up in the code, when I call the whole functi=
on.<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-prettif=
y">try</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>=C2=A0 read_int=
eger_vecs</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify">vec</span>=
<span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span sty=
le=3D"color: #000;" class=3D"styled-by-prettify"> text_data</span><span sty=
le=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: #=
660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" cla=
ss=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"style=
d-by-prettify">()</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">}</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div></code=
></div><br>Now, if I catch `std::errc` here, what do I know? Pretty much no=
thing. I have no idea which value was being read, I have no idea what the d=
ata was, nada.<br><br>If I instead caught a `from_chars_error`, I'd hav=
e access to a lot of things. The error would store the pointers, just in ca=
se they're still valid at the point where the exception is caught. But =
if they're not valid, it would <i>also</i> store a copy of the string i=
t attempted to convert.<br><br>Now, you might say "clearly, `read_inte=
ger_chars` should have caught the exception and done the conversion itself.=
" But the <i>whole point</i> of an exception is that it can be handled=
anywhere that it's reasonable to handle them. If the only place you ca=
n handle an exception is in the function that directly called it, then you =
wouldn't need exception handling.<br><br>You'd only need an error c=
ode.<br><br>This also goes back to your "[whatever the OS kernel tells=
you] is very valuable information to retain, unmodified, right up to the t=
opmost layer of code," statement. It's simply not true. Or rather,=
that information <i>alone</i> is not "valuable information".<br>=
<br>What good is a `std::error_code` to main? What can it know about the pr=
ocess that produced it? Oh sure, you've got the `error_category`, but a=
ll that will tell you is that it's from the "system" or "=
;iostream" or whatever. It says nothing about the particulars of the p=
roblem. And without the particulars, you know nothing about reporting that =
error to a human being.<br><br>The most you can do is shut everything down =
or restart the general task with some generic error report. And that recove=
ry would not use any of the information from the exception object, so `catc=
h(...)` would be no worse in such a case.<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>With Result, you instead do:</div><div><br></=
div><div>Foo out =3D low_level_function().value();</div><div><br></div><div=
>... and you get reasonably sane default behaviour.</div></blockquote><bloc=
kquote class=3D"gmail_quote" style=3D"margin: 0px 0px 0px 0.8ex; border-lef=
t: 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=
..8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><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>And `exception_ptr` is <=
i>not cheap</i> to throw around. Creating one is a heap allocation, and all=
ocating memory for a local problem is not the best way to deal with such th=
ings.<br></div></div></blockquote><div><br></div><div>exception_ptr is stil=
l much cheaper than throwing and catching an exception.</div></blockquote><=
div><br>So if `to_chars` were to return a `result<char*, std::exception_=
ptr>`, you would feel that that's a perfectly valid, reasonable inte=
rface? Of course not; `to_chars` should never, <i>ever</i> be allocating me=
mory, regardless of error states. And generally speaking, any API that woul=
d otherwise return an error code rather than real error objects is too low-=
level to be allocating memory on its own recognizance.<br><br>The only plac=
e where `result<Something, std::exception_ptr>` is a reasonable answe=
r is something involving communication where failure is signaled by an exce=
ption. An example would be getting a value from a `future<T>`, which =
can either return `T` or throw. Thus, a `result`-based interface could dela=
y the throwing of the exception.<br><br>But again, `expected<Something, =
std::exception_ptr>` is just as good an interface.<br><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>exception_ptr is specifically ava=
ilable because many folk like to store extra metadata with their exception =
type, and type erase it into an exception_ptr. The Filesystem TS does this =
for example with filesystem_error.</div></blockquote><div><br>Nobody ever c=
laimed that the FileSystem TS was the pinnacle of reasonable C++ error hand=
ling ;)<br><br>My feeling with error handling is essentially this: If you a=
re willing to pay the price to do memory allocation in order to get a serio=
us error object, then you're probably willing to pay the price of excep=
tion handling too. And conversely, if you are unwilling to pay the price to=
do memory allocation, then you're unwilling to pay the price to do exc=
eption handling.<br><br>Also, if you're willing to pay the price to hav=
e an error object that retains significant state about the cause of the err=
or, you <i>also</i> care about making sure that the error can be handled no=
n-locally. `result` and `expected` are primarily for <i>local</i> error han=
dling; you're not expected to store objects in an indeterminate state a=
round long-term. Exceptions are the primary C++ tool for non-local error ha=
ndling.<br><br>So again, why would you be throwing an integer error code?<b=
r><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></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>At least `bad_expect=
ed_access` allows you to tell the difference between
"Oops, I forgot to check whether the result was valid" and "=
;Yes, I really did mean
to throw this".<br></div></div></blockquote><div><br></div><div>You s=
trike exactly at one of the reasons why I think you need two types each wit=
h different behaviours here. Seeing a bad_expected_access thrown usually me=
ans a logic error: the programmer has written bad code.</div><div><br></div=
><div>This is also exactly why I think Expected's .value() needs to hav=
e a narrow contract by default so static analysis tooling can pick up on th=
e logic error at compile time, instead of throwing exceptions at runtime.</=
div></blockquote><div><br>Just because `vector::at` will throw on out-of-bo=
unds does not mean that static analysis tools should assume that you<i> exp=
ect</i> to be passing out-of-bounds values. The same goes here; expected::v=
alue has well-specified behavior when it is in an error state, but static a=
nalysis should not consider such paths to necessarily be valid.<br><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></div><div>I personally=
think Expected needs to lose all exception throwing entirely, and bad_expe=
cted_access can be removed.</div></blockquote><div><br>You should be able t=
o recover from logic errors in your code, if you would like to. That's =
part of what `vector::at` is for. Now maybe there should be an alternative =
function to get the value that also throws `bad_expected_access`, with `exp=
ected::value` not throwing. But we should still have the exception, for tho=
se who want to check such things.<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/4d1e3153-a022-48f4-99ea-1f06e8c9997b%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/4d1e3153-a022-48f4-99ea-1f06e8c9997b=
%40isocpp.org</a>.<br />
------=_Part_147_1922791418.1502309502899--
------=_Part_146_2001163800.1502309502898--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 9 Aug 2017 13:31:21 -0700 (PDT)
Raw View
------=_Part_132_1831630916.1502310681793
Content-Type: multipart/alternative;
boundary="----=_Part_133_1353930480.1502310681793"
------=_Part_133_1353930480.1502310681793
Content-Type: text/plain; charset="UTF-8"
On Wednesday, August 9, 2017 at 4:11:43 PM UTC-4, Nicol Bolas wrote:
>
> On Wednesday, August 9, 2017 at 12:13:07 PM UTC-4, Niall Douglas wrote:
>
>> With Result, you instead do:
>>
>> Foo out = low_level_function().value();
>>
>> ... and you get reasonably sane default behaviour.
>>
>
>>
> And `exception_ptr` is *not cheap* to throw around. Creating one is a
>>> heap allocation, and allocating memory for a local problem is not the best
>>> way to deal with such things.
>>>
>>
>> exception_ptr is still much cheaper than throwing and catching an
>> exception.
>>
>
> So if `to_chars` were to return a `result<char*, std::exception_ptr>`, you
> would feel that that's a perfectly valid, reasonable interface? Of course
> not; `to_chars` should never, *ever* be allocating memory, regardless of
> error states. And generally speaking, any API that would otherwise return
> an error code rather than real error objects is too low-level to be
> allocating memory on its own recognizance.
>
> The only place where `result<Something, std::exception_ptr>` is a
> reasonable answer is something involving communication where failure is
> signaled by an exception. An example would be getting a value from a
> `future<T>`, which can either return `T` or throw. Thus, a `result`-based
> interface could delay the throwing of the exception.
>
> But again, `expected<Something, std::exception_ptr>` is just as good an
> interface.
>
I also want to add that, in this case, the code would look like this:
auto exp = ...;
if(!exp) then { std::rethrow_exception(exp.error());}
Which means that I can look for the string "throw" to see who's throwing
exceptions. With your way, `rslt.value()` would *implicitly* be throwing
the `exception_ptr`. So if I want to track down the source of the
exception, it's rather more difficult.
Sometimes, verbosity and explicitness is a good thing.
--
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/a219ed19-8165-453a-99ca-32dbe64d51fc%40isocpp.org.
------=_Part_133_1353930480.1502310681793
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, August 9, 2017 at 4:11:43 PM UTC-4, 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">On =
Wednesday, August 9, 2017 at 12:13:07 PM UTC-4, Niall Douglas wrote:<br><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>With Result, you inste=
ad do:</div><div><br></div><div>Foo out =3D low_level_function().value();</=
div><div><br></div><div>... and you get reasonably sane default behaviour.<=
/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;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div></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>And `excepti=
on_ptr` is <i>not cheap</i> to throw around. Creating one is a heap allocat=
ion, and allocating memory for a local problem is not the best way to deal =
with such things.<br></div></div></blockquote><div><br></div><div>exception=
_ptr is still much cheaper than throwing and catching an exception.</div></=
blockquote><div><br>So if `to_chars` were to return a `result<char*, std=
::exception_ptr>`, you would feel that that's a perfectly valid, rea=
sonable interface? Of course not; `to_chars` should never, <i>ever</i> be a=
llocating memory, regardless of error states. And generally speaking, any A=
PI that would otherwise return an error code rather than real error objects=
is too low-level to be allocating memory on its own recognizance.<br><br>T=
he only place where `result<Something, std::exception_ptr>` is a reas=
onable answer is something involving communication where failure is signale=
d by an exception. An example would be getting a value from a `future<T&=
gt;`, which can either return `T` or throw. Thus, a `result`-based interfac=
e could delay the throwing of the exception.<br><br>But again, `expected<=
;Something, std::exception_ptr>` is just as good an interface.<br></div>=
</div></blockquote><div><br>I also want to add that, in this case, the code=
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; overflow-wrap: break-word;" class=3D"prettyprint"><code class=3D"pret=
typrint"><div class=3D"subprettyprint"><span style=3D"color: #008;" class=
=3D"styled-by-prettify">auto</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"> exp </span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> </span><span style=3D"color: #660;" class=3D"styled-by-prettify">...=
;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></spa=
n><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">exp</span><span style=3D"color:=
#660;" class=3D"styled-by-prettify">)</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"s=
tyled-by-prettify">then</span><span style=3D"color: #000;" class=3D"styled-=
by-prettify"> </span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">{</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> std<=
/span><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify">rethrow_exception</=
span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify">exp</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify">error</span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">());}</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br></span></div></code></div><br>Which means t=
hat I can look for the string "throw" to see who's throwing e=
xceptions. With your way, `rslt.value()` would <i>implicitly</i> be throwin=
g the `exception_ptr`. So if I want to track down the source of the excepti=
on, it's rather more difficult.<br><br>Sometimes, verbosity and explici=
tness is a good thing.</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/a219ed19-8165-453a-99ca-32dbe64d51fc%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/a219ed19-8165-453a-99ca-32dbe64d51fc=
%40isocpp.org</a>.<br />
------=_Part_133_1353930480.1502310681793--
------=_Part_132_1831630916.1502310681793--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Wed, 9 Aug 2017 16:33:07 -0400
Raw View
--94eb2c0672daddc13f055657fceb
Content-Type: text/plain; charset="UTF-8"
On Wed, Aug 9, 2017 at 12:13 PM, Niall Douglas <nialldouglas14@gmail.com>
wrote:
>
>>> There is also the difference that type E is locked into one of
>>> error_code, exception_ptr, is_error_code_enum or is_error_condition_enum.
>>> That lock in allows Result to directly throw the failure without any
>>> intermediate wrapper of bad_expected_access, and thus Result is better
>>> suited to use as a function return type. Also because we know that sizeof E
>>> is small, the non-union storage is safe. And because we know what E must
>>> be, all implicit construction is safe, which lets us safely use syntax
>>> short cuts when returning from functions etc.
>>>
>>
>> Why exactly would you want to catch those? With the exception of
>> `exception_ptr`, none of those are good exceptions to catch. They're just
>> numbers, and which one you catch tells you very little about the actual
>> cause of the exception.
>>
>
> The underlying design pattern is that the lowest level kernel adjacent
> code does not return failure via throwing exceptions as a try-catch cycle
> costs 15,000 to 30,000 CPU cycles. It returns failure via std::error_code.
>
> However there is a point as one traverses from lowest level code to
> application code where you want to traverse from std::error_code to C++
> exception throws as the latter are more convenient.
>
> You are also very wrong that error_code tells you very little about the
> actual cause of the exception. error_code lets you propagate the
> *original* error without losing information. That error is typically
> whatever the OS kernel tells you it is. It is very valuable information to
> retain, unmodified, right up to the topmost layer of code.
>
> Generally speaking with Expected the layer which turns error codes into
> exception throws needs to be something like:
>
> expected<Foo, std::error_code> _out = low_level_function();
> if(!_out)
> throw std::system_error(_out.error());
> Foo &out = _out.value();
>
> This gets tedious after a while. With Result, you instead do:
>
> Foo out = low_level_function().value();
>
> ... and you get reasonably sane default behaviour.
>
These are the kinds of examples we need to see. (And also discussions like
Nicol's about whether it is reasonable or not)
Assuming, for now, that this is reasonable code, is there an alternative?
What about:
// declaration:
expected<Foo, std::error_code> low_level_function();
// use
// note converting from expected<T, error_code> to expected<T,
system_error>:
expected<Foo, std::system_error> out = low_level_function();
do_something_with(out..value());
?
>
>>
>> And `exception_ptr` is *not cheap* to throw around. Creating one is a
>> heap allocation, and allocating memory for a local problem is not the best
>> way to deal with such things.
>>
>
> exception_ptr is still much cheaper than throwing and catching an
> exception.
>
> exception_ptr is specifically available because many folk like to store
> extra metadata with their exception type, and type erase it into an
> exception_ptr. The Filesystem TS does this for example with
> filesystem_error.
>
>
>>
>> At least `bad_expected_access` allows you to tell the difference between
>> "Oops, I forgot to check whether the result was valid" and "Yes, I really
>> did mean to throw this".
>>
>
> You strike exactly at one of the reasons why I think you need two types
> each with different behaviours here. Seeing a bad_expected_access thrown
> usually means a logic error: the programmer has written bad code.
>
> This is also exactly why I think Expected's .value() needs to have a
> narrow contract by default so static analysis tooling can pick up on the
> logic error at compile time, instead of throwing exceptions at runtime.
>
> I personally think Expected needs to lose all exception throwing entirely,
> and bad_expected_access can be removed.
>
> Niall
>
> --
> 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/6b76fd79-c542-4c42-
> 9bea-23108bef3a45%40isocpp.org
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/6b76fd79-c542-4c42-9bea-23108bef3a45%40isocpp.org?utm_medium=email&utm_source=footer>
> .
>
--
Be seeing you,
Tony
--
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/CAOHCbiuchrxY79jvrTKH2Y04iNGRqVBYk8z8YncWkTL3Q3_N5w%40mail.gmail.com.
--94eb2c0672daddc13f055657fceb
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Wed, Aug 9, 2017 at 12:13 PM, Niall Douglas <span dir=3D"ltr"><<a=
href=3D"mailto:nialldouglas14@gmail.com" target=3D"_blank">nialldouglas14@=
gmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=
=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding=
-left:1ex"><span class=3D"gmail-"><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 dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"marg=
in:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1e=
x"><div><br></div><div>There is also the difference that type E is locked i=
nto one of error_code, exception_ptr, is_error_code_enum or is_error_condit=
ion_enum. That lock in allows Result to directly throw the failure without =
any intermediate wrapper of bad_expected_access, and thus Result is better =
suited to use as a function return type. Also because we know that sizeof E=
is small, the non-union storage is safe. And because we know what E must b=
e, all implicit construction is safe, which lets us safely use syntax short=
cuts when returning from functions etc.</div></blockquote><div><br>Why exa=
ctly would you want to catch those? With the exception of `exception_ptr`, =
none of those are good exceptions to catch. They're just numbers, and w=
hich one you catch tells you very little about the actual cause of the exce=
ption.<br></div></div></blockquote><div><br></div></span><div>The underlyin=
g design pattern is that the lowest level kernel adjacent code does not ret=
urn failure via throwing exceptions as a try-catch cycle costs 15,000 to 30=
,000 CPU cycles. It returns failure via std::error_code.</div><div><br></di=
v><div>However there is a point as one traverses from lowest level code to =
application code where you want to traverse from std::error_code to C++ exc=
eption throws as the latter are more convenient.</div><div><br></div><div>Y=
ou are also very wrong that error_code tells you very little about the actu=
al cause of the exception. error_code lets you propagate the <i>original</i=
>=C2=A0error without losing information. That error is typically whatever t=
he OS kernel tells you it is. It is very valuable information to retain, un=
modified, right up to the topmost layer of code.</div><div><br></div><div>G=
enerally speaking with Expected the layer which turns error codes into exce=
ption throws needs to be something like:</div><div><br></div><div>expected&=
lt;Foo, std::error_code> _out =3D low_level_function();</div><div>if(!_o=
ut)</div><div>=C2=A0 throw std::system_error(_out.error()<wbr>);</div><div>=
Foo &out =3D _out.value();</div><div><br></div><div>This gets tedious a=
fter a while. With Result, you instead do:</div><div><br></div><div>Foo out=
=3D low_level_function().value();</div><div><br></div><div>... and you get=
reasonably sane default behaviour.</div></blockquote><div><br><br></div><d=
iv>These are the kinds of examples we need to see. (And also discussions li=
ke Nicol's about whether it is reasonable or not)<br><br></div><div>Ass=
uming, for now, that this is reasonable code, is there an alternative? What=
about:<br><br><div>// declaration:<br>expected<Foo, std::error_code>=
low_level_function();<br><br></div><div>// use<br></div><div>// note conve=
rting from expected<T, error_code> to expected<T, system_error>=
:<br></div><div><div>expected<Foo, std::system_error> out =3D low_lev=
el_function();</div></div><div>do_something_with(out..value());</div><div><=
br></div></div><div>=C2=A0<br>?<br><br><br></div><blockquote class=3D"gmail=
_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204=
,204);padding-left:1ex"><span class=3D"gmail-"><div>=C2=A0</div><blockquote=
class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px so=
lid rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div><br>And `excep=
tion_ptr` is <i>not cheap</i> to throw around. Creating one is a heap alloc=
ation, and allocating memory for a local problem is not the best way to dea=
l with such things.<br></div></div></blockquote><div><br></div></span><div>=
exception_ptr is still much cheaper than throwing and catching an exception=
..</div><div><br></div><div>exception_ptr is specifically available because =
many folk like to store extra metadata with their exception type, and type =
erase it into an exception_ptr. The Filesystem TS does this for example wit=
h filesystem_error.</div><span class=3D"gmail-"><div>=C2=A0</div><blockquot=
e class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px s=
olid rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div><br>At least =
`bad_expected_access` allows you to tell the difference between
"Oops, I forgot to check whether the result was valid" and "=
;Yes, I really did mean
to throw this".<br></div></div></blockquote><div><br></div></span><di=
v>You strike exactly at one of the reasons why I think you need two types e=
ach with different behaviours here. Seeing a bad_expected_access thrown usu=
ally means a logic error: the programmer has written bad code.</div><div><b=
r></div><div>This is also exactly why I think Expected's .value() needs=
to have a narrow contract by default so static analysis tooling can pick u=
p on the logic error at compile time, instead of throwing exceptions at run=
time.</div><div><br></div><div>I personally think Expected needs to lose al=
l exception throwing entirely, and bad_expected_access can be removed.</div=
><div><br></div><div>Niall=C2=A0</div><span class=3D"gmail-">
<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" target=3D"_=
blank">std-proposals+unsubscribe@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br></span>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/6b76fd79-c542-4c42-9bea-23108bef3a45%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" target=3D"_blank">=
https://groups.google.com/a/<wbr>isocpp.org/d/msgid/std-<wbr>proposals/6b76=
fd79-c542-4c42-<wbr>9bea-23108bef3a45%40isocpp.org</a><wbr>.<br>
</blockquote></div><br><br clear=3D"all"><br>-- <br><div class=3D"gmail_sig=
nature"><div dir=3D"ltr"><div>Be seeing you,<br></div>Tony<br></div></div>
</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/CAOHCbiuchrxY79jvrTKH2Y04iNGRqVBYk8z8=
YncWkTL3Q3_N5w%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">htt=
ps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAOHCbiuchrxY79jv=
rTKH2Y04iNGRqVBYk8z8YncWkTL3Q3_N5w%40mail.gmail.com</a>.<br />
--94eb2c0672daddc13f055657fceb--
.
Author: Niall Douglas <nialldouglas14@gmail.com>
Date: Wed, 9 Aug 2017 15:58:39 -0700 (PDT)
Raw View
------=_Part_237_611833055.1502319519312
Content-Type: multipart/alternative;
boundary="----=_Part_238_1711086115.1502319519312"
------=_Part_238_1711086115.1502319519312
Content-Type: text/plain; charset="UTF-8"
>
>
> Consider `from_chars`, which effectively returns a bulky `expected<T, E>`.
> If I were writing a throwing `from_chars` wrapper, it would look like this:
>
> auto result = from_chars(range.begin, range.end, value, ...)
> if(!result)
> throw std::from_chars_failure(range.begin, range.end, result.ec); //
> return result.ptr;
>
> I would never throw `result.ec` directly. It makes absolutely no sense.
>
Is your code experiencing a programmer unanticipated failure?
If yes then you need to be propagating the cause reported to you without
modification.
If not then you may be correct. Your code may expect the failure and do
something with that. Thus you'd not report the direct error upwards.
>
> Let's say I've got a string. And this string is expected to be
> comma-separated groups of 3 integer. A `from_chars` exception can happen
> anywhere during that process. But I'm only going to bother to catch it
> higher up in the code, when I call the whole function.
>
> try
> {
> read_integer_vecs(vec, text_data);
> }
> catch()
> {
> }
>
> Now, if I catch `std::errc` here, what do I know? Pretty much nothing. I
> have no idea which value was being read, I have no idea what the data was,
> nada.
>
> If I instead caught a `from_chars_error`, I'd have access to a lot of
> things. The error would store the pointers, just in case they're still
> valid at the point where the exception is caught. But if they're not valid,
> it would *also* store a copy of the string it attempted to convert.
>
> Now, you might say "clearly, `read_integer_chars` should have caught the
> exception and done the conversion itself." But the *whole point* of an
> exception is that it can be handled anywhere that it's reasonable to handle
> them. If the only place you can handle an exception is in the function that
> directly called it, then you wouldn't need exception handling.
>
Everything you just said indicated that you the programmer expected this
failure.
Therefore you probably don't want to report any failures told to you by a
third party routine because you the programmer have already written logic
to handle that exact failure case.
>
> This also goes back to your "[whatever the OS kernel tells you] is very
> valuable information to retain, unmodified, right up to the topmost layer
> of code," statement. It's simply not true. Or rather, that information
> *alone* is not "valuable information".
>
> What good is a `std::error_code` to main? What can it know about the
> process that produced it? Oh sure, you've got the `error_category`, but all
> that will tell you is that it's from the "system" or "iostream" or
> whatever. It says nothing about the particulars of the problem. And without
> the particulars, you know nothing about reporting that error to a human
> being.
>
> The most you can do is shut everything down or restart the general task
> with some generic error report. And that recovery would not use any of the
> information from the exception object, so `catch(...)` would be no worse in
> such a case.
>
Just because layers of code written by *you* don't know how to handle that
error doesn't mean that layers above you written by someone else don't
understand that error.
This is why it is so important to propagate the original error information,
unmapped, unmodified, up to code which does understand the error and can
deal with it. If your intermediate layers mess with the code e.g. mapping
it, transforming it, throwing your exception types whenever ANY failure
occurs, then you have written bad code.
>
> With Result, you instead do:
>>
>> Foo out = low_level_function().value();
>>
>> ... and you get reasonably sane default behaviour.
>>
>
>>
> And `exception_ptr` is *not cheap* to throw around. Creating one is a
>>> heap allocation, and allocating memory for a local problem is not the best
>>> way to deal with such things.
>>>
>>
>> exception_ptr is still much cheaper than throwing and catching an
>> exception.
>>
>
> So if `to_chars` were to return a `result<char*, std::exception_ptr>`, you
> would feel that that's a perfectly valid, reasonable interface? Of course
> not; `to_chars` should never, *ever* be allocating memory, regardless of
> error states. And generally speaking, any API that would otherwise return
> an error code rather than real error objects is too low-level to be
> allocating memory on its own recognizance.
>
I don't know what to_chars does. Maybe it costs 10M CPU cycles minimum. An
exception_ptr in that use case is just fine.
It's not for us to dictate to end users what's appropriate for their use
case. We can't know what their use case is.
>
>
> exception_ptr is specifically available because many folk like to store
>> extra metadata with their exception type, and type erase it into an
>> exception_ptr. The Filesystem TS does this for example with
>> filesystem_error.
>>
>
> Nobody ever claimed that the FileSystem TS was the pinnacle of reasonable
> C++ error handling ;)
>
It's better than what came before it.
>
> My feeling with error handling is essentially this: If you are willing to
> pay the price to do memory allocation in order to get a serious error
> object, then you're probably willing to pay the price of exception handling
> too. And conversely, if you are unwilling to pay the price to do memory
> allocation, then you're unwilling to pay the price to do exception handling.
>
> Also, if you're willing to pay the price to have an error object that
> retains significant state about the cause of the error, you *also* care
> about making sure that the error can be handled non-locally. `result` and
> `expected` are primarily for *local* error handling; you're not expected
> to store objects in an indeterminate state around long-term. Exceptions are
> the primary C++ tool for non-local error handling.
>
> So again, why would you be throwing an integer error code?
>
You are not throwing an integer error code.
If a layer of logic does not know what to do with an error code because it
was not anticipated by the programmer, it needs to send the failure
somewhere without destroying information. That's exactly why
std::system_error is in the standard: to send an unmodified error code via
the C++ exception throw mechanism to code which may understand it.
This stuff was not added to Boost and then to C++ 11 without a great deal
of thought. For some odd reason I am defending decisions taken by WG21 and
Boost nearly a decade ago. That's not my fight, more importantly, that ship
has sailed already. Precedent on this is well established.
Result takes the exact same design decisions as already in place in the C++
standard and naturally extends them. That's all.
>
> At least `bad_expected_access` allows you to tell the difference between
>>> "Oops, I forgot to check whether the result was valid" and "Yes, I really
>>> did mean to throw this".
>>>
>>
>> You strike exactly at one of the reasons why I think you need two types
>> each with different behaviours here. Seeing a bad_expected_access thrown
>> usually means a logic error: the programmer has written bad code.
>>
>> This is also exactly why I think Expected's .value() needs to have a
>> narrow contract by default so static analysis tooling can pick up on the
>> logic error at compile time, instead of throwing exceptions at runtime.
>>
>
> Just because `vector::at` will throw on out-of-bounds does not mean that
> static analysis tools should assume that you* expect* to be passing
> out-of-bounds values. The same goes here; expected::value has
> well-specified behavior when it is in an error state, but static analysis
> should not consider such paths to necessarily be valid.
>
Yet for some reason expected::error() has a narrow interface!
You cannot use an argument one way for expected::value() and then not apply
identical logic to expected::error(). They need to be all one way or the
other. Not inconsistent.
>
> I personally think Expected needs to lose all exception throwing entirely,
>> and bad_expected_access can be removed.
>>
>
> You should be able to recover from logic errors in your code, if you would
> like to.
>
No, logic errors should be trapped at compile time wherever possible. The
presence of std::logic_error was very unfortunate and a product of the
awful tooling of the time, and its use should not be encouraged further.
Niall
--
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/276901ba-886c-4bfb-91e4-ab230d0c725d%40isocpp.org.
------=_Part_238_1711086115.1502319519312
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<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><br>Cons=
ider `from_chars`, which effectively returns a bulky `expected<T, E>`=
.. If I were writing a throwing `from_chars` wrapper, it would look like thi=
s:<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">auto</span><span style=3D"color:#000"> result </span><span sty=
le=3D"color:#660">=3D</span><span style=3D"color:#000"> from_chars</span><s=
pan style=3D"color:#660">(</span><span style=3D"color:#000">range</span><sp=
an style=3D"color:#660">.</span><span style=3D"color:#008">begin</span><spa=
n style=3D"color:#660">,</span><span style=3D"color:#000"> range</span><spa=
n style=3D"color:#660">.</span><span style=3D"color:#008">end</span><span s=
tyle=3D"color:#660">,</span><span style=3D"color:#000"> value</span><span s=
tyle=3D"color:#660">,</span><span style=3D"color:#000"> </span><span style=
=3D"color:#660">...)</span><span style=3D"color:#000"><br></span><span styl=
e=3D"color:#008">if</span><span style=3D"color:#660">(!</span><span style=
=3D"color:#000">result</span><span style=3D"color:#660">)</span><span style=
=3D"color:#000"><br>=C2=A0 </span><span style=3D"color:#008">throw</span><s=
pan style=3D"color:#000"> std</span><span style=3D"color:#660">::</span><sp=
an style=3D"color:#000">from_chars_failure</span><span style=3D"color:#660"=
>(</span><span style=3D"color:#000">range</span><span style=3D"color:#660">=
..</span><span style=3D"color:#008"><wbr>begin</span><span style=3D"color:#6=
60">,</span><span style=3D"color:#000"> range</span><span style=3D"color:#6=
60">.</span><span style=3D"color:#008">end</span><span style=3D"color:#660"=
>,</span><span style=3D"color:#000"> result</span><span style=3D"color:#660=
">.</span><span style=3D"color:#000">ec</span><span style=3D"color:#660">);=
</span><span style=3D"color:#000"> </span><span style=3D"color:#800">//</sp=
an><span style=3D"color:#000"><br></span><span style=3D"color:#008">return<=
/span><span style=3D"color:#000"> result</span><span style=3D"color:#660">.=
</span><span style=3D"color:#000">ptr</span><span style=3D"color:#660">;</s=
pan></div></code></div><br>I would never throw `<a href=3D"http://result.ec=
" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"this.href=3D'http:/=
/www.google.com/url?q\x3dhttp%3A%2F%2Fresult.ec\x26sa\x3dD\x26sntz\x3d1\x26=
usg\x3dAFQjCNGbcVYQBJ2L3s-QjGcsyk7AeN1x3g';return true;" onclick=3D"thi=
s.href=3D'http://www.google.com/url?q\x3dhttp%3A%2F%2Fresult.ec\x26sa\x=
3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGbcVYQBJ2L3s-QjGcsyk7AeN1x3g';return t=
rue;">result.ec</a>` directly. It makes absolutely no sense.<br></div></div=
></blockquote><div><br></div><div>Is your code experiencing a programmer un=
anticipated failure?</div><div><br></div><div>If yes then you need to be pr=
opagating the cause reported to you without modification.</div><div><br></d=
iv><div>If not then you may be correct. Your code may expect the failure an=
d do something with that. Thus you'd not report the direct error upward=
s.</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><br>Let's say I've got a string. And this string i=
s expected to be comma-separated groups of 3 integer. A `from_chars` except=
ion can happen anywhere during that process. But I'm only going to both=
er to catch it higher up in the code, when I call the whole function.<br><b=
r><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">try</span><span style=3D"color:#000"><br></span><span style=3D"color:#=
660">{</span><span style=3D"color:#000"><br>=C2=A0 read_integer_vecs</span>=
<span style=3D"color:#660">(</span><span style=3D"color:#000">vec</span><sp=
an style=3D"color:#660">,</span><span style=3D"color:#000"> text_data</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><s=
pan style=3D"color:#008">catch</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:#660">}</span><span =
style=3D"color:#000"><br></span></div></code></div><br>Now, if I catch `std=
::errc` here, what do I know? Pretty much nothing. I have no idea which val=
ue was being read, I have no idea what the data was, nada.<br><br>If I inst=
ead caught a `from_chars_error`, I'd have access to a lot of things. Th=
e error would store the pointers, just in case they're still valid at t=
he point where the exception is caught. But if they're not valid, it wo=
uld <i>also</i> store a copy of the string it attempted to convert.<br><br>=
Now, you might say "clearly, `read_integer_chars` should have caught t=
he exception and done the conversion itself." But the <i>whole point</=
i> of an exception is that it can be handled anywhere that it's reasona=
ble to handle them. If the only place you can handle an exception is in the=
function that directly called it, then you wouldn't need exception han=
dling.<br></div></div></blockquote><div><br></div><div>Everything you just =
said indicated that you the programmer expected this failure.</div><div><br=
></div><div>Therefore you probably don't want to report any failures to=
ld to you by a third party routine because you the programmer have already =
written logic to handle that exact failure case.</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;"><div dir=3D"ltr"><div><br>This als=
o goes back to your "[whatever the OS kernel tells you] is very valuab=
le information to retain, unmodified, right up to the topmost layer of code=
," statement. It's simply not true. Or rather, that information <i=
>alone</i> is not "valuable information".<br><br>What good is a `=
std::error_code` to main? What can it know about the process that produced =
it? Oh sure, you've got the `error_category`, but all that will tell yo=
u is that it's from the "system" or "iostream" or w=
hatever. It says nothing about the particulars of the problem. And without =
the particulars, you know nothing about reporting that error to a human bei=
ng.<br><br>The most you can do is shut everything down or restart the gener=
al task with some generic error report. And that recovery would not use any=
of the information from the exception object, so `catch(...)` would be no =
worse in such a case.<br></div></div></blockquote><div><br></div><div>Just =
because layers of code written by <i>you</i>=C2=A0don't know how to han=
dle that error doesn't mean that layers above you written by someone el=
se don't understand that error.</div><div><br></div><div>This is why it=
is so important to propagate the original error information, unmapped, unm=
odified, up to code which does understand the error and can deal with it. I=
f your intermediate layers mess with the code e.g. mapping it, transforming=
it, throwing your exception types whenever ANY failure occurs, then you ha=
ve written bad code.</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><br></div><blockquote class=3D"gmail_quo=
te" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-=
left:1ex"><div>With Result, you instead do:</div><div><br></div><div>Foo ou=
t =3D low_level_function().value();</div><div><br></div><div>... and you ge=
t reasonably sane default behaviour.</div></blockquote><blockquote class=3D=
"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(2=
04,204,204);padding-left:1ex"><div>=C2=A0</div></blockquote><blockquote cla=
ss=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc=
solid;padding-left:1ex"><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>And `exception_ptr` is <i>not cheap</i> to throw aro=
und. Creating one is a heap allocation, and allocating memory for a local p=
roblem is not the best way to deal with such things.<br></div></div></block=
quote><div><br></div><div>exception_ptr is still much cheaper than throwing=
and catching an exception.</div></blockquote><div><br>So if `to_chars` wer=
e to return a `result<char*, std::exception_ptr>`, you would feel tha=
t that's a perfectly valid, reasonable interface? Of course not; `to_ch=
ars` should never, <i>ever</i> be allocating memory, regardless of error st=
ates. And generally speaking, any API that would otherwise return an error =
code rather than real error objects is too low-level to be allocating memor=
y on its own recognizance.<br></div></div></blockquote><div><br></div><div>=
I don't know what to_chars does. Maybe it costs 10M CPU cycles minimum.=
An exception_ptr in that use case is just fine.</div><div><br></div><div>I=
t's not for us to dictate to end users what's appropriate for their=
use case. We can't know what their use case is.</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><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>exception_ptr is specifi=
cally available because many folk like to store extra metadata with their e=
xception type, and type erase it into an exception_ptr. The Filesystem TS d=
oes this for example with filesystem_error.</div></blockquote><div><br>Nobo=
dy ever claimed that the FileSystem TS was the pinnacle of reasonable C++ e=
rror handling ;)<br></div></div></blockquote><div><br></div><div>It's b=
etter than what came before it.</div><div>=C2=A0</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><br>My feeling with error han=
dling is essentially this: If you are willing to pay the price to do memory=
allocation in order to get a serious error object, then you're probabl=
y willing to pay the price of exception handling too. And conversely, if yo=
u are unwilling to pay the price to do memory allocation, then you're u=
nwilling to pay the price to do exception handling.<br><br>Also, if you'=
;re willing to pay the price to have an error object that retains significa=
nt state about the cause of the error, you <i>also</i> care about making su=
re that the error can be handled non-locally. `result` and `expected` are p=
rimarily for <i>local</i> error handling; you're not expected to store =
objects in an indeterminate state around long-term. Exceptions are the prim=
ary C++ tool for non-local error handling.<br><br>So again, why would you b=
e throwing an integer error code?<br></div></div></blockquote><div><br></di=
v><div>You are not throwing an integer error code.</div><div><br></div><div=
>If a layer of logic does not know what to do with an error code because it=
was not anticipated by the programmer, it needs to send the failure somewh=
ere without destroying information. That's exactly why std::system_erro=
r is in the standard: to send an unmodified error code via the C++ exceptio=
n throw mechanism to code which may understand it.</div><div><br></div><div=
>This stuff was not added to Boost and then to C++ 11 without a great deal =
of thought. For some odd reason I am defending decisions taken by WG21 and =
Boost nearly a decade ago. That's not my fight, more importantly, that =
ship has sailed already. Precedent on this is well established.</div><div><=
br></div><div>Result takes the exact same design decisions as already in pl=
ace in the C++ standard and naturally extends them. That's all.</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=
"><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></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>At least `bad_expect=
ed_access` allows you to tell the difference between
"Oops, I forgot to check whether the result was valid" and "=
;Yes, I really did mean
to throw this".<br></div></div></blockquote><div><br></div><div>You s=
trike exactly at one of the reasons why I think you need two types each wit=
h different behaviours here. Seeing a bad_expected_access thrown usually me=
ans a logic error: the programmer has written bad code.</div><div><br></div=
><div>This is also exactly why I think Expected's .value() needs to hav=
e a narrow contract by default so static analysis tooling can pick up on th=
e logic error at compile time, instead of throwing exceptions at runtime.</=
div></blockquote><div><br>Just because `vector::at` will throw on out-of-bo=
unds does not mean that static analysis tools should assume that you<i> exp=
ect</i> to be passing out-of-bounds values. The same goes here; expected::v=
alue has well-specified behavior when it is in an error state, but static a=
nalysis should not consider such paths to necessarily be valid.<br></div></=
div></blockquote><div><br></div><div>Yet for some reason expected::error() =
has a narrow interface!</div><div><br></div><div>You cannot use an argument=
one way for expected::value() and then not apply identical logic to expect=
ed::error(). They need to be all one way or the other. Not inconsistent.</d=
iv><div>=C2=A0</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><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0=
;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div></div>=
<div>I personally think Expected needs to lose all exception throwing entir=
ely, and bad_expected_access can be removed.</div></blockquote><div><br>You=
should be able to recover from logic errors in your code, if you would lik=
e to.<br></div></div></blockquote><div><br></div><div>No, logic errors shou=
ld be trapped at compile time wherever possible. The presence of std::logic=
_error was very unfortunate and a product of the awful tooling of the time,=
and its use should not be encouraged further.</div><div><br></div><div>Nia=
ll</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/276901ba-886c-4bfb-91e4-ab230d0c725d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/276901ba-886c-4bfb-91e4-ab230d0c725d=
%40isocpp.org</a>.<br />
------=_Part_238_1711086115.1502319519312--
------=_Part_237_611833055.1502319519312--
.
Author: Niall Douglas <nialldouglas14@gmail.com>
Date: Wed, 9 Aug 2017 16:00:54 -0700 (PDT)
Raw View
------=_Part_283_529297216.1502319654481
Content-Type: multipart/alternative;
boundary="----=_Part_284_1014709384.1502319654481"
------=_Part_284_1014709384.1502319654481
Content-Type: text/plain; charset="UTF-8"
>
>
> I also want to add that, in this case, the code would look like this:
>
> auto exp = ...;
> if(!exp) then { std::rethrow_exception(exp.error());}
>
> Which means that I can look for the string "throw" to see who's throwing
> exceptions. With your way, `rslt.value()` would *implicitly* be throwing
> the `exception_ptr`. So if I want to track down the source of the
> exception, it's rather more difficult.
>
> Sometimes, verbosity and explicitness is a good thing.
>
Many debuggers let you trap the creation of an exception_ptr. Furthermore,
if a rethrow happens, you don't want it to trap there, you want it to trap
where the exception_ptr originated. I see no merit in this line of argument.
Niall
--
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/812b9007-92ac-4a0d-9fed-223112abb343%40isocpp.org.
------=_Part_284_1014709384.1502319654481
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<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><br>I al=
so want to add that, in this case, the code would look like this:<br><br><d=
iv 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"=
>auto</span><span style=3D"color:#000"> exp </span><span style=3D"color:#66=
0">=3D</span><span style=3D"color:#000"> </span><span style=3D"color:#660">=
....;</span><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">ex=
p</span><span style=3D"color:#660">)</span><span style=3D"color:#000"> </sp=
an><span style=3D"color:#008">then</span><span style=3D"color:#000"> </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">rethrow_excep=
tion</span><span style=3D"color:#660">(</span><span style=3D"color:#000">ex=
p</span><span style=3D"color:#660">.</span><span style=3D"color:#000">err<w=
br>or</span><span style=3D"color:#660">());}</span><span style=3D"color:#00=
0"><br></span></div></code></div><br>Which means that I can look for the st=
ring "throw" to see who's throwing exceptions. With your way,=
`rslt.value()` would <i>implicitly</i> be throwing the `exception_ptr`. So=
if I want to track down the source of the exception, it's rather more =
difficult.<br><br>Sometimes, verbosity and explicitness is a good thing.</d=
iv></div></blockquote><div><br></div><div>Many debuggers let you trap the c=
reation of an exception_ptr. Furthermore, if a rethrow happens, you don'=
;t want it to trap there, you want it to trap where the exception_ptr origi=
nated. I see no merit in this line of argument.</div><div><br></div><div>Ni=
all</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/812b9007-92ac-4a0d-9fed-223112abb343%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/812b9007-92ac-4a0d-9fed-223112abb343=
%40isocpp.org</a>.<br />
------=_Part_284_1014709384.1502319654481--
------=_Part_283_529297216.1502319654481--
.
Author: Niall Douglas <nialldouglas14@gmail.com>
Date: Wed, 9 Aug 2017 16:04:03 -0700 (PDT)
Raw View
------=_Part_304_1949644060.1502319843128
Content-Type: multipart/alternative;
boundary="----=_Part_305_1225773215.1502319843129"
------=_Part_305_1225773215.1502319843129
Content-Type: text/plain; charset="UTF-8"
>
>
> These are the kinds of examples we need to see. (And also discussions like
> Nicol's about whether it is reasonable or not)
>
> Assuming, for now, that this is reasonable code, is there an alternative?
> What about:
>
> // declaration:
> expected<Foo, std::error_code> low_level_function();
>
> // use
> // note converting from expected<T, error_code> to expected<T,
> system_error>:
> expected<Foo, std::system_error> out = low_level_function();
> do_something_with(out..value());
>
>
Why would you do this?
The C++ 11 standard specifically designates std::system_error as *the* C++
exception type used to wrap an unhandled error_code for propagation into
the C++ exception handling system.
Why would you deviate from the C++ standard's specific design and intent
when providing these facilities?
Niall
--
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/be23676c-4a19-40d7-a5b4-9383b48af9c9%40isocpp.org.
------=_Part_305_1225773215.1502319843129
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div><div class=3D"gmail_quote"><div><br></div><div>These are the kinds=
of examples we need to see. (And also discussions like Nicol's about w=
hether it is reasonable or not)<br><br></div><div>Assuming, for now, that t=
his is reasonable code, is there an alternative? What about:<br><br><div>//=
declaration:<br>expected<Foo, std::error_code> low_level_function();=
<br><br></div><div>// use<br></div><div>// note converting from expected<=
;T, error_code> to expected<T, system_error>:<br></div><div><div>e=
xpected<Foo, std::system_error> out =3D low_level_function();</div></=
div><div>do_something_with(out..value()<wbr>);</div><div><br></div></div></=
div></div></div></blockquote><div><br></div><div>Why would you do this?</di=
v><div><br></div><div>The C++ 11 standard specifically designates std::syst=
em_error as <b>the</b>=C2=A0C++ exception type used to wrap an unhandled er=
ror_code for propagation into the C++ exception handling system.</div><div>=
<br></div><div>Why would you deviate from the C++ standard's specific d=
esign and intent when providing these facilities?</div><div><br></div><div>=
Niall</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/be23676c-4a19-40d7-a5b4-9383b48af9c9%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/be23676c-4a19-40d7-a5b4-9383b48af9c9=
%40isocpp.org</a>.<br />
------=_Part_305_1225773215.1502319843129--
------=_Part_304_1949644060.1502319843128--
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Wed, 9 Aug 2017 22:30:23 -0400
Raw View
--001a114c800085dfac05565cfa5a
Content-Type: text/plain; charset="UTF-8"
On Wed, Aug 9, 2017 at 7:04 PM, Niall Douglas <nialldouglas14@gmail.com>
wrote:
>
>> These are the kinds of examples we need to see. (And also discussions
>> like Nicol's about whether it is reasonable or not)
>>
>> Assuming, for now, that this is reasonable code, is there an alternative?
>> What about:
>>
>> // declaration:
>> expected<Foo, std::error_code> low_level_function();
>>
>> // use
>> // note converting from expected<T, error_code> to expected<T,
>> system_error>:
>> expected<Foo, std::system_error> out = low_level_function();
>> do_something_with(out..value());
>>
>>
> Why would you do this?
>
Sorry, I should have also added a change where expected would throw E
instead of throwing bad_expected_access<E>. Then this would be the same as
your code, I think.
the choices for expected throwing are:
0. throw E
this is not really an option. throwing things like int is probably not a
good idea.
1. throw bad_expected_access<E>
OK, sure.
2. throw E if E derives from std::exception, or throw the exception if E is
exception_ptr, else throw bad_expected_access<E>
ie the rule would be "ensure Standard things always throw std::exception
things"
3. some custom handler/converter of E to exception. But I don't think ADL
works here (you would need to wrap ints into unique types for each
occasion), so it would need to be part of the expected type or
type-erased. Not sure either of those are worth it.
I was thinking 2.
>
> The C++ 11 standard specifically designates std::system_error as *the* C++
> exception type used to wrap an unhandled error_code for propagation into
> the C++ exception handling system.
>
>
If expected<Foo, std::system_error> throws on value() when it's an error,
and expected<Foo, error_code> is convertable to expected<Foo,
system_error>, then we get the user opting-in to the point where that
conversion from low-level to expection-level happens.
> Why would you deviate from the C++ standard's specific design and intent
> when providing these facilities?
>
> Niall
>
> --
> 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/be23676c-4a19-40d7-
> a5b4-9383b48af9c9%40isocpp.org
> <https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/be23676c-4a19-40d7-a5b4-9383b48af9c9%40isocpp.org?utm_medium=email&utm_source=footer>
> .
>
--
Be seeing you,
Tony
--
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/CAOHCbitY01%3Da77zSoAPjOT30oAXza-mQ__w%3Dro8s%2B05xoZMsQA%40mail.gmail.com.
--001a114c800085dfac05565cfa5a
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Wed, Aug 9, 2017 at 7:04 PM, Niall Douglas <span dir=3D"ltr"><<a =
href=3D"mailto:nialldouglas14@gmail.com" target=3D"_blank">nialldouglas14@g=
mail.com</a>></span> wrote:<br><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 dir=3D"ltr"><span class=3D"gmail-"><blockquote class=3D"gma=
il_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,2=
04,204);padding-left:1ex"><div dir=3D"ltr"><div><div class=3D"gmail_quote">=
<div><br></div><div>These are the kinds of examples we need to see. (And al=
so discussions like Nicol's about whether it is reasonable or not)<br><=
br></div><div>Assuming, for now, that this is reasonable code, is there an =
alternative? What about:<br><br><div>// declaration:<br>expected<Foo, st=
d::error_code> low_level_function();<br><br></div><div>// use<br></div><=
div>// note converting from expected<T, error_code> to expected<T,=
system_error>:<br></div><div><div>expected<Foo, std::system_error>=
; out =3D low_level_function();</div></div><div>do_something_with(out..valu=
e()<wbr>);</div><div><br></div></div></div></div></div></blockquote><div><b=
r></div></span><div>Why would you do this?</div></div></blockquote><div><br=
></div><div>Sorry, I should have also added a change where expected would t=
hrow E instead of throwing bad_expected_access<E>.=C2=A0 Then this wo=
uld be the same as your code, I think.<br><br></div><div>the choices for ex=
pected throwing are:<br><br></div><div>0. throw E<br></div><div>this is not=
really an option.=C2=A0 throwing things like int is probably not a good id=
ea.<br></div><div>1. throw bad_expected_access<E><br></div><div>OK, s=
ure.<br></div><div>2. throw E if E derives from std::exception, or throw th=
e exception if E is exception_ptr, else throw bad_expected_access<E><=
br></div><div>ie the rule would be "ensure Standard things always thro=
w std::exception things"<br></div><div><br></div><div>3. some custom h=
andler/converter of E to exception.=C2=A0 But I don't think ADL works h=
ere (you would need to wrap ints into unique types for each occasion), so i=
t would need to be part of the expected type or type-erased.=C2=A0 Not sure=
either of those are worth it.<br><br><br>I was thinking 2.<br></div><div>=
=C2=A0<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0=
px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir=
=3D"ltr"><div><br></div><div>The C++ 11 standard specifically designates st=
d::system_error as <b>the</b>=C2=A0C++ exception type used to wrap an unhan=
dled error_code for propagation into the C++ exception handling system.</di=
v><div><br></div></div></blockquote><div><br></div><div>If expected<Foo,=
std::system_error> throws on value() when it's an error, and expect=
ed<Foo, error_code> is convertable to expected<Foo, system_error&g=
t;, then we get the user opting-in to the point where that conversion from =
low-level to expection-level happens.<br><br></div><div><br>=C2=A0</div><bl=
ockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-lef=
t:1px solid rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div></div>=
<div>Why would you deviate from the C++ standard's specific design and =
intent when providing these facilities?</div><div><br></div><div>Niall</div=
></div><span class=3D"gmail-">
<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" target=3D"_=
blank">std-proposals+unsubscribe@<wbr>isocpp.org</a>.<br>
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org" target=3D"_blank">std-proposals@isocpp.org</a>.<br></span>
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/be23676c-4a19-40d7-a5b4-9383b48af9c9%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter" target=3D"_blank">=
https://groups.google.com/a/<wbr>isocpp.org/d/msgid/std-<wbr>proposals/be23=
676c-4a19-40d7-<wbr>a5b4-9383b48af9c9%40isocpp.org</a><wbr>.<br>
</blockquote></div><br><br clear=3D"all"><br>-- <br><div class=3D"gmail_sig=
nature"><div dir=3D"ltr"><div>Be seeing you,<br></div>Tony<br></div></div>
</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/CAOHCbitY01%3Da77zSoAPjOT30oAXza-mQ__=
w%3Dro8s%2B05xoZMsQA%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfoote=
r">https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAOHCbitY01=
%3Da77zSoAPjOT30oAXza-mQ__w%3Dro8s%2B05xoZMsQA%40mail.gmail.com</a>.<br />
--001a114c800085dfac05565cfa5a--
.
Author: Niall Douglas <nialldouglas14@gmail.com>
Date: Wed, 9 Aug 2017 20:55:34 -0700 (PDT)
Raw View
------=_Part_462_1438842287.1502337334658
Content-Type: multipart/alternative;
boundary="----=_Part_463_435448485.1502337334659"
------=_Part_463_435448485.1502337334659
Content-Type: text/plain; charset="UTF-8"
>
>
> the choices for expected throwing are:
>
> 0. throw E
> this is not really an option. throwing things like int is probably not a
> good idea.
> 1. throw bad_expected_access<E>
> OK, sure.
> 2. throw E if E derives from std::exception, or throw the exception if E
> is exception_ptr, else throw bad_expected_access<E>
> ie the rule would be "ensure Standard things always throw std::exception
> things"
>
> 3. some custom handler/converter of E to exception. But I don't think ADL
> works here (you would need to wrap ints into unique types for each
> occasion), so it would need to be part of the expected type or
> type-erased. Not sure either of those are worth it.
>
You forgot a fourth option: 4. Expected never ever throws an exception, not
its place.
>
> I was thinking 2.
>
Option 3 incidentally *is* implemented by Outcome as an extension. Indeed
AFIO uses ADL hooking to inject fun custom semantics into Result. And it
also implements a generalised Option 2 via policy classes, so you can
supply any arbitrary interpretation of some type E. But I digress.
Regarding Option 2, why is it so important that Expected do all the heavy
lifting? Let the type system lessen the cognitive load on the programmer:
Result has a very restricted type E, and therefore what its wide contract
observers throw is obvious given you can't feed it any type E which doesn't
have an obvious corresponding throw type. That eliminates programmer
surprise.
>
>
>>
>> The C++ 11 standard specifically designates std::system_error as *the* C++
>> exception type used to wrap an unhandled error_code for propagation into
>> the C++ exception handling system.
>>
>>
> If expected<Foo, std::system_error> throws on value() when it's an error,
> and expected<Foo, error_code> is convertable to expected<Foo,
> system_error>, then we get the user opting-in to the point where that
> conversion from low-level to expection-level happens.
>
>
I can see the logic behind this. I'm still not keen on magic semantics
depending on types used unless you impose strict restrictions on the types
usable.
Niall
--
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/60491a64-7f5c-42b8-bda5-1c2e08e38825%40isocpp.org.
------=_Part_463_435448485.1502337334659
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<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 cla=
ss=3D"gmail_quote"><div><br></div><div>the choices for expected throwing ar=
e:<br><br></div><div>0. throw E<br></div><div>this is not really an option.=
=C2=A0 throwing things like int is probably not a good idea.<br></div><div>=
1. throw bad_expected_access<E><br></div><div>OK, sure.<br></div><div=
>2. throw E if E derives from std::exception, or throw the exception if E i=
s exception_ptr, else throw bad_expected_access<E><br></div><div>ie t=
he rule would be "ensure Standard things always throw std::exception t=
hings"<br></div><div><br></div><div>3. some custom handler/converter o=
f E to exception.=C2=A0 But I don't think ADL works here (you would nee=
d to wrap ints into unique types for each occasion), so it would need to be=
part of the expected type or type-erased.=C2=A0 Not sure either of those a=
re worth it.<br></div></div></div></div></blockquote><div><br></div><div>Yo=
u forgot a fourth option: 4. Expected never ever throws an exception, not i=
ts place.</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 class=3D"gmail_quote"><div><br>I was thinking =
2.<br></div></div></div></div></blockquote><div><br></div><div>Option 3 inc=
identally <b>is</b>=C2=A0implemented by Outcome as an extension. Indeed AFI=
O uses ADL hooking to inject fun custom semantics into Result. And it also =
implements a generalised Option 2 via policy classes, so you can supply any=
arbitrary interpretation of some type E. But I digress.</div><div><br></di=
v><div>Regarding Option 2, why is it so important that Expected do all the =
heavy lifting? Let the type system lessen the cognitive load on the program=
mer: Result has a very restricted type E, and therefore what its wide contr=
act observers throw is obvious given you can't feed it any type E which=
doesn't have an obvious corresponding throw type. That eliminates prog=
rammer surprise.</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><div class=3D"gmail_quote"><div></div><div>=
=C2=A0<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0=
px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir=
=3D"ltr"><div><br></div><div>The C++ 11 standard specifically designates st=
d::system_error as <b>the</b>=C2=A0C++ exception type used to wrap an unhan=
dled error_code for propagation into the C++ exception handling system.</di=
v><div><br></div></div></blockquote><div><br></div><div>If expected<Foo,=
std::system_error> throws on value() when it's an error, and expect=
ed<Foo, error_code> is convertable to expected<Foo, system_error&g=
t;, then we get the user opting-in to the point where that conversion from =
low-level to expection-level happens.<br><br></div></div></div></div></bloc=
kquote><div><br></div><div>I can see the logic behind this. I'm still n=
ot keen on magic semantics depending on types used unless you impose strict=
restrictions on the types usable.</div><div><br></div><div>Niall</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/60491a64-7f5c-42b8-bda5-1c2e08e38825%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/60491a64-7f5c-42b8-bda5-1c2e08e38825=
%40isocpp.org</a>.<br />
------=_Part_463_435448485.1502337334659--
------=_Part_462_1438842287.1502337334658--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Wed, 9 Aug 2017 23:27:05 -0700 (PDT)
Raw View
------=_Part_484_294989460.1502346425647
Content-Type: multipart/alternative;
boundary="----=_Part_485_556493053.1502346425648"
------=_Part_485_556493053.1502346425648
Content-Type: text/plain; charset="UTF-8"
On Wednesday, August 9, 2017 at 6:58:39 PM UTC-4, Niall Douglas wrote:
>
>
>> Consider `from_chars`, which effectively returns a bulky `expected<T,
>> E>`. If I were writing a throwing `from_chars` wrapper, it would look like
>> this:
>>
>> auto result = from_chars(range.begin, range.end, value, ...)
>> if(!result)
>> throw std::from_chars_failure(range.begin, range.end, result.ec); //
>> return result.ptr;
>>
>> I would never throw `result.ec` directly. It makes absolutely no sense.
>>
>
> Is your code experiencing a programmer unanticipated failure?
>
.... I'm not sure that's relevant. If the writer of this function did not
anticipate failure, they wouldn't be throwing something. And if the caller
of the function did not anticipate the failure, then they won't catch the
exception.
If yes then you need to be propagating the cause reported to you without
> modification.
>
Why? You say this a lot, but you give no justification for it. You simply
declare it as though it were an obvious fact. By contrast, I've given you
examples of cases when throwing just an error_code is not sufficient
information to resolve an error effectively.
If not then you may be correct. Your code may expect the failure and do
> something with that. Thus you'd not report the direct error upwards.
>
Who is "you" in this example? The only code I posted here is a prospective
wrapper of `from_chars` that throws on errors rather than returning an
error code.
Let's say I've got a string. And this string is expected to be
>> comma-separated groups of 3 integer. A `from_chars` exception can happen
>> anywhere during that process. But I'm only going to bother to catch it
>> higher up in the code, when I call the whole function.
>>
>> try
>> {
>> read_integer_vecs(vec, text_data);
>> }
>> catch()
>> {
>> }
>>
>> Now, if I catch `std::errc` here, what do I know? Pretty much nothing. I
>> have no idea which value was being read, I have no idea what the data was,
>> nada.
>>
>> If I instead caught a `from_chars_error`, I'd have access to a lot of
>> things. The error would store the pointers, just in case they're still
>> valid at the point where the exception is caught. But if they're not valid,
>> it would *also* store a copy of the string it attempted to convert.
>>
>> Now, you might say "clearly, `read_integer_chars` should have caught the
>> exception and done the conversion itself." But the *whole point* of an
>> exception is that it can be handled anywhere that it's reasonable to handle
>> them. If the only place you can handle an exception is in the function that
>> directly called it, then you wouldn't need exception handling.
>>
>
> Everything you just said indicated that you the programmer expected this
> failure.
>
> Therefore you probably don't want to report any failures told to you by a
> third party routine because you the programmer have already written logic
> to handle that exact failure case.
>
.... again, I have no idea which "the programmer" you're referring to here.
Are we talking about the person who wrote `read_integer_vecs`, the person
who wrote the throwing `from_chars`, or the person calling
`read_integer_vecs`? That's 3 different programmers, and it's really
important to know which perspective you're looking at it from, and who this
mysterious "third party" is.
This also goes back to your "[whatever the OS kernel tells you] is very
>> valuable information to retain, unmodified, right up to the topmost layer
>> of code," statement. It's simply not true. Or rather, that information
>> *alone* is not "valuable information".
>>
>> What good is a `std::error_code` to main? What can it know about the
>> process that produced it? Oh sure, you've got the `error_category`, but all
>> that will tell you is that it's from the "system" or "iostream" or
>> whatever. It says nothing about the particulars of the problem. And without
>> the particulars, you know nothing about reporting that error to a human
>> being.
>>
>> The most you can do is shut everything down or restart the general task
>> with some generic error report. And that recovery would not use any of the
>> information from the exception object, so `catch(...)` would be no worse in
>> such a case.
>>
>
> Just because layers of code written by *you* don't know how to handle
> that error doesn't mean that layers above you written by someone else don't
> understand that error.
>
.... yes, it does. As a general rule, the farther up the call stack you go,
the *less* information you have on the specific implementation details of
whatever produced that error. `main` does not know or care that you created
a `thread`, nor does it have any idea what to do if that failed to happen
due to some system-specific failure.
Error codes are the most context-specific kind of error delivery that
exists. An error code is increasingly less meaningful the farther you get
from their point of origin, where its context lives.
If you directly call `filesystem::exists(path, ec)`, then clearly you the
caller have access to the path that provoked any errors from `ec`. By
contrast, if you're 4 levels deep in a call graph, and someone calls the
throwing version of `exists`, you likely know nothing about what path
produced that error. Indeed, odds are good that you don't even know that it
was a call to `filesystem::exists` that provoked the error.
So how can you possibly handle it as anything other than general
termination of whatever thing you were trying to do? At which point, it *doesn't
matter* if the error code were modified or unmodified; you got an
exception, so you've failed to accomplish the task.
This is precisely why exceptions in C++ can be something more than just raw
integer error codes. This is why FileSystem doesn't throw `system_error`
directly; it throws `filesystem_error`, which contains at least some of the
state needed to know what's going on.
Are there exceptions to this? Certainly: callbacks, algorithms, and other
such systems. But even then, you lose a lot of context information when
throwing through algorithms (like which specific value was being operated
on). Even in such cases, a stateful exception is far superior to a
stateless one.
Furthermore, if what you say is true, then you should be able to explain
what this means:
int main(...)
{
try
{
//stuff
}
catch(std::system_error ec)
{
}
}
If a filesystem-thrown `error_code` bubbled its way up to `main`, how would
`main` handle it in a reasonable way? If an iostream `error_code`
manifested, how would `main` handle it? If you attempt to try_lock a mutex
too much and get a `system_error`, how exactly is `main` going to fix that?
Give me some concrete, non-toy examples of a program that can genuinely do
something useful in such a `catch` statement. Something besides just
logging the error code and quitting, that is.
This is why it is so important to propagate the original error information,
> unmapped, unmodified, up to code which does understand the error and can
> deal with it. If your intermediate layers mess with the code e.g. mapping
> it, transforming it, throwing your exception types whenever ANY failure
> occurs, then you have written bad code.
>
What is bad about it? Why should the higher-level code know about what the
lower-level code is doing? Isn't the whole point of encapsulation,
abstraction, and the like to *insulate* high-level code from the low-level
implementation details?
I don't care about the specific error code number for `std::from_chars`'s
failure. The thing that matters most to me, when it comes to actually *dealing
with* the error case, is the location where the failure happened and the
string it failed on. Those are things that I can show to a user, to help
them figure out what happened and how to fix it.
And `exception_ptr` is *not cheap* to throw around. Creating one is a heap
>>>> allocation, and allocating memory for a local problem is not the best way
>>>> to deal with such things.
>>>>
>>>
>>> exception_ptr is still much cheaper than throwing and catching an
>>> exception.
>>>
>>
>> So if `to_chars` were to return a `result<char*, std::exception_ptr>`,
>> you would feel that that's a perfectly valid, reasonable interface? Of
>> course not; `to_chars` should never, *ever* be allocating memory,
>> regardless of error states. And generally speaking, any API that would
>> otherwise return an error code rather than real error objects is too
>> low-level to be allocating memory on its own recognizance.
>>
>
> I don't know what to_chars does.
>
It does this. <http://en.cppreference.com/w/cpp/utility/to_chars> It's a
part of the C++17 standard library.
Maybe it costs 10M CPU cycles minimum. An exception_ptr in that use case is
> just fine.
>
> It's not for us to dictate to end users what's appropriate for their use
> case. We can't know what their use case is.
>
And yet, you seem to want to dictate what exception `expected::value`
throws, or more to the point doesn't throw.
All interfaces are ultimately about making choices based on what we feel
works best for users. I feel that `expected::value` throwing something
other than `E` works best for users.
That being said, I do recognize at least one use case for the type. But I'd
still much rather it be `expected<T, exception_ptr>`, and that you have to
explicitly rethrow it.
I personally think Expected needs to lose all exception throwing entirely,
>>> and bad_expected_access can be removed.
>>>
>>
>> You should be able to recover from logic errors in your code, if you
>> would like to.
>>
>
> No, logic errors should be trapped at compile time wherever possible. The
> presence of std::logic_error was very unfortunate and a product of the
> awful tooling of the time, and its use should not be encouraged further.
>
So why does `dynamic_cast` throw if you provide a reference? Why does
`any_cast` throw if you provide a value/reference? Those are both logic
errors; the user explicitly expects the object to be of the given type, and
if it isn't, then something has almost certainly gone wrong in the system.
Those exception types may not derive from `logic_error`, but they are
programming logic errors never-the-less.
Why do these throw? Because we recognize the fact that not all logic errors
can be trapped at compile time, but we still need to be able to trap 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/f3d99188-248b-4da0-b839-51128bb04627%40isocpp.org.
------=_Part_485_556493053.1502346425648
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Wednesday, August 9, 2017 at 6:58:39 PM UTC-4, Niall Do=
uglas wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-lef=
t: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><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><br>Consider `from_chars`, whi=
ch effectively returns a bulky `expected<T, E>`. If I were writing a =
throwing `from_chars` wrapper, it 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">auto</s=
pan><span style=3D"color:#000"> result </span><span style=3D"color:#660">=
=3D</span><span style=3D"color:#000"> from_chars</span><span style=3D"color=
:#660">(</span><span style=3D"color:#000">range</span><span style=3D"color:=
#660">.</span><span style=3D"color:#008">begin</span><span style=3D"color:#=
660">,</span><span style=3D"color:#000"> range</span><span style=3D"color:#=
660">.</span><span style=3D"color:#008">end</span><span style=3D"color:#660=
">,</span><span style=3D"color:#000"> value</span><span style=3D"color:#660=
">,</span><span style=3D"color:#000"> </span><span style=3D"color:#660">...=
)</span><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">resul=
t</span><span style=3D"color:#660">)</span><span style=3D"color:#000"><br>=
=C2=A0 </span><span style=3D"color:#008">throw</span><span style=3D"color:#=
000"> std</span><span style=3D"color:#660">::</span><span style=3D"color:#0=
00">from_chars_failure</span><span style=3D"color:#660">(</span><span style=
=3D"color:#000">range</span><span style=3D"color:#660">.</span><span style=
=3D"color:#008"><wbr>begin</span><span style=3D"color:#660">,</span><span s=
tyle=3D"color:#000"> range</span><span style=3D"color:#660">.</span><span s=
tyle=3D"color:#008">end</span><span style=3D"color:#660">,</span><span styl=
e=3D"color:#000"> result</span><span style=3D"color:#660">.</span><span sty=
le=3D"color:#000">ec</span><span style=3D"color:#660">);</span><span style=
=3D"color:#000"> </span><span style=3D"color:#800">//</span><span style=3D"=
color:#000"><br></span><span style=3D"color:#008">return</span><span style=
=3D"color:#000"> result</span><span style=3D"color:#660">.</span><span styl=
e=3D"color:#000">ptr</span><span style=3D"color:#660">;</span></div></code>=
</div><br>I would never throw `<a href=3D"http://result.ec" rel=3D"nofollow=
" target=3D"_blank" onmousedown=3D"this.href=3D'http://www.google.com/u=
rl?q\x3dhttp%3A%2F%2Fresult.ec\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGbcV=
YQBJ2L3s-QjGcsyk7AeN1x3g';return true;" onclick=3D"this.href=3D'htt=
p://www.google.com/url?q\x3dhttp%3A%2F%2Fresult.ec\x26sa\x3dD\x26sntz\x3d1\=
x26usg\x3dAFQjCNGbcVYQBJ2L3s-QjGcsyk7AeN1x3g';return true;">result.ec</=
a>` directly. It makes absolutely no sense.<br></div></div></blockquote><di=
v><br></div><div>Is your code experiencing a programmer unanticipated failu=
re?</div></blockquote><div><br>... I'm not sure that's relevant. If=
the writer of this function did not anticipate failure, they wouldn't =
be throwing something. And if the caller of the function did not anticipate=
the failure, then they won't catch the exception.<br><br></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>If yes then you need to be propa=
gating the cause reported to you without modification.</div></blockquote><d=
iv><br>Why? You say this a lot, but you give no justification for it. You s=
imply declare it as though it were an obvious fact. By contrast, I've g=
iven you examples of cases when throwing just an error_code is not sufficie=
nt information to resolve an error effectively.<br><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></div><div>If not then you may be corre=
ct. Your code may expect the failure and do something with that. Thus you&#=
39;d not report the direct error upwards.</div></blockquote><div><br>Who is=
"you" in this example? The only code I posted here is a prospect=
ive wrapper of `from_chars` that throws on errors rather than returning an =
error code.<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>=
</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>Let'=
;s say I've got a string. And this string is expected to be comma-separ=
ated groups of 3 integer. A `from_chars` exception can happen anywhere duri=
ng that process. But I'm only going to bother to catch it higher up in =
the code, when I call the whole function.<br><br><div style=3D"background-c=
olor:rgb(250,250,250);border-color:rgb(187,187,187);border-style:solid;bord=
er-width:1px"><code><div><span style=3D"color:#008">try</span><span style=
=3D"color:#000"><br></span><span style=3D"color:#660">{</span><span style=
=3D"color:#000"><br>=C2=A0 read_integer_vecs</span><span style=3D"color:#66=
0">(</span><span style=3D"color:#000">vec</span><span style=3D"color:#660">=
,</span><span style=3D"color:#000"> text_data</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></span><span style=3D"color:#008"=
>catch</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=
></span></div></code></div><br>Now, if I catch `std::errc` here, what do I =
know? Pretty much nothing. I have no idea which value was being read, I hav=
e no idea what the data was, nada.<br><br>If I instead caught a `from_chars=
_error`, I'd have access to a lot of things. The error would store the =
pointers, just in case they're still valid at the point where the excep=
tion is caught. But if they're not valid, it would <i>also</i> store a =
copy of the string it attempted to convert.<br><br>Now, you might say "=
;clearly, `read_integer_chars` should have caught the exception and done th=
e conversion itself." But the <i>whole point</i> of an exception is th=
at it can be handled anywhere that it's reasonable to handle them. If t=
he only place you can handle an exception is in the function that directly =
called it, then you wouldn't need exception handling.<br></div></div></=
blockquote><div><br></div><div>Everything you just said indicated that you =
the programmer expected this failure.</div><div><br></div><div>Therefore yo=
u probably don't want to report any failures told to you by a third par=
ty routine because you the programmer have already written logic to handle =
that exact failure case.</div></blockquote><div><br>... again, I have no id=
ea which "the programmer" you're referring to here. Are we ta=
lking about the person who wrote `read_integer_vecs`, the person who wrote =
the throwing `from_chars`, or the person calling `read_integer_vecs`? That&=
#39;s 3 different programmers, and it's really important to know which =
perspective you're looking at it from, and who this mysterious "th=
ird party" is.<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></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=
>This also goes back to your "[whatever the OS kernel tells you] is ve=
ry valuable information to retain, unmodified, right up to the topmost laye=
r of code," statement. It's simply not true. Or rather, that infor=
mation <i>alone</i> is not "valuable information".<br><br>What go=
od is a `std::error_code` to main? What can it know about the process that =
produced it? Oh sure, you've got the `error_category`, but all that wil=
l tell you is that it's from the "system" or "iostream&q=
uot; or whatever. It says nothing about the particulars of the problem. And=
without the particulars, you know nothing about reporting that error to a =
human being.<br><br>The most you can do is shut everything down or restart =
the general task with some generic error report. And that recovery would no=
t use any of the information from the exception object, so `catch(...)` wou=
ld be no worse in such a case.<br></div></div></blockquote><div><br></div><=
div>Just because layers of code written by <i>you</i>=C2=A0don't know h=
ow to handle that error doesn't mean that layers above you written by s=
omeone else don't understand that error.</div></blockquote><div><br>...=
yes, it does. As a general rule, the farther up the call stack you go, the=
<i>less</i> information you have on the specific implementation details of=
whatever produced that error. `main` does not know or care that you create=
d a `thread`, nor does it have any idea what to do if that failed to happen=
due to some system-specific failure.<br><br>Error codes are the most conte=
xt-specific kind of error delivery that exists. An error code is increasing=
ly less meaningful the farther you get from their point of origin, where it=
s context lives.<br><br>If you directly call `filesystem::exists(path, ec)`=
, then clearly you the caller have access to the path that provoked any err=
ors from `ec`. By contrast, if you're 4 levels deep in a call graph, an=
d someone calls the throwing version of `exists`, you likely know nothing a=
bout what path produced that error. Indeed, odds are good that you don'=
t even know that it was a call to `filesystem::exists` that provoked the er=
ror.<br><br>So how can you possibly handle it as anything other than genera=
l termination of whatever thing you were trying to do? At which point, it <=
i>doesn't matter</i> if the error code were modified or unmodified; you=
got an exception, so you've failed to accomplish the task.<br><br>This=
is precisely why exceptions in C++ can be something more than just raw int=
eger error codes. This is why FileSystem doesn't throw `system_error` d=
irectly; it throws `filesystem_error`, which contains at least some of the =
state needed to know what's going on.<br><br>Are there exceptions to th=
is? Certainly: callbacks, algorithms, and other such systems. But even then=
, you lose a lot of context information when throwing through algorithms (l=
ike which specific value was being operated on). Even in such cases, a stat=
eful exception is far superior to a stateless one.<br><br>Furthermore, if w=
hat you say is true, then you should be able to explain what this means:<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: brea=
k-word;" class=3D"prettyprint"><code class=3D"prettyprint"><div class=3D"su=
bprettyprint"><span style=3D"color: #008;" class=3D"styled-by-prettify">int=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> main</spa=
n><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">try</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 =C2=A0 </span><span style=3D"color: #8=
00;" class=3D"styled-by-prettify">//stuff</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: #008;" clas=
s=3D"styled-by-prettify">catch</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify">std</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">syst=
em_error ec</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: #660;" class=3D"styled-by-prettify">}</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br></span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">}</span></div></code></div><=
br>If a filesystem-thrown `error_code` bubbled its way up to `main`, how wo=
uld `main` handle it in a reasonable way? If an iostream `error_code` manif=
ested, how would `main` handle it? If you attempt to try_lock a mutex too m=
uch and get a `system_error`, how exactly is `main` going to fix that?<br><=
br>Give me some concrete, non-toy examples of a program that can genuinely =
do something useful in such a `catch` statement. Something besides just log=
ging the error code and quitting, that is.<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>This is why it is so important to propagat=
e the original error information, unmapped, unmodified, up to code which do=
es understand the error and can deal with it. If your intermediate layers m=
ess with the code e.g. mapping it, transforming it, throwing your exception=
types whenever ANY failure occurs, then you have written bad code.</div></=
blockquote><div><br>What is bad about it? Why should the higher-level code =
know about what the lower-level code is doing? Isn't the whole point of=
encapsulation, abstraction, and the like to <i>insulate</i> high-level cod=
e from the low-level implementation details?<br><br>I don't care about =
the specific error code number for `std::from_chars`'s failure. The thi=
ng that matters most to me, when it comes to actually <i>dealing with</i> t=
he error case, is the location where the failure happened and the string it=
failed on. Those are things that I can show to a user, to help them figure=
out what happened and how to fix it.<br><br></div><blockquote class=3D"gma=
il_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid=
;padding-left: 1ex;"><div></div><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"><div></div><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></div></blockquote><blockquote class=3D"gmail_quote" style=3D"margin:0=
;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div></div>=
<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"><div>And `exceptio=
n_ptr` is <i>not cheap</i> to throw around. Creating one is a heap allocati=
on, and allocating memory for a local problem is not the best way to deal w=
ith such things.<br></div></div></blockquote><div><br></div><div>exception_=
ptr is still much cheaper than throwing and catching an exception.</div></b=
lockquote><div><br>So if `to_chars` were to return a `result<char*, std:=
:exception_ptr>`, you would feel that that's a perfectly valid, reas=
onable interface? Of course not; `to_chars` should never, <i>ever</i> be al=
locating memory, regardless of error states. And generally speaking, any AP=
I that would otherwise return an error code rather than real error objects =
is too low-level to be allocating memory on its own recognizance.<br></div>=
</div></blockquote><div><br></div><div>I don't know what to_chars does.=
</div></blockquote><div><br><a href=3D"http://en.cppreference.com/w/cpp/uti=
lity/to_chars">It does this.</a>=C2=A0It's a part of the C++17 standard=
library.<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>Ma=
ybe it costs 10M CPU cycles minimum. An exception_ptr in that use case is j=
ust fine.</div><div><br></div><div>It's not for us to dictate to end us=
ers what's appropriate for their use case. We can't know what their=
use case is.</div></blockquote><div><br>And yet, you seem to want to dicta=
te what exception `expected::value` throws, or more to the point doesn'=
t throw.<br><br>All interfaces are ultimately about making choices based on=
what we feel works best for users. I feel that `expected::value` throwing =
something other than `E` works best for users.<br><br>That being said, I do=
recognize at least one use case for the type. But I'd still much rathe=
r it be `expected<T, exception_ptr>`, and that you have to explicitly=
rethrow 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=
></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></div>=
<blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;borde=
r-left:1px #ccc solid;padding-left:1ex"><div></div><div>I personally think =
Expected needs to lose all exception throwing entirely, and bad_expected_ac=
cess can be removed.</div></blockquote><div><br>You should be able to recov=
er from logic errors in your code, if you would like to.<br></div></div></b=
lockquote><div><br></div><div>No, logic errors should be trapped at compile=
time wherever possible. The presence of std::logic_error was very unfortun=
ate and a product of the awful tooling of the time, and its use should not =
be encouraged further.</div></blockquote><div><br>So why does `dynamic_cast=
` throw if you provide a reference? Why does `any_cast` throw if you provid=
e a value/reference? Those are both logic errors; the user explicitly expec=
ts the object to be of the given type, and if it isn't, then something =
has almost certainly gone wrong in the system. Those exception types may no=
t derive from `logic_error`, but they are programming logic errors never-th=
e-less.<br><br>Why do these throw? Because we recognize the fact that not a=
ll logic errors can be trapped at compile time, but we still need to be abl=
e to trap them.<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/f3d99188-248b-4da0-b839-51128bb04627%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/f3d99188-248b-4da0-b839-51128bb04627=
%40isocpp.org</a>.<br />
------=_Part_485_556493053.1502346425648--
------=_Part_484_294989460.1502346425647--
.
Author: Niall Douglas <nialldouglas14@gmail.com>
Date: Thu, 10 Aug 2017 07:26:16 -0700 (PDT)
Raw View
------=_Part_974_1708972886.1502375176483
Content-Type: multipart/alternative;
boundary="----=_Part_975_2007442612.1502375176483"
------=_Part_975_2007442612.1502375176483
Content-Type: text/plain; charset="UTF-8"
>
>
>>>
>> Is your code experiencing a programmer unanticipated failure?
>>
>
> ... I'm not sure that's relevant. If the writer of this function did not
> anticipate failure, they wouldn't be throwing something. And if the caller
> of the function did not anticipate the failure, then they won't catch the
> exception.
>
It's exactly why it's relevant. When a function reports failure, it is
explicitly telling code which is calling it that "I give up on success".
If the function returns failure from itself via some throw or code
originating in that function, then the programmer anticipated the failure
and coded for it.
If the function is merely an intermediary propagating unanticipated failure
from some third party function it called, then it is important not to mess
with the detail in the failure because the programmer by definition did not
anticipate that failure.
>
> If yes then you need to be propagating the cause reported to you without
>> modification.
>>
>
> Why? You say this a lot, but you give no justification for it. You simply
> declare it as though it were an obvious fact. By contrast, I've given you
> examples of cases when throwing just an error_code is not sufficient
> information to resolve an error effectively.
>
Your arguments make no sense. If you are working with C++ exceptions or
std::error_code, then by definition you are enabling propagation of
unanticipated failure. It's one of the major tenets of good programming: do
not write code such as:
void myfunc()
{
try
{
someotherfunc();
}
catch(...)
{
throw myfunc_failed(); // and throw away why someotherfunc failed
}
}
Such patterns are information destroying. Don't do that.
>
>> Just because layers of code written by *you* don't know how to handle
>> that error doesn't mean that layers above you written by someone else don't
>> understand that error.
>>
>
> ... yes, it does.
>
No, it *really* doesn't.
If function A calls function B which calls function C which calls your
from_chars() routine which fails, then if function B messes with the cause
of the failure then function A can't know why.
If function A supplied the data which caused function C to fail
from_chars(), *then it needs to know about that in detail*. Function B
returning some generic "I failed" error is *bad*. Don't do it.
> As a general rule, the farther up the call stack you go, the *less*
> information you have on the specific implementation details of whatever
> produced that error. `main` does not know or care that you created a
> `thread`, nor does it have any idea what to do if that failed to happen due
> to some system-specific failure.
>
> Error codes are the most context-specific kind of error delivery that
> exists. An error code is increasingly less meaningful the farther you get
> from their point of origin, where its context lives.
>
I have no idea where you are drawing any of these claims from. If I didn't
know better, I would assume that you are either trolling or you're a first
year compsci student.
It *may* be the case in some code bases that main knows little. It *may* also
be the case that main knows the most. Indeed, entire algorithms may be
written around deeply nested third party code failing in precisely a
specific way that only main can know the meaning of and handle correctly.
You can't draw these sweeping generalisations about what main level code
knows and doesn't know. You don't know what the end user is doing.
> If a filesystem-thrown `error_code` bubbled its way up to `main`, how
> would `main` handle it in a reasonable way? If an iostream `error_code`
> manifested, how would `main` handle it? If you attempt to try_lock a mutex
> too much and get a `system_error`, how exactly is `main` going to fix that?
>
Entirely depends on the application being programmed.
>
>>
>> It's not for us to dictate to end users what's appropriate for their use
>> case. We can't know what their use case is.
>>
>
> And yet, you seem to want to dictate what exception `expected::value`
> throws, or more to the point doesn't throw.
>
No, I want excepted::value to not throw at all. Not ever. Others have
suggested expected::value doing stuff other than throwing
bad_expected_access. Not me.
I want instead for an additional Result type to implement throwing value
observers with clearly defined rules because the choice of type E is
severely constrained. If the programmer choose Result, they get exactly the
throwing behaviours guaranteed. They cannot supply a type E which does not
produce those guaranteed throwing behaviours, because it won't compile.
Niall
--
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/9369b663-a220-4a2f-a41f-2e214383580d%40isocpp.org.
------=_Part_975_2007442612.1502375176483
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;b=
order-left:1px #ccc solid;padding-left:1ex"><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></div></div></blockquote><div><br></div>=
<div>Is your code experiencing a programmer unanticipated failure?</div></b=
lockquote><div><br>... I'm not sure that's relevant. If the writer =
of this function did not anticipate failure, they wouldn't be throwing =
something. And if the caller of the function did not anticipate the failure=
, then they won't catch the exception.<br></div></div></blockquote><div=
><br></div><div>It's exactly why it's relevant. When a function rep=
orts failure, it is explicitly telling code which is calling it that "=
I give up on success".</div><div><br></div><div>If the function return=
s failure from itself via some throw or code originating in that function, =
then the programmer anticipated the failure and coded for it.</div><div><br=
></div><div>If the function is merely an intermediary propagating unanticip=
ated failure from some third party function it called, then it is important=
not to mess with the detail in the failure because the programmer by defin=
ition did not anticipate that failure.</div><div>=C2=A0</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><br></div><blockquote =
class=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #=
ccc solid;padding-left:1ex"><div>If yes then you need to be propagating the=
cause reported to you without modification.</div></blockquote><div><br>Why=
? You say this a lot, but you give no justification for it. You simply decl=
are it as though it were an obvious fact. By contrast, I've given you e=
xamples of cases when throwing just an error_code is not sufficient informa=
tion to resolve an error effectively.<br></div></div></blockquote><div><br>=
</div><div>Your arguments make no sense. If you are working with C++ except=
ions or std::error_code, then by definition you are enabling propagation of=
unanticipated failure. It's one of the major tenets of good programmin=
g: do not write code such as:</div><div><br></div><div>void myfunc()</div><=
div>{</div><div>=C2=A0 try</div><div>=C2=A0 {</div><div>=C2=A0 =C2=A0 someo=
therfunc();</div><div>=C2=A0 }</div><div>=C2=A0 catch(...)</div><div>=C2=A0=
{</div><div>=C2=A0 =C2=A0 throw myfunc_failed(); // and throw away why som=
eotherfunc failed</div><div>=C2=A0 }</div><div>}</div><div><br></div><div>S=
uch patterns are information destroying. Don't do that.</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><br></div><div>Just because layers=
of code written by <i>you</i>=C2=A0don't know how to handle that error=
doesn't mean that layers above you written by someone else don't u=
nderstand that error.</div></blockquote><div><br>... yes, it does.</div></d=
iv></blockquote><div><br></div><div>No, it <i>really</i>=C2=A0doesn't.<=
/div><div><br></div><div>If function A calls function B which calls functio=
n C which calls your from_chars() routine which fails, then if function B m=
esses with the cause of the failure then function A can't know why.</di=
v><div><br></div><div>If function A supplied the data which caused function=
C to fail from_chars(), <i>then it needs to know about that in detail</i>.=
Function B returning some generic "I failed" error is <b>bad</b>=
.. Don't do it.</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"><div> As a general rule, the farther up the cal=
l stack you go, the <i>less</i> information you have on the specific implem=
entation details of whatever produced that error. `main` does not know or c=
are that you created a `thread`, nor does it have any idea what to do if th=
at failed to happen due to some system-specific failure.<br><br>Error codes=
are the most context-specific kind of error delivery that exists. An error=
code is increasingly less meaningful the farther you get from their point =
of origin, where its context lives.<br></div></div></blockquote><div><br></=
div><div>I have no idea where you are drawing any of these claims from. If =
I didn't know better, I would assume that you are either trolling or yo=
u're a first year compsci student.</div><div><br></div><div>It <i>may</=
i>=C2=A0be the case in some code bases that main knows little. It <i>may</i=
>=C2=A0also be the case that main knows the most. Indeed, entire algorithms=
may be written around deeply nested third party code failing in precisely =
a specific way that only main can know the meaning of and handle correctly.=
</div><div><br></div><div>You can't draw these sweeping generalisations=
about what main level code knows and doesn't know. You don't know =
what the end user is doing.</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></div></div></blockquote><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"><div>If a filesystem-=
thrown `error_code` bubbled its way up to `main`, how would `main` handle i=
t in a reasonable way? If an iostream `error_code` manifested, how would `m=
ain` handle it? If you attempt to try_lock a mutex too much and get a `syst=
em_error`, how exactly is `main` going to fix that?<br></div></div></blockq=
uote><div><br></div><div>Entirely depends on the application being programm=
ed.</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></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"><blockquote class=3D"gmail_quote" style=3D"ma=
rgin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><br><=
div><br></div><div>It's not for us to dictate to end users what's a=
ppropriate for their use case. We can't know what their use case is.</d=
iv></blockquote><div><br>And yet, you seem to want to dictate what exceptio=
n `expected::value` throws, or more to the point doesn't throw.<br></di=
v></div></blockquote><div><br></div><div>No, I want excepted::value to not =
throw at all. Not ever. Others have suggested expected::value doing stuff o=
ther than throwing bad_expected_access. Not me.</div><div><br></div><div>I =
want instead for an additional Result type to implement throwing value obse=
rvers with clearly defined rules because the choice of type E is severely c=
onstrained. If the programmer choose Result, they get exactly the throwing =
behaviours guaranteed. They cannot supply a type E which does not produce t=
hose guaranteed throwing behaviours, because it won't compile.</div><di=
v><br></div><div>Niall</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/9369b663-a220-4a2f-a41f-2e214383580d%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/9369b663-a220-4a2f-a41f-2e214383580d=
%40isocpp.org</a>.<br />
------=_Part_975_2007442612.1502375176483--
------=_Part_974_1708972886.1502375176483--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Thu, 10 Aug 2017 17:40:08 +0300
Raw View
On 10 August 2017 at 17:26, Niall Douglas <nialldouglas14@gmail.com> wrote:
> No, I want excepted::value to not throw at all. Not ever. Others have
> suggested expected::value doing stuff other than throwing
> bad_expected_access. Not me.
So calling expected::value is UB if the expected holds something else?
> I want instead for an additional Result type to implement throwing value
> observers with clearly defined rules because the choice of type E is
> severely constrained. If the programmer choose Result, they get exactly the
> throwing behaviours guaranteed. They cannot supply a type E which does not
> produce those guaranteed throwing behaviours, because it won't compile.
I would like to see a comparison of Result and Expected.
--
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/CAFk2RUYSkSzUPzhX2xBoax11pxMWtGhCkCCG0%2BnDjPa0m0YOeA%40mail.gmail.com.
.
Author: Matthew Woehlke <mwoehlke.floss@gmail.com>
Date: Thu, 10 Aug 2017 11:04:26 -0400
Raw View
On 2017-08-10 10:26, Niall Douglas wrote:
> When a function reports failure, it is explicitly telling code which
> is calling it that "I give up on success".
>=20
> If the function returns failure from itself via some throw or code=20
> originating in that function, then the programmer anticipated the failure=
=20
> and coded for it.
>=20
> If the function is merely an intermediary propagating unanticipated failu=
re=20
> from some third party function it called, then it is important not to mes=
s=20
> with the detail in the failure because the programmer by definition did n=
ot=20
> anticipate that failure.
But... by catching and modifying the exception, isn't "anticipating the
failure" exactly what you *are* doing?
I think you've just successfully argued Nicol's point...
> Your arguments make no sense. If you are working with C++ exceptions or=
=20
> std::error_code, then by definition you are enabling propagation of=20
> unanticipated failure. It's one of the major tenets of good programming: =
do=20
> not write code such as:
>=20
> void myfunc()
> {
> try
> {
> someotherfunc();
> }
> catch(...)
> {
> throw myfunc_failed(); // and throw away why someotherfunc failed
> }
> }
>=20
> Such patterns are information destroying. Don't do that.
....but it also *adds* information. The above example replaces a
context-free error with one that has better locality of context. Sure,
totally throwing out the lower level information is less than ideal, but
I'm *absolutely* unconvinced that the far-context information is more
useful than the near-context information. (Better, of course, is to have
both, which is why the outer exception ought to *contain* the inner
exception. Which... the original example *did*. You're setting up a
straw-man here...)
> If function A calls function B which calls function C which calls your=20
> from_chars() routine which fails, then if function B messes with the caus=
e=20
> of the failure then function A can't know why.
....So? How is function A even supposed to know that from_chars was
called? How does it know that the failure occurred in B =E2=86=92 C =E2=86=
=92
from_chars? Even if it does, how is that meaningful to A?
> If function A supplied the data which caused function C to fail=20
> from_chars(), *then it needs to know about that in detail*.
....and *what if it didn't*? How does it help A to know that something in
some implementation detail unknown to A, that may or may not be directly
related to what A passed to B, went sideways?
> Function B returning some generic "I failed" error is *bad*. Don't do
> it.
Well... yeah. If B is returning such a generic error that A can't know
that the problem was the input it supplied that ultimately caused
from_chars to fail, then yeah, that's bad, but it means the B has a
*really* poorly thought out error reporting mechanism.
*This is a straw man*. Arguing a case that *everyone* agrees is broken
is not productive, and it undermines your own arguments.
> It *may* be the case in some code bases that main knows little. It *may* =
also=20
> be the case that main knows the most. Indeed, entire algorithms may be=20
> written around deeply nested third party code failing in precisely a=20
> specific way that only main can know the meaning of and handle correctly.
I'd be interested to see an example of that...
--=20
Matthew
--=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/e6c36ed7-a875-1181-4710-357dd3360cd9%40gmail.com=
..
.
Author: Tony V E <tvaneerd@gmail.com>
Date: Thu, 10 Aug 2017 11:38:39 -0400
Raw View
--001a113564aa9db902055667fde7
Content-Type: text/plain; charset="UTF-8"
On Thu, Aug 10, 2017 at 10:26 AM, Niall Douglas <nialldouglas14@gmail.com>
wrote:
>
>>>>
>>> Is your code experiencing a programmer unanticipated failure?
>>>
>>
>> ... I'm not sure that's relevant. If the writer of this function did not
>> anticipate failure, they wouldn't be throwing something. And if the caller
>> of the function did not anticipate the failure, then they won't catch the
>> exception.
>>
>
> It's exactly why it's relevant. When a function reports failure, it is
> explicitly telling code which is calling it that "I give up on success".
>
> If the function returns failure from itself via some throw or code
> originating in that function, then the programmer anticipated the failure
> and coded for it.
>
> If the function is merely an intermediary propagating unanticipated
> failure from some third party function it called, then it is important not
> to mess with the detail in the failure because the programmer by definition
> did not anticipate that failure.
>
>
>>
>> If yes then you need to be propagating the cause reported to you without
>>> modification.
>>>
>>
>> Why? You say this a lot, but you give no justification for it. You simply
>> declare it as though it were an obvious fact. By contrast, I've given you
>> examples of cases when throwing just an error_code is not sufficient
>> information to resolve an error effectively.
>>
>
> Your arguments make no sense. If you are working with C++ exceptions or
> std::error_code, then by definition you are enabling propagation of
> unanticipated failure. It's one of the major tenets of good programming: do
> not write code such as:
>
> void myfunc()
> {
> try
> {
> someotherfunc();
> }
> catch(...)
> {
> throw myfunc_failed(); // and throw away why someotherfunc failed
> }
> }
>
> Such patterns are information destroying. Don't do that.
>
>
>>
>>> Just because layers of code written by *you* don't know how to handle
>>> that error doesn't mean that layers above you written by someone else don't
>>> understand that error.
>>>
>>
>> ... yes, it does.
>>
>
> No, it *really* doesn't.
>
> If function A calls function B which calls function C which calls your
> from_chars() routine which fails, then if function B messes with the cause
> of the failure then function A can't know why.
>
> If function A supplied the data which caused function C to fail
> from_chars(), *then it needs to know about that in detail*. Function B
> returning some generic "I failed" error is *bad*. Don't do it.
>
from_chars() is an implementation detail. C previously used atoi(), which
fails differently. Next year C will use something like parse_int() which
differently fails differently.
It might be best if someone along the chain, maybe B or C, throws
parseError(where_parse_failed, what_it_was_expecting), which is part of the
*interface*, not implementation detail.
So, agreed - don't throw out important information.
But it may require repackaging the error in order to separate
implementation detail from interface.
?
--
Be seeing you,
Tony
--
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/CAOHCbitopW38U-xbnToC%2BHD2kBnPdPBw3vm8KBSsubeVtAefUQ%40mail.gmail.com.
--001a113564aa9db902055667fde7
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Thu, Aug 10, 2017 at 10:26 AM, Niall Douglas <span dir=3D"ltr"><<=
a href=3D"mailto:nialldouglas14@gmail.com" target=3D"_blank">nialldouglas14=
@gmail.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=
=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=
=3D"ltr"><span class=3D""><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"><blockquote class=3D"gmail=
_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padd=
ing-left:1ex"><div dir=3D"ltr"><div><br></div></div></blockquote><div><br><=
/div><div>Is your code experiencing a programmer unanticipated failure?</di=
v></blockquote><div><br>... I'm not sure that's relevant. If the wr=
iter of this function did not anticipate failure, they wouldn't be thro=
wing something. And if the caller of the function did not anticipate the fa=
ilure, then they won't catch the exception.<br></div></div></blockquote=
><div><br></div></span><div>It's exactly why it's relevant. When a =
function reports failure, it is explicitly telling code which is calling it=
that "I give up on success".</div><div><br></div><div>If the fun=
ction returns failure from itself via some throw or code originating in tha=
t function, then the programmer anticipated the failure and coded for it.</=
div><div><br></div><div>If the function is merely an intermediary propagati=
ng unanticipated failure from some third party function it called, then it =
is important not to mess with the detail in the failure because the program=
mer by definition did not anticipate that failure.</div><span class=3D""><d=
iv>=C2=A0</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><br></div><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-left=
:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div>If yes then you ne=
ed to be propagating the cause reported to you without modification.</div><=
/blockquote><div><br>Why? You say this a lot, but you give no justification=
for it. You simply declare it as though it were an obvious fact. By contra=
st, I've given you examples of cases when throwing just an error_code i=
s not sufficient information to resolve an error effectively.<br></div></di=
v></blockquote><div><br></div></span><div>Your arguments make no sense. If =
you are working with C++ exceptions or std::error_code, then by definition =
you are enabling propagation of unanticipated failure. It's one of the =
major tenets of good programming: do not write code such as:</div><div><br>=
</div><div>void myfunc()</div><div>{</div><div>=C2=A0 try</div><div>=C2=A0 =
{</div><div>=C2=A0 =C2=A0 someotherfunc();</div><div>=C2=A0 }</div><div>=C2=
=A0 catch(...)</div><div>=C2=A0 {</div><div>=C2=A0 =C2=A0 throw myfunc_fail=
ed(); // and throw away why someotherfunc failed</div><div>=C2=A0 }</div><d=
iv>}</div><div><br></div><div>Such patterns are information destroying. Don=
't do that.</div><span class=3D""><div>=C2=A0</div><blockquote class=3D=
"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc soli=
d;padding-left:1ex"><div dir=3D"ltr"><blockquote class=3D"gmail_quote" styl=
e=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex=
"><div><br></div><div>Just because layers of code written by <i>you</i>=C2=
=A0don't know how to handle that error doesn't mean that layers abo=
ve you written by someone else don't understand that error.</div></bloc=
kquote><div><br>... yes, it does.</div></div></blockquote><div><br></div></=
span><div>No, it <i>really</i>=C2=A0doesn't.</div><div><br></div><div>I=
f function A calls function B which calls function C which calls your from_=
chars() routine which fails, then if function B messes with the cause of th=
e failure then function A can't know why.</div><div><br></div><div>If f=
unction A supplied the data which caused function C to fail from_chars(), <=
i>then it needs to know about that in detail</i>. Function B returning some=
generic "I failed" error is <b>bad</b>. Don't do it.</div></=
div></blockquote><div><br></div><div>from_chars() is an implementation deta=
il. C previously used atoi(), which fails differently.=C2=A0 Next year C wi=
ll use something like parse_int() which differently fails differently.<br><=
/div><div><br>It might be best if someone along the chain, maybe B or C, th=
rows parseError(where_parse_failed, what_it_was_expecting), which is part o=
f the *interface*, not implementation detail.<br><br></div><div>So, agreed =
- don't throw out important information.<br></div><div>But it may requi=
re repackaging the error in order to separate implementation detail from in=
terface.<br><br>?<br></div></div><br>-- <br><div class=3D"gmail_signature" =
data-smartmail=3D"gmail_signature"><div dir=3D"ltr"><div>Be seeing you,<br>=
</div>Tony<br></div></div>
</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/CAOHCbitopW38U-xbnToC%2BHD2kBnPdPBw3v=
m8KBSsubeVtAefUQ%40mail.gmail.com?utm_medium=3Demail&utm_source=3Dfooter">h=
ttps://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAOHCbitopW38U-=
xbnToC%2BHD2kBnPdPBw3vm8KBSsubeVtAefUQ%40mail.gmail.com</a>.<br />
--001a113564aa9db902055667fde7--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Thu, 10 Aug 2017 08:39:47 -0700 (PDT)
Raw View
------=_Part_974_1352152280.1502379587643
Content-Type: multipart/alternative;
boundary="----=_Part_975_810675200.1502379587643"
------=_Part_975_810675200.1502379587643
Content-Type: text/plain; charset="UTF-8"
On Thursday, August 10, 2017 at 10:26:16 AM UTC-4, Niall Douglas wrote:
>
>
>>>>
>>> Is your code experiencing a programmer unanticipated failure?
>>>
>>
>> ... I'm not sure that's relevant. If the writer of this function did not
>> anticipate failure, they wouldn't be throwing something. And if the caller
>> of the function did not anticipate the failure, then they won't catch the
>> exception.
>>
>
> It's exactly why it's relevant. When a function reports failure, it is
> explicitly telling code which is calling it that "I give up on success".
>
> If the function returns failure from itself via some throw or code
> originating in that function, then the programmer anticipated the failure
> and coded for it.
>
> If the function is merely an intermediary propagating unanticipated
> failure from some third party function it called, then it is important not
> to mess with the detail in the failure because the programmer by definition
> did not anticipate that failure.
>
Again, which "the programmer" are we talking about? The programmer of the
intermediary function? How do you know that the writer of that function
*didn't* anticipate the failure? How do you know that they didn't expose
that exception as a deliberate part of its interface?
There's a difference between "I didn't know this function could throw, and
I'm letting it through because I'm ignorant" and "I'm well aware that this
function throws, and I want that as part of my interface". Granted, we
don't have a way to specify the different with actual C++ syntax, but these
are different cases.
If yes then you need to be propagating the cause reported to you without
>>> modification.
>>>
>>
>> Why? You say this a lot, but you give no justification for it. You simply
>> declare it as though it were an obvious fact. By contrast, I've given you
>> examples of cases when throwing just an error_code is not sufficient
>> information to resolve an error effectively.
>>
>
> Your arguments make no sense. If you are working with C++ exceptions or
> std::error_code, then by definition you are enabling propagation of
> unanticipated failure. It's one of the major tenets of good programming: do
> not write code such as:
>
> void myfunc()
> {
> try
> {
> someotherfunc();
> }
> catch(...)
> {
> throw myfunc_failed(); // and throw away why someotherfunc failed
> }
> }
>
> Such patterns are information destroying. Don't do that.
>
First, nobody is suggesting that people write that code, so that's a
strawman example.
Second, there is nothing a priori wrong with that. It's all a matter of the
needs of `myfunc`.
If `myfunc` doesn't catch exceptions spit out by its implementation
details, then `myfunc` is *explicitly declaring* that the outside world is
not insulated from its implementation details. If `myfunc` happens to call
a filesystem function that throws, then the outer code knows that `myfunc`
is calling `filesystem` functions, since the outer code needs to know that
such exceptions are possible. This is now part of `myfunc`'s API.
But maybe that's not what is wanted. Maybe `myfunc` wants to insulate the
caller from its implementation details. Maybe `myfunc` wants the freedom to
change filesystem APIs. To purchase that freedom, it must now provide its
own exceptions/errors/etc, which now requires it to translate errors
generated by its current-filesystem-API-of-choice to an explicit part of
its API.
That is a *legitimate API*. It is just as legitimate a decision as letting
`filesystem_error` bubble up through it.
Just because layers of code written by *you* don't know how to handle that
>>> error doesn't mean that layers above you written by someone else don't
>>> understand that error.
>>>
>>
>> ... yes, it does.
>>
>
> No, it *really* doesn't.
>
> If function A calls function B which calls function C which calls your
> from_chars() routine which fails, then if function B messes with the cause
> of the failure then function A can't know why.
>
Define "messes with the cause of the failure".
If function A supplied the data which caused function C to fail
> from_chars(), *then it needs to know about that in detail*.
>
Let's assume that's true. How exactly does throwing `std::errc` constitute
"in detail"?
It says nothing about the value `to_chars` was give that caused the
emission of that error. All you know is that there was a conversion
failure. Where are the details that the person catching that error "needs
to know"?
Function B returning some generic "I failed" error is *bad*. Don't do it.
>
This is also a strawman; nobody is suggesting that intermediary functions
return "some generic 'I failed' error". Indeed, the example I provided for
`from_chars` still stored the specific error code. But it *also* stored
additional information. So it's hardly a "generic 'I failed' error".
My point is not that having access to the error code is bad. My point is
that having access to *just* the error_code is bad, that throwing the
error_code *alone* is a bad exception. The error_code is (potentially)
necessary, but *not sufficient* for non-local error handling. As such, if
all you have is `result<T, error_code>`, throwing that error_code is a bad
exception interface. You should always wrap it in something that has an
actual interface and useful state, if possible (the thread system doesn't
really have "useful state" that it can package, which is why it uses
`system_error` directly. Sadly, they didn't give it its own exception type).
And note that the FileSystem TS agrees with me; `filesystem_error` has
additional useful state. We should not encourage the creation of poor
interfaces.
As a general rule, the farther up the call stack you go, the *less*
>> information you have on the specific implementation details of whatever
>> produced that error. `main` does not know or care that you created a
>> `thread`, nor does it have any idea what to do if that failed to happen due
>> to some system-specific failure.
>>
>> Error codes are the most context-specific kind of error delivery that
>> exists. An error code is increasingly less meaningful the farther you get
>> from their point of origin, where its context lives.
>>
>
> I have no idea where you are drawing any of these claims from. If I didn't
> know better, I would assume that you are either trolling or you're a first
> year compsci student.
>
> It *may* be the case in some code bases that main knows little. It *may* also
> be the case that main knows the most. Indeed, entire algorithms may be
> written around deeply nested third party code failing in precisely a
> specific way that only main can know the meaning of and handle correctly.
>
Can you give me an example of such an algorithm? Again, a non-toy example?
Because I've given you a concrete example of a case where a mere
`system_error` is about as useful to `main` as a naked `std::runtime_error`.
You can't draw these sweeping generalisations about what main level code
> knows and doesn't know. You don't know what the end user is doing.
>
And yet you're drawing the same "sweeping generalisations[sic]", just in
the opposite direction. I just feel my generalizations mimic reality more
closely than yours.
It's not for us to dictate to end users what's appropriate for their use
>>> case. We can't know what their use case is.
>>>
>>
>> And yet, you seem to want to dictate what exception `expected::value`
>> throws, or more to the point doesn't throw.
>>
>
> No, I want excepted::value to not throw at all. Not ever. Others have
> suggested expected::value doing stuff other than throwing
> bad_expected_access. Not me.
>
I don't see how that changes what I said. Requiring that something throw
nothing is still "dictating what exception" it throws.
I want instead for an additional Result type to implement throwing value
> observers with clearly defined rules because the choice of type E is
> severely constrained. If the programmer choose Result, they get exactly the
> throwing behaviours guaranteed. They cannot supply a type E which does not
> produce those guaranteed throwing behaviours, because it won't compile.
>
And I don't believe that we should have a variant-error type that throws
the error_code. Or more to the point, we shouldn't have a variant-error
type where the error part is a thing which is a complete enough object that
throwing it constitutes a reasonable exception interface.
Variant-error types, to me
<https://11080372623597421729.googlegroups.com/attach/a8bf61b2beb10bec/Survey%20of%20Error%20Handling.html?part=0.1&view=1&vt=ANaJVrEuWdkMEUHVl8Qrbf1xMKzGZNqSxVVbv4u_1_5wbflNpDWuaY1LV97Aaez-XDfJ_Gzes8TlZWzNRZxKt1XgGBIawBy0ANkQYqmXalrOk72eWQd7jTQ>,
are for *local* error processing. They provide minimal information about
the error, because the local code (which has the context of the error) is
the one expected to process it. If the local context is incapable of
resolving the error, then the local code is expected to package the error, *including
appropriate local state*, and send it to whatever non-local code is
expected to deal with it.
The goal should not be to make it as if the non-local code had been
directly returned the error_code. Throwing a light-weight error code is not
a good exception interface.
I brought this up on the thread about expected a few years back
<https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/G1YheYoGznw/discussion>,
and my argument remains essentially unchanged. Non-local error handling
needs more information than an error code, but we shouldn't overburden our
local error handling primitives (ie: `expected`) with such state. If the
local code wants to punt on resolving the error, it should be up to the
local code to decide what to throw.
And let's consider one more thing. Let's say that throwing a light-weight
error code really is a good exception interface. I submit that in such
cases, that decision about whether this is a good exception interface *should
not* be made by the function that originally emitted the error. It is not
`to/from_chars` who can make that determination; it is the code *calling*
that function who should make the determination on whether the error_code
represents a sufficient exception interface.
That is, a function should not be able to *tell me* that throwing a
`system_error` is a valid way to handle its errors. That's for me to
determine on a case-by-case basis. That's another reason why I prefer
`bad_expected_access` to throwing the error code directly. By not throwing
the error code by default, it means that each user *must* determine for
themselves how to pass it to non-local code if they so desire.
--
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/d04a64e2-2c22-4652-9d31-2ff864a27ccc%40isocpp.org.
------=_Part_975_810675200.1502379587643
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, August 10, 2017 at 10:26:16 AM UTC-4, Niall D=
ouglas wrote:<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">=
<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"><blockquote class=
=3D"gmail_quote" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc s=
olid;padding-left:1ex"><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><br></div></div></blockquote><div><br></div><div>Is your code exp=
eriencing a programmer unanticipated failure?</div></blockquote><div><br>..=
.. I'm not sure that's relevant. If the writer of this function did =
not anticipate failure, they wouldn't be throwing something. And if the=
caller of the function did not anticipate the failure, then they won't=
catch the exception.<br></div></div></blockquote><div><br></div><div>It=
9;s exactly why it's relevant. When a function reports failure, it is e=
xplicitly telling code which is calling it that "I give up on success&=
quot;.</div><div><br></div><div>If the function returns failure from itself=
via some throw or code originating in that function, then the programmer a=
nticipated the failure and coded for it.</div><div><br></div><div>If the fu=
nction is merely an intermediary propagating unanticipated failure from som=
e third party function it called, then it is important not to mess with the=
detail in the failure because the programmer by definition did not anticip=
ate that failure.</div></div></blockquote><div><br>Again, which "the p=
rogrammer" are we talking about? The programmer of the intermediary fu=
nction? How do you know that the writer of that function <i>didn't</i> =
anticipate the failure? How do you know that they didn't expose that ex=
ception as a deliberate part of its interface?<br><br>There's a differe=
nce between "I didn't know this function could throw, and I'm =
letting it through because I'm ignorant" and "I'm well aw=
are that this function throws, and I want that as part of my interface"=
;. Granted, we don't have a way to specify the different with actual C+=
+ syntax, but these are different cases.<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><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></div><blockquote class=3D"gmail_quo=
te" style=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-=
left:1ex"><div>If yes then you need to be propagating the cause reported to=
you without modification.</div></blockquote><div><br>Why? You say this a l=
ot, but you give no justification for it. You simply declare it as though i=
t were an obvious fact. By contrast, I've given you examples of cases w=
hen throwing just an error_code is not sufficient information to resolve an=
error effectively.<br></div></div></blockquote><div><br></div><div>Your ar=
guments make no sense. If you are working with C++ exceptions or std::error=
_code, then by definition you are enabling propagation of unanticipated fai=
lure. It's one of the major tenets of good programming: do not write co=
de such as:</div><div><br></div><div>void myfunc()</div><div>{</div><div>=
=C2=A0 try</div><div>=C2=A0 {</div><div>=C2=A0 =C2=A0 someotherfunc();</div=
><div>=C2=A0 }</div><div>=C2=A0 catch(...)</div><div>=C2=A0 {</div><div>=C2=
=A0 =C2=A0 throw myfunc_failed(); // and throw away why someotherfunc faile=
d</div><div>=C2=A0 }</div><div>}</div><div><br></div><div>Such patterns are=
information destroying. Don't do that.</div></div></blockquote><div><b=
r>First, nobody is suggesting that people write that code, so that's a =
strawman example.<br><br>Second, there is nothing a priori wrong with that.=
It's all a matter of the needs of `myfunc`.<br><br>If `myfunc` doesn&#=
39;t catch exceptions spit out by its implementation details, then `myfunc`=
is <i>explicitly declaring</i> that the outside world is not insulated fro=
m its implementation details. If `myfunc` happens to call a filesystem func=
tion that throws, then the outer code knows that `myfunc` is calling `files=
ystem` functions, since the outer code needs to know that such exceptions a=
re possible. This is now part of `myfunc`'s API.<br><br>But maybe that&=
#39;s not what is wanted. Maybe `myfunc` wants to insulate the caller from =
its implementation details. Maybe `myfunc` wants the freedom to change file=
system APIs. To purchase that freedom, it must now provide its own exceptio=
ns/errors/etc, which now requires it to translate errors generated by its c=
urrent-filesystem-API-of-choice to an explicit part of its API.<br><br>That=
is a <i>legitimate API</i>. It is just as legitimate a decision as letting=
`filesystem_error` bubble up through 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></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"><blockquote class=3D"gmail_quote" style=
=3D"margin:0;margin-left:0.8ex;border-left:1px #ccc solid;padding-left:1ex"=
><div></div><div>Just because layers of code written by <i>you</i>=C2=A0don=
't know how to handle that error doesn't mean that layers above you=
written by someone else don't understand that error.</div></blockquote=
><div><br>... yes, it does.</div></div></blockquote><div><br></div><div>No,=
it <i>really</i>=C2=A0doesn't.</div><div><br></div><div>If function A =
calls function B which calls function C which calls your from_chars() routi=
ne which fails, then if function B messes with the cause of the failure the=
n function A can't know why.</div></div></blockquote><div><br>Define &q=
uot;messes with the cause of the failure".<br><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></div><div>If function=
A supplied the data which caused function C to fail from_chars(), <i>then =
it needs to know about that in detail</i>.</div></div></blockquote><div><br=
>Let's assume that's true. How exactly does throwing `std::errc` co=
nstitute "in detail"?<br><br>It says nothing about the value `to_=
chars` was give that caused the emission of that error. All you know is tha=
t there was a conversion failure. Where are the details that the person cat=
ching that error "needs to know"?<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>Function B returning some=
generic "I failed" error is <b>bad</b>. Don't do it.</div></=
div></blockquote><div><br>This is also a strawman; nobody is suggesting tha=
t intermediary functions return "some generic 'I failed' error=
". Indeed, the example I provided for `from_chars` still stored the sp=
ecific error code. But it <i>also</i> stored additional information. So it&=
#39;s hardly a "generic 'I failed' error".<br><br>My poin=
t is not that having access to the error code is bad. My point is that havi=
ng access to <i>just</i> the error_code is bad, that throwing the error_cod=
e <i>alone</i> is a bad exception. The error_code is (potentially) necessar=
y, but <i>not sufficient</i> for non-local error handling. As such, if all =
you have is `result<T, error_code>`, throwing that error_code is a ba=
d exception interface. You should always wrap it in something that has an a=
ctual interface and useful state, if possible (the thread system doesn'=
t really have "useful state" that it can package, which is why it=
uses `system_error` directly. Sadly, they didn't give it its own excep=
tion type).<br><br>And note that the FileSystem TS agrees with me; `filesys=
tem_error` has additional useful state. We should not encourage the creatio=
n of poor interfaces.<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"><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> As a general rule, the farther up the call stack you go, the <i>=
less</i> information you have on the specific implementation details of wha=
tever produced that error. `main` does not know or care that you created a =
`thread`, nor does it have any idea what to do if that failed to happen due=
to some system-specific failure.<br><br>Error codes are the most context-s=
pecific kind of error delivery that exists. An error code is increasingly l=
ess meaningful the farther you get from their point of origin, where its co=
ntext lives.<br></div></div></blockquote><div><br></div><div>I have no idea=
where you are drawing any of these claims from. If I didn't know bette=
r, I would assume that you are either trolling or you're a first year c=
ompsci student.</div><div><br></div><div>It <i>may</i>=C2=A0be the case in =
some code bases that main knows little. It <i>may</i>=C2=A0also be the case=
that main knows the most. Indeed, entire algorithms may be written around =
deeply nested third party code failing in precisely a specific way that onl=
y main can know the meaning of and handle correctly.</div></div></blockquot=
e><div><br>Can you give me an example of such an algorithm? Again, a non-to=
y example? Because I've given you a concrete example of a case where a =
mere `system_error` is about as useful to `main` as a naked `std::runtime_e=
rror`.<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><div>You can't draw these sweeping generalisations =
about what main level code knows and doesn't know. You don't know w=
hat the end user is doing.</div></div></blockquote><div><br>And yet you'=
;re drawing the same "sweeping generalisations[sic]", just in the=
opposite direction. I just feel my generalizations mimic reality more clos=
ely than yours.<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></div></blockquote><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></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><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"><blockquote class=3D"gmail_quote" style=3D"margin:0;margin-l=
eft:0.8ex;border-left:1px #ccc solid;padding-left:1ex"><div></div><div>It&#=
39;s not for us to dictate to end users what's appropriate for their us=
e case. We can't know what their use case is.</div></blockquote><div><b=
r>And yet, you seem to want to dictate what exception `expected::value` thr=
ows, or more to the point doesn't throw.<br></div></div></blockquote><d=
iv><br></div><div>No, I want excepted::value to not throw at all. Not ever.=
Others have suggested expected::value doing stuff other than throwing bad_=
expected_access. Not me.</div></div></blockquote><div><br>I don't see h=
ow that changes what I said. Requiring that something throw nothing is stil=
l "dictating what exception" it throws.<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>I want instead for a=
n additional Result type to implement throwing value observers with clearly=
defined rules because the choice of type E is severely constrained. If the=
programmer choose Result, they get exactly the throwing behaviours guarant=
eed. They cannot supply a type E which does not produce those guaranteed th=
rowing behaviours, because it won't compile.</div></div></blockquote><d=
iv><br>And I don't believe that we should have a variant-error type tha=
t throws the error_code. Or more to the point, we shouldn't have a vari=
ant-error type where the error part is a thing which is a complete enough o=
bject that throwing it constitutes a reasonable exception interface.<br><br=
>Variant-error types, <a href=3D"https://11080372623597421729.googlegroups.=
com/attach/a8bf61b2beb10bec/Survey%20of%20Error%20Handling.html?part=3D0.1&=
amp;view=3D1&vt=3DANaJVrEuWdkMEUHVl8Qrbf1xMKzGZNqSxVVbv4u_1_5wbflNpDWua=
Y1LV97Aaez-XDfJ_Gzes8TlZWzNRZxKt1XgGBIawBy0ANkQYqmXalrOk72eWQd7jTQ">to me</=
a>, are for <i>local</i> error processing. They provide minimal information=
about the error, because the local code (which has the context of the erro=
r) is the one expected to process it. If the local context is incapable of =
resolving the error, then the local code is expected to package the error, =
<i>including appropriate local state</i>, and send it to whatever non-local=
code is expected to deal with it.<br><br>The goal should not be to make it=
as if the non-local code had been directly returned the error_code. Throwi=
ng a light-weight error code is not a good exception interface.<br><br>I br=
ought this up on <a href=3D"https://groups.google.com/a/isocpp.org/forum/#!=
topic/std-proposals/G1YheYoGznw/discussion">the thread about expected a few=
years back</a>, and my argument remains essentially unchanged. Non-local e=
rror handling needs more information than an error code, but we shouldn'=
;t overburden our local error handling primitives (ie: `expected`) with suc=
h state. If the local code wants to punt on resolving the error, it should =
be up to the local code to decide what to throw.<br><br>And let's consi=
der one more thing. Let's say that throwing a light-weight error code r=
eally is a good exception interface. I submit that in such cases, that deci=
sion about whether this is a good exception interface <i>should not</i> be =
made by the function that originally emitted the error. It is not `to/from_=
chars` who can make that determination; it is the code <i>calling</i> that =
function who should make the determination on whether the error_code repres=
ents a sufficient exception interface.<br><br>That is, a function should no=
t be able to <i>tell me</i> that throwing a `system_error` is a valid way t=
o handle its errors. That's for me to determine on a case-by-case basis=
.. That's another reason why I prefer `bad_expected_access` to throwing =
the error code directly. By not throwing the error code by default, it mean=
s that each user <i>must</i> determine for themselves how to pass it to non=
-local code if they so desire.<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/d04a64e2-2c22-4652-9d31-2ff864a27ccc%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/d04a64e2-2c22-4652-9d31-2ff864a27ccc=
%40isocpp.org</a>.<br />
------=_Part_975_810675200.1502379587643--
------=_Part_974_1352152280.1502379587643--
.
Author: Niall Douglas <nialldouglas14@gmail.com>
Date: Thu, 10 Aug 2017 17:12:17 -0700 (PDT)
Raw View
------=_Part_1448_1594877951.1502410337495
Content-Type: multipart/alternative;
boundary="----=_Part_1449_1534403770.1502410337495"
------=_Part_1449_1534403770.1502410337495
Content-Type: text/plain; charset="UTF-8"
On Thursday, August 10, 2017 at 3:40:11 PM UTC+1, Ville Voutilainen wrote:
>
> On 10 August 2017 at 17:26, Niall Douglas <nialldo...@gmail.com
> <javascript:>> wrote:
> > No, I want excepted::value to not throw at all. Not ever. Others have
> > suggested expected::value doing stuff other than throwing
> > bad_expected_access. Not me.
>
> So calling expected::value is UB if the expected holds something else?
>
Yes. This is highly desirable. We have so much better tooling nowadays.
clang-tidy will pick up the logic error frequently at compile time. The UB
sanitiser will pick it up at runtime. No need to ever throw
std::logic_error (which bad_expected_access subclasses) ever again in new
code. Ideally a near future C++ standard will officially make throwing
std::logic_error an unrecoverable program failure, and we can be done with
it forever.
>
> > I want instead for an additional Result type to implement throwing value
> > observers with clearly defined rules because the choice of type E is
> > severely constrained. If the programmer choose Result, they get exactly
> the
> > throwing behaviours guaranteed. They cannot supply a type E which does
> not
> > produce those guaranteed throwing behaviours, because it won't compile.
>
> I would like to see a comparison of Result and Expected.
>
That is literally P0762R0 (in progress).
Niall
--
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/477054b4-faa8-4a11-aff9-b94a13d91316%40isocpp.org.
------=_Part_1449_1534403770.1502410337495
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, August 10, 2017 at 3:40:11 PM UTC+1, Ville Vo=
utilainen wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin=
-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 10 August 2=
017 at 17:26, Niall Douglas <<a href=3D"javascript:" target=3D"_blank" g=
df-obfuscated-mailto=3D"hwcTfUB5BwAJ" rel=3D"nofollow" onmousedown=3D"this.=
href=3D'javascript:';return true;" onclick=3D"this.href=3D'java=
script:';return true;">nialldo...@gmail.com</a>> wrote:
<br>> No, I want excepted::value to not throw at all. Not ever. Others h=
ave
<br>> suggested expected::value doing stuff other than throwing
<br>> bad_expected_access. Not me.
<br>
<br>So calling expected::value is UB if the expected holds something else?
<br></blockquote><div><br></div><div>Yes. This is highly desirable. We have=
so much better tooling nowadays. clang-tidy will pick up the logic error f=
requently at compile time. The UB sanitiser will pick it up at runtime. No =
need to ever throw std::logic_error (which bad_expected_access subclasses) =
ever again in new code. Ideally a near future C++ standard will officially =
make throwing std::logic_error an unrecoverable program failure, and we can=
be done with it forever.</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;">
<br>> I want instead for an additional Result type to implement throwing=
value
<br>> observers with clearly defined rules because the choice of type E =
is
<br>> severely constrained. If the programmer choose Result, they get ex=
actly the
<br>> throwing behaviours guaranteed. They cannot supply a type E which =
does not
<br>> produce those guaranteed throwing behaviours, because it won't=
compile.
<br>
<br>I would like to see a comparison of Result and Expected.
<br></blockquote><div><br></div><div>That is literally P0762R0 (in progress=
).</div><div><br></div><div>Niall</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/477054b4-faa8-4a11-aff9-b94a13d91316%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/477054b4-faa8-4a11-aff9-b94a13d91316=
%40isocpp.org</a>.<br />
------=_Part_1449_1534403770.1502410337495--
------=_Part_1448_1594877951.1502410337495--
.
Author: Niall Douglas <nialldouglas14@gmail.com>
Date: Thu, 10 Aug 2017 17:16:35 -0700 (PDT)
Raw View
------=_Part_721_2068955459.1502410595070
Content-Type: multipart/alternative;
boundary="----=_Part_722_531979555.1502410595070"
------=_Part_722_531979555.1502410595070
Content-Type: text/plain; charset="UTF-8"
>
> > Such patterns are information destroying. Don't do that.
>
> ...but it also *adds* information. The above example replaces a
> context-free error with one that has better locality of context. Sure,
> totally throwing out the lower level information is less than ideal, but
> I'm *absolutely* unconvinced that the far-context information is more
> useful than the near-context information. (Better, of course, is to have
> both, which is why the outer exception ought to *contain* the inner
> exception. Which... the original example *did*. You're setting up a
> straw-man here...)
>
Nested exceptions would indeed be better.
But you can nest error_code's too. Just wrap them in std::system_error as
the C++ standard intended you to do. Then nest those.
The point I am making here is that there is zero difference between
std::error_code and throwing a C++ exception. Indeed there is a 1-to-1
conversion between the STL exception types and std::errc's members. You can
readily convert between them if so desired.
All this discussion is over ideological strawmen and is not relevant to
Result's menu of choices for type E.
Niall
--
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/bbbf2ade-732d-4d8e-a98c-5698664430e0%40isocpp.org.
------=_Part_722_531979555.1502410595070
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">> Such pat=
terns are information destroying. Don't do that.
<br>
<br>...but it also *adds* information. The above example replaces a
<br>context-free error with one that has better locality of context. Sure,
<br>totally throwing out the lower level information is less than ideal, bu=
t
<br>I'm *absolutely* unconvinced that the far-context information is mo=
re
<br>useful than the near-context information. (Better, of course, is to hav=
e
<br>both, which is why the outer exception ought to *contain* the inner
<br>exception. Which... the original example *did*. You're setting up a
<br>straw-man here...)
<br></blockquote><div><br></div><div>Nested exceptions would indeed be bett=
er.</div><div><br></div><div>But you can nest error_code's too. Just wr=
ap them in std::system_error as the C++ standard intended you to do. Then n=
est those.</div><div><br></div><div>The point I am making here is that ther=
e is zero difference between std::error_code and throwing a C++ exception. =
Indeed there is a 1-to-1 conversion between the STL exception types and std=
::errc's members. You can readily convert between them if so desired.</=
div><div><br></div><div>All this discussion is over ideological strawmen an=
d is not relevant to Result's menu of choices for type E.</div><div><br=
></div><div>Niall</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/bbbf2ade-732d-4d8e-a98c-5698664430e0%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/bbbf2ade-732d-4d8e-a98c-5698664430e0=
%40isocpp.org</a>.<br />
------=_Part_722_531979555.1502410595070--
------=_Part_721_2068955459.1502410595070--
.
Author: Niall Douglas <nialldouglas14@gmail.com>
Date: Thu, 10 Aug 2017 17:17:57 -0700 (PDT)
Raw View
------=_Part_1462_129040794.1502410677115
Content-Type: multipart/alternative;
boundary="----=_Part_1463_1871187475.1502410677116"
------=_Part_1463_1871187475.1502410677116
Content-Type: text/plain; charset="UTF-8"
>
>
> It might be best if someone along the chain, maybe B or C, throws
> parseError(where_parse_failed, what_it_was_expecting), which is part of the
> *interface*, not implementation detail.
>
> So, agreed - don't throw out important information.
> But it may require repackaging the error in order to separate
> implementation detail from interface.
>
> Absolutely. You can trap one error_code and emit a new custom error_code,
exactly the same as with exceptions.
There is no difference here. This discussion is making mountains out of
molehills.
Niall
--
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/32e36576-a447-4748-91ac-0a059d4066ab%40isocpp.org.
------=_Part_1463_1871187475.1502410677116
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div><div class=3D"gmail_quote"><div><br>It might be best if someone al=
ong the chain, maybe B or C, throws parseError(where_parse_failed, what_it_=
was_expecting), which is part of the *interface*, not implementation detail=
..<br><br></div><div>So, agreed - don't throw out important information.=
<br></div><div>But it may require repackaging the error in order to separat=
e implementation detail from interface.<br><br></div></div></div></div></bl=
ockquote><div>Absolutely. You can trap one error_code and emit a new custom=
error_code, exactly the same as with exceptions.</div><div><br></div><div>=
There is no difference here. This discussion is making mountains out of mol=
ehills.</div><div><br></div><div>Niall=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/32e36576-a447-4748-91ac-0a059d4066ab%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/32e36576-a447-4748-91ac-0a059d4066ab=
%40isocpp.org</a>.<br />
------=_Part_1463_1871187475.1502410677116--
------=_Part_1462_129040794.1502410677115--
.
Author: Niall Douglas <nialldouglas14@gmail.com>
Date: Thu, 10 Aug 2017 17:40:57 -0700 (PDT)
Raw View
------=_Part_1521_138035212.1502412057821
Content-Type: multipart/alternative;
boundary="----=_Part_1522_603230372.1502412057821"
------=_Part_1522_603230372.1502412057821
Content-Type: text/plain; charset="UTF-8"
>
>
>
> My point is not that having access to the error code is bad. My point is
> that having access to *just* the error_code is bad, that throwing the
> error_code *alone* is a bad exception.
>
It is no different to throwing some third party subclass of std::exception.
Code in main() can only catch(std::exception). All that "context" you think
so important is exactly as lossy as with std::error_code. Or exactly as
retainable. There is no difference here. These are all strawman arguments.
> The error_code is (potentially) necessary, but *not sufficient* for
> non-local error handling. As such, if all you have is `result<T,
> error_code>`, throwing that error_code is a bad exception interface. You
> should always wrap it in something that has an actual interface and useful
> state, if possible (the thread system doesn't really have "useful state"
> that it can package, which is why it uses `system_error` directly. Sadly,
> they didn't give it its own exception type).
>
I have never at any stage said that one should throw error_code. The
correct way, as intended by the C++ standard, that error_code should be
represented in the C++ exception handling system is via being wrapped into
std::system_error.
You claim that sending error_code up the exception throw chain is a bad
exception interface. It's exactly the same as throwing some third party
exception type which main() catch clauses can only resolve to a
std::exception. No difference.
>
> I want instead for an additional Result type to implement throwing value
>> observers with clearly defined rules because the choice of type E is
>> severely constrained. If the programmer choose Result, they get exactly the
>> throwing behaviours guaranteed. They cannot supply a type E which does not
>> produce those guaranteed throwing behaviours, because it won't compile.
>>
>
> And I don't believe that we should have a variant-error type that throws
> the error_code. Or more to the point, we shouldn't have a variant-error
> type where the error part is a thing which is a complete enough object that
> throwing it constitutes a reasonable exception interface.
>
Throwing std::system_error(expected::error()) is far more useful than
throwing bad_expected_access<error_code>(expected::error()). Which is why
Result does that, and Expected should throw nothing so the static and
runtime UB tooling can catch it. Logic errors should never be represented
as recoverable exception throws. Very bad.
>
> Variant-error types, to me
> <https://11080372623597421729.googlegroups.com/attach/a8bf61b2beb10bec/Survey%20of%20Error%20Handling.html?part=0.1&view=1&vt=ANaJVrEuWdkMEUHVl8Qrbf1xMKzGZNqSxVVbv4u_1_5wbflNpDWuaY1LV97Aaez-XDfJ_Gzes8TlZWzNRZxKt1XgGBIawBy0ANkQYqmXalrOk72eWQd7jTQ>,
> are for *local* error processing.
>
That may be the case for you personally. But hundreds of millions of lines
of C code which work directly with C errno would prove you wrong.
It's a perfectly valid design to propagate error_code throughout the
program. Indeed quite a few over at SG14 low latency are very interested in
Result and Expected *precisely because* you can eliminate all C++ exception
throws entirely from a large codebase and just use Result/Expected
exclusively for all your failure handling. The Outcome library also adds an
outcome<T, EC, E> so you can return either a T, or an error_code, or an
exception_ptr. This lets SG14 type code return exception throws caused by
use of the STL without losing information, and return error codes with
custom or system or generic domains for everything else.
Just because you don't like it doesn't mean it isn't very viable, even
preferable, for many types of C++ program. All that C and POSIX code out
there more than proves this.
>
> And let's consider one more thing. Let's say that throwing a light-weight
> error code really is a good exception interface. I submit that in such
> cases, that decision about whether this is a good exception interface *should
> not* be made by the function that originally emitted the error. It is not
> `to/from_chars` who can make that determination; it is the code *calling*
> that function who should make the determination on whether the error_code
> represents a sufficient exception interface.
>
> That is, a function should not be able to *tell me* that throwing a
> `system_error` is a valid way to handle its errors. That's for me to
> determine on a case-by-case basis. That's another reason why I prefer
> `bad_expected_access` to throwing the error code directly. By not throwing
> the error code by default, it means that each user *must* determine for
> themselves how to pass it to non-local code if they so desire.
>
And once again we return to why I think there is a need for both a Result
and an Expected, and one object will be suboptimal for everybody if it
tries to straddle both use cases.
Result is for people who don't want to use C++ exception throws, or want a
two-tier failure handling mechanism whereby Result failure is recoverable
failure and throwing exceptions is unrecoverable (i.e. abort and rollback)
failure for some given operation. AFIO, and the stuff based on it, uses
this exact pattern.
Expected is for people who are writing program logic in a functional style,
as it would appear you are looking for.
Your preferred use case and thus preferred design can be satisfied happily
by Expected. Meanwhile there is a ton of people who want a Result type
design. The Boost peer review conclusion was unambiguous on that point at
least. Neither design precludes the other, if anything having two
countervailing designs better clarifies what makes each the best at its
particular role.
Niall
--
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/cf30dfd6-3d11-418d-a051-ec6ff5af8b12%40isocpp.org.
------=_Part_1522_603230372.1502412057821
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div><br><br>My point is not that having access to the error code is ba=
d. My point is that having access to <i>just</i> the error_code is bad, tha=
t throwing the error_code <i>alone</i> is a bad exception. </div></div></bl=
ockquote><div><br></div><div>It is no different to throwing some third part=
y subclass of std::exception. Code in main() can only catch(std::exception)=
.. All that "context" you think so important is exactly as lossy a=
s with std::error_code. Or exactly as retainable. There is no difference he=
re. These are all strawman arguments.</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>The error_code is (pote=
ntially) necessary, but <i>not sufficient</i> for non-local error handling.=
As such, if all you have is `result<T, error_code>`, throwing that e=
rror_code is a bad exception interface. You should always wrap it in someth=
ing that has an actual interface and useful state, if possible (the thread =
system doesn't really have "useful state" that it can package=
, which is why it uses `system_error` directly. Sadly, they didn't give=
it its own exception type).<br></div></div></blockquote><div><br></div><di=
v>I have never at any stage said that one should throw error_code. The corr=
ect way, as intended by the C++ standard, that error_code should be represe=
nted in the C++ exception handling system is via being wrapped into std::sy=
stem_error.</div><div><br></div><div>You claim that sending error_code up t=
he exception throw chain is a bad exception interface. It's exactly the=
same as throwing some third party exception type which main() catch clause=
s can only resolve to a std::exception. No difference.</div><div>=C2=A0</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><br></=
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"><div>I want in=
stead for an additional Result type to implement throwing value observers w=
ith clearly defined rules because the choice of type E is severely constrai=
ned. If the programmer choose Result, they get exactly the throwing behavio=
urs guaranteed. They cannot supply a type E which does not produce those gu=
aranteed throwing behaviours, because it won't compile.</div></div></bl=
ockquote><div><br>And I don't believe that we should have a variant-err=
or type that throws the error_code. Or more to the point, we shouldn't =
have a variant-error type where the error part is a thing which is a comple=
te enough object that throwing it constitutes a reasonable exception interf=
ace.<br></div></div></blockquote><div><br></div><div>Throwing std::system_e=
rror(expected::error()) is far more useful than throwing bad_expected_acces=
s<error_code>(expected::error()). Which is why Result does that, and =
Expected should throw nothing so the static and runtime UB tooling can catc=
h it. Logic errors should never be represented as recoverable exception thr=
ows. Very bad.</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><br>Variant-error types, <a href=3D"https://11=
080372623597421729.googlegroups.com/attach/a8bf61b2beb10bec/Survey%20of%20E=
rror%20Handling.html?part=3D0.1&view=3D1&vt=3DANaJVrEuWdkMEUHVl8Qrb=
f1xMKzGZNqSxVVbv4u_1_5wbflNpDWuaY1LV97Aaez-XDfJ_Gzes8TlZWzNRZxKt1XgGBIawBy0=
ANkQYqmXalrOk72eWQd7jTQ" target=3D"_blank" rel=3D"nofollow" onmousedown=3D"=
this.href=3D'https://11080372623597421729.googlegroups.com/attach/a8bf6=
1b2beb10bec/Survey%20of%20Error%20Handling.html?part\x3d0.1\x26view\x3d1\x2=
6vt\x3dANaJVrEuWdkMEUHVl8Qrbf1xMKzGZNqSxVVbv4u_1_5wbflNpDWuaY1LV97Aaez-XDfJ=
_Gzes8TlZWzNRZxKt1XgGBIawBy0ANkQYqmXalrOk72eWQd7jTQ';return true;" oncl=
ick=3D"this.href=3D'https://11080372623597421729.googlegroups.com/attac=
h/a8bf61b2beb10bec/Survey%20of%20Error%20Handling.html?part\x3d0.1\x26view\=
x3d1\x26vt\x3dANaJVrEuWdkMEUHVl8Qrbf1xMKzGZNqSxVVbv4u_1_5wbflNpDWuaY1LV97Aa=
ez-XDfJ_Gzes8TlZWzNRZxKt1XgGBIawBy0ANkQYqmXalrOk72eWQd7jTQ';return true=
;">to me</a>, are for <i>local</i> error processing.</div></div></blockquot=
e><div><br></div><div>That may be the case for you personally. But hundreds=
of millions of lines of C code which work directly with C errno would prov=
e you wrong.</div><div><br></div><div>It's a perfectly valid design to =
propagate error_code throughout the program. Indeed quite a few over at SG1=
4 low latency are very interested in Result and Expected <i>precisely becau=
se</i>=C2=A0you can eliminate all C++ exception throws entirely from a larg=
e codebase and just use Result/Expected exclusively for all your failure ha=
ndling. The Outcome library also adds an outcome<T, EC, E> so you can=
return either a T, or an error_code, or an exception_ptr. This lets SG14 t=
ype code return exception throws caused by use of the STL without losing in=
formation, and return error codes with custom or system or generic domains =
for everything else.</div><div><br></div><div>Just because you don't li=
ke it doesn't mean it isn't very viable, even preferable, for many =
types of C++ program. All that C and POSIX code out there more than proves =
this.</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><br>And let's consider one more thing. Let's sa=
y that throwing a light-weight error code really is a good exception interf=
ace. I submit that in such cases, that decision about whether this is a goo=
d exception interface <i>should not</i> be made by the function that origin=
ally emitted the error. It is not `to/from_chars` who can make that determi=
nation; it is the code <i>calling</i> that function who should make the det=
ermination on whether the error_code represents a sufficient exception inte=
rface.<br><br>That is, a function should not be able to <i>tell me</i> that=
throwing a `system_error` is a valid way to handle its errors. That's =
for me to determine on a case-by-case basis. That's another reason why =
I prefer `bad_expected_access` to throwing the error code directly. By not =
throwing the error code by default, it means that each user <i>must</i> det=
ermine for themselves how to pass it to non-local code if they so desire.<b=
r></div></div></blockquote><div><br></div><div>And once again we return to =
why I think there is a need for both a Result and an Expected, and one obje=
ct will be suboptimal for everybody if it tries to straddle both use cases.=
</div><div><br></div><div>Result is for people who don't want to use C+=
+ exception throws, or want a two-tier failure handling mechanism whereby R=
esult failure is recoverable failure and throwing exceptions is unrecoverab=
le (i.e. abort and rollback) failure for some given operation. AFIO, and th=
e stuff based on it, uses this exact pattern.</div><div><br></div><div>Expe=
cted is for people who are writing program logic in a functional style, as =
it would appear you are looking for.</div><div><br></div><div>Your preferre=
d use case and thus preferred design can be satisfied happily by Expected. =
Meanwhile there is a ton of people who want a Result type design. The Boost=
peer review conclusion was unambiguous on that point at least. Neither des=
ign precludes the other, if anything having two countervailing designs bett=
er clarifies what makes each the best at its particular role.</div><div><br=
></div><div>Niall</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/cf30dfd6-3d11-418d-a051-ec6ff5af8b12%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/cf30dfd6-3d11-418d-a051-ec6ff5af8b12=
%40isocpp.org</a>.<br />
------=_Part_1522_603230372.1502412057821--
------=_Part_1521_138035212.1502412057821--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Fri, 11 Aug 2017 08:12:02 +0300
Raw View
On 11 August 2017 at 03:12, Niall Douglas <nialldouglas14@gmail.com> wrote:
>> So calling expected::value is UB if the expected holds something else?
> Yes. This is highly desirable. We have so much better tooling nowadays.
> clang-tidy will pick up the logic error frequently at compile time. The UB
That's not the reason why UB is good. UB is good because that's what
the lowest-level
building block should do; I can add checking and additionally a throw
on top of an UB interface,
whereas making a throwing interface not throw carries a cost.
> sanitiser will pick it up at runtime. No need to ever throw std::logic_error
> (which bad_expected_access subclasses) ever again in new code. Ideally a
> near future C++ standard will officially make throwing std::logic_error an
> unrecoverable program failure, and we can be done with it forever.
That's a bit drastic since it turns off systems where logic_errors are
not causes for termination.
Such systems exist; the idea is that a lower layer can report any
error, even a logic_error, and
the upper layer chooses to limp along anyway. I've seen a case of this
where a video codec
threw a logic error due to a state machine bug, but that was no reason
to terminate the application
used to display photos and videos - just because you can't watch
videos of certain format
doesn't mean you shouldn't be able to view your photos, even if the
video part has logic errors
in it.
--
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/CAFk2RUYUx1vjssJhK9dnoRMR%3DZw2KmLJL2cEiXpxLwgcVj4c4A%40mail.gmail.com.
.
Author: Niall Douglas <nialldouglas14@gmail.com>
Date: Fri, 11 Aug 2017 04:25:01 -0700 (PDT)
Raw View
------=_Part_1881_1914146221.1502450701718
Content-Type: multipart/alternative;
boundary="----=_Part_1882_1245191269.1502450701718"
------=_Part_1882_1245191269.1502450701718
Content-Type: text/plain; charset="UTF-8"
On Friday, August 11, 2017 at 6:12:05 AM UTC+1, Ville Voutilainen wrote:
>
> On 11 August 2017 at 03:12, Niall Douglas <nialldo...@gmail.com
> <javascript:>> wrote:
> >> So calling expected::value is UB if the expected holds something else?
> > Yes. This is highly desirable. We have so much better tooling nowadays.
> > clang-tidy will pick up the logic error frequently at compile time. The
> UB
>
> That's not the reason why UB is good. UB is good because that's what
> the lowest-level
> building block should do; I can add checking and additionally a throw
> on top of an UB interface,
> whereas making a throwing interface not throw carries a cost.
>
That's the other side of the argument, also absolutely valid too. Both
support all-narrow observers on Expected.
Here's some code for a C++ which does not exist yet, but may do one day:
// getting the list of (x, y, z) such that
// - 1 <= x <= y < z < 11
// - x^2 + y^2 == z^2
auto l = bind(ints(32, 1), [](int z){
bind(ints(1, z), [&](int x){
bind(ints(x, z), [&](int y){
bind([&]() -> expected<void, void> {
if(x * x + y * y == z * z)
return {in_place}; // successful void
else
return unexpected{}; // failed void
}, [&]{ return tuple(x, y, z); }
)))).collect();
Here we apply monadic bind to a Range. Potentially 32 * 32 * 32 expecteds
will be created and checked and permuted. Because this is an entirely
statically analysable construct, if expected has an all-narrow observer
interface, the compiler can warn or refuse to compile logic errors in such
logic. It cannot do this if there is any wide observer interface in there.
Note that Vicente intends Expected to be narrowly observed when used in
bind() via traits, and that's fine. I'm striking at the deeper question
here: *what gain versus what loss does narrow expected::value() have over
wide expected::value()? What gain versus what loss does throwing and
catching bad_expected_access<E> have over there being no exception throws
at all?*
This also asks the question *Should Expected look like Optional or should
it look differently?*
And finally, *Was the wide expected::value() a mistake with the benefit of
hindsight?* Because having watched it be deployed in the wild, a lot of
people type *optional thinking it means the same as optional.value(). With
the benefit of hindsight, optional probably should have been all-narrow,
end users don't make such silly cognitve mistakes if they know that no
member function will ever throw. I would apply the same logic to Expected:
make it all-narrow or all-wide. Don't make operator* do different things to
expected::value() which is also different again to expected::error().
>
> > sanitiser will pick it up at runtime. No need to ever throw
> std::logic_error
> > (which bad_expected_access subclasses) ever again in new code. Ideally a
> > near future C++ standard will officially make throwing std::logic_error
> an
> > unrecoverable program failure, and we can be done with it forever.
>
>
> That's a bit drastic since it turns off systems where logic_errors are
> not causes for termination.
>
They can throw a runtime_error if they don't want termination. Or even just
a plain exception.
> Such systems exist; the idea is that a lower layer can report any
> error, even a logic_error, and
> the upper layer chooses to limp along anyway. I've seen a case of this
> where a video codec
> threw a logic error due to a state machine bug, but that was no reason
> to terminate the application
> used to display photos and videos - just because you can't watch
> videos of certain format
> doesn't mean you shouldn't be able to view your photos, even if the
> video part has logic errors
> in it.
>
I would call that not a logic error, and so it should not be reported as
one. Logic errors are unintentional mistakes in the programming code.
Historically we have been lenient on their treatment in C++. I would be of
that faction which believes stronger treatment is needed in the future. But
that's another discussion for another day.
Niall
--
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/21aaf308-0f2b-49af-9c21-292fb89a3dc2%40isocpp.org.
------=_Part_1882_1245191269.1502450701718
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Friday, August 11, 2017 at 6:12:05 AM UTC+1, Ville Vout=
ilainen wrote:<blockquote class=3D"gmail_quote" style=3D"margin: 0;margin-l=
eft: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;">On 11 August 201=
7 at 03:12, Niall Douglas <<a href=3D"javascript:" target=3D"_blank" gdf=
-obfuscated-mailto=3D"lYvU2dSoBwAJ" rel=3D"nofollow" onmousedown=3D"this.hr=
ef=3D'javascript:';return true;" onclick=3D"this.href=3D'javasc=
ript:';return true;">nialldo...@gmail.com</a>> wrote:
<br>>> So calling expected::value is UB if the expected holds somethi=
ng else?
<br>> Yes. This is highly desirable. We have so much better tooling nowa=
days.
<br>> clang-tidy will pick up the logic error frequently at compile time=
.. The UB
<br>
<br>That's not the reason why UB is good. UB is good because that's=
what
<br>the lowest-level
<br>building block should do; I can add checking and additionally a throw
<br>on top of an UB interface,
<br>whereas making a throwing interface not throw carries a cost.
<br></blockquote><div><br></div><div>That's the other side of the argum=
ent, also absolutely valid too. Both support all-narrow observers on Expect=
ed.</div><div><br></div><div>Here's some code for a C++ which does not =
exist yet, but may do one day:</div><div><br></div><div><div>// getting the=
list of (x, y, z) such that</div><div>// =C2=A0- 1 <=3D x <=3D y <=
; z < 11</div><div>// =C2=A0- x^2 + y^2 =3D=3D z^2</div><div>auto l =3D =
bind(ints(32, 1), [](int z){</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0bind(ints(1, z), [&](int x){</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0bind(ints(x, z), [&](int y){</div><div>=C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0bind([&]() -> expect=
ed<void, void> {</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0if(x * x + y * y =3D=3D z * z)</div><div>=C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return {in_place}; =
=C2=A0 =C2=A0// successful void</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0else</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return unexpected{}; =C2=A0// fail=
ed void</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0},=
[&]{ return tuple(x, y, z); }</div><div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0)))).collect();</div></div><div><br></div><div>Here we apply monadic =
bind to a Range. Potentially 32 * 32 * 32 expecteds will be created and che=
cked and permuted. Because this is an entirely statically analysable constr=
uct, if expected has an all-narrow observer interface, the compiler can war=
n or refuse to compile logic errors in such logic. It cannot do this if the=
re is any wide observer interface in there.</div><div><br></div><div>Note t=
hat Vicente intends Expected to be narrowly observed when used in bind() vi=
a traits, and that's fine. I'm striking at the deeper question here=
: <i>what gain versus what loss does narrow expected::value() have over wid=
e expected::value()? What gain versus what loss does throwing and catching =
bad_expected_access<E> have over there being no exception throws at a=
ll?</i></div><div><br></div><div>This also asks the question <i>Should Expe=
cted look like Optional or should it look differently?</i></div><div><br></=
div><div>And finally, <i>Was the wide expected::value() a mistake with the =
benefit of hindsight?</i>=C2=A0Because having watched it be deployed in the=
wild, a lot of people type *optional thinking it means the same as optiona=
l.value(). With the benefit of hindsight, optional probably should have bee=
n all-narrow, end users don't make such silly cognitve mistakes if they=
know that no member function will ever throw. I would apply the same logic=
to Expected: make it all-narrow or all-wide. Don't make operator* do d=
ifferent things to expected::value() which is also different again to expec=
ted::error().</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;">
<br>> sanitiser will pick it up at runtime. No need to ever throw std::l=
ogic_error
<br>> (which bad_expected_access subclasses) ever again in new code. Ide=
ally a
<br>> near future C++ standard will officially make throwing std::logic_=
error an
<br>> unrecoverable program failure, and we can be done with it forever.
<br>
<br>
<br>That's a bit drastic since it turns off systems where logic_errors =
are
<br>not causes for termination.
<br></blockquote><div><br></div><div>They can throw a runtime_error if they=
don't want termination. Or even just a plain exception.</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;">Such systems exist; t=
he idea is that a lower layer can report any
<br>error, even a logic_error, and
<br>the upper layer chooses to limp along anyway. I've seen a case of t=
his
<br>where a video codec
<br>threw a logic error due to a state machine bug, but that was no reason
<br>to terminate the application
<br>used to display photos and videos - just because you can't watch
<br>videos of certain format
<br>doesn't mean you shouldn't be able to view your photos, even if=
the
<br>video part has logic errors
<br>in it.
<br></blockquote><div><br></div><div>I would call that not a logic error, a=
nd so it should not be reported as one. Logic errors are unintentional mist=
akes in the programming code. Historically we have been lenient on their tr=
eatment in C++. I would be of that faction which believes stronger treatmen=
t is needed in the future. But that's another discussion for another da=
y.</div><div><br></div><div>Niall</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/21aaf308-0f2b-49af-9c21-292fb89a3dc2%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/21aaf308-0f2b-49af-9c21-292fb89a3dc2=
%40isocpp.org</a>.<br />
------=_Part_1882_1245191269.1502450701718--
------=_Part_1881_1914146221.1502450701718--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 11 Aug 2017 15:46:04 -0700 (PDT)
Raw View
------=_Part_2670_319632688.1502491564620
Content-Type: multipart/alternative;
boundary="----=_Part_2671_719675285.1502491564620"
------=_Part_2671_719675285.1502491564620
Content-Type: text/plain; charset="UTF-8"
On Thursday, August 10, 2017 at 8:40:57 PM UTC-4, Niall Douglas wrote:
>
> My point is not that having access to the error code is bad. My point is
>> that having access to *just* the error_code is bad, that throwing the
>> error_code *alone* is a bad exception.
>>
>
> It is no different to throwing some third party subclass of
> std::exception. Code in main() can only catch(std::exception). All that
> "context" you think so important is exactly as lossy as with
> std::error_code. Or exactly as retainable. There is no difference here.
> These are all strawman arguments.
>
First, that's not what "strawman" means. A "strawman" argument is what
happens when you set up a position that *pretends* to be your opponent's
position, then argue against that position rather than your opponent's
actual position.
My position is that throwing error codes by themselves is not something
that users should do, that it leads to bad interfaces, and we shouldn't
encourage such exception interfaces.
Your argument against this was to suggest that I was arguing that we should
be constantly translating exceptions at every layer of our program. That's
what made it a "strawman"; it's not the position I was arguing.
Your position is that throwing *just* error codes is a good exception
interface. And that's what I'm arguing against. Therefore, I'm not putting
forth a strawman.
Second, you *cannot* throw `std::exception`; it's a pure-virtual class. So
the class that was actually thrown was something derived from it. And
therefore, it is at least theoretically possible for `main` to have access
to the actual class you threw. If the exception type contained useful
context information, it is therefore possible for the eventual catcher to
consume that information.
If `main` only catches `std::exception`, it still remains possible for
`main` to have caught something with more context information. And
therefore, the user who is catching `std::exception` is giving up that
context information *by choice*.
By the choice of the one who is resolving the error, not the choice of the
one who is sending it.
By contrast, if you throw a `system_error`, the receiver has exactly 3
things: the error code, the error category, and a string. Unless that
string encoded context information, the receiver of that error has no
context information about the exception.
With a context-rich exception interface, the receiver only loses
information by their choice. In a `system_error` throwing world, the
receiver has no choice about losing that state.
So there's a difference.
The error_code is (potentially) necessary, but *not sufficient* for
>> non-local error handling. As such, if all you have is `result<T,
>> error_code>`, throwing that error_code is a bad exception interface. You
>> should always wrap it in something that has an actual interface and useful
>> state, if possible (the thread system doesn't really have "useful state"
>> that it can package, which is why it uses `system_error` directly. Sadly,
>> they didn't give it its own exception type).
>>
>
> I have never at any stage said that one should throw error_code. The
> correct way, as intended by the C++ standard, that error_code should be
> represented in the C++ exception handling system is via being wrapped into
> std::system_error.
>
Semantics.
`system_error` contains only an `error_code` and a string. And in the case
of what `result<T, error_code>` would throw, that string will be completely
devoid of useful context information. So my point stands: `result<T,
error_code>::value` will throw an exception that is devoid of context
information.
> You claim that sending error_code up the exception throw chain is a bad
> exception interface. It's exactly the same as throwing some third party
> exception type which main() catch clauses can only resolve to a
> std::exception. No difference.
>
>
>>
>> I want instead for an additional Result type to implement throwing value
>>> observers with clearly defined rules because the choice of type E is
>>> severely constrained. If the programmer choose Result, they get exactly the
>>> throwing behaviours guaranteed. They cannot supply a type E which does not
>>> produce those guaranteed throwing behaviours, because it won't compile.
>>>
>>
>> And I don't believe that we should have a variant-error type that throws
>> the error_code. Or more to the point, we shouldn't have a variant-error
>> type where the error part is a thing which is a complete enough object that
>> throwing it constitutes a reasonable exception interface.
>>
>
> Throwing std::system_error(expected::error()) is far more useful than
> throwing bad_expected_access<error_code>(expected::error()). Which is why
> Result does that, and Expected should throw nothing so the static and
> runtime UB tooling can catch it. Logic errors should never be represented
> as recoverable exception throws. Very bad.
>
I'm with Ville Voutilainen on logic errors; there is no reason for us to
deny people the ability to recover from them if they so desire.
Variant-error types, to me
>> <https://11080372623597421729.googlegroups.com/attach/a8bf61b2beb10bec/Survey%20of%20Error%20Handling.html?part=0.1&view=1&vt=ANaJVrEuWdkMEUHVl8Qrbf1xMKzGZNqSxVVbv4u_1_5wbflNpDWuaY1LV97Aaez-XDfJ_Gzes8TlZWzNRZxKt1XgGBIawBy0ANkQYqmXalrOk72eWQd7jTQ>,
>> are for *local* error processing.
>>
>
> That may be the case for you personally. But hundreds of millions of lines
> of C code which work directly with C errno would prove you wrong.
>
I was talking about variant-error types as return values. `std::errno` is
not a return value. So how does that statement even follow from what I said?
Admittedly, the survey I linked was an older, less complete version. A more
complete one is here
<https://github.com/NicolBolas/Proposal-Ideas/blob/master/older/Survey of
Error Handling.md>. In that taxonomy, `std::errno` is an out-of-band
reporting system. Such systems work best for non-local error processing. It
is nothing at all like return values, since you have to explicitly query
them. Indeed, the primary point of out-of-band errors is that you can check
them later, in non-local contexts.
It's a perfectly valid design to propagate error_code throughout the
> program. Indeed quite a few over at SG14 low latency are very interested in
> Result and Expected *precisely because* you can eliminate all C++
> exception throws entirely from a large codebase and just use
> Result/Expected exclusively for all your failure handling. The Outcome
> library also adds an outcome<T, EC, E> so you can return either a T, or an
> error_code, or an exception_ptr. This lets SG14 type code return exception
> throws caused by use of the STL without losing information, and return
> error codes with custom or system or generic domains for everything else.
>
> Just because you don't like it doesn't mean it isn't very viable, even
> preferable, for many types of C++ program. All that C and POSIX code out
> there more than proves this.
>
How much an error mechanism is used should not be used to claim that it is
a *good* one. C has plenty of alternatives, and a lot of code uses `errno`
because they have to (that's what the API they're using uses), not because
they want to or like it.
And let's consider one more thing. Let's say that throwing a light-weight
>> error code really is a good exception interface. I submit that in such
>> cases, that decision about whether this is a good exception interface *should
>> not* be made by the function that originally emitted the error. It is
>> not `to/from_chars` who can make that determination; it is the code
>> *calling* that function who should make the determination on whether the
>> error_code represents a sufficient exception interface.
>>
>> That is, a function should not be able to *tell me* that throwing a
>> `system_error` is a valid way to handle its errors. That's for me to
>> determine on a case-by-case basis. That's another reason why I prefer
>> `bad_expected_access` to throwing the error code directly. By not throwing
>> the error code by default, it means that each user *must* determine for
>> themselves how to pass it to non-local code if they so desire.
>>
>
> And once again we return to why I think there is a need for both a Result
> and an Expected, and one object will be suboptimal for everybody if it
> tries to straddle both use cases.
>
> Result is for people who don't want to use C++ exception throws, or want a
> two-tier failure handling mechanism whereby Result failure is recoverable
> failure and throwing exceptions is unrecoverable (i.e. abort and rollback)
> failure for some given operation.
>
So the type that is for people who don't want to throw is... the one that
you want `::value` to throw. How does that make any sense at all? The type
for people who don't want exceptions should not throw on `::value`. And
you've been arguing that `expected::value` shouldn't throw.
Therefore, people who don't want exceptions will use *that*.
> AFIO, and the stuff based on it, uses this exact pattern.
>
> Expected is for people who are writing program logic in a functional
> style, as it would appear you are looking for.
>
I'm not a functional programmer by nature, and I don't know a whole lot
about the functional model. But as I understood it, this:
auto val = some_operation().value();
is more functional in style than:
auto exp_val = some_operation();
if(!exp_val)
{
throw appropriate_exception(exp_val.error(), other, stuff);
}
The latter is what I want to essentially *enforce*, by making the exception
thrown by the former style a program logic error.
> Your preferred use case and thus preferred design can be satisfied happily
> by Expected. Meanwhile there is a ton of people who want a Result type
> design. The Boost peer review conclusion was unambiguous on that point at
> least. Neither design precludes the other, if anything having two
> countervailing designs better clarifies what makes each the best at its
> particular role.
>
The problem I have is exactly what I said: who is enforcing their exception
desires upon whom.
In the world I want, where `::value` throwing is considered a logic error
rather than an expected part of your function's interface, the final
decision about how the nature of what is thrown will default to the user.
The user *must* make that decision, since there is no default.
In the world you want, you want the default to be *used*. You expect the
default to be used. Oh sure, you still allow the user to provide an
alternative if their particular circumstances allow it. But your
expectation with `result` is that the user will just snatch a value out of
it or throw the error code.
I do not want to encourage programming of that style. I do not believe that
it leads to good interfaces. If someone wants to throw that object, they
should have to explicitly ask to do so, not have it be an implicit
side-effect.
So give `expected` a `value_or_throw` that throws the error code, with some
specialization for specific error types.
--
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/02ab5e39-7a5f-4783-a41c-bf4f3a8300b6%40isocpp.org.
------=_Part_2671_719675285.1502491564620
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, August 10, 2017 at 8:40:57 PM UTC-4, Niall Do=
uglas wrote:<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"><div>My point is no=
t that having access to the error code is bad. My point is that having acce=
ss to <i>just</i> the error_code is bad, that throwing the error_code <i>al=
one</i> is a bad exception. </div></div></blockquote><div><br></div><div>It=
is no different to throwing some third party subclass of std::exception. C=
ode in main() can only catch(std::exception). All that "context" =
you think so important is exactly as lossy as with std::error_code. Or exac=
tly as retainable. There is no difference here. These are all strawman argu=
ments.</div></div></blockquote><div><br>First, that's not what "st=
rawman" means. A "strawman" argument is what happens when yo=
u set up a position that <i>pretends</i> to be your opponent's position=
, then argue against that position rather than your opponent's actual p=
osition.<br><br>My position is that throwing error codes by themselves is n=
ot something that users should do, that it leads to bad interfaces, and we =
shouldn't encourage such exception interfaces.<br><br>Your argument aga=
inst this was to suggest that I was arguing that we should be constantly tr=
anslating exceptions at every layer of our program. That's what made it=
a "strawman"; it's not the position I was arguing.<br><br>Yo=
ur position is that throwing <i>just</i> error codes is a good exception in=
terface. And that's what I'm arguing against. Therefore, I'm no=
t putting forth a strawman.<br><br>Second, you <i>cannot</i> throw `std::ex=
ception`; it's a pure-virtual class. So the class that was actually thr=
own was something derived from it. And therefore, it is at least theoretica=
lly possible for `main` to have access to the actual class you threw. If th=
e exception type contained useful context information, it is therefore poss=
ible for the eventual catcher to consume that information.<br><br>If `main`=
only catches `std::exception`, it still remains possible for `main` to hav=
e caught something with more context information. And therefore, the user w=
ho is catching `std::exception` is giving up that context information <i>by=
choice</i>.<br><br>By the choice of the one who is resolving the error, no=
t the choice of the one who is sending it.<br><br>By contrast, if you throw=
a `system_error`, the receiver has exactly 3 things: the error code, the e=
rror category, and a string. Unless that string encoded context information=
, the receiver of that error has no context information about the exception=
..<br><br>With a context-rich exception interface, the receiver only loses i=
nformation by their choice. In a `system_error` throwing world, the receive=
r has no choice about losing that state.<br><br>So there's a 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><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>=
The error_code is (potentially) necessary, but <i>not sufficient</i> for no=
n-local error handling. As such, if all you have is `result<T, error_cod=
e>`, throwing that error_code is a bad exception interface. You should a=
lways wrap it in something that has an actual interface and useful state, i=
f possible (the thread system doesn't really have "useful state&qu=
ot; that it can package, which is why it uses `system_error` directly. Sadl=
y, they didn't give it its own exception type).<br></div></div></blockq=
uote><div><br></div><div>I have never at any stage said that one should thr=
ow error_code. The correct way, as intended by the C++ standard, that error=
_code should be represented in the C++ exception handling system is via bei=
ng wrapped into std::system_error.</div></div></blockquote><div><br>Semanti=
cs.<br><br>`system_error` contains only an `error_code` and a string. And i=
n the case of what `result<T, error_code>` would throw, that string w=
ill be completely devoid of useful context information. So my point stands:=
`result<T, error_code>::value` will throw an exception that is devoi=
d of context information.<br>=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"><div>You claim that sending error_code up the e=
xception throw chain is a bad exception interface. It's exactly the sam=
e as throwing some third party exception type which main() catch clauses ca=
n only resolve to a std::exception. No difference.</div><div>=C2=A0</div><b=
lockquote 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></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"><div>I want instead for=
an additional Result type to implement throwing value observers with clear=
ly defined rules because the choice of type E is severely constrained. If t=
he programmer choose Result, they get exactly the throwing behaviours guara=
nteed. They cannot supply a type E which does not produce those guaranteed =
throwing behaviours, because it won't compile.</div></div></blockquote>=
<div><br>And I don't believe that we should have a variant-error type t=
hat throws the error_code. Or more to the point, we shouldn't have a va=
riant-error type where the error part is a thing which is a complete enough=
object that throwing it constitutes a reasonable exception interface.<br><=
/div></div></blockquote><div><br></div><div>Throwing std::system_error(expe=
cted::<wbr>error()) is far more useful than throwing bad_expected_access<=
;error_<wbr>code>(expected::error()). Which is why Result does that, and=
Expected should throw nothing so the static and runtime UB tooling can cat=
ch it. Logic errors should never be represented as recoverable exception th=
rows. Very bad.</div></div></blockquote><div><br>I'm with Ville Voutila=
inen on logic errors; there is no reason for us to deny people the ability =
to recover from them if they so desire.<br><br></div><blockquote class=3D"g=
mail_quote" style=3D"margin: 0;margin-left: 0.8ex;border-left: 1px #ccc sol=
id;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>Variant-error types, <a href=3D"https=
://11080372623597421729.googlegroups.com/attach/a8bf61b2beb10bec/Survey%20o=
f%20Error%20Handling.html?part=3D0.1&view=3D1&vt=3DANaJVrEuWdkMEUHV=
l8Qrbf1xMKzGZNqSxVVbv4u_1_5wbflNpDWuaY1LV97Aaez-XDfJ_Gzes8TlZWzNRZxKt1XgGBI=
awBy0ANkQYqmXalrOk72eWQd7jTQ" rel=3D"nofollow" target=3D"_blank" onmousedow=
n=3D"this.href=3D'https://11080372623597421729.googlegroups.com/attach/=
a8bf61b2beb10bec/Survey%20of%20Error%20Handling.html?part\x3d0.1\x26view\x3=
d1\x26vt\x3dANaJVrEuWdkMEUHVl8Qrbf1xMKzGZNqSxVVbv4u_1_5wbflNpDWuaY1LV97Aaez=
-XDfJ_Gzes8TlZWzNRZxKt1XgGBIawBy0ANkQYqmXalrOk72eWQd7jTQ';return true;"=
onclick=3D"this.href=3D'https://11080372623597421729.googlegroups.com/=
attach/a8bf61b2beb10bec/Survey%20of%20Error%20Handling.html?part\x3d0.1\x26=
view\x3d1\x26vt\x3dANaJVrEuWdkMEUHVl8Qrbf1xMKzGZNqSxVVbv4u_1_5wbflNpDWuaY1L=
V97Aaez-XDfJ_Gzes8TlZWzNRZxKt1XgGBIawBy0ANkQYqmXalrOk72eWQd7jTQ';return=
true;">to me</a>, are for <i>local</i> error processing.</div></div></bloc=
kquote><div><br></div><div>That may be the case for you personally. But hun=
dreds of millions of lines of C code which work directly with C errno would=
prove you wrong.</div></div></blockquote><div><br>I was talking about vari=
ant-error types as return values. `std::errno` is not a return value. So ho=
w does that statement even follow from what I said?<br><br>Admittedly, the =
survey I linked was an older, less complete version. <a href=3D"https://git=
hub.com/NicolBolas/Proposal-Ideas/blob/master/older/Survey of Error Handlin=
g.md">A more complete one is here</a>. In that taxonomy, `std::errno` is an=
out-of-band reporting system. Such systems work best for non-local error p=
rocessing. It is nothing at all like return values, since you have to expli=
citly query them. Indeed, the primary point of out-of-band errors is that y=
ou can check them later, in non-local contexts.<br><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>It's a perfectly v=
alid design to propagate error_code throughout the program. Indeed quite a =
few over at SG14 low latency are very interested in Result and Expected <i>=
precisely because</i>=C2=A0you can eliminate all C++ exception throws entir=
ely from a large codebase and just use Result/Expected exclusively for all =
your failure handling. The Outcome library also adds an outcome<T, EC, E=
> so you can return either a T, or an error_code, or an exception_ptr. T=
his lets SG14 type code return exception throws caused by use of the STL wi=
thout losing information, and return error codes with custom or system or g=
eneric domains for everything else.</div><div><br></div><div>Just because y=
ou don't like it doesn't mean it isn't very viable, even prefer=
able, for many types of C++ program. All that C and POSIX code out there mo=
re than proves this.</div></div></blockquote><div><br>How much an error mec=
hanism is used should not be used to claim that it is a <i>good</i> one. C =
has plenty of alternatives, and a lot of code uses `errno` because they hav=
e to (that's what the API they're using uses), not because they wan=
t to or like it.<br><br></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></div><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>And let's consider one more thing. Let's say that th=
rowing a light-weight error code really is a good exception interface. I su=
bmit that in such cases, that decision about whether this is a good excepti=
on interface <i>should not</i> be made by the function that originally emit=
ted the error. It is not `to/from_chars` who can make that determination; i=
t is the code <i>calling</i> that function who should make the determinatio=
n on whether the error_code represents a sufficient exception interface.<br=
><br>That is, a function should not be able to <i>tell me</i> that throwing=
a `system_error` is a valid way to handle its errors. That's for me to=
determine on a case-by-case basis. That's another reason why I prefer =
`bad_expected_access` to throwing the error code directly. By not throwing =
the error code by default, it means that each user <i>must</i> determine fo=
r themselves how to pass it to non-local code if they so desire.<br></div><=
/div></blockquote><div><br></div><div>And once again we return to why I thi=
nk there is a need for both a Result and an Expected, and one object will b=
e suboptimal for everybody if it tries to straddle both use cases.</div><di=
v><br></div><div>Result is for people who don't want to use C++ excepti=
on throws, or want a two-tier failure handling mechanism whereby Result fai=
lure is recoverable failure and throwing exceptions is unrecoverable (i.e. =
abort and rollback) failure for some given operation.</div></div></blockquo=
te><div><br>So the type that is for people who don't want to throw is..=
.. the one that you want `::value` to throw. How does that make any sense at=
all? The type for people who don't want exceptions should not throw on=
`::value`. And you've been arguing that `expected::value` shouldn'=
t throw.<br><br>Therefore, people who don't want exceptions will use <i=
>that</i>.<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>AFIO, and the stuff based on it, uses this exact pattern.=
</div><div><br></div><div>Expected is for people who are writing program lo=
gic in a functional style, as it would appear you are looking for.</div></d=
iv></blockquote><div><br>I'm not a functional programmer by nature, and=
I don't know a whole lot about the functional model. But as I understo=
od it, this:<br><br><div style=3D"background-color: rgb(250, 250, 250); bor=
der-color: rgb(187, 187, 187); border-style: solid; border-width: 1px; over=
flow-wrap: break-word;" class=3D"prettyprint"><code class=3D"prettyprint"><=
div class=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">auto</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> val </span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>=3D</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> some_=
operation</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(=
).</span><span style=3D"color: #000;" class=3D"styled-by-prettify">value</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">();</span><sp=
an style=3D"color: #000;" class=3D"styled-by-prettify"><br></span></div></c=
ode></div><br>is more functional in style than:<br><br><div style=3D"backgr=
ound-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-st=
yle: solid; border-width: 1px; overflow-wrap: break-word;" class=3D"prettyp=
rint"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=
=3D"color: #008;" class=3D"styled-by-prettify">auto</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"> exp_val </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"> some_operation</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;" clas=
s=3D"styled-by-prettify">if</span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">(!</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify">exp_val</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>=C2=A0 </span>=
<span style=3D"color: #008;" class=3D"styled-by-prettify">throw</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> appropriate_exception=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">(</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify">exp_val</span><span=
style=3D"color: #660;" class=3D"styled-by-prettify">.</span><span style=3D=
"color: #000;" class=3D"styled-by-prettify">error</span><span style=3D"colo=
r: #660;" class=3D"styled-by-prettify">(),</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"> other</span><span style=3D"color: #660;" c=
lass=3D"styled-by-prettify">,</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> stuff</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">);</span><span style=3D"color: #000;" class=3D"styled-by-pre=
ttify"><br></span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>}</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br></sp=
an></div></code></div><br>The latter is what I want to essentially <i>enfor=
ce</i>, by making the exception thrown by the former style a program logic =
error.<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>Your preferred use case and thus preferred design can be sati=
sfied happily by Expected. Meanwhile there is a ton of people who want a Re=
sult type design. The Boost peer review conclusion was unambiguous on that =
point at least. Neither design precludes the other, if anything having two =
countervailing designs better clarifies what makes each the best at its par=
ticular role.</div></div></blockquote><div><br>The problem I have is exactl=
y what I said: who is enforcing their exception desires upon whom.<br><br>I=
n the world I want, where `::value` throwing is considered a logic error ra=
ther than an expected part of your function's interface, the final deci=
sion about how the nature of what is thrown will default to the user. The u=
ser <i>must</i> make that decision, since there is no default.<br><br>In th=
e world you want, you want the default to be <i>used</i>. You expect the de=
fault to be used. Oh sure, you still allow the user to provide an alternati=
ve if their particular circumstances allow it. But your expectation with `r=
esult` is that the user will just snatch a value out of it or throw the err=
or code.<br><br>I do not want to encourage programming of that style. I do =
not believe that it leads to good interfaces. If someone wants to throw tha=
t object, they should have to explicitly ask to do so, not have it be an im=
plicit side-effect.<br><br>So give `expected` a `value_or_throw` that throw=
s the error code, with some specialization for specific error types.<br></d=
iv></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/02ab5e39-7a5f-4783-a41c-bf4f3a8300b6%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/02ab5e39-7a5f-4783-a41c-bf4f3a8300b6=
%40isocpp.org</a>.<br />
------=_Part_2671_719675285.1502491564620--
------=_Part_2670_319632688.1502491564620--
.
Author: Nicol Bolas <jmckesson@gmail.com>
Date: Fri, 11 Aug 2017 16:08:51 -0700 (PDT)
Raw View
------=_Part_2724_1567423208.1502492931992
Content-Type: multipart/alternative;
boundary="----=_Part_2725_1799012844.1502492931993"
------=_Part_2725_1799012844.1502492931993
Content-Type: text/plain; charset="UTF-8"
On Thursday, August 10, 2017 at 8:40:57 PM UTC-4, Niall Douglas wrote:
>
> My point is not that having access to the error code is bad. My point is
>> that having access to *just* the error_code is bad, that throwing the
>> error_code *alone* is a bad exception.
>>
>
> It is no different to throwing some third party subclass of
> std::exception. Code in main() can only catch(std::exception). All that
> "context" you think so important is exactly as lossy as with
> std::error_code. Or exactly as retainable. There is no difference here.
> These are all strawman arguments.
>
First, that's not what "strawman" means. A "strawman" argument is what
happens when you set up a position that *pretends* to be your opponent's
position, then argue against that position rather than your opponent's
actual position.
My position is that throwing error codes by themselves is not something
that users should do, that it leads to bad interfaces, and we shouldn't
encourage such exception interfaces.
Your argument against this was to suggest that I was arguing that we should
be constantly translating exceptions at every layer of our program. That's
what made it a "strawman"; it's not the position I was arguing.
Your position is that throwing *just* error codes is a good exception
interface. And that's what I'm arguing against. Therefore, I'm not putting
forth a strawman.
Second, you *cannot* throw `std::exception`; it's a pure-virtual class. So
the class that was actually thrown was something derived from it. And
therefore, it is at least theoretically possible for `main` to have access
to the actual class you threw. If the exception type contained useful
context information, it is therefore possible for the eventual catcher to
consume that information.
If `main` only catches `std::exception`, it still remains possible for
`main` to have caught something with more context information. And
therefore, the user who is catching `std::exception` is giving up that
context information *by choice*.
By the choice of the one who is resolving the error, not the choice of the
one who is sending it.
By contrast, if you throw a `system_error`, the receiver has exactly 3
things: the error code, the error category, and a string. Unless that
string encoded context information, the receiver of that error has no
context information about the exception.
With a context-rich exception interface, the receiver only loses
information by their choice. In a `system_error` throwing world, the
receiver has no choice about losing that state.
So there's a difference.
The error_code is (potentially) necessary, but *not sufficient* for
>> non-local error handling. As such, if all you have is `result<T,
>> error_code>`, throwing that error_code is a bad exception interface. You
>> should always wrap it in something that has an actual interface and useful
>> state, if possible (the thread system doesn't really have "useful state"
>> that it can package, which is why it uses `system_error` directly. Sadly,
>> they didn't give it its own exception type).
>>
>
> I have never at any stage said that one should throw error_code. The
> correct way, as intended by the C++ standard, that error_code should be
> represented in the C++ exception handling system is via being wrapped into
> std::system_error.
>
Semantics.
`system_error` contains only an `error_code` and a string. And in the case
of what `result<T, error_code>` would throw, that string will be completely
devoid of useful context information. So my point stands: `result<T,
error_code>::value` will throw an exception that is devoid of context
information.
That you're technically throwing `std::system_error` is an implementation
detail. What matters is that the only information the receiving end gets is
an `error_code`.
> You claim that sending error_code up the exception throw chain is a bad
> exception interface. It's exactly the same as throwing some third party
> exception type which main() catch clauses can only resolve to a
> std::exception. No difference.
>
>
>>
>> I want instead for an additional Result type to implement throwing value
>>> observers with clearly defined rules because the choice of type E is
>>> severely constrained. If the programmer choose Result, they get exactly the
>>> throwing behaviours guaranteed. They cannot supply a type E which does not
>>> produce those guaranteed throwing behaviours, because it won't compile.
>>>
>>
>> And I don't believe that we should have a variant-error type that throws
>> the error_code. Or more to the point, we shouldn't have a variant-error
>> type where the error part is a thing which is a complete enough object that
>> throwing it constitutes a reasonable exception interface.
>>
>
> Throwing std::system_error(expected::error()) is far more useful than
> throwing bad_expected_access<error_code>(expected::error()). Which is why
> Result does that, and Expected should throw nothing so the static and
> runtime UB tooling can catch it. Logic errors should never be represented
> as recoverable exception throws. Very bad.
>
I'm with Ville Voutilainen on logic errors; there is no reason for us to
deny people the ability to recover from them if they so desire.
Variant-error types, to me
>> <https://11080372623597421729.googlegroups.com/attach/a8bf61b2beb10bec/Survey%20of%20Error%20Handling.html?part=0.1&view=1&vt=ANaJVrEuWdkMEUHVl8Qrbf1xMKzGZNqSxVVbv4u_1_5wbflNpDWuaY1LV97Aaez-XDfJ_Gzes8TlZWzNRZxKt1XgGBIawBy0ANkQYqmXalrOk72eWQd7jTQ>,
>> are for *local* error processing.
>>
>
> That may be the case for you personally. But hundreds of millions of lines
> of C code which work directly with C errno would prove you wrong.
>
I was talking about variant-error types as return values. `std::errno` is
not a return value. So how does that statement even follow from what I said?
Admittedly, the survey I linked was an older, less complete version. A more
complete one is here
<https://github.com/NicolBolas/Proposal-Ideas/blob/master/older/Survey of
Error Handling.md>. In that taxonomy, `std::errno` is an out-of-band
reporting system. Such systems work best for non-local error processing. It
is nothing at all like return values, since you have to explicitly query
them. Indeed, the primary point of out-of-band errors is that you can check
them later, in non-local contexts.
It's a perfectly valid design to propagate error_code throughout the
> program. Indeed quite a few over at SG14 low latency are very interested in
> Result and Expected *precisely because* you can eliminate all C++
> exception throws entirely from a large codebase and just use
> Result/Expected exclusively for all your failure handling. The Outcome
> library also adds an outcome<T, EC, E> so you can return either a T, or an
> error_code, or an exception_ptr. This lets SG14 type code return exception
> throws caused by use of the STL without losing information, and return
> error codes with custom or system or generic domains for everything else.
>
> Just because you don't like it doesn't mean it isn't very viable, even
> preferable, for many types of C++ program. All that C and POSIX code out
> there more than proves this.
>
How much an error mechanism is used should not be used to claim that it is
a *good* one. C has plenty of alternatives, and a lot of code uses `errno`
because they have to (that's what the API they're using uses), not because
they want to or like it.
And let's consider one more thing. Let's say that throwing a light-weight
>> error code really is a good exception interface. I submit that in such
>> cases, that decision about whether this is a good exception interface *should
>> not* be made by the function that originally emitted the error. It is
>> not `to/from_chars` who can make that determination; it is the code
>> *calling* that function who should make the determination on whether the
>> error_code represents a sufficient exception interface.
>>
>> That is, a function should not be able to *tell me* that throwing a
>> `system_error` is a valid way to handle its errors. That's for me to
>> determine on a case-by-case basis. That's another reason why I prefer
>> `bad_expected_access` to throwing the error code directly. By not throwing
>> the error code by default, it means that each user *must* determine for
>> themselves how to pass it to non-local code if they so desire.
>>
>
> And once again we return to why I think there is a need for both a Result
> and an Expected, and one object will be suboptimal for everybody if it
> tries to straddle both use cases.
>
> Result is for people who don't want to use C++ exception throws, or want a
> two-tier failure handling mechanism whereby Result failure is recoverable
> failure and throwing exceptions is unrecoverable (i.e. abort and rollback)
> failure for some given operation.
>
So the type that is for people who don't want to throw is... the one that
you want `::value` to throw. How does that make any sense at all? The type
for people who don't want exceptions should not throw on `::value`. And
you've been arguing that `expected::value` shouldn't throw.
Therefore, people who don't want exceptions will use *that*.
> AFIO, and the stuff based on it, uses this exact pattern.
>
> Expected is for people who are writing program logic in a functional
> style, as it would appear you are looking for.
>
I'm not a functional programmer by nature, and I don't know a whole lot
about the functional model. But as I understood it, this:
auto val = some_operation().value();
is more functional in style than:
auto exp_val = some_operation();
if(!exp_val)
{
throw appropriate_exception(exp_val.error(), other, stuff);
}
The latter is what I want to essentially *enforce*, by making the exception
thrown by the former style a program logic error.
> Your preferred use case and thus preferred design can be satisfied happily
> by Expected. Meanwhile there is a ton of people who want a Result type
> design. The Boost peer review conclusion was unambiguous on that point at
> least. Neither design precludes the other, if anything having two
> countervailing designs better clarifies what makes each the best at its
> particular role.
>
The problem I have is exactly what I said: who is enforcing their exception
desires upon whom.
In the world I want, where `::value` throwing is considered a logic error
rather than an expected part of your function's interface, the final
decision about how the nature of what is thrown will default to the user.
The user *must* make that decision, since there is no default.
In the world you want, you want the default to be *used*. You expect the
default to be used. Oh sure, you still allow the user to provide an
alternative if their particular circumstances allow it. But your
expectation with `result` is that the user will just snatch a value out of
it or throw the error code.
I do not want to encourage programming of that style. I do not believe that
it leads to good interfaces. If someone wants to throw that object, they
should have to explicitly ask to do so, not have it be an implicit
side-effect.
So give `expected` a `value_or_throw` that throws the error code, with some
specialization for specific error types. This puts the decision in the
hands of the correct party: the person receiving the variant-error, not the
person providing it.
--
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/0e9031e4-a1b9-4c38-989c-211ea27cbec1%40isocpp.org.
------=_Part_2725_1799012844.1502492931993
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr">On Thursday, August 10, 2017 at 8:40:57 PM UTC-4, Niall Do=
uglas wrote:<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"><div>My point is no=
t that having access to the error code is bad. My point is that having acce=
ss to <i>just</i> the error_code is bad, that throwing the error_code <i>al=
one</i> is a bad exception. </div></div></blockquote><div><br></div><div>It=
is no different to throwing some third party subclass of std::exception. C=
ode in main() can only catch(std::exception). All that "context" =
you think so important is exactly as lossy as with std::error_code. Or exac=
tly as retainable. There is no difference here. These are all strawman argu=
ments.</div></div></blockquote><div><br>First, that's not what "st=
rawman" means. A "strawman" argument is what happens when yo=
u set up a position that <i>pretends</i> to be your opponent's position=
, then argue against that position rather than your opponent's actual p=
osition.<br><br>My position is that throwing error codes by themselves is n=
ot something that users should do, that it leads to bad interfaces, and we =
shouldn't encourage such exception interfaces.<br><br>Your argument aga=
inst this was to suggest that I was arguing that we should be constantly tr=
anslating exceptions at every layer of our program. That's what made it=
a "strawman"; it's not the position I was arguing.<br><br>Yo=
ur position is that throwing <i>just</i> error codes is a good exception in=
terface. And that's what I'm arguing against. Therefore, I'm no=
t putting forth a strawman.<br><br>Second, you <i>cannot</i> throw `std::ex=
ception`; it's a pure-virtual class. So the class that was actually thr=
own was something derived from it. And therefore, it is at least theoretica=
lly possible for `main` to have access to the actual class you threw. If th=
e exception type contained useful context information, it is therefore poss=
ible for the eventual catcher to consume that information.<br><br>If `main`=
only catches `std::exception`, it still remains possible for `main` to hav=
e caught something with more context information. And therefore, the user w=
ho is catching `std::exception` is giving up that context information <i>by=
choice</i>.<br><br>By the choice of the one who is resolving the error, no=
t the choice of the one who is sending it.<br><br>By contrast, if you throw=
a `system_error`, the receiver has exactly 3 things: the error code, the e=
rror category, and a string. Unless that string encoded context information=
, the receiver of that error has no context information about the exception=
..<br><br>With a context-rich exception interface, the receiver only loses i=
nformation by their choice. In a `system_error` throwing world, the receive=
r has no choice about losing that state.<br><br>So there's a 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><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>=
The error_code is (potentially) necessary, but <i>not sufficient</i> for no=
n-local error handling. As such, if all you have is `result<T, error_cod=
e>`, throwing that error_code is a bad exception interface. You should a=
lways wrap it in something that has an actual interface and useful state, i=
f possible (the thread system doesn't really have "useful state&qu=
ot; that it can package, which is why it uses `system_error` directly. Sadl=
y, they didn't give it its own exception type).<br></div></div></blockq=
uote><div><br></div><div>I have never at any stage said that one should thr=
ow error_code. The correct way, as intended by the C++ standard, that error=
_code should be represented in the C++ exception handling system is via bei=
ng wrapped into std::system_error.</div></div></blockquote><div><br>Semanti=
cs.<br><br>`system_error` contains only an `error_code` and a string. And i=
n the case of what `result<T, error_code>` would throw, that string w=
ill be completely devoid of useful context information. So my point stands:=
`result<T, error_code>::value` will throw an exception that is devoi=
d of context information.<br><br>That you're technically throwing `std:=
:system_error` is an implementation detail. What matters is that the only i=
nformation the receiving end gets is an `error_code`.<br>=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>You claim that=
sending error_code up the exception throw chain is a bad exception interfa=
ce. It's exactly the same as throwing some third party exception type w=
hich main() catch clauses can only resolve to a std::exception. No differen=
ce.</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><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 want instead for an additional Result type to implement throwi=
ng value observers with clearly defined rules because the choice of type E =
is severely constrained. If the programmer choose Result, they get exactly =
the throwing behaviours guaranteed. They cannot supply a type E which does =
not produce those guaranteed throwing behaviours, because it won't comp=
ile.</div></div></blockquote><div><br>And I don't believe that we shoul=
d have a variant-error type that throws the error_code. Or more to the poin=
t, we shouldn't have a variant-error type where the error part is a thi=
ng which is a complete enough object that throwing it constitutes a reasona=
ble exception interface.<br></div></div></blockquote><div><br></div><div>Th=
rowing std::system_error(expected::<wbr>error()) is far more useful than th=
rowing bad_expected_access<error_<wbr>code>(expected::error()). Which=
is why Result does that, and Expected should throw nothing so the static a=
nd runtime UB tooling can catch it. Logic errors should never be represente=
d as recoverable exception throws. Very bad.</div></div></blockquote><div><=
br>I'm with Ville Voutilainen on logic errors; there is no reason for u=
s to deny people the ability to recover from them if they so desire.<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><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>Variant-=
error types, <a href=3D"https://11080372623597421729.googlegroups.com/attac=
h/a8bf61b2beb10bec/Survey%20of%20Error%20Handling.html?part=3D0.1&view=
=3D1&vt=3DANaJVrEuWdkMEUHVl8Qrbf1xMKzGZNqSxVVbv4u_1_5wbflNpDWuaY1LV97Aa=
ez-XDfJ_Gzes8TlZWzNRZxKt1XgGBIawBy0ANkQYqmXalrOk72eWQd7jTQ" rel=3D"nofollow=
" target=3D"_blank" onmousedown=3D"this.href=3D'https://110803726235974=
21729.googlegroups.com/attach/a8bf61b2beb10bec/Survey%20of%20Error%20Handli=
ng.html?part\x3d0.1\x26view\x3d1\x26vt\x3dANaJVrEuWdkMEUHVl8Qrbf1xMKzGZNqSx=
VVbv4u_1_5wbflNpDWuaY1LV97Aaez-XDfJ_Gzes8TlZWzNRZxKt1XgGBIawBy0ANkQYqmXalrO=
k72eWQd7jTQ';return true;" onclick=3D"this.href=3D'https://11080372=
623597421729.googlegroups.com/attach/a8bf61b2beb10bec/Survey%20of%20Error%2=
0Handling.html?part\x3d0.1\x26view\x3d1\x26vt\x3dANaJVrEuWdkMEUHVl8Qrbf1xMK=
zGZNqSxVVbv4u_1_5wbflNpDWuaY1LV97Aaez-XDfJ_Gzes8TlZWzNRZxKt1XgGBIawBy0ANkQY=
qmXalrOk72eWQd7jTQ';return true;">to me</a>, are for <i>local</i> error=
processing.</div></div></blockquote><div><br></div><div>That may be the ca=
se for you personally. But hundreds of millions of lines of C code which wo=
rk directly with C errno would prove you wrong.</div></div></blockquote><di=
v><br>I was talking about variant-error types as return values. `std::errno=
` is not a return value. So how does that statement even follow from what I=
said?<br><br>Admittedly, the survey I linked was an older, less complete v=
ersion. <a href=3D"https://github.com/NicolBolas/Proposal-Ideas/blob/master=
/older/Survey of Error Handling.md">A more complete one is here</a>. In tha=
t taxonomy, `std::errno` is an out-of-band reporting system. Such systems w=
ork best for non-local error processing. It is nothing at all like return v=
alues, since you have to explicitly query them. Indeed, the primary point o=
f out-of-band errors is that you can check them later, in non-local context=
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>It's a perfectly valid design to propagate error_code throughou=
t the program. Indeed quite a few over at SG14 low latency are very interes=
ted in Result and Expected <i>precisely because</i>=C2=A0you can eliminate =
all C++ exception throws entirely from a large codebase and just use Result=
/Expected exclusively for all your failure handling. The Outcome library al=
so adds an outcome<T, EC, E> so you can return either a T, or an erro=
r_code, or an exception_ptr. This lets SG14 type code return exception thro=
ws caused by use of the STL without losing information, and return error co=
des with custom or system or generic domains for everything else.</div><div=
><br></div><div>Just because you don't like it doesn't mean it isn&=
#39;t very viable, even preferable, for many types of C++ program. All that=
C and POSIX code out there more than proves this.</div></div></blockquote>=
<div><br>How much an error mechanism is used should not be used to claim th=
at it is a <i>good</i> one. C has plenty of alternatives, and a lot of code=
uses `errno` because they have to (that's what the API they're usi=
ng uses), not because they want to or like it.<br><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"><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>And let's consider one mor=
e thing. Let's say that throwing a light-weight error code really is a =
good exception interface. I submit that in such cases, that decision about =
whether this is a good exception interface <i>should not</i> be made by the=
function that originally emitted the error. It is not `to/from_chars` who =
can make that determination; it is the code <i>calling</i> that function wh=
o should make the determination on whether the error_code represents a suff=
icient exception interface.<br><br>That is, a function should not be able t=
o <i>tell me</i> that throwing a `system_error` is a valid way to handle it=
s errors. That's for me to determine on a case-by-case basis. That'=
s another reason why I prefer `bad_expected_access` to throwing the error c=
ode directly. By not throwing the error code by default, it means that each=
user <i>must</i> determine for themselves how to pass it to non-local code=
if they so desire.<br></div></div></blockquote><div><br></div><div>And onc=
e again we return to why I think there is a need for both a Result and an E=
xpected, and one object will be suboptimal for everybody if it tries to str=
addle both use cases.</div><div><br></div><div>Result is for people who don=
't want to use C++ exception throws, or want a two-tier failure handlin=
g mechanism whereby Result failure is recoverable failure and throwing exce=
ptions is unrecoverable (i.e. abort and rollback) failure for some given op=
eration.</div></div></blockquote><div><br>So the type that is for people wh=
o don't want to throw is... the one that you want `::value` to throw. H=
ow does that make any sense at all? The type for people who don't want =
exceptions should not throw on `::value`. And you've been arguing that =
`expected::value` shouldn't throw.<br><br>Therefore, people who don'=
;t want exceptions will use <i>that</i>.<br>=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"><div>AFIO, and the stuff based=
on it, uses this exact pattern.</div><div><br></div><div>Expected is for p=
eople who are writing program logic in a functional style, as it would appe=
ar you are looking for.</div></div></blockquote><div><br>I'm not a func=
tional programmer by nature, and I don't know a whole lot about the fun=
ctional model. But as I understood it, this:<br><br><div style=3D"backgroun=
d-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style=
: solid; border-width: 1px; overflow-wrap: break-word;" class=3D"prettyprin=
t"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D=
"color: #008;" class=3D"styled-by-prettify">auto</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> val </span><span style=3D"color: #66=
0;" class=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> some_operation</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">().</span><span style=3D"color: #000;" class=
=3D"styled-by-prettify">value</span><span style=3D"color: #660;" class=3D"s=
tyled-by-prettify">();</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br></span></div></code></div><br>is more functional in style t=
han:<br><br><div style=3D"background-color: rgb(250, 250, 250); border-colo=
r: rgb(187, 187, 187); border-style: solid; border-width: 1px; overflow-wra=
p: break-word;" class=3D"prettyprint"><code class=3D"prettyprint"><div clas=
s=3D"subprettyprint"><span style=3D"color: #008;" class=3D"styled-by-pretti=
fy">auto</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> e=
xp_val </span><span style=3D"color: #660;" class=3D"styled-by-prettify">=3D=
</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> some_oper=
ation</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 sty=
le=3D"color: #660;" class=3D"styled-by-prettify">(!</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify">exp_val</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"style=
d-by-prettify"><br>=C2=A0 </span><span style=3D"color: #008;" class=3D"styl=
ed-by-prettify">throw</span><span style=3D"color: #000;" class=3D"styled-by=
-prettify"> appropriate_exception</span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">(</span><span style=3D"color: #000;" class=3D"style=
d-by-prettify">exp_val</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-prettif=
y">error</span><span style=3D"color: #660;" class=3D"styled-by-prettify">()=
,</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> other</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">,</span><span=
style=3D"color: #000;" class=3D"styled-by-prettify"> stuff</span><span sty=
le=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: #=
660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"><br></span></div></code></div><br>The latter is w=
hat I want to essentially <i>enforce</i>, by making the exception thrown by=
the former style a program logic error.<br>=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"><div>Your preferred use case a=
nd thus preferred design can be satisfied happily by Expected. Meanwhile th=
ere is a ton of people who want a Result type design. The Boost peer review=
conclusion was unambiguous on that point at least. Neither design preclude=
s the other, if anything having two countervailing designs better clarifies=
what makes each the best at its particular role.</div></div></blockquote><=
div><br>The problem I have is exactly what I said: who is enforcing their e=
xception desires upon whom.<br><br>In the world I want, where `::value` thr=
owing is considered a logic error rather than an expected part of your func=
tion's interface, the final decision about how the nature of what is th=
rown will default to the user. The user <i>must</i> make that decision, sin=
ce there is no default.<br><br>In the world you want, you want the default =
to be <i>used</i>. You expect the default to be used. Oh sure, you still al=
low the user to provide an alternative if their particular circumstances al=
low it. But your expectation with `result` is that the user will just snatc=
h a value out of it or throw the error code.<br><br>I do not want to encour=
age programming of that style. I do not believe that it leads to good inter=
faces. If someone wants to throw that object, they should have to explicitl=
y ask to do so, not have it be an implicit side-effect.<br><br>So give `exp=
ected` a `value_or_throw` that throws the error code, with some specializat=
ion for specific error types. This puts the decision in the hands of the co=
rrect party: the person receiving the variant-error, not the person providi=
ng it.<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/0e9031e4-a1b9-4c38-989c-211ea27cbec1%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/0e9031e4-a1b9-4c38-989c-211ea27cbec1=
%40isocpp.org</a>.<br />
------=_Part_2725_1799012844.1502492931993--
------=_Part_2724_1567423208.1502492931992--
.
Author: Niall Douglas <nialldouglas14@gmail.com>
Date: Sat, 12 Aug 2017 09:06:16 -0700 (PDT)
Raw View
------=_Part_3281_779356892.1502553976852
Content-Type: multipart/alternative;
boundary="----=_Part_3282_760748993.1502553976853"
------=_Part_3282_760748993.1502553976853
Content-Type: text/plain; charset="UTF-8"
>
>
> Second, you *cannot* throw `std::exception`; it's a pure-virtual class.
>
I've never seen it be pure virtual in any implementation I've seen.
> So the class that was actually thrown was something derived from it. And
> therefore, it is at least theoretically possible for `main` to have access
> to the actual class you threw. If the exception type contained useful
> context information, it is therefore possible for the eventual catcher to
> consume that information.
>
> If `main` only catches `std::exception`, it still remains possible for
> `main` to have caught something with more context information. And
> therefore, the user who is catching `std::exception` is giving up that
> context information *by choice*.
>
> By the choice of the one who is resolving the error, not the choice of the
> one who is sending it.
>
> By contrast, if you throw a `system_error`, the receiver has exactly 3
> things: the error code, the error category, and a string. Unless that
> string encoded context information, the receiver of that error has no
> context information about the exception.
>
> With a context-rich exception interface, the receiver only loses
> information by their choice. In a `system_error` throwing world, the
> receiver has no choice about losing that state.
>
> So there's a difference.
>
I have absolutely no idea what you're talking about.
Almost all of the STL exception types map exactly onto std::errc and can be
fully represented by std::errc right down to identical message text. There
is zero "context information loss" with STL exception type throws.
For custom subclasses of std::exception, it is exactly analogous to custom
error categories. Zero "context information loss".
The only final remaining difference is in payload, custom subclasses of
std::exception might contain additional payload. But as I've repeated
several times by now, to recognise additional payload requires the
main-level code to explicitly trap the subclassed type, and therefore it
needs to know of that subclassed type. And if it knows all that, when
catching a system error it can simply catch a subclass of system error
which contains additional payload.
The STL *already does this*. filesystem_error which carries payload which
you've already mentioned several times itself subclasses std::system_error,
adding payload. It is exactly a demonstration of why your argument makes no
sense as the STL is *already throwing error codes* and this design pattern
is precisely the one already in use by the STL.
You are free of course to say that this should not be so. But the ship has
sailed on that design decision. It's established practice, and Result
follows that established idiom exactly. When error_code needs to enter the
C++ exception throw mechanism, it gets wrapped into a std::system_error.
std::system_error may be subclassed with payload if that is felt
appropriate.
>
>
> It's a perfectly valid design to propagate error_code throughout the
>> program. Indeed quite a few over at SG14 low latency are very interested in
>> Result and Expected *precisely because* you can eliminate all C++
>> exception throws entirely from a large codebase and just use
>> Result/Expected exclusively for all your failure handling. The Outcome
>> library also adds an outcome<T, EC, E> so you can return either a T, or an
>> error_code, or an exception_ptr. This lets SG14 type code return exception
>> throws caused by use of the STL without losing information, and return
>> error codes with custom or system or generic domains for everything else.
>>
>> Just because you don't like it doesn't mean it isn't very viable, even
>> preferable, for many types of C++ program. All that C and POSIX code out
>> there more than proves this.
>>
>
> How much an error mechanism is used should not be used to claim that it is
> a *good* one. C has plenty of alternatives, and a lot of code uses
> `errno` because they have to (that's what the API they're using uses), not
> because they want to or like it.
>
I keep repeating: it depends on the application. You cannot do sweeping
generalisations as to what is best for "all code". You don't know.
Meanwhile, I follow what is established practice. I don't judge if it's
good or bad, just if it's popular. As all ISO standards are supposed to do,
incidentally.
>
>
>> Result is for people who don't want to use C++ exception throws, or want
>> a two-tier failure handling mechanism whereby Result failure is recoverable
>> failure and throwing exceptions is unrecoverable (i.e. abort and rollback)
>> failure for some given operation.
>>
>
> So the type that is for people who don't want to throw is... the one that
> you want `::value` to throw. How does that make any sense at all? The type
> for people who don't want exceptions should not throw on `::value`. And
> you've been arguing that `expected::value` shouldn't throw.
>
> Therefore, people who don't want exceptions will use *that*.
>
Outcome's implementation of Result calls std::terminate if it would throw
an exception, but C++ exceptions are disabled.
One cannot require that behaviour in a C++ standardised Result as it is UB
to have C++ exceptions disabled. I believe though it can be footnoted as
implementation guidance.
Result's observers are *always* wide. No matter what. That is in keeping
with its primary use case, which is returning *surprise*.
That's also why I think Expected's observers ought to be always narrow as
it mainly returns uncertainty rather than surprise, and let the UB tooling
figure out misuse.
>
>
> In the world you want, you want the default to be *used*. You expect the
> default to be used. Oh sure, you still allow the user to provide an
> alternative if their particular circumstances allow it. But your
> expectation with `result` is that the user will just snatch a value out of
> it or throw the error code.
>
> I do not want to encourage programming of that style. I do not believe
> that it leads to good interfaces. If someone wants to throw that object,
> they should have to explicitly ask to do so, not have it be an implicit
> side-effect.
>
> It is very, very common at the layer boundary between low-level
noexcept-land and higher level to convert error code based failure into C++
exception throws. You write oodles of that code if you're at that layer.
Something which requires as little typing and effort as possible, and does
reasonably sane default behaviours is an amazing value add and time saver.
I think you ought to read though the Boost.Outcome peer review. I know it's
long, 800+ emails, but people had ideas like yours which as the discussion
progressed it became obvious that they were misplaced. There is no one
proper way to design a codebase. Nor would we want to dictate or impose,
this is C++, not Rust. There are many, equally correct and incorrect, ways
of designing a C++ program. It's on standards to facilitate existing
practice, not dictate it.
Niall
--
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/ef8b0759-58c7-40ac-8808-7df3a7490845%40isocpp.org.
------=_Part_3282_760748993.1502553976853
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
<div dir=3D"ltr"><blockquote class=3D"gmail_quote" style=3D"margin: 0;margi=
n-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir=3D"l=
tr"><div><br>Second, you <i>cannot</i> throw `std::exception`; it's a p=
ure-virtual class.</div></div></blockquote><div><br></div><div>I've nev=
er seen it be pure virtual in any implementation I've seen.</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"><=
div> So the class that was actually thrown was something derived from it. A=
nd therefore, it is at least theoretically possible for `main` to have acce=
ss to the actual class you threw. If the exception type contained useful co=
ntext information, it is therefore possible for the eventual catcher to con=
sume that information.<br><br>If `main` only catches `std::exception`, it s=
till remains possible for `main` to have caught something with more context=
information. And therefore, the user who is catching `std::exception` is g=
iving up that context information <i>by choice</i>.<br><br>By the choice of=
the one who is resolving the error, not the choice of the one who is sendi=
ng it.<br><br>By contrast, if you throw a `system_error`, the receiver has =
exactly 3 things: the error code, the error category, and a string. Unless =
that string encoded context information, the receiver of that error has no =
context information about the exception.<br><br>With a context-rich excepti=
on interface, the receiver only loses information by their choice. In a `sy=
stem_error` throwing world, the receiver has no choice about losing that st=
ate.<br><br>So there's a difference.<br></div></div></blockquote><div><=
br></div><div>I have absolutely no idea what you're talking about.</div=
><div><br></div><div>Almost all of the STL exception types map exactly onto=
std::errc and can be fully represented by std::errc right down to identica=
l message text. There is zero "context information loss" with STL=
exception type throws.</div><div><br></div><div>For custom subclasses of s=
td::exception, it is exactly analogous to custom error categories. Zero &qu=
ot;context information loss".</div><div><br></div><div>The only final =
remaining difference is in payload, custom subclasses of std::exception mig=
ht contain additional payload. But as I've repeated several times by no=
w, to recognise additional payload requires the main-level code to explicit=
ly trap the subclassed type, and therefore it needs to know of that subclas=
sed type. And if it knows all that, when catching a system error it can sim=
ply catch a subclass of system error which contains additional payload.</di=
v><div><br></div><div>The STL <i>already does this</i>. filesystem_error wh=
ich carries payload which you've already mentioned several times itself=
subclasses std::system_error, adding payload. It is exactly a demonstratio=
n of why your argument makes no sense as the STL is <i>already throwing err=
or codes</i>=C2=A0and this design pattern is precisely the one already in u=
se by the STL.</div><div><br></div><div>You are free of course to say that =
this should not be so. But the ship has sailed on that design decision. It&=
#39;s established practice, and Result follows that established idiom exact=
ly. When error_code needs to enter the C++ exception throw mechanism, it ge=
ts wrapped into a std::system_error. std::system_error may be subclassed wi=
th payload if that is felt appropriate.</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;"><div dir=3D"ltr"><div><br></div><div><br></=
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"><div>It's =
a perfectly valid design to propagate error_code throughout the program. In=
deed quite a few over at SG14 low latency are very interested in Result and=
Expected <i>precisely because</i>=C2=A0you can eliminate all C++ exception=
throws entirely from a large codebase and just use Result/Expected exclusi=
vely for all your failure handling. The Outcome library also adds an outcom=
e<T, EC, E> so you can return either a T, or an error_code, or an exc=
eption_ptr. This lets SG14 type code return exception throws caused by use =
of the STL without losing information, and return error codes with custom o=
r system or generic domains for everything else.</div><div><br></div><div>J=
ust because you don't like it doesn't mean it isn't very viable=
, even preferable, for many types of C++ program. All that C and POSIX code=
out there more than proves this.</div></div></blockquote><div><br>How much=
an error mechanism is used should not be used to claim that it is a <i>goo=
d</i> one. C has plenty of alternatives, and a lot of code uses `errno` bec=
ause they have to (that's what the API they're using uses), not bec=
ause they want to or like it.<br></div></div></blockquote><div><br></div><d=
iv>I keep repeating: it depends on the application. You cannot do sweeping =
generalisations as to what is best for "all code". You don't =
know.</div><div><br></div><div>Meanwhile, I follow what is established prac=
tice. I don't judge if it's good or bad, just if it's popular. =
As all ISO standards are supposed to do, incidentally.</div><div>=C2=A0</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><br></=
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"><div><br></div=
><div>Result is for people who don't want to use C++ exception throws, =
or want a two-tier failure handling mechanism whereby Result failure is rec=
overable failure and throwing exceptions is unrecoverable (i.e. abort and r=
ollback) failure for some given operation.</div></div></blockquote><div><br=
>So the type that is for people who don't want to throw is... the one t=
hat you want `::value` to throw. How does that make any sense at all? The t=
ype for people who don't want exceptions should not throw on `::value`.=
And you've been arguing that `expected::value` shouldn't throw.<br=
><br>Therefore, people who don't want exceptions will use <i>that</i>.<=
br></div></div></blockquote><div><br></div><div>Outcome's implementatio=
n of Result calls std::terminate if it would throw an exception, but C++ ex=
ceptions are disabled.</div><div><br></div><div>One cannot require that beh=
aviour in a C++ standardised Result as it is UB to have C++ exceptions disa=
bled. I believe though it can be footnoted as implementation guidance.</div=
><div><br></div><div>Result's observers are <b>always</b>=C2=A0wide. No=
matter what. That is in keeping with its primary use case, which is return=
ing <b>surprise</b>.</div><div><br></div><div>That's also why I think E=
xpected's observers ought to be always narrow as it mainly returns unce=
rtainty rather than surprise, and let the UB tooling figure out misuse.</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;"><div dir=3D=
"ltr"><div><br></div><div><br>In the world you want, you want the default t=
o be <i>used</i>. You expect the default to be used. Oh sure, you still all=
ow the user to provide an alternative if their particular circumstances all=
ow it. But your expectation with `result` is that the user will just snatch=
a value out of it or throw the error code.<br><br>I do not want to encoura=
ge programming of that style. I do not believe that it leads to good interf=
aces. If someone wants to throw that object, they should have to explicitly=
ask to do so, not have it be an implicit side-effect.<br><br></div></div><=
/blockquote><div>It is very, very common at the layer boundary between low-=
level noexcept-land and higher level to convert error code based failure in=
to C++ exception throws. You write oodles of that code if you're at tha=
t layer. Something which requires as little typing and effort as possible, =
and does reasonably sane default behaviours is an amazing value add and tim=
e saver.</div><div><br></div><div>I think you ought to read though the Boos=
t.Outcome peer review. I know it's long, 800+ emails, but people had id=
eas like yours which as the discussion progressed it became obvious that th=
ey were misplaced. There is no one proper way to design a codebase. Nor wou=
ld we want to dictate or impose, this is C++, not Rust. There are many, equ=
ally correct and incorrect, ways of designing a C++ program. It's on st=
andards to facilitate existing practice, not dictate it.</div><div><br></di=
v><div>Niall</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/ef8b0759-58c7-40ac-8808-7df3a7490845%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/ef8b0759-58c7-40ac-8808-7df3a7490845=
%40isocpp.org</a>.<br />
------=_Part_3282_760748993.1502553976853--
------=_Part_3281_779356892.1502553976852--
.
Author: Ville Voutilainen <ville.voutilainen@gmail.com>
Date: Sat, 12 Aug 2017 19:35:04 +0300
Raw View
On 12 August 2017 at 19:06, Niall Douglas <nialldouglas14@gmail.com> wrote:
>>
>> Second, you cannot throw `std::exception`; it's a pure-virtual class.
>
>
> I've never seen it be pure virtual in any implementation I've seen.
std::exception isn't abstract; it's specified not to be. The claim
that you can't throw it is nonsense.
--
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/CAFk2RUadKs7s3ed%3DmrOd8ZquuKQqRekYjDX3JrmpFnX03Va3WQ%40mail.gmail.com.
.