Should I use throw() when implementing non-throwing swap? - c++

When implementing the non-throwing swap idiom, should I use throw()?
namespace A
{
struct B
{
void swap( B& other ) throw()
{ /* fancy stuff that doesn't throw */ }
};
void swap( B& lhs, B& rhs ) throw()
{ lhs.swap(rhs); }
}
namespace std
{
template<>
void swap( A::B& lhs, A::B& rhs ) throw()
{ lhs.swap(rhs); }
}
In particular I worry about putting the throw() specification on the specialization of std::swap.
Bonus question:
Is the answer different when using C++0x's noexcept keyword?

In C++03 you can put it there, but if it's true that the fancy stuff doesn't throw, it's basically just documentation. It may or may not affect performance by adding the equivalent of try / catch(...) { std::unexpected(); } around calls to the function: it's up to the implementation whether it can do it without affecting performance.
If you're planning to use the noexcept operator (5.3.7) in C++0x, then suddenly it becomes worth having non-throwing exception specifications, so that the operator gives the "right" answer. I don't really know what the noexcept operator is for, but if there's a clever generic use for it, for example algorithms that become more efficient when something is non-throwing, then I guess it's going to become necessary to mark functions as non-throwing, to get whatever the benefit is.
For example:
void foo() noexcept;
void bar();
template <void(*FUNC)()>
void generic_thing() {
if (noexcept(FUNC()) {
// this won't throw, perhaps we can somehow take advantage of that
FUNC();
} else {
// this might throw
FUNC();
}
}
Old style exception specifications (dynamic-exception-specification) are deprecated in C++0x (and pointless in C++03).

It's not a good idea, no. The reason is that the standard knows that at times it's impossible to enforce the throw() correctness, which is what throw() was brought in for in the first place. In particular, in the case of templates where an exception may or may not be thrown depending on the instantiation it's impossible to check for correctness without the template instantiation. The standard therefore doesn't even require compilers to enforce the exception specifier; in fact, it forbids an implementation from rejecting an expression "merely because when executed it throws or might throw an exception that the containing function does not allow" (15.4/11).
If throw() has no effect other than documentation then it should be commented out; this way at least it doesn't pose a risk of misleading the human observer.
The case with noexcept is wholly different. noexcept comes to be for a different reason; that of performance. If you can guarantee the compiler no exception is thrown then the compiler allows itself to perform some optimizations. But you will have to do the checks yourself. So, if indeed swap() doesn't throw (and it shouldn't; that's its raison d'être) then specifying noexcept is a good idea.

Realistically, no. Exception specifications were a lovely idea, but the reality of them was that they hindered more than helped the majority of code. Nobody uses them and they're deprecated in C++0x. Don't spend time writing exception specifications in modern C++.

Related

Must a compiler always remove a try-catch block if it's proven to be non-throwing

Consider this:
#include <stdexcept>
template <class T>
void F(T &&t) {
try {
t();
} catch(...) {}
}
int main() {
F([]() noexcept {}); // Call 1
F([]{}); // Call 2
F([]{ throw std::exception{}; });// Call 3
}
I found on clang++-6.0 with flags -std=c++17, regardless of the optimization flags I gave, there is always no __gxx_personality and any exception handling code for Call 1.
Can such optimization be relied on when using a different compiler? I only consider C++11 and above.
noexcept specifier was added to c++11 as a replacement for throw(). It guarantees that the function will not throw. The difference between it and throw() is that with noexcept, if the function actually throws, the stack only maybe gets unwinded, which was not the case with the former one (stack always gets unwinded). This enables more optimizations, such as completely omitting the exception handling.
To summarize, it's up to compiler when it decides to omit the exception handling, but with noexcept it has no reason to not do so, which was really hard to determinate in other case.

Can a noexcept function still call a function that throws in C++17?

In P0012R1, "Make exception specifications be part of the type system",
I see that noexcept is now becoming a part of the function type.
I can't tell whether this will prevent noexcept(true) functions from still being able to call noexcept(false) functions.
Will the following code still be valid for C++17?
void will_throw() noexcept(false){
throw 0;
}
void will_not_throw() noexcept(true){
will_throw();
}
According to cppreference:
Note that a noexcept specification on a function is not a compile-time
check; it is merely a method for a programmer to inform the compiler
whether or not a function should throw exceptions.
So the syntax of your code is valid, but std::terminate will be called when executed.
Unfortunately it is valid at compile time.
Although noexcept is used by the compiler to optimize the exception handling code, making the code more performant, it's a shame they didn't push it further to give noexcept a semantic meaning.
Ideally, when you mark a method as noexcept it should also mean that the method is not supposed to let any exceptions bubble up. So if you have a method marked as noexcept but it calls other methods that are not marked as noexcept, that should give you a compile error, unless there is a try/catch block surrounding anything that can throw.
Simply calling std::terminate is a very poor language design choice, because it doesn't put any responsibility at the hands of whoever writes the noexcept method. On the contrary, it harms software reuse by making it impossible even to the consumer to work the problem around.
For example, say that I am a bad library developer and I wrote the following code:
Header file Foo.h that ships with my library:
class Foo
{
public:
void DoSomething() noexcept;
};
You are happy consumer of FooLib writing a Bar application:
Bar.cpp
#include "Foo.h"
int main()
{
Foo foo;
try
{
foo.DoSomething();
}
catch (...)
{
std::cout << "Yay!" << std::endl;
}
return 0;
}
That code compiles fine and runs fine until you have Foo throwing an exception... And it doesn't make any difference if you enclose the call to foo.DoSomething() with a try/catch block. The code will simply abort.
If you don't have the code of Foo, you can't fix it. The only solution in this case is to throw away Foo library and write your own.
The contents of Foo.cpp can be something like this:
static void PotentiallyThrowException()
{
throw 0;
}
void Foo::DoSomething() noexcept
{
PotentiallyThrowException();
}
Note that it's up to the implementer of Foo::DoSomething() to wrap their own calls into try/catch. But due to the same issue, if they are calling other methods that are marked as noexcept and those developers didn't do the same, now it's Foo::DoSomething() that is hosed. And so on, and so forth.
We can safely say that from the semantic point of view noexcept is not only useless, but it's also harmful.
noexcept(true) functions can call noexcept(false) functions. There will be a runtime error if an exception is thrown. The canonical example of why this is allowed is:
double hypotenuse(double opposite, double adjacent) noexcept(true)
{
return std::sqrt(opposite*opposite + adjacent*adjacent);
}
std::sqrt will throw domain_error if its argument is negative, but clearly that will never happen here.
(In an ideal world, it would be forbidden by default with an exception_cast to allow it where required. The result could either be UB if an exception is thrown, or std::terminate).
Including the exception specification in the function type is orthogonal to whether a function can call another function with an incompatible exception specification (without handling the exceptions that were not included in its exception specification). The former is about type safety with respect to function pointers (so that you cannot call a throwing function through a function pointer that was known not to throw). Regarding the latter, we can either prohibit it during compilation (as in Java), or treat it as a runtime error (leading to the termination of the program, as is chosen for the C++ current standard).
One may argue by brining the analogy of calling a non-const (non-static) member function from a const (non-static) member function. However the difference is that indirectly modifying an object inside a non-const member function called through a const member function would go undetected (or else would be too costly to detect) and may lead to nasty bugs, that's why it has to be prevented during compilation. Whereas the act of throwing an exception is (should be) an exceptional event and we can afford inserting run-time checks of whether the exception complies with the exception specification and should be let out, or it violates the program logic and should instead terminate the program.

Noexcept and copy, move constructors

Everywhere I look it seems to be the agreement that the standard library must call copy constructors instead of move constructors when the move constructor is noexcept(false).
Now I do not understand why this is the case. And futher more Visual Studio VC v140 and gcc v 4.9.2 seems to do this differently.
I do not understand why noexcept this is a concern of e.g. vector. I mean how should vector::resize() be able to give strong exception guarantee if T does not. As I see it the exception level of vector will be dependend on T. Regardless if copy or move is used.
I understand noexcept to solely be a wink to the compiler to do exception handling optimization.
This little program calls the copy constructor when compiled with gcc and move constructor when compiled with Visual Studio.
include <iostream>
#include <vector>
struct foo {
foo() {}
// foo( const foo & ) noexcept { std::cout << "copy\n"; }
// foo( foo && ) noexcept { std::cout << "move\n"; }
foo( const foo & ) { std::cout << "copy\n"; }
foo( foo && ) { std::cout << "move\n"; }
~foo() noexcept {}
};
int main() {
std::vector< foo > v;
for ( int i = 0; i < 3; ++i ) v.emplace_back();
}
This is a multi-faceted question, so bear with me while I go through the various aspects.
The standard library expects all user types to always give the basic exception guarantee. This guarantee says that when an exception is thrown, the involved objects are still in a valid, if unknown, state, that no resources are leaked, that no fundamental language invariants are violated, and that no spooky action at a distance happened (that last one isn't part of the formal definition, but it is an implicit assumption actually made).
Consider a copy constructor for a class Foo:
Foo(const Foo& o);
If this constructor throws, the basic exception guarantee gives you the following knowledge:
No new object was created. If a constructor throws, the object is not created.
o was not modified. Its only involvement here is via a const reference, so it must not be modified. Other cases fall under the "spooky action at a distance" heading, or possibly "fundamental language invariant".
No resources were leaked, the program as a whole is still coherent.
In a move constructor:
Foo(Foo&& o);
the basic guarantee gives less assurance. o can be modified, because it is involved via a non-const reference, so it may be in any state.
Next, look at vector::resize. Its implementation will generally follow the same scheme:
void vector<T, A>::resize(std::size_t newSize) {
if (newSize == size()) return;
if (newSize < size()) makeSmaller(newSize);
else if (newSize <= capacity()) makeBiggerSimple(newSize);
else makeBiggerComplicated(newSize);
}
void vector<T, A>::makeBiggerComplicated(std::size_t newSize) {
auto newMemory = allocateNewMemory(newSize);
constructAdditionalElements(newMemory, size(), newSize);
transferExistingElements(newMemory);
replaceInternalBuffer(newMemory, newSize);
}
The key function here is transferExistingElements. If we only use copying, it has a simple guarantee: it cannot modify the source buffer. So if at any point an operation throws, we can just destroy the newly created objects (keep in mind that the standard library absolutely cannot work with throwing destructors), throw away the new buffer, and rethrow. The vector will look as if it had never been modified. This means we have the strong guarantee, even though the element's copy constructor only offers the weak guarantee.
But if we use moving instead, this doesn't work. Once one object is moved from, any subsequent exception means that the source buffer has changed. And because we have no guarantee that moving objects back doesn't throw too, we cannot even recover. Thus, in order to keep the strong guarantee, we have to demand that the move operation doesn't throw any exceptions. If we have that, we're fine. And that's why we have move_if_noexcept.
As to the difference between MSVC and GCC: MSVC only supports noexcept since version 14, and since that is still in development, I suspect the standard library hasn't been updated to take advantage yet.
The core issue is that it's impossible to offer strong exception safety with a throwing move constructor. Imagine if, in vector resize, half way through moving the elements to the new buffer, a move constructor throws. How could you possibly restore the previous state? You can't use the move constructor again because, well, that could just keep throwing.
Copying works for strong exception safety guarantee regardless of it's throwing nature because the original state is not damaged, so if you can't construct the whole new state, you can just clean up the partially-built state and then you're done, because the old state is still here waiting for you. Move constructors don't offer this safety net.
It's fundamentally impossible to offer strongly exception safe resize() with a throwing move, but easy with a throwing copy. This fundamental fact is reflected everywhere over the Standard library.
GCC and VS treat this differently because they are in different stages of conformance. VS has left noexcept to be one of the last features they implement, so their behaviour is a kind of mid-way between C++03's behaviour and C++11/14's. Particularly, since they don't have the ability to tell if your move constructor is actually noexcept or not, they basically just have to guess. From memory they simply assume that it is noexcept because throwing move constructors are not common and not being able to move would be a critical problem.

confusion about non-throw functions

I have 2 questions about non-throwing functions:
Why make a function non-throwing?
How to make a function non-throwing? If the code inside the function actually may throw, then should I still make it non-throwing?
Here is an example:
void swap(Type t1, Type t2) throw()
{
//swap
}
If the code in swap won't throw at all, should I still append throw()? Why?
throw() (or noexcept in C++11) is useful for two reasons:
It allows the compiler to be more aggressive in its optimisations.
It tells function users that they can use this function in their own non-throwing functions.
Non-throwing functions are very important for writing exception safe code. For instance, the usual way of writing an exception safe operator= is via a non-throwing swap() function.
On the other hand, other exception specifications are useless and have been justly deprecated in the current standard. They don't mix well at all with templates and are too expensive to enforce.
Now, if you use a noexcept specification in a function that might actually throw, all bets are off. Even if your compiler does not terminate the program when an exception leaves the function (VS does not do it for runtime efficiency reasons, for instance), your code might not do what you thought because of optimisations. For example:
void f() noexcept
{
a();
b();
}
If a() actually throws and b() has side effects, the function behaviour will be unpredictable, because your compiler may decide to execute b() before a(), since you have told it that no exceptions will be thrown.
EDIT: Now for the second part of your question: how to make a function non-throwing?
First you need to ask yourself whether your function should really be non-throwing. For instance:
class C
{
C* CreateInstance()
{
return new C();
}
}
Since operator new can throw a std::bad_alloc, CreateInstance() can throw. You could try to avoid it with a try-catch block, handling or swallowing any exceptions that may be thrown inside the try block, but would that really be sensible? For instance:
C* CreateInstance()
{
try
{
return new C();
}
catch (...)
{
return null;
}
}
Problem solved, it seems, but would your callers be prepared for CreateInstance() returning null? If not, a crash will ensue when they try to use that pointer. Besides, a std::bad_alloc usually means that you have run out of memory and you would just be postponing the problem.
So be careful: some functions can be made non-throwing, but others should be allowed to throw. Exception safety is not a trivial matter.
Why make a function non-throwing?
So callers of the function can call it without having to take any actions to deal with exceptions being raised by the function.
How to make a function non-throwing? If the code inside the function actually may throw, then should I still make it non-throwing?
You can make the code non-throwing by putting all code which could throw the inside a try block, and deal with any exceptions without re-throwing.
void swap(T t1, T t2) noexcept {
try {
// ....
} catch (const std::exception& ex) {
// ....
} catch (...) {
// ....
}
}
If you claim your function doesn't throw, then you have to make it non-throwing. But this doesn't mean adding an exception specification, which you shouldn't do anyway, since it is deprecated. It means you must ensure the function doesn't throw, no matter what. The C++11 keyword noexcept gives you some compile-time safety in this respect.

return by value and noexcept

I'm currently trying to get my head around noexcept (like almost everyone I avoided the old "runtime exception specification"). Whilst I think I get the basic idea of noexcept, I'm not sure what happens in a situation like:
class sample {
public:
sample() noexcept { }//this doesn't throw
sample(const sample & s) noexcept { }
sample(sample && s) noexcept { }
sample & operator=(const sample & s) noexcept {...}
sample & operator=(sample && s) noexcept { ... }
~sample() noexcept() { }//this should never ever throw
sample operator-() const { return *this * -1; }//assuming that there is a operator*…
sample & operator*=(const sample & s) noexcept { ... }
};
sample operator*(sample s1, const sample & s2) { return s1 *= s2; }//same problem as with operator-…
Is it safe to declar sample::operator- as noexcept, or not? (considering that it's calling a constructor on return)
EDIT: I updated the code section as it seems that the central part of the question was not clear…
After the edit: Your implementation of operator- is guaranteed not to throw any exception (well, at least if you mark operator* as noexcept, that is), and it is thus safe to mark it as noexcept. I don't really understand your concern, though so I might be missing the reason for the question. All of the operations, including the potential copy or move construction are explicitly marked noexcept... where is the issue?
Unless you explicitly mark it as noexcept it will not have that qualification. Now, depending on the implementation of operator* and the copy-constructor it might actually never throw, but that does not make it noexcept.
As of the copy-constructor, if you don't define it, the implicitly declared copy constructor will be noexcept or not depending on whether all the members of your type are noexcept (again, not only that they don't throw, but that they have that qualification)
Your question is, "is it safe?". I would rather ask, "does it even make sense to declare some functions as noexcept only because they do not throw exceptions?".
Strictly speaking, there are two things that noexcept offers:
Anyone can check at compile-time if your function is declared as noexcept. (This is, in practice useful only in one std function: move_if_noexcept)
You get a run-time guarantee that if your function nonetheless tries to throw an exception, it does not get out of the function (because std::terminate is called instead).
More interestingly, to list what noexcept does not offer:
Automatic checking at compile-time if the function really doesn't throw
Even more importantly, it does not offer any "exception safety guarantee".
I believe that the second item is often overlooked when learning the noexcept. If you want to provide a no-fail guarantee (note that this is different than no-throw guarantee, because the function may fail, but not throw), you can simply implement it in your function and throw nothing, and document it somewhere. You do not need to mark your function as noexcept. It will provide no-fail exception safety anyway.
About the only reasonable place for using noexcept is when providing move constructor or move assignment in your type, and only if you feel you need to define them yourself rather than relying on compiler-generated versions. This is useful, because some STL container operations will work faster, because they use function std::move_if_noexcept in their implementations.
I also recommend this article on details of noexcept functionality.