
When noexcept? - setra
https://blog.quasardb.net/when-noexcept-2/
======
alschwalm
It is probably also worth noting that there is a good optimization opportunity
when using noexcept move constructors. std::vector::push_back has a strong
exception safety guarantee, so the normal behavior when the vector is at
capacity is to create a new buffer and copy construct each item in the vector
into it. If the copy constructor of any element throws, the original buffer is
still in a coherent state.

If the type has a move constructor that is noexcept, then each element can be
move-constructed without fear of an exception occurring. For many types, this
is vastly more efficient.

------
leeter
These are my uses for unconditional noexcept, they are not all encompassing
but they work for me, in all cases the exception guarantee of the code should
be noted:

* Code that will never throw an exception

* Code where throwing an unanticipated and therefore uncaught exception should trigger a failfast and crashing is not only the right behavior but the desired behavior. This should be the rarest of cases, but it does happen.

* Code that is called across an ABI boundary that it is not safe for an exception to cross. This is the most common case as OS callbacks fit this. This should be noexcept because having the exception propagate across exception unaware code causes bad things to happen, it's also undefined behavior to boot.

------
blub
My dream exception-related feature would be compile-time verification of
noexcept.

I don't care _what_ gets thrown, because it's in the end going to be an
std::exception (this is the part that Java messed up)

I do care if a function will throw, because it radically changes its behavior.

The problem I want to avoid is a silly function such as stoi throwing and
having the exception propagated up to main, after which the whole program
(orderly) shuts down. Right now this can be avoided only with careful
exception design and making sure all exception "escape points" to C functions,
message loops, etc are covered.

Swift I think is one of the few languages supporting this.

~~~
saurik
> I don't care what gets thrown, because it's in the end going to be an
> std::exception (this is the part that Java messed up)

I don't understand: std::exception is entirely optional (and I, for example,
never use it: I always build my own exception hierarchy; but, even though I
write my native code almost exclusively in C++, I believe it is absolutely
incorrect to expose a C++ API from a library, so you'd never know or care)
while in Java you absolutely have to implement Throwable and Exception is
actually designed well enough that most people (not me, of course ;P)
generally use it... I mean, in C++ you literally can just throw a "const char
*" and catch that.

~~~
jasonzemos
I happen to believe the inverse of all of this. Yes std::exception is
optional, but _why not_ use it to root your hierarchy? The only time I've
answered in the negative is when the project specifically required no standard
library could be used (yes, great that it's optional!). I sympathize with
C-compatible API's to simplify an interface, though it's not my first choice.
Rooting hierarchies in std::exception integrates library code safely and
consistently -- especially over time and code revision to both the library and
your end -- because at some point after specific exceptions are all missed
some `catch(std::exception)` is hit on errors from both you and the library,
and a consistent `what()` call can eventually inform the user with a message.

~~~
saurik
> I happen to believe the inverse of all of this.

I will say that I didn't provide an argument for not using std::exception, nor
was I trying to convince someone else not to do so; I was simply stating that
C++ does not require it and a lot of code doesn't use it: it sounded like the
person I was responding to was claiming that in C++ you knew everything was
eventually std::exception while that wasn't the case for Java, when the exact
opposite is actually true (that in C++ you can and often do run into cases
where an exception is just some random data type, and in Java all exceptions
fundamentally must implement Throwable as an engine constraint). I only used
the fact that I don't use it as an example of someone who doesn't. FWIW, I
actually use a lot of my code in environments where I can't use the standard
library, so even your paragraph of why you supposedly believe the opposite of
some ancillary point I wasn't trying to make you have admitted why I do what I
do is valid even to you.

> I sympathize with C-compatible API's to simplify an interface, though it's
> not my first choice.

It isn't about simplifying an interface: it is because in addition to the C++
ABI being itself fundamentally brittle (due to vtable ordering), you have to
remember that some people use libstdc++ while others are now annoyingly using
libc++ (I blame Apple, and I have absolutely no sympathy: they have ruined
what little interoperability we used to have in this ecosystem they cared
absolutely nothing for), and the ABIs between popular compilers is different;
so when someone uses a C++ interface for their library I spend the next three
days cursing their name and adding them to my "never let this person program
anything ever again" list while I waste my time pulling crazy stunts to
dynamically look up mangled symbol names and working around egregious
incompatibilities in basic things like "when a C++ member function returns a
structure, MinGW puts the hidden structure return pointer first while MSVC
puts it after the hidden this pointer".

At this point I know the ABI of every major compiler on every major
architecture, and I have been considering switching entirely to gcc and
contributing a ton of patches that let me #pragma mark entire regions of code
(due to header files) with specific calling conventions and layout ABIs, as
this attitude that C++ is somehow appropriate for this purpose is creeping
into more and more places as C++11 has caused more and more people to start
using C++ without understanding its limits :/.

------
praptak
There is also the nuclear option of telling the compiler not to use exceptions
at all: -fno-exceptions.

In the 3+ years I'm working in C++ without exceptions, I haven't missed them
once.

~~~
lmm
Do you do RAII? It effectively forces exceptions, because nontrivial
initialization necessarily means the possibility of failure, but exceptions
are the only mechanism available for constructors to report failure (well,
except for even worse things like an errno-like global variable).

~~~
cmrdporcupine
I've gotten in the habit of doing "RAII"-like as:

    
    
      - basic non-throwing initialization only constructor
      - a "bool Initialize" method which does what the constructor would have done, but returns false on fail
      - destructor as usual to clean up
    

But this is because I'm at Google where exceptions-are-no.

~~~
brandmeyer
GOOG is a big company, and not everyone handles this the same way. At least
some teams are doing what the sibling mentioned: A static factory-like method
that returns a discriminated union of either T or an error type. It is
_conceptually_ similar to std::variant<T, std::error_condition>, but
syntactically optimized for this use case.

~~~
praptak
Google has StatusOr<T> for this purpose:
[https://github.com/google/protobuf/blob/master/src/google/pr...](https://github.com/google/protobuf/blob/master/src/google/protobuf/stubs/statusor.h)

~~~
brandmeyer
Yep, that's the one.

------
makecheck
The entire concept of an unending exception chain seems flawed to me, and
having to carefully annotate or check everywhere is still error-prone for
programmers.

It ought to be possible to create impenetrable exception boundaries, such as:

\- A compilation unit / file.

\- Something identified as a “library” (perhaps based on namespace).

\- The program itself.

If I want my “library” to automatically trap all exceptions that I throw, I
should be able to. I shouldn’t have to worry that _entire programs may crash_
because of mistakes from exceptions. Similarly, a programmer should be able to
say, ONCE (regardless of any functions added in the future), “trap all
exceptions from code in this file using this function” and be done with it.

And, if the language had been designed with this kind of visibility into
exceptions, one would also have more useful information at the time they are
trapped. For instance, obviously exceptions propagating all the way to main()
have very little useful context but knowing that an exception is trapped in a
_file scope_ would be huge for debugging.

~~~
wvenable
> I shouldn’t have to worry that entire programs may crash because of mistakes
> from exceptions.

Why? This is the best possible outcome. Continuing to run is the worst
possible outcome from a correctness, security, and stability perspective. I
can't imagine more of an anti-feature.

~~~
coezbek
Haha, tell that to the user who did not get his work saved because the
programming language terminates the program. All because the programmer made a
mistake of defining code noexcept when in reality an exception was thrown.

noexcept is a bullshit feature if you care about stability

~~~
gpderetta
An assertion failure or unhandled exception is the last of your worries:
segfaults, external kills, power loss, etc are all more likely.

A program that loses user data on a crash (any crash), is just not designed
for reliability, period.

A reliable program will probably use transactional storage and periodic
checkpoints.

Look-up "crash only software".

------
pjc50
They _still_ made it a runtime failure rather than a compile-time enforcement
of no exceptions? What is the point of that?

~~~
maxlybbert
One of the ground rules for the old exception specifications was that it had
to be possible to link code compiled at different times. Which meant that
there might never be a moment when the compiler had access to all the source
code. And, given that most code did not have exception specifications, the
only way to enforce them at compile time would have been to require them on
all functions.

I didn't follow the development of noexcept, so I can only guess at the
motives. By and large, there were three complaints about exception
specifications that I am familiar with: (1) by requiring stack unwinding when
a no-throw specification was violated, they often caused worse performance
(or, at least, didn't allow an optimization opportunity); (2) generally, the
important question is whether a function might throw, not which exceptions it
might throw; and (3) the rules around when exception specifications affect a
function's signature -- e.g., does a pointer to a function have to match the
specification exactly? -- were convoluted. I think it was reasonable for the
Committee to focus on those issues.

~~~
gpderetta
A possible solution would have been optional static enforcement of exception
specifications plus fallback on the existing dynamic enforcement.

Existing unmarked functions would be expeced to possibly throw everything,
while functions with throw specifications would be statically checked.

You can call the later from the former, but to do the reverse you need an
explicit try/catch. Some form of throw(auto) would enable automatic deduction
of exception specifications for e.g. template code.

Dyanamic exception specifications will be removed fron the language in c++17,
so the synax is open to be reused for such a feature in the future.

~~~
palunon
The problem is C code. You know it won't throw, but there will never be any
exception specification on it.

------
jeffinhat
noexcept is a messier than const because it's not straightforward to assess if
code you rely on should be throwing or not since that's an implementation
detail versus a contract around data ownership. This makes maintenance hard as
implementations change.

It'd be nice to see compilers infer the exception behavior themselves and do
these optimizations when appropriate.

