How on earth did noexcept get through the standards process?

325 views
Skip to first unread message

Andrew

unread,
Mar 14, 2011, 2:17:04 PM3/14/11
to

I have just come across the new noexcept feature and I am horrified.

Once upon a time I was very keen indeed on full statically checked
exception specifications. And by that I mean full proper checks, not
the weedy kind that will be deprecated. I proposed this in a
discussion paper, way back in 2001. See
http://www.andrewpetermarlow.co.uk/goodies/proposal.pdf.
Writing this paper made me think about the issue alot and eventually I
withdrew the proposal.

As I came to see it, there were just too many difficulties and not
enough benefit. The main difficulty is that when using such exception
speciifcations, exceptions become single level propagation. They also
have extremely limited use in the presence of templates, which makes
them unsuitable for many parts of the standard library. Since those
days I entered the world of java and my experiences there just confirm
the conclusion I came to. I think Bruce Eckel sums it up very well in
his article http://www.mindview.net/Etc/Discussions/CheckedExceptions
where he says that checked exceptions in java are a failed experiment.

So why on earth do we have noexcept? And given that it is there, why
are the checks not strict? It is the lack of strictness that seems to
be causing the controversy, i.e. undefined behaviour versus
std::terminate. I reckon the answer is that old chestnut, premature
optimization is the root of all evil.

Discuss!

Andrew M.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

itaj sherman

unread,
Mar 14, 2011, 7:31:13 PM3/14/11
to

On Mar 14, 8:17 pm, Andrew <marlow.and...@gmail.com> wrote:
> I have just come across the new noexcept feature and I am horrified.
>

>

> So why on earth do we have noexcept? And given that it is there, why
> are the checks not strict? It is the lack of strictness that seems to
> be causing the controversy, i.e. undefined behaviour versus
> std::terminate. I reckon the answer is that old chestnut, premature
> optimization is the root of all evil.
>
> Discuss!
>

There are two main different kinds of "exception specification" for a
function:
1) "requests" - the programmer requests the compiler to verify that
the function applies to them (in some certain defined ways at compile
and/or runtime).
2) "promises" - the programmer promises that the function applies,
allowing the compiler to assume so for whatever it does (that can help
exception safety concept checking, and optimization).

The old specifications where of the first kind, and for various
reasons many people concluded they do more harm then good (especially
for performance critical languages).
The noexcept is of the second kind. More specifically, allowing only a
yes/no specification rather than exception type specific. The
programmer promises that the function throws nothing, the compiler is
allowed to assume so for whatever it does. The implementation is also
allowed to check that if they want, but generally they don't have to
do so, so that they don't cause unnecessary runtime overhead.

If I read it right, your ex-proposal discusses specifications of the
first kind "requests", so whether incorporating noexcept isn't much
related.

itaj

Nevin :-] Liber

unread,
Mar 15, 2011, 6:37:44 AM3/15/11
to
In article <bd9d80b3-3526-41e0...@i39g2000prd.googlegroups.com>,
itaj sherman <itajs...@gmail.com> wrote:

> The noexcept is of the second kind. More specifically, allowing only a
> yes/no specification rather than exception type specific. The
> programmer promises that the function throws nothing, the compiler is
> allowed to assume so for whatever it does. The implementation is also
> allowed to check that if they want, but generally they don't have to
> do so, so that they don't cause unnecessary runtime overhead.

They have to check, and call std::terminate if an exception is thrown
from a function declared noexcept(true). See 15.5.1 in n3242 (the
latest draft) for details.

--
Nevin ":-)" Liber <mailto:ne...@eviloverlord.com> 773 961-1620

Andy Venikov

unread,
Mar 15, 2011, 6:35:55 AM3/15/11
to
On 03/14/2011 07:31 PM, itaj sherman wrote:
<snip>

> The noexcept is of the second kind. More specifically, allowing only a
> yes/no specification rather than exception type specific. The
> programmer promises that the function throws nothing, the compiler is
> allowed to assume so for whatever it does. The implementation is also
> allowed to check that if they want, but generally they don't have to
> do so, so that they don't cause unnecessary runtime overhead.

Well, actually not...
15.4.9 of the latest N3242 says that throwing from noexcept will result
in a call to std::terminate. So the compiler may not ignore noexcept()
sepcification and must insure that if any exception is trying to
propagate from noexcept function, terminate() will be called.
It smells just like throw(). Are we getting into the same quagmire?

Other than being able to test at compile time if a function was
noexcept-ed (which is yes, useful), I don't see much improvement over
throw(). Compiler will still have to insert extra code to noexcept
functions. Was that the intent?

Thanks,
Andy.


P.S. The only explanation I can think of is that the implementors came
back and said that noexcept feature will somehow perform on par with
regular functions. I guess it can be done.

Andrew

unread,
Mar 15, 2011, 6:48:02 AM3/15/11
to
On Mar 14, 11:31 pm, itaj sherman <itajsher...@gmail.com> wrote:
> On Mar 14, 8:17 pm, Andrew <marlow.and...@gmail.com> wrote:
>
> > I have just come across the new noexcept feature and I am horrified.
>
> > So why on earth do we have noexcept? And given that it is there, why
> > are the checks not strict?

> There are two main different kinds of "exception specification" for a


> function:
> 1) "requests" - the programmer requests the compiler to verify that
> the function applies to them (in some certain defined ways at compile
> and/or runtime).
> 2) "promises" - the programmer promises that the function applies,
> allowing the compiler to assume so

[snip]

> The noexcept is of the second kind.

> If I read it right, your ex-proposal discusses specifications of the


> first kind "requests", so whether incorporating noexcept isn't much
> related.

Err, yes, you're right. And I suppose that noexcept is of the second
kind partly because it is so hard to do the static check fully, I as
found out when writing my proposal.

Another thing I hadn't fully appreciated is that the implementation of
noexcept can detect the violation at the point of throwing rather than
at catch point. Detecting at the catch point would defeat the kind of
optimisation which is the whole point of noexcept. Detecting at throw
point allows stack unwinding to be optional before std::terminate is
called.

I have been thinking about noexcept because a colleague has drawn my
attention to N3248, where the issue of testing noexcept functions is
discussed. N3248 argues that when noexcept is violated it should be
undefined behaviour, rather than calling std::terminate. It is said
that UB gives the implementer of noexcept functions the freedom to
define behaviour in the case of debug mode builds such that
precondition assertion failures can be detected and handled in a unit
test harness.

My inclination is that a test harness that is trying to test that
precondition violation of noexcept functions is working properly needs
to override the default handler for std::terminate. Their handler can
integrate with their unit test framework.

Regards,

Andrew Marlow

DeMarcus

unread,
Mar 15, 2011, 6:50:35 AM3/15/11
to


With noexcept the compiler can help you provide exception guarantees. See

http://www.boost.org/community/exception_safety.html


Regards,
Daniel

itaj sherman

unread,
Mar 15, 2011, 10:34:13 PM3/15/11
to

On Mar 15, 12:48 pm, Andrew <marlow.and...@gmail.com> wrote:

>
> I have been thinking about noexcept because a colleague has drawn my
> attention to N3248, where the issue of testing noexcept functions is
> discussed. N3248 argues that when noexcept is violated it should be
> undefined behaviour, rather than calling std::terminate. It is said
> that UB gives the implementer of noexcept functions the freedom to
> define behaviour in the case of debug mode builds such that
> precondition assertion failures can be detected and handled in a unit
> test harness.
>

Core language issue 1053 2010-3 seems to be exactly about this:
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1053

it seems to have rejected the unspecified behaviour for throwing from
a noexcept function. I hope N3248 can change things now for the
better.

itaj

itaj sherman

unread,
Mar 15, 2011, 10:32:02 PM3/15/11
to

On Mar 15, 12:37 pm, "Nevin :-] Liber" <ne...@eviloverlord.com> wrote:
> In article <bd9d80b3-3526-41e0-a8bb-5c685abbf...@i39g2000prd.googlegroups.com>,

> itaj sherman <itajsher...@gmail.com> wrote:
>
>> The noexcept is of the second kind. More specifically, allowing only a
>> yes/no specification rather than exception type specific. The
>> programmer promises that the function throws nothing, the compiler is
>> allowed to assume so for whatever it does. The implementation is also
>> allowed to check that if they want, but generally they don't have to
>> do so, so that they don't cause unnecessary runtime overhead.
>
> They have to check, and call std::terminate if an exception is thrown
> from a function declared noexcept(true). See 15.5.1 in n3242 (the
> latest draft) for details.
>

OMG, I had some big misconception about noexcept. It actually does
belong to the "request" kind of exception specifications.
I can't remember now when it was that I read about this and got
convinced that this was the point of the difference between noexcept
and throw(), but it's apparantly wrong. I was so sure that was the
whole point of noexcept that I didn't even bother to check it again.

Well then, if noexcept actually does force the compiler to add runtime
checking, then I truely agree with the OP really how on earth did it
get through the standard process?

itaj


--

James Kanze

unread,
Mar 15, 2011, 10:34:07 PM3/15/11
to

On Mar 14, 11:31 pm, itaj sherman <itajsher...@gmail.com> wrote:
> On Mar 14, 8:17 pm, Andrew <marlow.and...@gmail.com> wrote:

>> I have just come across the new noexcept feature and I am horrified.

>> So why on earth do we have noexcept? And given that it is there, why
>> are the checks not strict? It is the lack of strictness that seems to
>> be causing the controversy, i.e. undefined behaviour versus
>> std::terminate. I reckon the answer is that old chestnut, premature
>> optimization is the root of all evil.

>> Discuss!

> There are two main different kinds of "exception specification" for a
> function:
> 1) "requests" - the programmer requests the compiler to verify that
> the function applies to them (in some certain defined ways at compile
> and/or runtime).
> 2) "promises" - the programmer promises that the function applies,
> allowing the compiler to assume so for whatever it does (that can help
> exception safety concept checking, and optimization).

> The old specifications where of the first kind, and for
> various reasons many people concluded they do more harm then
> good (especially for performance critical languages).

Actually, the performance impact on most platforms was zero.

> The noexcept is of the second kind. More specifically, allowing only a
> yes/no specification rather than exception type specific. The
> programmer promises that the function throws nothing, the compiler is
> allowed to assume so for whatever it does. The implementation is also
> allowed to check that if they want, but generally they don't have to
> do so, so that they don't cause unnecessary runtime overhead.

In other words, the introduce yet another case of undefined
behavior. I've not looked at them in detail, but if that's the
case, I'm against them.

The old ones actually worked pretty well. They provided perhaps
more than was needed---it's hard to think of a case where
anything other than throw() was appropriate. But at least when
you wrote throw(), you had a guarantee.

--
James Kanze

Goran

unread,
Mar 15, 2011, 10:33:46 PM3/15/11
to

On Mar 14, 7:17 pm, Andrew <marlow.and...@gmail.com> wrote:
> I have just come across the new noexcept feature and I am horrified.
>
> Once upon a time I was very keen indeed on full statically checked
> exception specifications. And by that I mean full proper checks, not
> the weedy kind that will be deprecated. I proposed this in a
> discussion paper, way back in 2001. Seehttp://www.andrewpetermarlow.co.uk/goodies/proposal.pdf.

> Writing this paper made me think about the issue alot and eventually I
> withdrew the proposal.
>
> As I came to see it, there were just too many difficulties and not
> enough benefit. The main difficulty is that when using such exception
> speciifcations, exceptions become single level propagation. They also
> have extremely limited use in the presence of templates, which makes
> them unsuitable for many parts of the standard library. Since those
> days I entered the world of java and my experiences there just confirm
> the conclusion I came to. I think Bruce Eckel sums it up very well in
> his articlehttp://www.mindview.net/Etc/Discussions/CheckedExceptions

> where he says that checked exceptions in java are a failed experiment.
>
> So why on earth do we have noexcept? And given that it is there, why
> are the checks not strict? It is the lack of strictness that seems to
> be causing the controversy, i.e. undefined behaviour versus
> std::terminate. I reckon the answer is that old chestnut, premature
> optimization is the root of all evil.

Well, I personally am +/- happy with this explanation (http://
www.codeguru.com/cpp/misc/print.php/c18357/An-Interview-with-C-Creator-Bjarne-Stroustrup.htm):

"noexcept addresses the one case where the exception specifications
sometimes worked well: simply stating that a function is not supposed
to throw. In C++98, some people express that by saying throw(), but
they can not know whether their implementation then imposed a
significant overhead (some do) and might end up executing a
(potentially unknown) unexpected handler. With noexcept a throw is
considered a fatal design error and the program immediately
terminated. That gives security and major optimization opportunities."

To me, optimization is just fine as a reason. Currently, we are (well,
I am, at least) writing sections of code that I know must never throw
(and if they do, I must fix them), and use no exception spec (boost
guys do the same, see "never throws" comments in their code). With
nothrow, I can move those into a function and reap following benefits:

* mark that "nothrow" presumption more clearly,
* benefit from optimization.

With old throw(), that wasn't possible in the same manner (albeit at
least one well-known compiler coughMScough) ignored what standard
mandated for throw().

So not all is that bad.

Goran.

itaj sherman

unread,
Mar 15, 2011, 10:33:27 PM3/15/11
to

On Mar 15, 12:48 pm, Andrew <marlow.and...@gmail.com> wrote:

>
> I have been thinking about noexcept because a colleague has drawn my
> attention to N3248, where the issue of testing noexcept functions is
> discussed. N3248 argues that when noexcept is violated it should be
> undefined behaviour, rather than calling std::terminate. It is said
> that UB gives the implementer of noexcept functions the freedom to
> define behaviour in the case of debug mode builds such that
> precondition assertion failures can be detected and handled in a unit
> test harness.
>

Yeah, what I meant is exactly what's in this N3248. For some reason I
was sure that was the current state of the standard already. Maybe the
missleading wording of 15.4/8 made me think there was this difference:

"A function is said to allow an exception of type E if its dynamic-
exception-specification contains a type T for
which a handler of type T would be a match (15.3) for an exception of
type E."

As this doesn't mention noexcept, this means that a function with
noexcept allows any exception - but the next paragraph that states
when the validation should be done, doesn't use the "function allows"
definition, but resorts to "exception specification allows".

I think this N3248 is an important change. Forcing the compiler to
test for exceptions might cause more overhead than the possible
optimizations can save. I hope it gets accepted before the standard is
concluded, otherwise it will be a backwards-compatibility nightmare to
ever change it in the future.

itaj

SG

unread,
Mar 16, 2011, 7:38:33 AM3/16/11
to

On 14 Mrz., 19:17, Andrew wrote:
> [...]

> Once upon a time I was very keen indeed on full statically checked
> exception specifications. [...]

> Writing this paper made me think about the issue alot and eventually
> I withdrew the proposal.
>
> As I came to see it, there were just too many difficulties and not
> enough benefit. The main difficulty is that when using such exception
> speciifcations, exceptions become single level propagation. They also
> have extremely limited use in the presence of templates, which makes
> them unsuitable for many parts of the standard library. [...]

>
> So why on earth do we have noexcept?

Let me get this straight. Your first paragraph basically says "static
checking is not worth the hassle". Your second paragraph says
"exception specifications are bad". Right?

Since the current incarnation of noexcept does not require any static
checking of whether a function's body *might* violate its noexcept-
specification and since your two examples about the badness of
exception specifications don't seem to apply to the new noexcept
exception specification, I don't see what exactly you are complaining
about.

> And given that it is there, why are the checks not strict?

> [...]
> Discuss!

Are you talking about static checking of the new noexcept exception
specifications? If so, I suggest you start compiling a list of pros
and cons. I would not be surprized if there was some overlap with the
list of pros and cons w.r.t. static checking of *old* exception
specifications. And the latter list obviously made you say something
along the lines of "static checking is not worth the hassle".

Cheers!
SG

itaj sherman

unread,
Mar 16, 2011, 10:42:27 AM3/16/11
to

On Mar 16, 4:34 am, James Kanze <james.ka...@gmail.com> wrote:
> On Mar 14, 11:31 pm, itaj sherman <itajsher...@gmail.com> wrote:

> > There are two main different kinds of "exception specification" for a
> > function:
> > 1) "requests" - the programmer requests the compiler to verify that
> > the function applies to them (in some certain defined ways at compile
> > and/or runtime).
> > 2) "promises" - the programmer promises that the function applies,
> > allowing the compiler to assume so for whatever it does (that can help
> > exception safety concept checking, and optimization).
> > The old specifications where of the first kind, and for
> > various reasons many people concluded they do more harm then
> > good (especially for performance critical languages).
>
> Actually, the performance impact on most platforms was zero.
>

It was?
I mean, they compared code compiled with no-throw optimizations and
runtime checks to the same code with no-throw optimizations without
checks?
Then what makes 'noexcept' better than 'throw()' wrt performance? Is
it just the fact that the compiler knows no exception can be thrown
there (no user defined std::unexcpected can throw anything else and
demand continue execution)?

Actually that makes sense. IMO, practically it still puts 'noexcept'
in what I callled 'promises' kind. I.e Instead the programmer promises
not to throw out of a noexcept function, he can do that, but he knows
the only consequence of it is that the program will end and there's
nothing he can do about it (unlike std::unexpected). These are
practically the same. I still don't see why they bothered to specify
that and not just leave it undefined - but if it doesn't hurt
performance, an important benefit of noexcept IMO, is still there.

itaj

Andrew

unread,
Mar 16, 2011, 5:46:46 PM3/16/11
to

On Mar 16, 2:34 am, itaj sherman <itajsher...@gmail.com> wrote:
> On Mar 15, 12:48 pm, Andrew <marlow.and...@gmail.com> wrote:
>> I have been thinking about noexcept because a colleague has drawn my
>> attention to N3248, where the issue of testing noexcept functions is
>> discussed. N3248 argues that when noexcept is violated it should be
>> undefined behaviour, rather than calling std::terminate. It is said
>> that UB gives the implementer of noexcept functions the freedom to
>> define behaviour in the case of debug mode builds such that
>> precondition assertion failures can be detected and handled in a unit
>> test harness.
>
> Core language issue 1053 2010-3 seems to be exactly about this:http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1053

1053 is closed as not a defect (NAD). The title of 1053 is "Terminate
vs undefined behavior for noexcept violation". Since 1053 is closed I
presume 3248 was raised to resurrect the discussion.

I think the contraversial part of 3248 is the bit where it proposes
support for a debug build mode. Until now I think the only part of the
std that talked about debug mode was the NDEBUG macro as used by the C
assert macro. 3248 would significantly expand the notion of a debug
build versus a release build. This makes me very wary.

My understanding of 3248 is that UB is proposed so that in a debug
build, a noexcept violation can allow an exception to propagate so
that it can be caught and handled by unit test machinery. This allows
tests to be constructed that test what happens when noexcept is
violated and to test that it is violated by move ctors that invoke
throwing operations. I am not sure this is a good idea. Aaprt from
introducing the idea of debug builds into the std, I reckon the aim of
library testability in this area can be acheived another way. How
about the test harness installing its own terminate handler?

> it seems to have rejected the unspecified behaviour for throwing from
> a noexcept function. I hope N3248 can change things now for the
> better.
>
> itaj

I don't see how 3248 changes things for the better. I think that
calling std::terminate instead of it being UB does not inhibit
testing, since the test harness can set its own terminate handler.
Bear in mind that the motivation of 3248 is for library testability.
It is not about performance optimisations. Noexcept is all about
optimisation, as 3248 says:-

"This solution [noexcept] also opens up a long desired optimization
for compilers to exploit, where marking a function that cannot throw
allows the suppression of code to handle exceptional stack unwinding".

So 3248 is not, AFAICS, proposing something that further aids
optimisation. That's not what 3248 is for.

I found other N-items such as 3180 which propose much more extensive
use of noexcept. 3248 seems to be advocating the opposite, as it says:
"The risk from overly aggressive use of noexcept specifications is
that programs with hidden terminate calls are produced". Surely the
implementers of std libraries must have something to say about this. I
wonder what Dinkumware thinks. And the authors of STLPort. I don't
know how Dinkumware, STLPort and any others plan to test this aspect
of their std library implementations (perhaps we should ask them) but
as I have said, one way would be for the test harness to set up its
own terminate handler then invoke a noexcept function that throws.

Regards,

Andrew Marlow

Alexander Terekhov

unread,
Mar 16, 2011, 5:46:18 PM3/16/11
to

Andrew wrote:
[...]


> So why on earth do we have noexcept?

I suppose that the plan is to have noexcept_except() in the next
iteration: The general idea is that an unexpected/uncaught throw will
cause program termination at throw point with core dump recorded at
that point as well. The current noexcept makes all uncaught
downthrows unexpected but that may well be relaxed in the future by
noexcept_except() or some such. (A program calling
noexcept_except(E) may well catch and handle E upcall.)

regards,
alexander.

DeMarcus

unread,
Mar 16, 2011, 5:45:54 PM3/16/11
to

I read the N3248 paper and believe the most clean solution would be something similar to std::atexit.

Create a function std::atnothrow( std::function<void()> ) that will be run whenever a nothrow is violated. The default behavior at violation is std::terminate.

The function taken as argument to std::atnothrow should be an exception handler or exception dispatcher. See

http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.15


Now anyone can override default behavior by doing the following.

std::atnothrow( myNothrowHandler );

static void myNothrowHandler()
{
// Allow any exception.
throw;
}

... or ...

static void myNothrowHandler()
{
// Allow only my logic errors.
try
{
throw;
}
catch( MyLogicErrorException& )
{
throw;
}

std::terminate();
}


/ Daniel

itaj sherman

unread,
Mar 16, 2011, 5:44:35 PM3/16/11
to

On Mar 15, 1:31 am, itaj sherman <itajsher...@gmail.com> wrote:
>> Discuss!
>
> There are two main different kinds of "exception specification" for a
> function:
> 1) "requests" - the programmer requests the compiler to verify that
> the function applies to them (in some certain defined ways at compile
> and/or runtime).
> 2) "promises" - the programmer promises that the function applies,
> allowing the compiler to assume so for whatever it does (that can help
> exception safety concept checking, and optimization).
>

To sum up what everyone corrected about my post:

There are actually 3 kinds:

0) "check and continue" - when a violation of the specification
occurs, the programmer can define a valid way to continue the
execution (in std::unexpected), which can actually be throwing an
exception. That means no-throw optimizations cannot be done at all.
1) "check and die" - when a violation of the specification occurs the
program dies immediately. this forces runtime checks but still allows
no-throw optimizations.
2) "no check" - when a violation of the specification occurs the
behaviour is undefined. this allows no-throw optimizations with no
runtime checks.

'no check' is like my original 'promises'.
'check and continue' and 'check and die' are the important parting if
my original 'requests'.
The point seems to be that the big performance difference is
practically between 'check and continue' and 'check and die'.

So the old 'dynamic-specifications' are of kind 'check and continue',
while 'noexcept' is in 'check and die'.
Core issue 1053 was about moving 'noexcept' further into 'no check'.

Martin B.

unread,
Mar 16, 2011, 6:11:34 PM3/16/11
to

On 16.03.2011 15:42, itaj sherman wrote:
>
> On Mar 16, 4:34 am, James Kanze<james.ka...@gmail.com> wrote:
>> On Mar 14, 11:31 pm, itaj sherman<itajsher...@gmail.com> wrote:
>
>>> There are two main different kinds of "exception specification" for a
>>> function:
>>> 1) "requests" - the programmer requests the compiler to verify that
>>> the function applies to them (in some certain defined ways at compile
>>> and/or runtime).
>>> 2) "promises" - the programmer promises that the function applies,
>>> allowing the compiler to assume so for whatever it does (that can help
>>> exception safety concept checking, and optimization).
>>> The old specifications where of the first kind, and for
>>> various reasons many people concluded they do more harm then
>>> good (especially for performance critical languages).
>>
>> Actually, the performance impact on most platforms was zero.
>>
>
> It was?
> I mean, they compared code compiled with no-throw optimizations and
> runtime checks to the same code with no-throw optimizations without
> checks?
> Then what makes 'noexcept' better than 'throw()' wrt performance? Is
> it just the fact that the compiler knows no exception can be thrown
> there (no user defined std::unexcpected can throw anything else and
> demand continue execution)?
>

As far as I understood it the last time I tried to follow the `noexcept` discussion, the difference is with stack unwinding:
`throw()` needs stack unwinding, wheres `noexcept` doesn't, which somehow makes a big difference.

cheers,
Martin

DeMarcus

unread,
Mar 17, 2011, 7:13:29 AM3/17/11
to
On 2011-03-16 22:44, itaj sherman wrote:
>
> On Mar 15, 1:31 am, itaj sherman<itajsher...@gmail.com> wrote:
>>> Discuss!
>>
>> There are two main different kinds of "exception specification" for a
>> function:
>> 1) "requests" - the programmer requests the compiler to verify that
>> the function applies to them (in some certain defined ways at compile
>> and/or runtime).
>> 2) "promises" - the programmer promises that the function applies,
>> allowing the compiler to assume so for whatever it does (that can help
>> exception safety concept checking, and optimization).
>>
>
> To sum up what everyone corrected about my post:
>
> There are actually 3 kinds:
>
> 0) "check and continue" - when a violation of the specification
> occurs, the programmer can define a valid way to continue the
> execution (in std::unexpected), which can actually be throwing an
> exception. That means no-throw optimizations cannot be done at all.
> 1) "check and die" - when a violation of the specification occurs the
> program dies immediately. this forces runtime checks but still allows
> no-throw optimizations.
> 2) "no check" - when a violation of the specification occurs the
> behaviour is undefined. this allows no-throw optimizations with no
> runtime checks.
>

I don't understand the difference between 0) and 1). In 0) the user can
provide an unexpected handler with std::set_unexpected but in 1) the
user can also provide a handler with std::set_terminate.

Why can 1) do no-throw optimizations but not 0) ?


Thanks,
Daniel

Goran

unread,
Mar 17, 2011, 9:16:15 AM3/17/11
to

On Mar 16, 11:11 pm, "Martin B." <0xCDCDC...@gmx.at> wrote:
> As far as I understood it the last time I tried to follow the `noexcept` discussion,
> the difference is with stack unwinding:
> `throw()` needs stack unwinding, wheres `noexcept` doesn't, which somehow makes a big difference.

That was my understanding, too. ( "Big" in "makes a big difference" is
a big word, though ;-) ).

I find the "OK, but what when noexcept does throw?" question over the
top. UB, end of, what's wrong with that!? There's too many UBs and
gotchas in C and C++ anyhow, and they are already much more surprising
than this one would IMO be. Even the call to std::terminate is too
much there.

Goran.

itaj sherman

unread,
Mar 18, 2011, 4:05:44 AM3/18/11
to

The handler for terminate (default and user) must terminate the
program and never return 18.8.3 (this also means not throw).
So 'noexcept' clearly allows for no-throw optimizations.
As for unexpected, it can actually only throw an exception that is
listed in the dynamic specification 15.4/10. I think it means that
'thow()' also belongs to kind 1 'check and die', and does allow no-
throw optimizations.
It seems that currently 'noexcept' is only better than 'throw()' by
allowing the code to check whether a function is 'noexcept'.

itaj

itaj sherman

unread,
Mar 18, 2011, 4:06:56 AM3/18/11
to
On Mar 17, 3:16 pm, Goran <goran.pu...@gmail.com> wrote:
> On Mar 16, 11:11 pm, "Martin B." <0xCDCDC...@gmx.at> wrote:
>
> > As far as I understood it the last time I tried to follow the `noexcept` discussion,
> > the difference is with stack unwinding:
> > `throw()` needs stack unwinding, wheres `noexcept` doesn't, which somehow makes a big difference.
>
> That was my understanding, too. ( "Big" in "makes a big difference" is
> a big word, though ;-) ).

Does seem so.
http://groups.google.com/group/comp.std.c++/browse_frm/thread/82cd3599ce330676/d41f0839f6d54e5e?q=throw+noexcept+group:comp.*.c%2B%2B*

I didn't get into all the details, but it seems it's mainly
optimizations in the callee (inside the noexcept function) that
benefit from this difference.

>
> I find the "OK, but what when noexcept does throw?" question over the
> top. UB, end of, what's wrong with that!? There's too many UBs and
> gotchas in C and C++ anyhow, and they are already much more surprising
> than this one would IMO be. Even the call to std::terminate is too
> much there.
>

Yeah, this UB would be pretty much straightforward and simple to
understand comparing to many others. I don't see why they need to go
ahead and restrict it for everyone, rather than leave it
implementation defined.

itaj

Agents Marlow

unread,
Mar 18, 2011, 4:10:10 AM3/18/11
to
On Mar 17, 1:16 pm, Goran <goran.pu...@gmail.com> wrote:
> On Mar 16, 11:11 pm, "Martin B." <0xCDCDC...@gmx.at> wrote:
>
> > As far as I understood it the last time I tried to follow the `noexcept` discussion,
> > the difference is with stack unwinding:
> > `throw()` needs stack unwinding, wheres `noexcept` doesn't, which somehow makes a big difference.
>
> That was my understanding, too. ( "Big" in "makes a big difference" is
> a big word, though ;-) ).

I think the point is that noexcept violations are detected and handled
at throw time, saving a stack unwind. throw() violations are detected
at catch time before the function exits, so this is after a stack
unwind has occurred.

> I find the "OK, but what when noexcept does throw?" question over the
> top. UB, end of, what's wrong with that!?

Plenty. It's asymmetric with other contract violations, such as
throw() violations (unexpected) and throwing whilst handling an
exception in progress (terminate). In these cases behaviour is defined
so IMO it should be defined here also. I am in the std::terminate camp
for noexcept violations.

> There's too many UBs and gotchas in C and C++ anyhow,

Indeed, so we do not want to add to the evil thereof.

-Andrew M.

itaj sherman

unread,
Mar 18, 2011, 7:49:46 PM3/18/11
to

And that it is not strict about when and whether stack unwind should
be done (which has been explained to be a cause for performance)

http://groups.google.com/group/comp.std.c++/browse_frm/thread/82cd3599ce330676/d41f0839f6d54e5e?q=throw+noexcept+group:comp.*.c%2B%2B*

James Kanze

unread,
Mar 21, 2011, 12:36:05 AM3/21/11
to
On Mar 16, 2:42 pm, itaj sherman <itajsher...@gmail.com> wrote:
> On Mar 16, 4:34 am, James Kanze <james.ka...@gmail.com> wrote:

> > On Mar 14, 11:31 pm, itaj sherman <itajsher...@gmail.com> wrote:
> > > There are two main different kinds of "exception specification" for a
> > > function:
> > > 1) "requests" - the programmer requests the compiler to verify that
> > > the function applies to them (in some certain defined ways at compile
> > > and/or runtime).
> > > 2) "promises" - the programmer promises that the function applies,
> > > allowing the compiler to assume so for whatever it does (that can help
> > > exception safety concept checking, and optimization).
> > > The old specifications where of the first kind, and for
> > > various reasons many people concluded they do more harm then
> > > good (especially for performance critical languages).

> > Actually, the performance impact on most platforms was zero.

> It was?
> I mean, they compared code compiled with no-throw optimizations and
> runtime checks to the same code with no-throw optimizations without
> checks?

I mean, I compared code with no exception specifications with
code which had exception specifications, and found no
difference.

> Then what makes 'noexcept' better than 'throw()' wrt performance? Is
> it just the fact that the compiler knows no exception can be thrown
> there (no user defined std::unexcpected can throw anything else and
> demand continue execution)?

I don't know. If 'noexcept' gives the same guarantees as
throw(), then I don't see why it's better. About the only real
difference I see is that 'throw()' gives you the option to
specify some exceptions which might pass (and I can imagine that
causes a small performance loss in some special cases), and
noexcept doesn't.

> Actually that makes sense. IMO, practically it still puts 'noexcept'
> in what I callled 'promises' kind.

Both exception specifications (in C++) and noexcept are a
specification of a contract. It's up to the programmer to
respect the contract, or bad things will happen. Other
languages have tried to ensure statically that the contract was
respected, but in practice, that doesn't work too well; regard
the mess Java made of it.

> I.e Instead the programmer promises
> not to throw out of a noexcept function, he can do that, but he knows
> the only consequence of it is that the program will end and there's
> nothing he can do about it (unlike std::unexpected).

You can replaced std::terminate with your own function, and a
programmer wasn't allowed to do much except call std::terminate
in std::unexpected. (He could throw some other exception, which
was allowed, but in the case of 'throw()', no such other
exception exists. Otherwise, he must call terminate.)

> These are practically the same. I still don't see why they
> bothered to specify that and not just leave it undefined - but
> if it doesn't hurt performance, an important benefit of
> noexcept IMO, is still there.

Leave what undefined? (I've not read up on nothrow: if it
doesn't behave exactly like 'throw()', then I'm against it,
since the final behavior in the case of exception specifications
is one thing they got right---even if they aren't too useful
except when empty.)

--
James

James Kanze

unread,
Mar 21, 2011, 12:36:28 AM3/21/11
to
On Mar 16, 10:11 pm, "Martin B." <0xCDCDC...@gmx.at> wrote:
> On 16.03.2011 15:42, itaj sherman wrote:

[...]


> As far as I understood it the last time I tried to follow the
> `noexcept` discussion, the difference is with stack unwinding:
> `throw()` needs stack unwinding, wheres `noexcept` doesn't,
> which somehow makes a big difference.

As far as I understand it (and I've confirmed it with actual
benchmarks with Sun CC under Solaris), stack unwinding only has
a cost if you throw an exception, Not an issue with
noexcept/throw(), since if you throw an exception, you're hosed
anyway. (After all, you promessed not to.)

--
James Kanze

CornedBee

unread,
Mar 21, 2011, 12:32:54 AM3/21/11
to
On Mar 18, 9:05 am, itaj sherman <itajsher...@gmail.com> wrote:
> It seems that currently 'noexcept' is only better than 'throw()' by
> allowing the code to check whether a function is 'noexcept'.

Well, a throw() specification is a "non-throwing specification" as
well, so the noexcept() operator would recognize such a function as
non-throwing.

No, the big advantage of the noexcept specification is that it allows
a compile-time expression as an argument, which makes it useful in
templates such as std::pair (much more useful than throw()).

Also, for Itanium ABI architectures, the code generated for a noexcept
specification is far simpler than for a throw() specification.

Sebastian

Dragan Milenkovic

unread,
Mar 21, 2011, 12:33:51 AM3/21/11
to

Well, I want my core dump in case of a noexcept function throwing
instead of UB (unless my compiler vendor implements this UB
as little men going to the scene of crime and investigating
and submitting the bug report).

--
Dragan

DeMarcus

unread,
Mar 21, 2011, 8:45:15 AM3/21/11
to

Correct me if I'm wrong, but isn't there one more difference; unlike
throw(), noexcept is checked in compile-time so I get a warning or error
if a noexcept function throws?

itaj sherman

unread,
Mar 21, 2011, 11:19:08 AM3/21/11
to

On Mar 21, 6:33 am, Dragan Milenkovic <dra...@plusplus.rs> wrote:

>
> Well, I want my core dump in case of a noexcept function throwing
> instead of UB (unless my compiler vendor implements this UB
> as little men going to the scene of crime and investigating
> and submitting the bug report).
>

In debug/testing version certainly always.
In release version, I suppose usually. But, if the runtime checking
for throw violation has near zero overhead, I'm sure anyone can
imagine a situation so performance critical that he would want the
most efficient implementation possible, possibly ommitting any runtime
check. I don't see why the standard has to impose the runtime check on
all implementations rather than let then decide which option to take.

itaj


--

Felipe Magno de Almeida

unread,
Mar 24, 2011, 2:58:21 AM3/24/11
to
On Mar 21, 12:19 pm, itaj sherman <itajsher...@gmail.com> wrote:
> On Mar 21, 6:33 am, Dragan Milenkovic <dra...@plusplus.rs> wrote:

[snip]

> > Well, I want my core dump in case of a noexcept function throwing
> > instead of UB (unless my compiler vendor implements this UB
> > as little men going to the scene of crime and investigating
> > and submitting the bug report).
>
> In debug/testing version certainly always.
> In release version, I suppose usually. But, if the runtime checking
> for throw violation has near zero overhead, I'm sure anyone can
> imagine a situation so performance critical that he would want the
> most efficient implementation possible, possibly ommitting any runtime
> check. I don't see why the standard has to impose the runtime check on
> all implementations rather than let then decide which option to take.

I feel the same way. I also want a core dump in case I try to use
operator[] with an index which is beyond the vector's size. But I
wouldn't want the standard to impose this overhead to all
implementations. That's why I use a checked STL while debugging
and testing, but define NDEBUG for a few projects in release
(when I can prove that it makes a difference).

With noexcept it is even worse, because even if a function doesn't
throw and the noexcept implementation is not the best for a compiler,
I will have to not use noexcept, which might require some generic
libraries to use the copy-constructor for these types. So we will have
to test it with and without and see which is worse. This is a little
contrary to the "do not pay for what you don't use" in my opinion.
Using and not using noexcept might incur unnecessary overhead.

> itaj

Regards,
--
Felipe Magno de Almeida

ThosRTanner

unread,
Mar 25, 2011, 1:03:40 AM3/25/11
to
On Mar 14, 6:17 pm, Andrew <marlow.and...@gmail.com> wrote:
> I have just come across the new noexcept feature and I am horrified.
>
> Once upon a time I was very keen indeed on full statically checked
> exception specifications. And by that I mean full proper checks, not
> the weedy kind that will be deprecated. I proposed this in a
> discussion paper, way back in 2001. Seehttp://www.andrewpetermarlow.co.uk/goodies/proposal.pdf.
> Writing this paper made me think about the issue alot and eventually I
> withdrew the proposal.
>
(snip)

>
> So why on earth do we have noexcept? And given that it is there, why
> are the checks not strict? It is the lack of strictness that seems to
> be causing the controversy, i.e. undefined behaviour versus
> std::terminate. I reckon the answer is that old chestnut, premature
> optimization is the root of all evil.
>

Where I'm coming from, non-statically checked exception specifications
are completely useless. We can't afford a program crashing because it
threw an exception it wasn't meant to.

And this doesn't help things at all.

As far as I can see they've just dropped the ability to specify what
exceptions you think you might throw and offered no significant
benefits (apart presumably from the checking being quicker)


--

Alexander Terekhov

unread,
Mar 25, 2011, 12:00:48 PM3/25/11